frigate/web/e2e/specs/review.spec.ts

201 lines
6.4 KiB
TypeScript
Raw Normal View History

2026-04-06 19:15:22 +03:00
/**
* Review/Events page tests -- CRITICAL tier.
*
2026-04-06 20:04:51 +03:00
* Tests severity tab switching by name (Alerts/Detections/Motion),
* filter popover opening with camera names, show reviewed toggle,
* calendar button, and filter button interactions.
2026-04-06 19:15:22 +03:00
*/
import { test, expect } from "../fixtures/frigate-test";
import { BasePage } from "../pages/base.page";
test.describe("Review Page - Severity Tabs @critical", () => {
test("severity tabs render with Alerts, Detections, Motion", async ({
frigateApp,
}) => {
2026-04-06 19:15:22 +03:00
await frigateApp.goto("/review");
await expect(frigateApp.page.getByLabel("Alerts")).toBeVisible({
timeout: 10_000,
});
await expect(frigateApp.page.getByLabel("Detections")).toBeVisible();
2026-04-06 20:04:51 +03:00
// Motion uses role="radio" to distinguish from other Motion elements
await expect(
frigateApp.page.getByRole("radio", { name: "Motion" }),
).toBeVisible();
});
2026-04-06 20:04:51 +03:00
test("Alerts tab is active by default", async ({ frigateApp }) => {
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
const alertsTab = frigateApp.page.getByLabel("Alerts");
await expect(alertsTab).toHaveAttribute("data-state", "on");
});
test("clicking Detections tab makes it active and deactivates Alerts", async ({
frigateApp,
}) => {
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
const alertsTab = frigateApp.page.getByLabel("Alerts");
const detectionsTab = frigateApp.page.getByLabel("Detections");
2026-04-06 20:04:51 +03:00
await detectionsTab.click();
await frigateApp.page.waitForTimeout(500);
await expect(detectionsTab).toHaveAttribute("data-state", "on");
await expect(alertsTab).toHaveAttribute("data-state", "off");
2026-04-06 19:15:22 +03:00
});
2026-04-06 20:04:51 +03:00
test("clicking Motion tab makes it active", async ({ frigateApp }) => {
2026-04-06 19:15:22 +03:00
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
const motionTab = frigateApp.page.getByRole("radio", { name: "Motion" });
await motionTab.click();
await frigateApp.page.waitForTimeout(500);
await expect(motionTab).toHaveAttribute("data-state", "on");
2026-04-06 19:15:22 +03:00
});
2026-04-06 20:04:51 +03:00
test("switching back to Alerts from Detections works", async ({
frigateApp,
}) => {
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
await frigateApp.page.getByLabel("Detections").click();
await frigateApp.page.waitForTimeout(300);
await frigateApp.page.getByLabel("Alerts").click();
await frigateApp.page.waitForTimeout(300);
await expect(frigateApp.page.getByLabel("Alerts")).toHaveAttribute(
"data-state",
"on",
);
});
});
2026-04-06 19:15:22 +03:00
test.describe("Review Page - Filters @critical", () => {
2026-04-06 20:04:51 +03:00
test("All Cameras filter button opens popover with camera names", async ({
frigateApp,
}) => {
if (frigateApp.isMobile) {
2026-04-06 20:04:51 +03:00
test.skip();
return;
}
2026-04-06 19:15:22 +03:00
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
2026-04-06 20:04:51 +03:00
const camerasBtn = frigateApp.page.getByRole("button", {
name: /cameras/i,
});
await expect(camerasBtn).toBeVisible({ timeout: 5_000 });
await camerasBtn.click();
await frigateApp.page.waitForTimeout(500);
2026-04-06 20:04:51 +03:00
// Popover should open with camera names from config
const popover = frigateApp.page.locator(
"[data-radix-popper-content-wrapper]",
);
await expect(popover.first()).toBeVisible({ timeout: 3_000 });
2026-04-06 20:04:51 +03:00
// Camera names should be present
await expect(frigateApp.page.getByText("Front Door")).toBeVisible();
2026-04-06 20:04:51 +03:00
await frigateApp.page.keyboard.press("Escape");
});
test("Show Reviewed toggle is clickable", async ({ frigateApp }) => {
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
2026-04-06 20:04:51 +03:00
const showReviewed = frigateApp.page.getByRole("button", {
name: /reviewed/i,
});
if (await showReviewed.isVisible().catch(() => false)) {
await showReviewed.click();
await frigateApp.page.waitForTimeout(500);
2026-04-06 20:04:51 +03:00
// Toggle should change state
await expect(frigateApp.page.locator("body")).toBeVisible();
}
});
test("Last 24 Hours calendar button opens date picker", async ({
frigateApp,
}) => {
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
2026-04-06 20:04:51 +03:00
const calendarBtn = frigateApp.page.getByRole("button", {
name: /24 hours|calendar|date/i,
});
if (await calendarBtn.isVisible().catch(() => false)) {
await calendarBtn.click();
await frigateApp.page.waitForTimeout(500);
2026-04-06 20:04:51 +03:00
// Popover should open
const popover = frigateApp.page.locator(
"[data-radix-popper-content-wrapper]",
);
2026-04-06 20:04:51 +03:00
if (
await popover
.first()
.isVisible()
.catch(() => false)
) {
await frigateApp.page.keyboard.press("Escape");
}
}
2026-04-06 19:15:22 +03:00
});
test("Filter button opens filter popover", async ({ frigateApp }) => {
2026-04-06 19:15:22 +03:00
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(1000);
2026-04-06 20:04:51 +03:00
const filterBtn = frigateApp.page.getByRole("button", {
name: /^filter$/i,
});
if (await filterBtn.isVisible().catch(() => false)) {
await filterBtn.click();
await frigateApp.page.waitForTimeout(500);
2026-04-06 20:04:51 +03:00
// Popover or dialog should open
const popover = frigateApp.page.locator(
"[data-radix-popper-content-wrapper], [role='dialog']",
);
if (
await popover
.first()
.isVisible()
.catch(() => false)
) {
await frigateApp.page.keyboard.press("Escape");
}
}
2026-04-06 19:15:22 +03:00
});
});
2026-04-06 19:15:22 +03:00
2026-04-06 20:04:51 +03:00
test.describe("Review Page - Timeline @critical", () => {
test("review page has timeline with time markers (desktop)", async ({
frigateApp,
}) => {
if (frigateApp.isMobile) {
test.skip();
return;
}
2026-04-06 19:15:22 +03:00
await frigateApp.goto("/review");
await frigateApp.page.waitForTimeout(2000);
2026-04-06 20:04:51 +03:00
// Timeline renders time labels like "4:30 PM"
const pageText = await frigateApp.page.textContent("#pageRoot");
expect(pageText).toMatch(/[AP]M/);
2026-04-06 19:15:22 +03:00
});
});
2026-04-06 20:04:51 +03:00
test.describe("Review Page - Navigation @critical", () => {
test("navigate to review from live page works", async ({ frigateApp }) => {
await frigateApp.goto("/");
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
await base.navigateTo("/review");
await expect(frigateApp.page).toHaveURL(/\/review/);
// Severity tabs should be visible
await expect(frigateApp.page.getByLabel("Alerts")).toBeVisible({
timeout: 10_000,
});
});
});