Public: anyone can read this; the crew can change it.

The README meeting walkthrough covers the week view, showings, the seller update and link previews, and its test walks them #99

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/listing-launch:mason/97-the-readme-meeting-walkthrough-covers-th → main 1 commit fork

  • Merged. mason/97-the-readme-meeting-walkthrough-covers-th was merged into main as a0f1eb7.

Review

Sign in to review this change.
2 files changed +89 −0
README.md +23
@@ -153,6 +153,29 @@ to make a listing of your own.
153153 In the terminal it is the last asset of the listing: `j` to it, `a` to approve
154154 or withdraw. The seller report leaves it out; it is a note, not something
155155 that goes out.
156 16. **See the coming week.** Press **This week** above the list on the first
157 screen: the next seven days, a section for each day, with every listing's
158 posts, emails and open houses that go out that day, and who approved each
159 (or Draft). At the top, **Still needs approval** names each listing with
160 some of its words not yet approved, such as "3 of 7 approved". *412 Alder
161 Lane* shows its open house there. **Add to calendar** puts the same week
162 in your calendar. Nothing is sent from this page.
163 17. **Write down a showing.** On your own listing, scroll to **Showings**.
164 Leave the day as today, type the buyer's agent if you know them, pick how
165 interested they were (Not interested, Maybe, Interested or Offer likely),
166 write one line of what they said and press **Log showing**. It lands at the
167 top of the list, newest first, and the first screen now shows "1 showing"
168 beside your listing. **Remove** takes it back out. Only you see this log:
169 it is not on the property page, the flyer or the email. (The sample
170 listings belong to the sample agent, so their showings are hers to see.)
171 18. **Approve the seller update.** On your listing open the **Seller update**
172 tab: the weekly email to your seller, already written, with what you
173 approved this week in it. Read it, then press **Approve**. Until you do, it says "Draft — not approved".
174 19. **Paste the property page link.** On a listing, copy the property page
175 link (the **Copy** button) and paste it into a text or a post: the phone
176 shows a preview with the address, the price, the beds and baths and the
177 first photo. *412 Alder Lane* is approved, so its link works for anyone;
178 yours shows a page only once you approve the MLS description.
156179
157180 `src/walkthrough.test.ts` walks these steps on every `bun test`, so this
158181 list cannot drift from the app.
src/walkthrough.test.ts +66
@@ -266,3 +266,69 @@ test("every step of the section works, with the labels it names", async () => {
266266 expect(await (await get(mine)).text()).toContain("data-copy-link=");
267267 expect((await fetch(`${base}${mine.replace("/listings/", "/homes/")}`)).status).toBe(404);
268268 });
269
270 test("the week, a showing, the seller update and the link preview, as the section says", async () => {
271 const home = await (await get("/")).text();
272 const sample = idOf(home, "412 Alder Lane");
273 const mine = `/listings/${idOf(home, "9 Walkthrough Way")}`;
274
275 // 16. The coming week.
276 for (const label of ["This week", "Still needs approval", "Add to calendar"]) expect(section).toContain(label);
277 expect(home).toMatch(control("This week"));
278 const week = await get("/week");
279 expect(week.status).toBe(200);
280 const weekHtml = await week.text();
281 expect(weekHtml).toContain("Still needs approval");
282 expect(weekHtml).toContain("412 Alder Lane");
283 expect(weekHtml).toContain("Draft — not approved yet");
284 expect(weekHtml).toMatch(control("Add to calendar"));
285
286 // 17. Write down a showing.
287 for (const label of ["Showings", "Log showing", "Remove"]) expect(section).toContain(label);
288 for (const word of ["Not interested", "Maybe", "Interested", "Offer likely"]) expect(section).toContain(word);
289 const before = await (await get(mine)).text();
290 expect(before).toContain('id="showings"');
291 expect(before).toMatch(control("Log showing"));
292 expect(before).not.toContain("1 showing");
293 const showing = new FormData();
294 showing.set("agent", "Pat Buyer, Walk Realty");
295 showing.set("interest", "interested");
296 showing.set("feedback", "Loved the kitchen.");
297 expect((await post(`${mine}/showings`, showing)).status).toBe(303);
298 const logged = await (await get(mine)).text();
299 expect(logged).toContain("Loved the kitchen.");
300 expect(logged).toContain("Pat Buyer, Walk Realty");
301 expect(logged).toMatch(control("Remove"));
302 expect(await (await get("/")).text()).toContain("1 showing");
303 // The sample's showings belong to the sample agent: this realtor sees none, and so the section says.
304 expect(await (await get(`/listings/${sample}`)).text()).not.toContain('id="showings"');
305 // Only the realtor: nothing of it reaches the property page's public view.
306 expect(await (await fetch(base + mine.replace("/listings/", "/homes/"))).text()).not.toContain("Pat Buyer");
307
308 // 18. The seller update waits for approval, then is approved.
309 expect(section).toContain("**Seller update**");
310 expect(logged).toContain("Seller update");
311 expect(logged).toContain("Draft — not approved");
312 const block = /<section class="asset" id="email_update"[^]*?<\/section>/.exec(logged)![0];
313 expect(block).toMatch(/<button[^>]*formaction="[^"]*\/assets\/email_update\/approve"[^>]*>Approve</);
314 const update = new FormData();
315 update.set("approved", "1");
316 update.set("seen", /name="seen" value="([^"]+)"/.exec(block)![1]!.replaceAll("&amp;", "&"));
317 update.set("text", textareaOf(block));
318 expect((await post(`${mine}/assets/email_update/approve`, update)).status).toBe(303);
319 const after = await (await get(mine)).text();
320 const approvedBlock = /<section class="asset" id="email_update"[^]*?<\/section>/.exec(after)![0];
321 expect(approvedBlock).toContain("✓ Approved by");
322 expect(approvedBlock).toContain("Withdraw");
323
324 // 19. The link preview: an approved listing's page carries the tags a phone reads.
325 expect(section).toContain("Copy");
326 expect(section).toContain("412 Alder Lane");
327 const page = await fetch(`${base}/homes/${sample}`);
328 expect(page.status).toBe(200);
329 const preview = await page.text();
330 expect(preview).toMatch(/<meta property="og:title" content="412 Alder Lane[^"]*\$\d/);
331 expect(preview).toMatch(/<meta property="og:image" content="https?:\/\/[^"]+"/);
332 expect(preview).toContain('name="twitter:card"');
333 expect(await (await get(mine)).text()).toContain("data-copy-link=");
334 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs