agent-market/tests/browser_e2e.js

79 lines
5.0 KiB
JavaScript

// Headless browser walkthrough. Usage: NODE_PATH=<dir with puppeteer-core> node tests/browser_e2e.js http://127.0.0.1:8795 [screenshot_dir]
const puppeteer = require("puppeteer-core");
const BASE = process.argv[2] || "http://127.0.0.1:8795";
const SHOTS = process.argv[3] || "";
const results = [];
const check = (name, ok, d = "") => { results.push(ok); console.log((ok ? "PASS " : "FAIL ") + name + (d ? ` [${d}]` : "")); };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
(async () => {
const browser = await puppeteer.launch({ executablePath: process.env.CHROME || "/usr/bin/google-chrome", headless: "new",
args: ["--no-sandbox", "--disable-gpu", "--user-data-dir=/tmp/am-pptr-profile"] });
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 860 });
const errors = []; page.on("pageerror", (e) => errors.push(e.message));
await page.goto(BASE + "/", { waitUntil: "networkidle0" });
await page.waitForSelector(".card", { timeout: 15000 });
check("landing renders agent-chosen cards", (await page.$$(".card")).length >= 4);
const badge = await page.$eval("#agentBadge", (n) => n.textContent);
check("agent mode badge shown", /fallback|LLM/.test(badge), badge);
// chat search
await page.click("#chatLauncher");
await page.type("#chatInput", "show me bikes");
await page.keyboard.press("Enter");
await page.waitForFunction(() => [...document.querySelectorAll("#stage h2")].some((h) => /bike/i.test(h.textContent)), { timeout: 15000 });
const titles = await page.$$eval("#stage .card h3", (ns) => ns.map((n) => n.textContent));
check("chat search renders bike cards", titles.length && titles.every((t) => /bike/i.test(t)), titles.join(" | "));
if (SHOTS) { await sleep(600); } if (SHOTS) await page.screenshot({ path: SHOTS + "/1-landing-chat-search.png" });
// online checkout
const roadBtn = await page.evaluateHandle(() => [...document.querySelectorAll(".card")].find((c) => /road bike/i.test(c.textContent)).querySelector("button.btn:not(.cash)"));
await roadBtn.click();
await page.waitForSelector("[data-component=checkout]", { timeout: 15000 });
const fee = await page.$eval("[data-testid=fee]", (n) => n.textContent);
const total = await page.$eval("[data-testid=total]", (n) => n.textContent);
check("checkout shows 5% fee and total", fee === "$9.00" && total === "$189.00", `fee ${fee} total ${total}`);
if (SHOTS) { await sleep(600); } if (SHOTS) await page.screenshot({ path: SHOTS + "/2-checkout-fee.png" });
await page.click("[data-component=checkout] button[type=submit]");
await page.waitForSelector("[data-component=receipt]", { timeout: 15000 });
const rfee = await page.$eval("[data-testid=receipt-fee]", (n) => n.textContent);
check("test payment confirms, receipt shows fee", rfee === "$9.00", rfee);
// cash meetup
await page.type("#chatInput", "show lamp");
await page.keyboard.press("Enter");
await page.waitForFunction(() => [...document.querySelectorAll("#stage .card h3")].some((h) => /lamp/i.test(h.textContent)), { timeout: 15000 });
const cashBtn = await page.evaluateHandle(() => [...document.querySelectorAll(".card")].find((c) => /ceramic/i.test(c.textContent)).querySelector("button.cash"));
await cashBtn.click();
await page.waitForSelector("[data-component=cash-meetup]", { timeout: 15000 });
const cfee = await page.$eval("[data-testid=cash-fee]", (n) => n.textContent);
check("cash meetup shows $0 fee", cfee === "$0.00", cfee);
if (SHOTS) { await sleep(600); } if (SHOTS) await page.screenshot({ path: SHOTS + "/3-cash-meetup.png" });
await page.click("[data-component=cash-meetup] button.cash");
await page.waitForSelector("[data-component=receipt]", { timeout: 15000 });
check("cash deal completed with $0 fee", (await page.$eval("[data-testid=receipt-fee]", (n) => n.textContent)) === "$0.00");
// sell
await page.click("nav [data-event=sell]");
await page.waitForSelector("[data-component=listing-form]", { timeout: 15000 });
await page.type("[name=title]", "Test-only bookshelf");
await page.type("[name=price]", "30");
await page.type("[name=description]", "Fake listing created by the browser test");
await page.click("[data-component=listing-form] button[type=submit]");
await page.waitForFunction(() => [...document.querySelectorAll("#stage .card h3")].some((h) => h.textContent === "Test-only bookshelf"), { timeout: 15000 });
check("listing form publishes a new card", true);
// compare
await page.type("#chatInput", "compare tutoring");
await page.keyboard.press("Enter");
await page.waitForSelector("[data-component=compare]", { timeout: 15000 });
check("compare view renders", (await page.$$("[data-component=compare] th")).length >= 3);
check("no page JS errors", errors.length === 0, errors.join("; "));
await browser.close();
const passed = results.filter(Boolean).length;
console.log(`\n${passed}/${results.length} passed`);
process.exit(passed === results.length ? 0 : 1);
})().catch((e) => { console.error(e); process.exit(2); });