Skip to content

playwright stabilization reasons #194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@ function checkIsElementVisible(element: Element) {
*/
export const plugin = {
name: "waitForAriaBusy" as const,
beforeEach() {
Array.from(document.images).every((img) => {
// Force sync decoding
if (img.decoding !== "sync") {
img.decoding = "sync";
}

// Force eager loading
if (img.loading !== "eager") {
img.loading = "eager";
}
});
return undefined;
},
wait: {
for: () => {
return Array.from(document.querySelectorAll('[aria-busy="true"]')).every(
Expand Down
54 changes: 41 additions & 13 deletions packages/playwright/src/screenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,46 @@ async function beforeEach(page: Page, options: ArgosScreenshotOptions) {
};
}

/**
* Increase the timeout for the test x3.
* Returns a function to reset the timeout.
*/
async function increaseTimeout() {
const testInfo = await getTestInfo();
if (testInfo) {
const { timeout } = testInfo;
// Like in "slow" mode but we don't use it because we want to
// be able to reset it.
testInfo.setTimeout(timeout * 3);
return {
value: timeout,
reset: () => {
testInfo.setTimeout(timeout);
},
};
}
return null;
}

/**
* Wait for the UI to be ready before taking the screenshot.
*/
async function waitForReadiness(page: Page, options: ArgosScreenshotOptions) {
const context = getStabilizationContext(options);
// We increase the timeout, so we will be able to get reasons
// if the stabilization fails.
const timeout = await increaseTimeout();

try {
await page.waitForFunction(
(context) => ((window as any).__ARGOS__ as ArgosGlobal).waitFor(context),
(context) => {
const argos = (window as any).__ARGOS__ as ArgosGlobal;
return argos.waitFor(context);
},
context,
timeout ? { timeout: timeout.value } : undefined,
);
timeout?.reset();
} catch (error) {
const reasons = await page.evaluate(
(context) =>
Expand Down Expand Up @@ -354,17 +383,6 @@ export async function argosScreenshot(
};

const stabilizeAndScreenshot = async (name: string) => {
await options.beforeScreenshot?.({
runStabilization: (stabilizationOptions) =>
waitForReadiness(page, {
...options,
stabilize: stabilizationOptions ?? options.stabilize,
}),
});

await waitForReadiness(page, options);
const afterEach = await beforeEach(page, options);

const names = getScreenshotNames(name, testInfo);

const metadata = await collectMetadata(testInfo);
Expand All @@ -389,6 +407,17 @@ export async function argosScreenshot(
await mkdir(dirname(screenshotPath), { recursive: true });
}

await options.beforeScreenshot?.({
runStabilization: (stabilizationOptions) =>
waitForReadiness(page, {
...options,
stabilize: stabilizationOptions ?? options.stabilize,
}),
});

await waitForReadiness(page, options);
const afterEach = await beforeEach(page, options);

await Promise.all([
handle.screenshot({
path: screenshotPath,
Expand All @@ -415,7 +444,6 @@ export async function argosScreenshot(
}

await afterEach();

await options.afterScreenshot?.();
};

Expand Down