[Bug]: codegen is not able to keep track of tabs and popups opened and will refer non-existing variables
Version
1.52.0
Steps to reproduce
- Create
bug.htmlwith this HTML:
<!DOCTYPE html>
<html>
<head>
<title>Tab and Popup</title>
</head>
<body>
<button onclick="openTabAndPopup()">Open Tab and Popup</button>
<script>
function openTabAndPopup() {
const newTab = window.open('', '_blank');
if (newTab) {
newTab.document.write(`
<html>
<head><title>New Tab</title></head>
<body>
<h1>New Tab Content</h1>
<script>
window.onload = function() {
const popup = window.open('', '', 'width=300,height=200');
if (popup) {
popup.document.write('<p>This is a popup from the new tab.</p>');
popup.document.close();
window.close(); // Close the tab
} else {
alert('Popup was blocked.');
}
};
<\/script>
</body>
</html>
`);
newTab.document.close();
} else {
alert('Tab was blocked.');
}
}
</script>
</body>
</html>
- Run codegen
playwright codegen ~/<path>/bug.html - Click button to open popup
- You should now see the following recorded steps:
using Microsoft.Playwright;
using System;
using System.Threading.Tasks;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = false,
});
var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
await page.GotoAsync("file:///Users/<user>/Desktop/bug.html");
var page2 = await page.RunAndWaitForPopupAsync(async () =>
{
await page.GetByRole(AriaRole.Button, new() { Name = "Open Tab and Popup" }).ClickAsync();
});
await page1.CloseAsync();
Expected behavior
Playwright to be able to keep track of tabs and popups opened and closed referring real variable names.
Actual behavior
Playwright refers a non-existing variable page1, specifically the last line:
await page1.CloseAsync();
page1 never existed.
Additional context
No response
Environment
- Operating System: [macOS Sequoia 15.5]
- CPU: [arm64]
- Browser: [All]
- .NET Version (TFM): [net8.0]
- Other info:
I can also reproduce with Codegen with Node.js in Library mode.
Thanks for the report, Mikkel! I can repro with this test:
test('should generate correct variables when opening and closing popup', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36274' } }, async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="openTabAndPopup()">Open Tab and Popup</button>
<script>
function openTabAndPopup() {
const newTab = window.open('', '_blank');
newTab.document.write(\`
<script>
window.onload = function() {
const popup = window.open('', '', 'width=300,height=200');
popup.document.write('<p>This is a popup from the new tab.</p>');
popup.document.close();
window.close();
};
<\\/script>
\`);
newTab.document.close();
}
</script>
`);
await recorder.hoverOverElement('button');
await recorder.trustedClick();
const sources = await recorder.waitForOutput('JavaScript', 'Open Tab and Popup');
expect(sources.get('JavaScript')!.text).not.toContain(`page1.close()`);
});
Thanks for the report, Mikkel! I can repro with this test:
test('should generate correct variables when opening and closing popup', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36274' } }, async ({ openRecorder }) => { const { recorder } = await openRecorder(); });
Hi @Skn0tt, I'm curious about how the openRecord() method was. Could you share this function?
openRecord() is a method in our own test harness, not a Playwright feature.
The bug here is in how we treat popups. There's two popups from the same button press, but we only take the first into account: https://github.com/microsoft/playwright/blob/64dd5ca5693775b2d1ee5c6e0aeb3e4dc8f03d64/packages/playwright-core/src/server/recorder/recorderCollection.ts#L113-L117 Since the second popup opens on the first popup, I don't see a trivial fix for this.
I'll mark it as P3 for now, let's collect feedback on whether this is a common bug. If it is, that might warrant some bigger changes in codegen to fix it.