import { expect, test } from "@playwright/test"; test("cleans an initialized pthread attempt before one single fallback", async ({ page }) => { const variantRequests: string[] = []; page.on("request", (request) => { const pathname = new URL(request.url()).pathname; if (pathname.startsWith("/vendor/blender/single/") || pathname.startsWith("/vendor/blender/pthread/")) { variantRequests.push(pathname); } }); await page.goto("/"); await expect(page.locator(".status-bar")).toContainText("Manifest: verified"); variantRequests.length = 0; const report = await page.evaluate(async () => { const { detectBrowserCapabilities } = await import("/src/platform/capabilities.ts"); const { bootstrapWebEngineRelease, engineVariantStatusLabel, } = await import("/src/engine-client/engine-variant-bootstrap.ts"); const { createBrowserEngineVariantSession } = await import("/src/engine-client/browser-engine-variant-session.ts"); const manifest = await fetch("/engine-manifest.json", { cache: "no-store" }).then((response) => response.json()); const outcome = await bootstrapWebEngineRelease( manifest.releaseId, manifest, "AUTO", detectBrowserCapabilities(), { initialize: createBrowserEngineVariantSession }, undefined, { failPthreadAfterInitialize: true, seedTrackedPthreadResources: true }, ); if (!outcome.session) throw new Error("current release unexpectedly requires refresh"); const activeBeforeDispose = outcome.session.resourceState(); const label = engineVariantStatusLabel(outcome.result); const activeAfterDispose = await outcome.session.dispose(); return { result: outcome.result, activeBeforeDispose, activeAfterDispose, label }; }); expect(report.result).toMatchObject({ status: "READY", selected: "single", attempted: ["pthread", "single"], fallbackReason: { code: "PTHREAD_INITIALIZATION_FAILED", message: "TEST_PTHREAD_INITIALIZATION_FAILURE", }, openCount: 0, failedAttemptCleanup: { handles: 0, workers: 0, timers: 0, pendingRequests: 0 }, }); expect(report.activeBeforeDispose).toEqual({ handles: 1, workers: 0, timers: 0, pendingRequests: 0 }); expect(report.activeAfterDispose).toEqual({ handles: 0, workers: 0, timers: 0, pendingRequests: 0 }); expect(report.label).toBe("Runtime: single (pthread fallback: PTHREAD_INITIALIZATION_FAILED)"); expect(report.label).not.toMatch(/pthread\s+ready/i); expect(variantRequests.filter((url) => url.endsWith("/pthread/web_engine.wasm"))).toHaveLength(1); expect(variantRequests.filter((url) => url.endsWith("/single/web_engine.wasm"))).toHaveLength(1); expect(variantRequests.filter((url) => url.endsWith("/pthread/web_engine.js")).length).toBeGreaterThanOrEqual(3); expect(variantRequests.filter((url) => url.endsWith("/single/web_engine.js")).length).toBeGreaterThanOrEqual(2); });