Assert on the Page the Click Opened

When a click opens a popup or a new tab, assert on that page. The opener staying put is not evidence the new window worked.

This post is part of the Playwright Essentials series. If you missed the previous post, read Part 14 — Files Users Actually Send first.


Introduction — The Opener Did Not Move

The test clicks Pay. Checkout is still on screen. The assertion on that page passes. The payment window opened behind it, showed an error, and the suite never looked.

Part 14 waited for a download because the file is not the click. A popup is the same kind of fact. The page that opened is the one the user is looking at.

Wait for the Popup Before the Click

waitForEvent('popup') has to be armed before the click. After the click, the window may already exist, and the wait misses it.

test('shows the amount in the payment window', async ({ page }) => {
  await page.goto('/checkout');
  const popupPromise = page.waitForEvent('popup'); // the window this click opens
  await page.getByRole('button', { name: 'Pay in a new window' }).click();
  const popup = await popupPromise;
  await expect(popup.getByRole('heading', { name: 'Pay 49.00' })).toBeVisible();
});

The decision is the popup wait. An assertion on page after this click only proves that checkout is still there.

Promise.all with the wait and the click is the same order. That is how part 14 waited for a download. Use the form your suite already has. Do not click first and start waiting afterwards.

A link with target="_blank" fires the same event. The role of the control does not matter. What matters is that the product opened another page.

Do Not Invent the Window

context.newPage() creates an empty tab the product did not open. Use it when the test is the one navigating. It is the wrong tool when the assertion is “this click opened the payment window.”

If you open the URL yourself, you skip the button, the window.open, and any token the opener put on the URL. A green test then means /pay loads when you type it. It does not mean the click works.

A Same-Tab Click Is Not a Popup

If the product navigates the current tab, waitForEvent('popup') waits until the test times out. Read the product. One of these is true:

  • the click opens another page — wait for popup and assert there
  • the click stays in this tab — assert toHaveURL or the heading on page

Do not keep a popup wait “just in case” on a long timeout. A hang is not a soft pass.

Conclusion

Arm waitForEvent('popup') before the click that should open a window. Assert on the page you get back. Leave context.newPage() for tabs the test opens on purpose. If the product stays in the same tab, do not wait for a popup at all.

This week’s exercise: Find one test that clicks a target="_blank" control, or a payment button, and then asserts on the original page. Wait for the popup and move the assertion onto it.


Next in the series: Part 16 — Controls Inside the Frame.