Playwright reaches into iframes via frameLocator(), and pierces open shadow DOM automatically with its normal locators. This removes two classic Selenium pain points: manual switchTo().frame() context switching and inability to see into web components.
In Selenium you must switchTo().frame(...) before interacting with iframe content and switch back afterward — easy to forget, and a common source of NoSuchElementException. Playwright uses page.frameLocator('iframe#checkout').getByRole('button', ...), scoping into the frame without changing global context, and you can chain further. For shadow DOM, Playwright's engine pierces open shadow roots transparently: getByRole('button', { name: 'Add' }) finds a button inside a web component's open shadow tree without special syntax. Closed shadow roots remain inaccessible (by design, as they are to users). This makes testing embedded widgets (payment iframes, third-party chat, design-system web components) markedly simpler.
A Stripe-style payment form lives in an iframe. In Selenium the team constantly forgot to switch back out of the frame, causing failures in the next step. In Playwright, page.frameLocator('iframe[name="card"]').getByLabel('Card number').fill('4242…') interacts inside the frame while the rest of the test continues against the main page normally.
// Interact inside an iframe — no switchTo needed
const card = page.frameLocator('iframe[name="card"]');
await card.getByLabel('Card number').fill('4242424242424242');
await card.getByLabel('Expiry').fill('12/34');
// Nested frames: chain frameLocator
await page
.frameLocator('#outer')
.frameLocator('#inner')
.getByRole('button', { name: 'Confirm' })
.click();
// Open shadow DOM: normal locators just work
await page.getByRole('button', { name: 'Add to cart' }).click();Scenario: A Selenium suite is riddled with switchTo().frame() / switchTo().defaultContent() calls and frequently fails because someone forgot to switch back. A payment widget also uses web components the team 'can't locate'. How does Playwright address both?