test(browser): wait for the file's own iframe before the first command

Every browser test iframe is named "vitest-iframe" and the Playwright
provider looks the frame up by that name. Once a page runs a second
file, the first file's iframe can still be found until its detach event
arrives, so the second file's first click lands in a frame that is going
away and fails with "Frame was detached". With fifteen browser files and
at most twelve pages, three pages now run two files each, and a full
local run failed this way in four of five tries. The setup now waits
until the frame found by name is its own.
This commit is contained in:
Marc-André Bombeck committed 2026-11-11 01:47:48 +01:00
1 parent 13fd7edfd8
commit a1cfb570c1
2 files changed
+35

No files matched your search

+10
View File
@@ -16,6 +16,7 @@
import "@/app/globals.css";
import { afterEach, beforeAll, beforeEach, vi } from "vitest";
import { commands } from "vitest/browser";
import { loadMessages } from "@/lib/i18n/load-locale";
@@ -24,7 +25,16 @@ import { rememberAddress, restoreAddress } from "./url";
document.documentElement.classList.add("dark");
declare module "vitest/browser" {
interface BrowserCommands {
/** Waits until the provider's frame lookup finds this file's iframe. */
awaitOwnFrame: () => Promise<void>;
}
}
beforeAll(async () => {
// See `awaitOwnFrame` in vitest.config.mts.
await commands.awaitOwnFrame();
await loadMessages("en");
});
+25
View File
@@ -165,6 +165,31 @@ export default defineConfig({
}),
instances: [{ browser: "chromium" }],
screenshotFailures: false,
commands: {
// Every test iframe is named "vitest-iframe", and the provider
// finds the one to act on by that name. When a page runs a
// second file, the first file's iframe can still be found
// until its detach event arrives, so the second file's first
// click lands in a frame that is going away ("Frame was
// detached"). The setup waits here until the iframe found by
// name is this file's own.
async awaitOwnFrame({ page, testPath }) {
const isOwn = () => {
const url = page.frame("vitest-iframe")?.url();
if (!url || !testPath) return false;
return new URL(url).searchParams.get("iframeId") === testPath;
};
const deadline = Date.now() + 5_000;
while (!isOwn()) {
if (Date.now() > deadline) {
throw new Error(
`the vitest-iframe found by name never became ${testPath}`,
);
}
await new Promise((done) => setTimeout(done, 10));
}
},
},
},
},
},