Files

65 lines
3.2 KiB
TypeScript

import { expect, test } from "@playwright/test";
const validUpload = { name: "sample.evtx", mimeType: "application/octet-stream", buffer: Buffer.from("synthetic") };
test("malformed successful analysis keeps the previous investigation", async ({ page }) => {
await page.goto("/#analysis");
await page.getByRole("button", { name: "Load demo", exact: true }).first().click();
await expect(page.getByRole("region", { name: "Current investigation context" })).toContainText("bundled-demo");
await page.route("**/api/analyze", (route) => route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ source: "bad.evtx", events: [], incidents: [{ id: "broken" }] }),
}));
await page.locator('input[type="file"]').setInputFiles(validUpload);
await expect(page.getByRole("alert")).toContainText("Analysis returned an invalid response.");
await expect(page.getByRole("region", { name: "Current investigation context" })).toContainText("bundled-demo");
await page.getByRole("button", { name: "Timeline", exact: false }).click();
await expect(page.getByRole("heading", { name: "Inspector", exact: true })).toBeVisible();
});
test("structured parser errors have safe, useful wording", async ({ page }) => {
await page.route("**/api/analyze", (route) => route.fulfill({
status: 422,
contentType: "application/json",
body: JSON.stringify({ detail: { code: "no_readable_events", message: "No readable Windows events were found in this file." } }),
}));
await page.goto("/#analysis");
await page.locator('input[type="file"]').setInputFiles(validUpload);
await expect(page.getByRole("alert")).toContainText("No readable Windows events were found in this file.");
await expect(page.getByRole("alert")).not.toContainText("HTTP 422");
});
test("rejecting an invalid file cancels an older pending analysis", async ({ page }) => {
await page.goto("/#analysis");
await page.getByRole("button", { name: "Load demo", exact: true }).first().click();
await expect(page.getByRole("region", { name: "Current investigation context" })).toContainText("bundled-demo");
let routeStarted!: () => void;
let releaseRoute!: () => void;
const started = new Promise<void>((resolve) => { routeStarted = resolve; });
const released = new Promise<void>((resolve) => { releaseRoute = resolve; });
await page.route("**/api/analyze", async (route) => {
routeStarted();
await released;
try {
await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ source: "late.evtx", events: [], incidents: [] }) });
} catch {
// The route can already be cancelled by the browser request abort.
}
});
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles(validUpload);
await started;
await fileInput.setInputFiles({ name: "invalid.txt", mimeType: "text/plain", buffer: Buffer.from("invalid") });
await expect(page.getByRole("alert")).toContainText("Choose a Windows .evtx file.");
releaseRoute();
await page.waitForTimeout(300);
await expect(page.getByRole("region", { name: "Current investigation context" })).toContainText("bundled-demo");
await expect(page.getByRole("alert")).toContainText("Choose a Windows .evtx file.");
});