mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 19:06:52 +03:00
share the setup wizard e2e helpers and mock users
This commit is contained in:
@@ -47,6 +47,7 @@ export interface ApiMockOverrides {
|
||||
recommended: string;
|
||||
available?: { key: string; presets: Record<string, string> }[];
|
||||
};
|
||||
users?: { username: string; role: string }[];
|
||||
}
|
||||
|
||||
export class ApiMocker {
|
||||
@@ -200,6 +201,16 @@ export class ApiMocker {
|
||||
}),
|
||||
);
|
||||
|
||||
// Users. GET lists them; POST/PUT (create, password) just succeed, so
|
||||
// tests assert on the intercepted request body instead of a response.
|
||||
await this.page.route("**/api/users**", (route) =>
|
||||
route.request().method() === "GET"
|
||||
? route.fulfill({
|
||||
json: overrides?.users ?? [{ username: "admin", role: "admin" }],
|
||||
})
|
||||
: route.fulfill({ json: { message: "ok" } }),
|
||||
);
|
||||
|
||||
// Go2RTC streams
|
||||
await this.page.route("**/api/go2rtc/streams**", (route) =>
|
||||
route.fulfill({ json: {} }),
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Shared setup-wizard e2e helpers.
|
||||
*
|
||||
* The wizard shows when config has no cameras, so a first run is mocked by
|
||||
* serving a camera-less config until the returned callback is fired.
|
||||
*/
|
||||
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect } from "../fixtures/frigate-test";
|
||||
import { configFactory } from "../fixtures/mock-data/config";
|
||||
import type { ApiMockOverrides } from "./api-mocker";
|
||||
|
||||
export async function installFirstRun(
|
||||
frigateApp: { installDefaults: (o?: ApiMockOverrides) => Promise<void> },
|
||||
page: Page,
|
||||
overrides?: ApiMockOverrides,
|
||||
): Promise<() => void> {
|
||||
await frigateApp.installDefaults(overrides);
|
||||
|
||||
const full = configFactory(overrides?.config);
|
||||
let cameras: unknown = {};
|
||||
|
||||
await page.route("**/api/config", (route) => {
|
||||
if (route.request().method() === "GET") {
|
||||
return route.fulfill({ json: { ...full, cameras } });
|
||||
}
|
||||
return route.fulfill({ json: { success: true } });
|
||||
});
|
||||
|
||||
return () => {
|
||||
cameras = full.cameras;
|
||||
};
|
||||
}
|
||||
|
||||
export async function gotoDetectorStep(page: Page, addCamera: () => void) {
|
||||
await page.getByRole("button", { name: "Get Started" }).click();
|
||||
await expect(page.getByText("Add Your First Camera")).toBeVisible();
|
||||
|
||||
// the camera step's Next only renders once its local addedCameras fills,
|
||||
// which SetupCamera does by refetching config when the dialog closes, so
|
||||
// opening and cancelling the dialog is what reveals Next
|
||||
await page.getByRole("button", { name: "Add Camera" }).click();
|
||||
addCamera();
|
||||
await page.getByRole("button", { name: "Cancel" }).click();
|
||||
|
||||
await expect(page.getByRole("button", { name: "Next" })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await page.getByRole("button", { name: "Next" }).click();
|
||||
await expect(page.getByText("Object Detection")).toBeVisible();
|
||||
}
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
import { test, expect } from "../../fixtures/frigate-test";
|
||||
import type { Page } from "@playwright/test";
|
||||
import { configFactory } from "../../fixtures/mock-data/config";
|
||||
import type { ApiMockOverrides } from "../../helpers/api-mocker";
|
||||
import { gotoDetectorStep, installFirstRun } from "../../helpers/setup-wizard";
|
||||
|
||||
const NVIDIA_HARDWARE = [
|
||||
{
|
||||
@@ -57,51 +56,6 @@ async function captureRestarts(page: Page): Promise<string[]> {
|
||||
return calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install mocks for a first run: the wizard shows when config has no cameras,
|
||||
* so the config route starts empty and only reports cameras once the returned
|
||||
* callback is fired, standing in for the camera the user adds.
|
||||
*/
|
||||
async function installFirstRun(
|
||||
frigateApp: { installDefaults: (o?: ApiMockOverrides) => Promise<void> },
|
||||
page: Page,
|
||||
overrides?: ApiMockOverrides,
|
||||
): Promise<() => void> {
|
||||
await frigateApp.installDefaults(overrides);
|
||||
|
||||
const full = configFactory(overrides?.config);
|
||||
let cameras: unknown = {};
|
||||
|
||||
await page.route("**/api/config", (route) => {
|
||||
if (route.request().method() === "GET") {
|
||||
return route.fulfill({ json: { ...full, cameras } });
|
||||
}
|
||||
return route.fulfill({ json: { success: true } });
|
||||
});
|
||||
|
||||
return () => {
|
||||
cameras = full.cameras;
|
||||
};
|
||||
}
|
||||
|
||||
async function gotoDetectorStep(page: Page, addCamera: () => void) {
|
||||
await page.getByRole("button", { name: "Get Started" }).click();
|
||||
await expect(page.getByText("Add Your First Camera")).toBeVisible();
|
||||
|
||||
// the camera step's Next only renders once its local addedCameras fills,
|
||||
// which SetupCamera does by refetching config when the dialog closes, so
|
||||
// opening and cancelling the dialog is what reveals Next
|
||||
await page.getByRole("button", { name: "Add Camera" }).click();
|
||||
addCamera();
|
||||
await page.getByRole("button", { name: "Cancel" }).click();
|
||||
|
||||
await expect(page.getByRole("button", { name: "Next" })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await page.getByRole("button", { name: "Next" }).click();
|
||||
await expect(page.getByText("Object Detection")).toBeVisible();
|
||||
}
|
||||
|
||||
test.describe("setup wizard hardware @high @mobile", () => {
|
||||
test("lists probed hardware and writes a models config", async ({
|
||||
frigateApp,
|
||||
|
||||
Reference in New Issue
Block a user