probe webrtc before reporting it as not configured

The WebRTC gate read only the Frigate config, so an install with no go2rtc candidates showed WebRTC as not configured, even though go2rtc fills in default candidates at startup (including the internal one under the HA app) and WebRTC often worked. Unset candidates now run the connectivity probe first, and only a failed probe reports not configured. The not-configured reason shows as a neutral note that names the setting and says WebRTC is optional, rather than as a red error.
This commit is contained in:
Josh Hawkins
2026-10-15 21:16:44 -05:00
parent 3cd4c9c55c
commit 87a7551aaa
5 changed files with 106 additions and 12 deletions
@@ -110,6 +110,15 @@ test.describe("WebRTC availability gating @critical", () => {
// distinguishes enabled from disabled options.
const mseOption = frigateApp.page.getByRole("option", { name: /MSE/ });
await expect(mseOption).not.toHaveAttribute("aria-disabled", "true");
// a missing setting, shown as a neutral note rather than an error
await expect(webrtcOption).toContainText(
"under go2rtc → webrtc → candidates",
);
await expect(webrtcOption).toContainText(
"Optional: live view works without it.",
);
await expect(webrtcOption.locator(".text-danger")).toHaveCount(0);
});
test("the unavailable reason is logged to the console once", async ({
@@ -214,6 +223,62 @@ test.describe("WebRTC availability gating @critical", () => {
await expect(webrtcOption).toContainText(/Checking WebRTC availability/i);
});
test("desktop: unset candidates run the probe before reporting not configured", async ({
frigateApp,
}) => {
test.skip(frigateApp.isMobile, "Desktop dropdown only");
// Count probe connections. The probe fails fast against the preview
// server, which with go2rtc's default candidates means setup is missing.
let probes = 0;
await frigateApp.page.routeWebSocket("**/live/webrtc/api/ws**", (ws) => {
probes++;
ws.close();
});
await frigateApp.installDefaults({
config: {
go2rtc: {
streams: { front_door: ["rtsp://127.0.0.1:8554/front_door"] },
},
},
});
await frigateApp.page.route("**/api/go2rtc/streams/front_door**", (route) =>
route.fulfill({
json: {
producers: [{ medias: ["video, recvonly, H264"] }],
consumers: [],
},
}),
);
await frigateApp.goto("/#front_door");
const live = new LivePage(frigateApp.page, true);
await expect(live.backButton).toBeVisible({ timeout: 10_000 });
await frigateApp.page.locator("button:has(svg)").last().click();
const menu = frigateApp.page
.locator('[role="menu"], [data-radix-menu-content]')
.first();
await expect(menu).toBeVisible({ timeout: 3_000 });
await menu
.locator('div:has(> label[for="streaming-mode"]) [role="combobox"]')
.first()
.click();
const webrtcOption = frigateApp.page.getByRole("option", {
name: /WebRTC/,
});
await expect(webrtcOption).toBeVisible({ timeout: 3_000 });
await expect(webrtcOption).toContainText(
"under go2rtc → webrtc → candidates",
);
expect(probes).toBeGreaterThan(0);
});
test("desktop: JSMpeg is no longer offered in the technology selector", async ({
frigateApp,
}) => {