Reading issue
← Back to microsoft/playwright
microsoft / playwright · Issue No. 41504
1.60.0
1.58.21.59.0 (up to 1.61.1) and run the tests againimport { expect, test } from "@playwright/test";
test("masked screenshot with global backdrop styling", async ({ page }) => {
await page.setContent(`
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Playwright Mask Backdrop Repro</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
body {
background: #ffffff;
font-family: sans-serif;
}
main[role="main"] {
width: 420px;
height: 280px;
background: rgb(243, 243, 243);
border: 1px solid rgb(180, 180, 180);
position: relative;
box-sizing: border-box;
overflow: hidden;
}
h1 {
margin: 12px;
font-size: 18px;
}
p {
margin: 12px;
}
#probe {
position: absolute;
top: 70px;
left: 12px;
width: 180px;
height: 42px;
box-sizing: border-box;
border: 3px solid rgb(0, 102, 204);
background: rgb(255, 255, 255);
color: rgb(0, 0, 0);
font-size: 16px;
padding: 6px 8px;
}
#secret {
position: absolute;
top: 140px;
left: 155px;
width: 80px;
height: 80px;
background: rgb(30, 30, 30);
}
/* Intentionally broad backdrop style to trigger interaction with popover-backed overlays. */
::backdrop,
::-webkit-backdrop {
background: rgba(0, 0, 0, 0.35);
}
</style>
</head>
<body>
<main role="main">
<h1>Mask + Backdrop Repro</h1>
<p>Blue bordered input should stay visually unchanged when applying mask.</p>
<input id="probe" value="UNMASKED AREA" readonly />
<div id="secret" aria-label="masked-target"></div>
</main>
</body>
</html>
`);
const container = page.getByRole("main");
const masked = page.locator("#secret");
await expect(masked).toBeVisible();
await expect(container).toHaveScreenshot("repro-no-mask.png");
await expect(container).toHaveScreenshot("repro-with-mask.png", {
mask: [masked],
});
});
Sample from test report:
Initially, an update to 1.60.0 from 1.58.2 was made, but then the actual breaking change was observed when updating from 1.58.2 to 1.59.0.
As a workaround, the following code fixed the issue:
await page.evaluate(() => {
const cspMeta = document
.querySelector("meta[http-equiv='Content-Security-Policy']")
?.getAttribute("content");
const cspNonce = cspMeta?.match(/'nonce-([^']+)'/)?.[1];
const styleNonce =
cspNonce ??
document.querySelector("script[nonce], style[nonce]")?.getAttribute("nonce");
const style = document.createElement("style");
if (styleNonce) style.setAttribute("nonce", styleNonce);
style.textContent = `
x-pw-glass::backdrop,
x-pw-glass::-webkit-backdrop {
background: transparent !important;
opacity: 0 !important;
}
`;
document.head.appendChild(style);
});
System:
OS: Windows 11 10.0.26100
CPU: (22) x64 Intel(R) Core(TM) Ultra 7 165H
Memory: 32.44 GB / 63.45 GB
Binaries:
Node: 24.13.0 - C:\Program Files\nodejs\node.EXE
npm: 11.9.0 - C:\Program Files\nodejs\npm.CMD
IDEs:
VSCode: 1.126.0 - C:\Users\REDACTED\AppData\Local\Programs\Microsoft VS Code\bin\code.CMD
Languages:
Bash: 5.2.21 - C:\WINDOWS\system32\bash.EXE
npmPackages:
@playwright/test: ^1.59.1 => 1.59.1
Relay reads this issue against the repository's contribution signals: the files it is likely to touch, how the maintainers triage work this size, and what the first contribution would exercise.
The full analysis for this issue is still being assembled. Until then, the description above and the thread on GitHub are the most reliable context.