← back to Malden House
test-e2e.js
80 lines
// End-to-end simulation — mirrors what signup.js + rental.js do in the browser.
const fns = require("./signup.js");
async function run() {
const demos = [
{ address: "471 S Peck Dr, Beverly Hills, CA 90210", host: "Steve Abrams", email: "steveabramsdesigns@gmail.com", phone: "(310) 713-0489" },
{ address: "462 S Beverwil Dr, Beverly Hills, CA 90212", host: "Steve Abrams", email: "steveabramsdesigns@gmail.com", phone: "(310) 713-0489" },
];
const store = {};
console.log("\n── 1/5 SEED TWO RENTALS ───────────────────────────────");
for (const d of demos) {
const geo = await fns.geocode(d.address);
const nearest = fns.nearestVenues({ lat: geo.lat, lng: geo.lng }, 6);
const baseline = fns.baselineFor(geo.zip || "");
const price = fns.priceModel(baseline, nearest);
const slug = fns.slugify((geo.street || d.address).split(",")[0]);
store[slug] = {
slug, host: d.host, email: d.email, phone: d.phone,
address: { raw: d.address, display: geo.display, street: geo.street, city: geo.city,
county: geo.county, state: geo.state, zip: geo.zip, lat: geo.lat, lng: geo.lng },
baseline, price, nearest,
createdAt: new Date().toISOString(),
verified: true,
inquiries: [], photos: [],
};
console.log(` ✓ ${slug} · ${geo.street} → closest ${nearest[0].headline} (${nearest[0].mi.toFixed(1)} mi) · $${price.mid}/night`);
await new Promise(r => setTimeout(r, 1200));
}
console.log("\n── 2/5 ELIGIBILITY GATE ───────────────────────────────");
// Try an address >30 mi from any venue (e.g., Palm Springs)
try {
const far = await fns.geocode("100 E Tahquitz Canyon Way, Palm Springs, CA 92262");
const n = fns.nearestVenues({ lat: far.lat, lng: far.lng }, 1);
const ok = n[0].mi <= 30;
console.log(` Palm Springs → ${n[0].name} = ${n[0].mi.toFixed(1)} mi · eligible: ${ok ? "YES" : "NO (correctly rejected)"}`);
} catch (e) { console.log(" ⚠ geocode error:", e.message); }
console.log("\n── 3/5 SIMULATE INQUIRY FROM A GUEST ──────────────────");
const target = Object.keys(store)[0];
const inquiry = {
id: "inq-" + Math.random().toString(36).slice(2, 10),
firstName: "Ruth", lastName: "Bader", email: "ruth@example.com",
checkIn: "2028-07-17", checkOut: "2028-07-23", guests: "4",
events: ["3x3 BASKETBALL", "SKATEBOARDING"],
message: "Flying in from Chicago — UCLA gymnastics + maybe some BMX. Any chance of early check-in on the 17th?",
createdAt: new Date().toISOString(),
};
store[target].inquiries.push(inquiry);
console.log(` ✓ Inquiry from ${inquiry.firstName} ${inquiry.lastName} saved to ${target}`);
console.log(` → checkin ${inquiry.checkIn} → checkout ${inquiry.checkOut} · ${inquiry.guests} guests`);
console.log("\n── 4/5 SIMULATE PHOTO UPLOAD ──────────────────────────");
// Minimal valid JPEG data URL — 1×1 red pixel. Good enough to verify the pipeline.
const onePx = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAABAAEDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAn/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AL+AAAAAAAf/2Q==";
store[target].photos.push(onePx, onePx, onePx);
console.log(` ✓ 3 photos pushed to ${target}.photos[] (total ${store[target].photos.length})`);
console.log("\n── 5/5 VERIFY RECORD SHAPE MATCHES DASHBOARD EXPECTATIONS ──");
const r = store[target];
const checks = [
["slug", !!r.slug],
["host/email/phone", r.host && r.email && r.phone],
["address.street/city/zip/lat/lng", r.address.street && r.address.city && r.address.zip && r.address.lat && r.address.lng],
["nearest[0] has headline+dates", r.nearest[0].headline && r.nearest[0].dates],
["price.low/mid/high", r.price.low && r.price.mid && r.price.high],
["inquiries[] + photos[]", Array.isArray(r.inquiries) && Array.isArray(r.photos)],
["createdAt ISO", !isNaN(new Date(r.createdAt).getTime())],
];
for (const [k, ok] of checks) console.log(` ${ok ? "✓" : "✗"} ${k}`);
console.log("\n──────────────────────────────────────────────────────");
console.log(" STORE OK — ready to import into localStorage.");
console.log(" Rentals:", Object.keys(store).join(", "));
console.log("──────────────────────────────────────────────────────\n");
return store;
}
run().catch(e => { console.error("FAIL:", e); process.exit(1); });