65 lines
3.2 KiB
TypeScript
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.");
|
|
});
|