diff --git a/lib/helper/Playwright.js b/lib/helper/Playwright.js index ad48bd819..f09d44a9b 100644 --- a/lib/helper/Playwright.js +++ b/lib/helper/Playwright.js @@ -3667,8 +3667,7 @@ class Playwright extends Helper { } try { - // Always create frame locator from page to avoid nested frame paths - this.frame = await Promise.race([this.page.frameLocator(locator), new Promise((_, reject) => setTimeout(() => reject(new Error('Frame locator timeout')), 5000))]) + this.frame = this.frame ? this.frame.frameLocator(locator) : this.page.frameLocator(locator) } catch (e) { console.warn('Warning during frame locator creation:', e.message) throw new Error(`Frame ${JSON.stringify(locator)} could not be accessed`) diff --git a/test/helper/webapi.js b/test/helper/webapi.js index 5d224d57c..a851c8650 100644 --- a/test/helper/webapi.js +++ b/test/helper/webapi.js @@ -1963,6 +1963,38 @@ export function tests() { }) }) + describe('#switchTo', () => { + beforeEach(function () { + if (isHelper('CDPBrowser')) this.skip() // switchTo/iframes are not implemented in CDPBrowser + }) + + it('should switch to nested iframes one by one', async () => { + await I.amOnPage('/iframe_nested') + await I.switchTo('[name=wrapper]') + await I.see('Iframe test') + await I.switchTo('[name=content]') + await I.see('Information') + await I.see('Lots of valuable data here') + }) + + it('should return to the top level context from a nested iframe', async () => { + await I.amOnPage('/iframe_nested') + await I.switchTo('[name=wrapper]') + await I.switchTo('[name=content]') + await I.see('Information') + await I.switchTo(null) + await I.see('Nested Iframe test') + }) + + it('should not find a nested iframe from the top level context', async () => { + await I.amOnPage('/iframe_nested') + await I.switchTo('[name=content]').then( + () => assert.fail('switched to an iframe which is not in the current context'), + err => assert.include(err.message, 'was not found'), + ) + }) + }) + describe('scroll: #scrollTo, #scrollPageToTop, #scrollPageToBottom', () => { beforeEach(function () { if (I.capabilities?.layout === 'none') this.skip() // scrolling requires a real layout engine