feat(web): waitForPopup follows a new tab, dialogs carry their type, downloads report their absolute path

Closed
OK
1mo ago
+1070-103

Stacked on oskar/det-gates-web.

const popup = await web.waitForPopup(() => screen.getByRole('link', { name: 'Open terms' }).tap());
await expect(web).toHaveURL(/terms/);   // screen, web, and expect(web) follow the popup
await popup.close();                    // back to the opener

const file = await web.waitForDownload(() => screen.getByRole('link', { name: 'Export' }).tap());
await screen.getByLabel('Import').setInputFiles(file.absolutePath);
  • A page stack inside the session state owns the active page. waitForPopup pushes the tab the trigger opened; observation, screenshots, dialog handlers, the video segment, and the CDP recovery target follow it. close(), or the app closing the tab, unwinds to the opener; out-of-order nested closes and a transport drop mid-popup recover. A tab that opens with no wait pending is left alone.
  • Dialog.type (alert | confirm | prompt | beforeunload) so a handler routes on the kind, not the message text.
  • waitForDownload resolves with absolutePath beside path, so a downloaded file goes straight back into setInputFiles.
  • Tests: popup.test.ts (strict and out-of-order nesting, a self-closing popup, a redirecting popup, video segments), recovery with a popup active, dialog kinds, the core kitchen sink. Web-benchmark twins new-tab-flow and file-round-trip land here. Docs: web reference, browser guide, migrate tables, security page. Changesets: @e2edev/web minor, patch.

Devin Review