78 lines
3 KiB
JavaScript
78 lines
3 KiB
JavaScript
|
|
import puppeteer from "puppeteer-core";
|
||
|
|
|
||
|
|
const CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
||
|
|
const BASE = "http://localhost:4004";
|
||
|
|
|
||
|
|
const browser = await puppeteer.launch({
|
||
|
|
executablePath: CHROME,
|
||
|
|
headless: "new",
|
||
|
|
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
||
|
|
defaultViewport: { width: 1280, height: 900 },
|
||
|
|
});
|
||
|
|
const page = await browser.newPage();
|
||
|
|
|
||
|
|
await page.goto(`${BASE}/login`, { waitUntil: "networkidle0" });
|
||
|
|
await page.type('input[name="identity"]', "david@rjbulk.local");
|
||
|
|
await page.type('input[name="password"]', "ChangeMe123!");
|
||
|
|
await Promise.all([
|
||
|
|
page.click('button[type="submit"]'),
|
||
|
|
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||
|
|
]);
|
||
|
|
|
||
|
|
// 1. Customers page — no search
|
||
|
|
await page.goto(`${BASE}/customers`, { waitUntil: "networkidle0" });
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-01-no-search.png", fullPage: true });
|
||
|
|
|
||
|
|
// 2. Search "Cash"
|
||
|
|
await page.type('input[name="q"]', "Cash");
|
||
|
|
await Promise.all([
|
||
|
|
page.click('button[type="submit"]'),
|
||
|
|
page.waitForNavigation({ waitUntil: "networkidle0" }),
|
||
|
|
]);
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-02-search-cash.png", fullPage: true });
|
||
|
|
|
||
|
|
// 3. Search "sj" → just SJ Coetzee
|
||
|
|
await page.goto(`${BASE}/customers?q=sj`, { waitUntil: "networkidle0" });
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-03-search-sj.png", fullPage: true });
|
||
|
|
|
||
|
|
// 4. Search "zzz" → empty state
|
||
|
|
await page.goto(`${BASE}/customers?q=zzz`, { waitUntil: "networkidle0" });
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-04-search-empty.png", fullPage: true });
|
||
|
|
|
||
|
|
// 5. Cash Customers row → open menu → show "Protected record"
|
||
|
|
await page.goto(`${BASE}/customers`, { waitUntil: "networkidle0" });
|
||
|
|
const clicked = await page.evaluate(() => {
|
||
|
|
const links = Array.from(document.querySelectorAll("a"));
|
||
|
|
const cashLink = links.find(a => a.textContent.includes("Cash Customers"));
|
||
|
|
if (!cashLink) return false;
|
||
|
|
const tr = cashLink.closest("tr");
|
||
|
|
if (!tr) return false;
|
||
|
|
const btn = tr.querySelector("button");
|
||
|
|
if (!btn) return false;
|
||
|
|
btn.click();
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
console.log("Cash Customers row clicked:", clicked);
|
||
|
|
await new Promise(r => setTimeout(r, 600));
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-05-cash-menu.png", fullPage: true });
|
||
|
|
|
||
|
|
// 6. SJ Coetzee row → open menu → delete should be available (not protected)
|
||
|
|
await page.goto(`${BASE}/customers`, { waitUntil: "networkidle0" });
|
||
|
|
const clicked2 = await page.evaluate(() => {
|
||
|
|
const links = Array.from(document.querySelectorAll("a"));
|
||
|
|
const sjLink = links.find(a => a.textContent.trim() === "SJ Coetzee");
|
||
|
|
if (!sjLink) return false;
|
||
|
|
const tr = sjLink.closest("tr");
|
||
|
|
if (!tr) return false;
|
||
|
|
const btn = tr.querySelector("button");
|
||
|
|
if (!btn) return false;
|
||
|
|
btn.click();
|
||
|
|
return true;
|
||
|
|
});
|
||
|
|
console.log("SJ Coetzee row clicked:", clicked2);
|
||
|
|
await new Promise(r => setTimeout(r, 600));
|
||
|
|
await page.screenshot({ path: "/tmp/rjbulk-screens/cust-06-sj-menu.png", fullPage: true });
|
||
|
|
|
||
|
|
await browser.close();
|
||
|
|
console.log("done");
|