Puppeteer's setViewport reloads the page whenever isMobile or hasTouch changes
Fact
page.setViewport() compares isMobile and hasTouch with the page's current emulation and, if either differs, ends by calling page.reload(). The documentation only says this happens "in certain cases". Changing just width, height or deviceScaleFactor never reloads.
Why it matters
- Switching a page into or out of phone emulation mid-test throws away everything the app held in memory: a game in progress, an open dialog, a filled form. The page is back at its start screen and nothing reports it.
- Before the first
gotothe reload re-createsabout:blank, and scripts registered withevaluateOnNewDocumentrun there. That document has an opaque origin, so touchinglocalStoragethrowsSecurityError: ... Access is denied for this document, which arrives as apageerrorand fails any "no page errors" assertion.
How to apply
- Pick
isMobileandhasTouchonce per page, before navigating, then sweep screen sizes withsetViewport({ width, height })and those two unchanged. - Size media queries (
width,height,aspect-ratio) need no mobile emulation at all; onlypointer/hoverqueries and meta-viewport layout do. - Guard init scripts that use storage: wrap them in
try { … } catch {}, or return early whenlocation.protocol === 'about:'.