jacquardSnapshot

← snapshot

1757 bytes
/** Jackie must say nothing until asked. */
import { chromium } from "@playwright/test";
const b = await chromium.launch();
const p = await b.newPage({ viewport: { width: 1400, height: 950 }, colorScheme: "dark" });

// Count anything that would make sound.
await p.addInitScript(() => {
  window.__spoke = 0;
  const orig = window.speechSynthesis?.speak?.bind(window.speechSynthesis);
  if (orig) window.speechSynthesis.speak = (u) => { window.__spoke++; return orig(u); };
  const of = window.fetch;
  window.__tts = 0;
  window.fetch = (...a) => {
    const url = typeof a[0] === "string" ? a[0] : a[0]?.url ?? "";
    if (url.includes("/speech") && (a[1]?.method === "POST")) window.__tts++;
    return of(...a);
  };
});

await p.goto("http://localhost:3000/", { waitUntil: "networkidle" });
await p.waitForTimeout(2500);
const pick = p.locator("button, a").filter({ hasText: /meridian/i }).first();
if (await pick.count()) { await pick.click(); await p.waitForTimeout(5000); }

const before = await p.evaluate(() => ({ spoke: window.__spoke, tts: window.__tts }));
console.log("before opt-in:", JSON.stringify(before), before.spoke === 0 && before.tts === 0 ? "SILENT ✓" : "SPOKE ✗");

const optIn = p.locator("button", { hasText: "Turn on Jackie's voice" }).first();
console.log("opt-in control present:", (await optIn.count()) > 0);
if (await optIn.count()) {
  await optIn.click();
  await p.waitForTimeout(700);
  const label = await p.locator("button", { hasText: /Silence Jackie|Turn on Jackie/ }).first().textContent();
  console.log("after click, control reads:", JSON.stringify(label?.trim()));
  const stored = await p.evaluate(() => localStorage.getItem("jac-jackie-voice"));
  console.log("remembered as:", stored);
}
await b.close();