← 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); });