import { test, expect } from "@playwright/test"; import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; const xml = readFileSync("fixtures/sample.sqlplan", "utf8"); test.use({ storageState: ".auth/user.json", permissions: ["clipboard-read", "clipboard-write"] }); test("full run: paste → stages → streamed report → copy → print", async ({ page }) => { await page.goto("/app"); await page.fill("#xml", xml); await page.fill("#note", "slow since the migration"); await page.getByRole("button", { name: "Analyse" }).click(); // Stages are named one at a time; the whole run takes tens of seconds with a real model. await expect(page.getByText(/1 of 4 · Reading the plan/)).toBeVisible({ timeout: 20_000 }); await expect(page.getByText(/4 of 4 · Writing the report/)).toBeVisible({ timeout: 180_000 }); // The report paints while oul is still arriving, so the headline shows up first. await expect(page.locator("#report h2").first()).toBeVisible({ timeout: 180_000 }); // The Analyse button only unlocks on the done frame: by then the whole report has arrived and parsed. await expect(page.getByRole("button", { name: "Analyse" })).toBeEnabled({ timeout: 180_000 }); expect(await page.locator("#report .card").count()).toBeGreaterThan(2); // No raw OpenUI Lang leaked into the page as text. expect(await page.locator("main").innerText()).not.toContain("root = Report("); await page.getByRole("button", { name: "Copy", exact: true }).click(); const clip = await page.evaluate(() => navigator.clipboard.readText()); expect(clip).toContain("slow since the migration"); await page.getByRole("button", { name: "Export to PDF" }).click(); // window.print() await page.emulateMedia({ media: "print" }); await expect(page.locator(".rail")).toBeHidden(); await expect(page.locator(".toolbar")).toBeHidden(); }); test("a dropped .sqlplan file decodes and is accepted", async ({ page }) => { await page.goto("/app"); await page.setInputFiles('input[type="file"]', "fixtures/sample.sqlplan"); const value = await page.locator("#xml").inputValue(); expect(value).toContain("ShowPlanXML"); expect(value).not.toContain("\u0000"); expect(value).not.toContain("\ufeff"); }); test("a UTF-16LE .sqlplan, which is what SSMS writes, decodes without NULs", async ({ page }) => { // fixtures/sample.sqlplan is UTF-8+BOM, so the test above never exercised the SSMS encoding. mkdirSync(".playwright-data", { recursive: true }); const path = ".playwright-data/upload-utf16le.sqlplan"; const clean = readFileSync("fixtures/sample.sqlplan", "utf8").replace(/^/, ""); writeFileSync(path, Buffer.from("\uFEFF" + clean, "utf16le")); await page.goto("/app"); await page.setInputFiles('input[type="file"]', path); const value = await page.locator("#xml").inputValue(); expect(value.startsWith(" { await page.goto("/app"); await page.fill("#xml", readFileSync("fixtures/sample.sqlplan", "utf8").slice(0, 900)); await page.getByRole("button", { name: "Analyse" }).click(); const alert = page.getByRole("alert").filter({ hasText: "digesting" }); await expect(alert).toBeVisible({ timeout: 30_000 }); expect(await alert.innerText()).toMatch(/stopped parsing|Unexpected|unclosed|tag name/i); }); test("a pasted SQL script is refused with a named reason", async ({ page }) => { await page.goto("/app"); await page.fill("#xml", "SELECT * FROM dbo.Orders WHERE CustomerId = 42;"); await page.getByRole("button", { name: "Analyse" }).click(); await expect(page.getByRole("alert").filter({ hasText: "digesting" })).toBeVisible({ timeout: 30_000 }); await expect(page.locator("#report")).toHaveCount(0); });