22. Seamless Handling of iFrames, Multi-Tabs & Native Dialogs

1. The frameLocator() API

You don't need to 'switch' context into a frame and then 'switch back' to default content:
// Directly locate elements inside an iframe:
const paymentFrame = page.frameLocator("#stripe-payment-frame");

// Nested iframes are simply chained:
const nestedFrame = paymentFrame.frameLocator("#card-number-subframe");

// Execute actions directly inside the frame:
await nestedFrame.getByLabel("Card Number").fill("4242 4242 4242 4242");

---

2. Multi-Tab & New Window Handling

When a link opens a new tab via target="_blank":
// Start waiting for the new page event BEFORE clicking the link:
const pagePromise = context.waitForEvent("page");
await page.getByRole("link", { name: "Open Terms in New Tab" }).click();
const newPage = await pagePromise;

// Verify content in the new tab:
await newPage.waitForLoadState();
await expect(newPage).toHaveTitle(/Terms of Service/);

// Close the tab and return focus to main page:
await newPage.close();

---

3. Native JavaScript Dialogs (alert, confirm, prompt)

By default, Playwright automatically dismisses native dialogs so tests don't hang. To accept or verify dialog message:
page.on("dialog", async (dialog) => {
  console.log("Dialog message:", dialog.message());
  // Accept confirm dialog:
  await dialog.accept();
  // Or dismiss: await dialog.dismiss();
  // Or provide prompt input: await dialog.accept("My Input");
});

await page.getByRole("button", { name: "Delete Account" }).click();

Task

  • Implement isDialogAccepted:
  • 1. Verify if dialogType matches 'alert', 'confirm', or 'prompt'.
  • 2. Return true if valid, false otherwise.
πŸ’‘Common doubts
Did you like the problem?
Lesson 22 of 36
TypeScript
Loading code editor…
Next