Skip to content

Taking a delayed screenshot causes a resize event with a document.documentElement.clientWidth of 1 #7251

@svanherk

Description

@svanherk

Steps to reproduce

Tell us about your environment:

  • Puppeteer version: 9.1.1
  • Platform / OS version: Windows 10, ubuntu 20.04.2
  • URLs (if applicable):
  • Node.js version: 12.19.0, 10.24.1

What steps will reproduce the problem?

While this looks to be a race condition that does not happen every time, I've gotten it to reliably occur for me with the code below. The issue seems to occur when taking a screenshot of a page that "takes a while" - because of a large screen size, an arbitrary delay, a series of tasks that need to be performed before the screenshot, etc.

Page:

<html>
<head>
	<script type="module">
		window.addEventListener('resize', () => {
			console.log('resize', document.documentElement.clientWidth); // or window.innerWidth
		});
	</script>
</head>
<body>
	<div id="test">Test Text</div>
</body>
</html>

Script:

const delay = async(page) => {
	await page.evaluate(() => {
		return new Promise(resolve => {
			setTimeout(resolve, 2000);
		});
	});
};

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 800, height: 800, deviceScaleFactor: 1 });
page.on('console', msg => console.log(msg.text()));
await page.goto(`<page above>`, { waitUntil: ['networkidle0', 'load'] });

await delay(page);
console.log('***');
await page.screenshot({ path: `1.png` });
await delay(page);
console.log('***');
await page.screenshot({ path: `2.png` });
await delay(page);
console.log('***');
await page.screenshot({ path: `3.png` });

Output:

***
resize 1
resize 800
***
resize 1
resize 800
***
resize 1
resize 800

Increasing the timeout duration and/or the size of the viewport increases the reliability that the resize of 1 will happen. If I go down to a small timeout on my machine, I'll see the resize 1 lines disappear (but the resize of 800 remains).

What is the expected result?
The resize event is not fired (or, if the core puppeteer code needs a resize to happen, a resize to a clientWidth of 1 should not happen).

What happens instead?
Sometimes, when the page takes a while to do something before the screenshot is taken, the screenshot will cause a resize event and a document.documentElement.clientWidth/window.innerWidth of 1.

This is triggering incorrect screenshots of UI code that reacts to resize events, where they will react to the size of 1 and then may not be able to recalculate with the 800 before the screenshot occurs. This may be the same issue as #3371, but that could also be referring to the size 800 resize events I'm seeing as well. The size 1 resize events occur without a tall element on the page (as shown above), and the described workaround there seems to make things worse for this issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions