test(e2e): e2e_export_download + e2e_roundtrip_noop (SD-0002 §6.8, PUC-9/10)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+37
-1
@@ -2,7 +2,8 @@
|
||||
// navigation (SD-0002 §5.2). Selectors are role/label-based against the real screens
|
||||
// (Landing.tsx, SignIn.tsx, CreateStorefront.tsx, Admin.tsx, ProductsPage.tsx).
|
||||
import { expect, type Page } from "@playwright/test";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const LOG = join(__dirname, ".backend.log");
|
||||
@@ -72,3 +73,38 @@ export async function uploadFixture(page: Page, fixture: string) {
|
||||
await expect(page.getByRole("heading", { name: "Import products" })).toBeVisible();
|
||||
await page.locator('input[type="file"]').setInputFiles(join(__dirname, "fixtures", fixture));
|
||||
}
|
||||
|
||||
// Import good.csv and confirm it, leaving a 2-product catalog. Returns nothing;
|
||||
// callers continue from the run-detail screen.
|
||||
export async function importGoodCsv(page: Page) {
|
||||
await uploadFixture(page, "good.csv");
|
||||
await expect(page.getByRole("heading", { name: "Import preview — good.csv" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Import 2 products" }).click();
|
||||
await expect(page.getByRole("heading", { level: 1, name: "good.csv" })).toBeVisible();
|
||||
}
|
||||
|
||||
// Click an Export status option and capture the downloaded CSV's text + path.
|
||||
export async function exportCatalog(page: Page, label: string): Promise<{ text: string; path: string }> {
|
||||
// Open the <details> menu, then click the status option, capturing the download.
|
||||
// The menu is a native <details> that *toggles* on each summary click and is
|
||||
// NOT closed by clicking a download <a> (a download doesn't navigate). So on a
|
||||
// second export the menu may already be open — deterministically open it
|
||||
// rather than blind-toggling, and wait for the status link to be visible.
|
||||
const details = page.locator("details.products__export");
|
||||
if (!(await details.evaluate((el: HTMLDetailsElement) => el.open))) {
|
||||
await details.locator("> summary").click();
|
||||
}
|
||||
const link = page.getByRole("link", { name: label, exact: true });
|
||||
await expect(link).toBeVisible();
|
||||
const [download] = await Promise.all([
|
||||
page.waitForEvent("download"),
|
||||
link.click(),
|
||||
]);
|
||||
const stream = await download.createReadStream();
|
||||
const chunks: Buffer[] = [];
|
||||
for await (const c of stream) chunks.push(c as Buffer);
|
||||
const text = Buffer.concat(chunks).toString("utf8");
|
||||
const path = join(tmpdir(), `export-${Date.now()}.csv`);
|
||||
await writeFile(path, text, "utf8");
|
||||
return { text, path };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user