Files
kvm/ui/e2e/ota-prerelease-unsigned.spec.ts
Adam Shiervani 41ea6b93ca fix(test): fix e2e flakiness from hook timeouts, EDID drops, and USB recovery (#1382)
OTA beforeAll/afterAll hooks were using the global 60s timeout while
performing multi-reboot sequences that need minutes. Add explicit
test.setTimeout(420000) inside each hook.

setEDID RPC can drop the WebSocket on some devices during HDMI re-link.
Tolerate RPC timeouts, reconnect page + WebRTC afterwards, and retry
agent resolution checks with a 15s polling loop.

EBUSY CDROM test used sysfs traversal that broke across kernel/host
variations. Switch to lsblk and skip gracefully when the host doesn't
enumerate USB mass storage as sr* devices.

USB recovery test left the device bricked (initUsbGadget crash loop)
when auto-recovery failed. Add try/catch that re-binds the UDC and
reboots on failure.

OTA reconnectAfterReboot retries increased from 15 to 30 (65s → 95s)
to handle slower devices.
2026-03-30 19:26:09 +02:00

78 lines
2.1 KiB
TypeScript

import { test, expect } from "@playwright/test";
import {
getCurrentVersion,
reconnectAfterReboot,
rebootDeviceViaSSH,
ensureLocalAuthMode,
verifyHidAndVideo,
createMockUpdateServer,
deployBinaryToDevice,
configureDeviceUpdateUrl,
restoreDeviceUpdateUrl,
setIncludePreRelease,
getOTAEnvVars,
toPreReleaseVersion,
type MockUpdateServer,
} from "./helpers";
test.describe("OTA Prerelease Unsigned", () => {
test.setTimeout(420000);
let mockServer: MockUpdateServer;
let preReleaseVersion: string;
test.beforeAll(async ({ browser }) => {
test.setTimeout(420000);
const env = getOTAEnvVars();
preReleaseVersion = toPreReleaseVersion(env.releaseVersion);
const context = await browser.newContext({ baseURL: process.env.JETKVM_URL });
const page = await context.newPage();
try {
await ensureLocalAuthMode(page, { mode: "noPassword" });
} finally {
await page.close();
await context.close();
}
mockServer = await createMockUpdateServer({
binaryPath: env.releasePath,
version: preReleaseVersion,
});
await deployBinaryToDevice(env.baselinePath);
await rebootDeviceViaSSH();
await configureDeviceUpdateUrl(mockServer.url);
await setIncludePreRelease(true);
await rebootDeviceViaSSH();
});
test("unsigned prerelease update succeeds", async ({ page }) => {
await page.goto("/settings/general/update");
await page.waitForLoadState("networkidle");
const initialVersion = await getCurrentVersion(page);
expect(initialVersion).not.toBeNull();
const updateButton = page.getByRole("button", { name: "Update Now" });
await expect(updateButton).toBeVisible({ timeout: 30000 });
await updateButton.click();
await reconnectAfterReboot(page, 35000, 30);
const finalVersion = await getCurrentVersion(page);
expect(finalVersion).not.toBeNull();
expect(finalVersion).not.toBe(initialVersion);
await verifyHidAndVideo(page);
});
test.afterAll(async () => {
test.setTimeout(420000);
await setIncludePreRelease(false);
await restoreDeviceUpdateUrl();
await mockServer?.close();
});
});