fix(ui): stabilize settings and update recovery E2E (#126538)

* test(ui): await settings takeover in app chrome E2E

* test(ui): assert current build after update recovery
This commit is contained in:
Peter Steinberger
2026-08-19 21:39:26 -07:00
committed by GitHub
parent 70b6f44f13
commit f289685bf3
2 changed files with 41 additions and 5 deletions
@@ -3,7 +3,10 @@ import { mkdir } from "node:fs/promises";
import path from "node:path";
import type { Locator, Page } from "playwright";
import { expect, it } from "vitest";
import { installMockGateway } from "../test-helpers/control-ui-e2e.ts";
import {
installMockGateway,
waitForControlUiSettingsTakeover,
} from "../test-helpers/control-ui-e2e.ts";
import { createControlUiE2eSuite } from "./control-ui-e2e-suite.test-support.ts";
const suite = createControlUiE2eSuite({
@@ -155,11 +158,10 @@ suite.define(() => {
// 650px even against the mock gateway's tiny config fixture; General
// became short enough to fit once the host panel moved to Gateway.
await page.goto(`${suite.server.baseUrl}settings/appearance`);
const settingsSidebar = page.locator(".settings-sidebar");
const { search: settingsSearch, sidebar: settingsSidebar } =
await waitForControlUiSettingsTakeover(page);
const settingsTitle = settingsSidebar.locator(".settings-sidebar__title");
const settingsSearch = settingsSidebar.locator(".settings-sidebar__search-input");
const content = page.locator(".content");
await settingsSidebar.waitFor();
await expect
.poll(() => content.evaluate((element) => element.scrollHeight))
.toBeGreaterThan(await content.evaluate((element) => element.clientHeight));
+35 -1
View File
@@ -448,10 +448,32 @@ describe("Control UI service-worker production update E2E", () => {
"catalog" in request.params,
);
expect(catalogOpensBeforeWorkerActivation.length).toBeLessThanOrEqual(1);
if (catalogOpensBeforeWorkerActivation.length > 0) {
const currentConnect = (await gateway.getRequests("connect")).at(-1);
expect(currentConnect?.params).toMatchObject({ client: { buildId: buildB } });
}
installGate.release();
await reloaded;
await ensureControlledPage(page, pageErrors, buildB);
await expect.poll(() => readWorkerUpdateVersions(page)).toContain(buildB);
await expect
.poll(async () => (await gateway.getRequests("connect")).at(-1)?.params)
.toMatchObject({ client: { buildId: buildB } });
await page.waitForFunction((expectedBuildId) => {
const controller = navigator.serviceWorker.controller;
return (
controller?.state === "activated" &&
new URL(controller.scriptURL).searchParams.get("v") === expectedBuildId
);
}, buildB);
expect(
await page.evaluate(() => {
const controller = navigator.serviceWorker.controller;
return {
buildId: controller ? new URL(controller.scriptURL).searchParams.get("v") : null,
state: controller?.state ?? null,
};
}),
).toEqual({ buildId: buildB, state: "activated" });
const terminal = page.locator("openclaw-terminal-panel[embedded]");
await terminal.waitFor({ state: "attached" });
@@ -499,6 +521,18 @@ describe("Control UI service-worker production update E2E", () => {
sha256: assetB.sha256,
});
expect(refreshedAsset.sha256).not.toBe(initialAsset.sha256);
await expect
.poll(() =>
page.evaluate(
async ({ assetPath, cacheName }) => {
const cache = await caches.open(cacheName);
const shell = await cache.match(new URL("./", window.location.origin));
return shell ? (await shell.text()).includes(assetPath) : false;
},
{ assetPath: assetB.path, cacheName: `openclaw-control-${buildB}` },
),
)
.toBe(true);
if (captureUiProof) {
await page.screenshot({