From cdee1568961e30cac3edfdfdd67a05ceed3a1d1c Mon Sep 17 00:00:00 2001 From: Mariusz Banach Date: Wed, 18 Feb 2026 05:18:55 +0100 Subject: [PATCH] MAESTRO: add e2e flow check for analysis --- ...Kit-web-header-analyzer-Phase-09-Polish.md | 2 +- frontend/e2e/example.spec.ts | 73 +++++++++++++++---- frontend/playwright.config.ts | 9 ++- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/Auto Run Docs/SpecKit-web-header-analyzer-Phase-09-Polish.md b/Auto Run Docs/SpecKit-web-header-analyzer-Phase-09-Polish.md index 7c48252..d6ebf21 100644 --- a/Auto Run Docs/SpecKit-web-header-analyzer-Phase-09-Polish.md +++ b/Auto Run Docs/SpecKit-web-header-analyzer-Phase-09-Polish.md @@ -29,7 +29,7 @@ This phase performs final integration, accessibility audit, responsive testing, ## Completion -- [ ] Complete flow works end-to-end: paste headers → configure tests → analyse → view report → export +- [x] Complete flow works end-to-end: paste headers → configure tests → analyse → view report → export. Notes: replaced Playwright example spec with end-to-end flow test (paste + configure + analyse + report + export), adjusted Playwright webServer ports/CORS for local 3100 runs, ran `npx playwright test e2e/example.spec.ts --project=chromium`. - [ ] File drop flow works: drop EML → auto-populate → analyse → report - [ ] Cache flow works: analyse → reload → see cached results → clear cache - [ ] Rate limiting flow works: exceed limit → CAPTCHA modal → solve → retry succeeds diff --git a/frontend/e2e/example.spec.ts b/frontend/e2e/example.spec.ts index 54a906a..f5994bb 100644 --- a/frontend/e2e/example.spec.ts +++ b/frontend/e2e/example.spec.ts @@ -1,18 +1,61 @@ -import { test, expect } from '@playwright/test'; +import { test, expect } from "@playwright/test"; +import fs from "fs/promises"; +import path from "path"; -test('has title', async ({ page }) => { - await page.goto('https://playwright.dev/'); +const headersPath = path.resolve(__dirname, "../../backend/tests/fixtures/sample_headers.txt"); - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); - -test('get started link', async ({ page }) => { - await page.goto('https://playwright.dev/'); - - // Click the get started link. - await page.getByRole('link', { name: 'Get started' }).click(); - - // Expects page to have a heading with the name of Installation. - await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +test("complete analysis flow from paste to export", async ({ page }) => { + const headers = await fs.readFile(headersPath, "utf8"); + + await page.goto("http://localhost:3100"); + + const headerInput = page.getByRole("textbox", { name: "Header Input" }); + await headerInput.fill(headers); + + const decodeToggle = page.getByTestId("toggle-decode-all"); + await decodeToggle.click(); + await expect(decodeToggle).toHaveAttribute("aria-checked", "true"); + + const firstCheckbox = page.locator('[data-testid^="test-checkbox-"]').first(); + await firstCheckbox.scrollIntoViewIfNeeded(); + await firstCheckbox.waitFor({ state: "visible" }); + await firstCheckbox.check(); + + const checkboxTestId = await firstCheckbox.getAttribute("data-testid"); + const testId = checkboxTestId?.replace("test-checkbox-", ""); + expect(testId).toBeTruthy(); + + await page.getByRole("button", { name: "Analyse Headers" }).click(); + + const reportContainer = page.getByTestId("report-container"); + await reportContainer.waitFor({ state: "visible", timeout: 30000 }); + + if (testId) { + await expect(page.getByTestId(`test-result-card-${testId}`)).toBeVisible(); + } + + const [jsonDownload] = await Promise.all([ + page.waitForEvent("download"), + page.getByTestId("report-export-json").click(), + ]); + expect(jsonDownload.suggestedFilename()).toBe("analysis-report.json"); + const jsonPath = await jsonDownload.path(); + if (!jsonPath) { + throw new Error("JSON export did not provide a download path."); + } + const jsonContents = await fs.readFile(jsonPath, "utf8"); + const parsed = JSON.parse(jsonContents) as { metadata?: Record }; + expect(parsed.metadata).toBeTruthy(); + + const [htmlDownload] = await Promise.all([ + page.waitForEvent("download"), + page.getByTestId("report-export-html").click(), + ]); + expect(htmlDownload.suggestedFilename()).toBe("analysis-report.html"); + const htmlPath = await htmlDownload.path(); + if (!htmlPath) { + throw new Error("HTML export did not provide a download path."); + } + const htmlContents = await fs.readFile(htmlPath, "utf8"); + expect(htmlContents).toContain("Email Header Analysis Report"); }); diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index eca2d6f..dc2bee8 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -73,14 +73,17 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: [ { - command: 'python -m uvicorn backend.app.main:app --port 8000', + command: 'python -m uvicorn app.main:app --app-dir backend --port 8000', url: 'http://localhost:8000', reuseExistingServer: !process.env.CI, cwd: '..', + env: { + WHA_CORS_ORIGINS: '["http://localhost:3100"]', + }, }, { - command: 'npm run dev -- --port 3000', - url: 'http://localhost:3000', + command: 'npm run dev -- --port 3100', + url: 'http://localhost:3100', reuseExistingServer: !process.env.CI, }, ],