tokencostguard / scripts /capture-e2e-screenshots.mjs
lixiaowww
CSP: allow huggingface.co frame-ancestors
249c849
Raw
History Blame Contribute Delete
4.1 kB
import { chromium } from "playwright";
import fs from "node:fs";
const baseUrl = process.env.E2E_BASE_URL ?? "http://localhost:3000";
const memberApiKey = process.env.MEMBER_API_KEY;
if (!memberApiKey) {
throw new Error("MEMBER_API_KEY is required");
}
fs.mkdirSync("artifacts", { recursive: true });
const browser = await chromium.launch({ headless: true });
try {
// Flow A: free user signup
const freeContext = await browser.newContext();
const freePage = await freeContext.newPage();
const freeSignupResp = await freeContext.request.post(`${baseUrl}/api/v1/signup/free`, {
data: { display_name: "E2E Free Proof" },
});
if (freeSignupResp.status() !== 201) {
throw new Error(`Free signup failed with status ${freeSignupResp.status()}`);
}
const freeData = await freeSignupResp.json();
const freeSetCookie = freeSignupResp.headers()["set-cookie"] ?? "";
const freeMatch = freeSetCookie.match(/tcg_session=([^;]+)/);
if (!freeMatch) {
throw new Error("Free signup did not return tcg_session cookie");
}
await freeContext.addCookies([
{
name: "tcg_session",
value: decodeURIComponent(freeMatch[1]),
domain: "localhost",
path: "/",
httpOnly: true,
sameSite: "Lax",
secure: false,
},
]);
await freePage.goto(baseUrl, { waitUntil: "domcontentloaded" });
await freePage.waitForTimeout(1200);
const freeTenantLabel = freePage.locator(`text=${freeData.tenant.id}`).first();
await freeTenantLabel.waitFor({ timeout: 15000 });
await freePage.screenshot({ path: "artifacts/e2e-free-user-success.png", fullPage: true });
await freeContext.close();
// Flow B: member login (API) -> UI session restore -> checkout redirect
const memberContext = await browser.newContext();
const memberPage = await memberContext.newPage();
const loginResp = await memberContext.request.post(`${baseUrl}/api/v1/auth/session`, {
data: { api_key: memberApiKey },
});
if (loginResp.status() !== 200) {
throw new Error(`Member login failed with status ${loginResp.status()}`);
}
const setCookie = loginResp.headers()["set-cookie"] ?? "";
const match = setCookie.match(/tcg_session=([^;]+)/);
if (!match) {
throw new Error("Member login did not return tcg_session cookie");
}
await memberContext.addCookies([
{
name: "tcg_session",
value: decodeURIComponent(match[1]),
domain: "localhost",
path: "/",
httpOnly: true,
sameSite: "Lax",
secure: false,
},
]);
await memberPage.goto(baseUrl, { waitUntil: "domcontentloaded" });
await memberPage.waitForTimeout(1200);
const memberTenantLabel = memberPage.locator("text=/tenant_staging_admin/i").first();
await memberTenantLabel.waitFor({ timeout: 15000 });
await memberPage.waitForTimeout(500);
await memberPage.getByRole("button", { name: /pricing \/ upgrade/i }).click();
await memberPage.waitForTimeout(800);
await memberPage.screenshot({ path: "artifacts/e2e-member-signedin-pricing.png", fullPage: true });
const checkoutResp = await memberContext.request.post(`${baseUrl}/api/v1/billing/checkout/session`, {
data: {
plan: "pro_guardian",
mode: "subscription",
success_url: `${baseUrl}/?checkout=success`,
cancel_url: `${baseUrl}/?checkout=cancel`,
},
});
if (checkoutResp.status() !== 200) {
throw new Error(`Checkout create failed with status ${checkoutResp.status()}`);
}
const checkoutData = await checkoutResp.json();
if (!checkoutData?.checkout_url) {
throw new Error("Checkout URL missing from checkout session response");
}
await memberPage.goto(checkoutData.checkout_url, { waitUntil: "domcontentloaded" });
await memberPage.waitForURL(/checkout\.stripe\.com/, { timeout: 30000 });
await memberPage.screenshot({ path: "artifacts/e2e-member-checkout-success.png", fullPage: true });
await memberContext.close();
} finally {
await browser.close();
}
console.log("Saved screenshots:");
console.log("- artifacts/e2e-free-user-success.png");
console.log("- artifacts/e2e-member-checkout-success.png");