mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-09 16:47:37 +03:00
199 lines
6.0 KiB
TypeScript
199 lines
6.0 KiB
TypeScript
|
|
/**
|
||
|
|
* Navigation tests -- CRITICAL tier.
|
||
|
|
*
|
||
|
|
* Tests sidebar (desktop) and bottombar (mobile) navigation,
|
||
|
|
* conditional nav items, settings menus, and route transitions.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { test, expect } from "../fixtures/frigate-test";
|
||
|
|
import { BasePage } from "../pages/base.page";
|
||
|
|
|
||
|
|
test.describe("Navigation @critical", () => {
|
||
|
|
test("app loads and renders page root", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(frigateApp.page.locator("#pageRoot")).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("logo is visible and links to home", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
|
||
|
|
if (!frigateApp.isMobile) {
|
||
|
|
// Desktop: logo in sidebar
|
||
|
|
const logo = base.sidebar.locator('a[href="/"]').first();
|
||
|
|
await expect(logo).toBeVisible();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Live nav item is active on root path", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const liveLink = frigateApp.page.locator('a[href="/"]').first();
|
||
|
|
await expect(liveLink).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("navigate to Review page", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
|
||
|
|
await base.navigateTo("/review");
|
||
|
|
await expect(frigateApp.page).toHaveURL(/\/review/);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("navigate to Explore page", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
|
||
|
|
await base.navigateTo("/explore");
|
||
|
|
await expect(frigateApp.page).toHaveURL(/\/explore/);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("navigate to Export page", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
|
||
|
|
await base.navigateTo("/export");
|
||
|
|
await expect(frigateApp.page).toHaveURL(/\/export/);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("all primary nav links are present", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
|
||
|
|
// Live, Review, Explore, Export are always present
|
||
|
|
await expect(frigateApp.page.locator('a[href="/"]').first()).toBeVisible();
|
||
|
|
await expect(
|
||
|
|
frigateApp.page.locator('a[href="/review"]').first(),
|
||
|
|
).toBeVisible();
|
||
|
|
await expect(
|
||
|
|
frigateApp.page.locator('a[href="/explore"]').first(),
|
||
|
|
).toBeVisible();
|
||
|
|
await expect(
|
||
|
|
frigateApp.page.locator('a[href="/export"]').first(),
|
||
|
|
).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("desktop sidebar is visible on desktop, hidden on mobile", async ({
|
||
|
|
frigateApp,
|
||
|
|
}) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
|
||
|
|
if (!frigateApp.isMobile) {
|
||
|
|
await expect(base.sidebar).toBeVisible();
|
||
|
|
} else {
|
||
|
|
await expect(base.sidebar).not.toBeVisible();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test("navigate between pages without crash", async ({ frigateApp }) => {
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
const base = new BasePage(frigateApp.page, !frigateApp.isMobile);
|
||
|
|
const pageRoot = frigateApp.page.locator("#pageRoot");
|
||
|
|
|
||
|
|
// Navigate through all main pages in sequence
|
||
|
|
await base.navigateTo("/review");
|
||
|
|
await expect(pageRoot).toBeVisible({ timeout: 10_000 });
|
||
|
|
|
||
|
|
await base.navigateTo("/explore");
|
||
|
|
await expect(pageRoot).toBeVisible({ timeout: 10_000 });
|
||
|
|
|
||
|
|
await base.navigateTo("/export");
|
||
|
|
await expect(pageRoot).toBeVisible({ timeout: 10_000 });
|
||
|
|
|
||
|
|
// Navigate back to review (not root, to avoid same-route re-render issues)
|
||
|
|
await base.navigateTo("/review");
|
||
|
|
await expect(pageRoot).toBeVisible({ timeout: 10_000 });
|
||
|
|
});
|
||
|
|
|
||
|
|
test("unknown route redirects to home", async ({ frigateApp }) => {
|
||
|
|
// Navigate to an unknown route - React Router's catch-all should redirect
|
||
|
|
await frigateApp.page.goto("/nonexistent-route");
|
||
|
|
// Wait for React to render and redirect
|
||
|
|
await frigateApp.page.waitForTimeout(2000);
|
||
|
|
// Should either be at root or show the page root (app didn't crash)
|
||
|
|
const url = frigateApp.page.url();
|
||
|
|
const hasPageRoot = await frigateApp.page
|
||
|
|
.locator("#pageRoot")
|
||
|
|
.isVisible()
|
||
|
|
.catch(() => false);
|
||
|
|
expect(url.endsWith("/") || hasPageRoot).toBeTruthy();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Faces nav hidden when face_recognition disabled", async ({
|
||
|
|
frigateApp,
|
||
|
|
}) => {
|
||
|
|
// Default config has face_recognition.enabled = false
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(frigateApp.page.locator('a[href="/faces"]')).not.toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Chat nav hidden when genai model is none", async ({ frigateApp }) => {
|
||
|
|
if (frigateApp.isMobile) {
|
||
|
|
test.skip();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
// Override config with genai.model = "none" to hide chat
|
||
|
|
await frigateApp.installDefaults({
|
||
|
|
config: {
|
||
|
|
genai: {
|
||
|
|
enabled: false,
|
||
|
|
provider: "ollama",
|
||
|
|
model: "none",
|
||
|
|
base_url: "",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(frigateApp.page.locator('a[href="/chat"]')).not.toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Faces nav visible when face_recognition enabled and admin on desktop", async ({
|
||
|
|
frigateApp,
|
||
|
|
page,
|
||
|
|
}) => {
|
||
|
|
if (frigateApp.isMobile) {
|
||
|
|
test.skip();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Re-install with face_recognition enabled
|
||
|
|
await frigateApp.installDefaults({
|
||
|
|
config: {
|
||
|
|
face_recognition: { enabled: true },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(page.locator('a[href="/faces"]')).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Chat nav visible when genai model set and admin on desktop", async ({
|
||
|
|
frigateApp,
|
||
|
|
page,
|
||
|
|
}) => {
|
||
|
|
if (frigateApp.isMobile) {
|
||
|
|
test.skip();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
await frigateApp.installDefaults({
|
||
|
|
config: {
|
||
|
|
genai: { enabled: true, model: "llava" },
|
||
|
|
},
|
||
|
|
});
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(page.locator('a[href="/chat"]')).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Classification nav visible for admin on desktop", async ({
|
||
|
|
frigateApp,
|
||
|
|
page,
|
||
|
|
}) => {
|
||
|
|
if (frigateApp.isMobile) {
|
||
|
|
test.skip();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
await frigateApp.goto("/");
|
||
|
|
await expect(page.locator('a[href="/classification"]')).toBeVisible();
|
||
|
|
});
|
||
|
|
});
|