From 287fc4240423f624beb62f3e78a4f92132d194d8 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 3 Sep 2026 06:44:18 -0500 Subject: [PATCH] Miscellaneous fixes (#24172) * fix frigate+ submission state bleeding onto the next tracked object * add Korean * fix tests --- web/e2e/fixtures/frigate-test.ts | 5 +- web/e2e/fixtures/mock-data/config.ts | 3 + web/e2e/helpers/api-mocker.ts | 5 +- web/e2e/specs/explore.spec.ts | 68 +++++++++++++++++++ .../overlay/detail/SearchDetailDialog.tsx | 32 ++++++--- web/src/lib/const.ts | 1 + 6 files changed, 102 insertions(+), 12 deletions(-) diff --git a/web/e2e/fixtures/frigate-test.ts b/web/e2e/fixtures/frigate-test.ts index bc28ab50c0..892df68417 100644 --- a/web/e2e/fixtures/frigate-test.ts +++ b/web/e2e/fixtures/frigate-test.ts @@ -54,8 +54,11 @@ export class FrigateApp { }); await this.ws.install(this.page); - await this.media.install(); await this.api.install(overrides); + // media goes last so its per-event routes win over the broader + // `**/api/events**` list route, which otherwise answers thumbnail and + // snapshot requests with the events JSON + await this.media.install(); } /** Navigate to a page. Always call installDefaults() first. */ diff --git a/web/e2e/fixtures/mock-data/config.ts b/web/e2e/fixtures/mock-data/config.ts index ba86425a9d..e337218e5a 100644 --- a/web/e2e/fixtures/mock-data/config.ts +++ b/web/e2e/fixtures/mock-data/config.ts @@ -52,6 +52,9 @@ function deepMerge>( export const BASE_CONFIG = { ...configSnapshot, version: "0.15.0-test", + // injected by the /config endpoint rather than the Pydantic model, so it + // is absent from the snapshot + plus: { enabled: false }, cameras: { ...configSnapshot.cameras, front_door: { diff --git a/web/e2e/helpers/api-mocker.ts b/web/e2e/helpers/api-mocker.ts index e1a191fe0b..34b15380e2 100644 --- a/web/e2e/helpers/api-mocker.ts +++ b/web/e2e/helpers/api-mocker.ts @@ -249,8 +249,9 @@ export class MediaMocker { }), ); - // Event thumbnails - await this.page.route("**/api/events/*/thumbnail.jpg**", (route) => + // Event thumbnails. The explore grid and detail dialog request .webp, + // everything else requests .jpg. + await this.page.route("**/api/events/*/thumbnail.{jpg,webp}**", (route) => route.fulfill({ contentType: "image/png", body: PLACEHOLDER_PNG, diff --git a/web/e2e/specs/explore.spec.ts b/web/e2e/specs/explore.spec.ts index 9d239a3f91..442a6d8d88 100644 --- a/web/e2e/specs/explore.spec.ts +++ b/web/e2e/specs/explore.spec.ts @@ -263,3 +263,71 @@ test.describe("Explore — mobile @high @mobile", () => { await expect(searchInput).toBeFocused(); }); }); + +// --------------------------------------------------------------------------- +// Frigate+ submission — desktop only +// The detail dialog's previous/next arrows only render on desktop. +// --------------------------------------------------------------------------- + +test.describe("Explore — Frigate+ submission (desktop) @high", () => { + test.skip( + ({ frigateApp }) => frigateApp.isMobile, + "Detail dialog navigation arrows are desktop-only", + ); + + test("in-flight submission does not mark the next tracked object as submitted", async ({ + frigateApp, + }) => { + await frigateApp.installDefaults({ config: { plus: { enabled: true } } }); + const page = frigateApp.page; + + // Hold the submission open so it is still in flight while the user moves + // on to the next tracked object. + let releaseSubmission: () => void = () => {}; + const submissionHeld = new Promise((resolve) => { + releaseSubmission = resolve; + }); + let submissions = 0; + await page.route("**/api/events/*/plus", async (route) => { + submissions += 1; + await submissionHeld; + await route.fulfill({ json: { success: true } }); + }); + + await frigateApp.goto("/explore?labels=person"); + + const firstResult = page.locator("[data-start]").first(); + await expect(firstResult).toBeVisible({ timeout: 10_000 }); + await firstResult.click(); + + // The label being confirmed is rendered in a tag inside the + // "Is this object a