From 4340d153df8d243829afb01ccfaad3999cd20ecc Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 26 Aug 2024 10:28:54 -0700 Subject: [PATCH] chore: deprecate locator.frameLocator() (#32306) --- docs/src/api/class-page.md | 1 + .../playwright-core/src/server/recorder.ts | 94 +++++----- .../src/server/recorder/codeGenerator.ts | 2 +- .../src/server/recorder/csharp.ts | 10 +- .../src/server/recorder/java.ts | 14 +- .../src/server/recorder/javascript.ts | 10 +- .../src/server/recorder/python.ts | 10 +- .../src/server/recorder/recorderActions.ts | 12 +- tests/library/inspector/cli-codegen-3.spec.ts | 160 +++++++++--------- 9 files changed, 133 insertions(+), 180 deletions(-) diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 9a3a25b225..da5d48f906 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -2195,6 +2195,7 @@ A glob pattern, regex pattern or predicate receiving frame's `url` as a [URL] ob ## method: Page.frameLocator * since: v1.17 +regular [`Locator`] instead. - returns: <[FrameLocator]> When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 9e2174303b..96e24e3210 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -191,15 +191,9 @@ export class Recorder implements InstrumentationListener { }); await this._context.exposeBinding('__pw_recorderSetSelector', false, async ({ frame }, selector: string) => { - const selectorPromises: Promise[] = []; - let currentFrame: Frame | null = frame; - while (currentFrame) { - selectorPromises.push(findFrameSelector(currentFrame)); - currentFrame = currentFrame.parentFrame(); - } - const fullSelector = (await Promise.all(selectorPromises)).filter(Boolean); - fullSelector.push(selector); - await this._recorderApp?.setSelector(fullSelector.join(' >> internal:control=enter-frame >> '), true); + const selectorChain = await generateFrameSelector(frame); + selectorChain.push(selector); + await this._recorderApp?.setSelector(selectorChain.join(' >> internal:control=enter-frame >> '), true); }); await this._context.exposeBinding('__pw_recorderSetMode', false, async ({ frame }, mode: Mode) => { @@ -539,45 +533,14 @@ class ContextRecorder extends EventEmitter { private _describeMainFrame(page: Page): actions.FrameDescription { return { pageAlias: this._pageAliases.get(page)!, - isMainFrame: true, + framePath: [], }; } private async _describeFrame(frame: Frame): Promise { - const page = frame._page; - const pageAlias = this._pageAliases.get(page)!; - const chain: Frame[] = []; - for (let ancestor: Frame | null = frame; ancestor; ancestor = ancestor.parentFrame()) - chain.push(ancestor); - chain.reverse(); - - if (chain.length === 1) - return this._describeMainFrame(page); - - const selectorPromises: Promise[] = []; - for (let i = 0; i < chain.length - 1; i++) - selectorPromises.push(findFrameSelector(chain[i + 1])); - - const result = await raceAgainstDeadline(() => Promise.all(selectorPromises), monotonicTime() + 2000); - if (!result.timedOut && result.result.every(selector => !!selector)) { - return { - pageAlias, - isMainFrame: false, - selectorsChain: result.result as string[], - }; - } - // Best effort to find a selector for the frame. - const selectorsChain = []; - for (let i = 0; i < chain.length - 1; i++) { - if (chain[i].name()) - selectorsChain.push(`iframe[name=${quoteCSSAttributeValue(chain[i].name())}]`); - else - selectorsChain.push(`iframe[src=${quoteCSSAttributeValue(chain[i].url())}]`); - } return { - pageAlias, - isMainFrame: false, - selectorsChain, + pageAlias: this._pageAliases.get(frame._page)!, + framePath: await generateFrameSelector(frame), }; } @@ -691,20 +654,41 @@ function isScreenshotCommand(metadata: CallMetadata) { return metadata.method.toLowerCase().includes('screenshot'); } -async function findFrameSelector(frame: Frame): Promise { - try { +async function generateFrameSelector(frame: Frame): Promise { + const selectorPromises: Promise[] = []; + while (frame) { const parent = frame.parentFrame(); - const frameElement = await frame.frameElement(); - if (!frameElement || !parent) - return; - const utility = await parent._utilityContext(); - const injected = await utility.injectedScript(); - const selector = await injected.evaluate((injected, element) => { - return injected.generateSelectorSimple(element as Element, { testIdAttributeName: '', omitInternalEngines: true }); - }, frameElement); - return selector; - } catch (e) { + if (!parent) + break; + selectorPromises.push(generateFrameSelectorInParent(parent, frame)); + frame = parent; } + const result = await Promise.all(selectorPromises); + return result.reverse(); +} + +async function generateFrameSelectorInParent(parent: Frame, frame: Frame): Promise { + const result = await raceAgainstDeadline(async () => { + try { + const frameElement = await frame.frameElement(); + if (!frameElement || !parent) + return; + const utility = await parent._utilityContext(); + const injected = await utility.injectedScript(); + const selector = await injected.evaluate((injected, element) => { + return injected.generateSelectorSimple(element as Element); + }, frameElement); + return selector; + } catch (e) { + return e.toString(); + } + }, monotonicTime() + 2000); + if (!result.timedOut && result.result) + return result.result; + + if (frame.name()) + return `iframe[name=${quoteCSSAttributeValue(frame.name())}]`; + return `iframe[src=${quoteCSSAttributeValue(frame.url())}]`; } async function innerPerformAction(frame: Frame, action: string, params: any, cb: (callMetadata: CallMetadata) => Promise): Promise { diff --git a/packages/playwright-core/src/server/recorder/codeGenerator.ts b/packages/playwright-core/src/server/recorder/codeGenerator.ts index d3bb5f86d9..0185302a08 100644 --- a/packages/playwright-core/src/server/recorder/codeGenerator.ts +++ b/packages/playwright-core/src/server/recorder/codeGenerator.ts @@ -146,7 +146,7 @@ export class CodeGenerator extends EventEmitter { this.addAction({ frame: { pageAlias, - isMainFrame: true, + framePath: [], }, committed: true, action: { diff --git a/packages/playwright-core/src/server/recorder/csharp.ts b/packages/playwright-core/src/server/recorder/csharp.ts index 52460f8121..504995c9a8 100644 --- a/packages/playwright-core/src/server/recorder/csharp.ts +++ b/packages/playwright-core/src/server/recorder/csharp.ts @@ -72,14 +72,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator { return formatter.format(); } - let subject: string; - if (actionInContext.frame.isMainFrame) { - subject = pageAlias; - } else { - const locators = actionInContext.frame.selectorsChain.map(selector => `.FrameLocator(${quote(selector)})`); - subject = `${pageAlias}${locators.join('')}`; - } - + const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.ContentFrame()`); + const subject = `${pageAlias}${locators.join('')}`; const signals = toSignalMap(action); if (signals.dialog) { diff --git a/packages/playwright-core/src/server/recorder/java.ts b/packages/playwright-core/src/server/recorder/java.ts index 72d5d9a995..e6f0b3f0ed 100644 --- a/packages/playwright-core/src/server/recorder/java.ts +++ b/packages/playwright-core/src/server/recorder/java.ts @@ -63,16 +63,8 @@ export class JavaLanguageGenerator implements LanguageGenerator { return formatter.format(); } - let subject: string; - let inFrameLocator = false; - if (actionInContext.frame.isMainFrame) { - subject = pageAlias; - } else { - const locators = actionInContext.frame.selectorsChain.map(selector => `.frameLocator(${quote(selector)})`); - subject = `${pageAlias}${locators.join('')}`; - inFrameLocator = true; - } - + const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector, false)}.contentFrame()`); + const subject = `${pageAlias}${locators.join('')}`; const signals = toSignalMap(action); if (signals.dialog) { @@ -82,7 +74,7 @@ export class JavaLanguageGenerator implements LanguageGenerator { });`); } - let code = this._generateActionCall(subject, action, inFrameLocator); + let code = this._generateActionCall(subject, action, !!actionInContext.frame.framePath.length); if (signals.popup) { code = `Page ${signals.popup.popupAlias} = ${pageAlias}.waitForPopup(() -> { diff --git a/packages/playwright-core/src/server/recorder/javascript.ts b/packages/playwright-core/src/server/recorder/javascript.ts index 104b3bcd53..37fd3c25a9 100644 --- a/packages/playwright-core/src/server/recorder/javascript.ts +++ b/packages/playwright-core/src/server/recorder/javascript.ts @@ -52,14 +52,8 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { return formatter.format(); } - let subject: string; - if (actionInContext.frame.isMainFrame) { - subject = pageAlias; - } else { - const locators = actionInContext.frame.selectorsChain.map(selector => `.frameLocator(${quote(selector)})`); - subject = `${pageAlias}${locators.join('')}`; - } - + const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.contentFrame()`); + const subject = `${pageAlias}${locators.join('')}`; const signals = toSignalMap(action); if (signals.dialog) { diff --git a/packages/playwright-core/src/server/recorder/python.ts b/packages/playwright-core/src/server/recorder/python.ts index d393fb38e4..3302089fbd 100644 --- a/packages/playwright-core/src/server/recorder/python.ts +++ b/packages/playwright-core/src/server/recorder/python.ts @@ -59,14 +59,8 @@ export class PythonLanguageGenerator implements LanguageGenerator { return formatter.format(); } - let subject: string; - if (actionInContext.frame.isMainFrame) { - subject = pageAlias; - } else { - const locators = actionInContext.frame.selectorsChain.map(selector => `.frame_locator(${quote(selector)})`); - subject = `${pageAlias}${locators.join('')}`; - } - + const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.content_frame()`); + const subject = `${pageAlias}${locators.join('')}`; const signals = toSignalMap(action); if (signals.dialog) diff --git a/packages/playwright-core/src/server/recorder/recorderActions.ts b/packages/playwright-core/src/server/recorder/recorderActions.ts index 295758aaeb..3ab7fb91ba 100644 --- a/packages/playwright-core/src/server/recorder/recorderActions.ts +++ b/packages/playwright-core/src/server/recorder/recorderActions.ts @@ -150,13 +150,7 @@ export type DialogSignal = BaseSignal & { export type Signal = NavigationSignal | PopupSignal | DownloadSignal | DialogSignal; -type FrameDescriptionMainFrame = { - isMainFrame: true; +export type FrameDescription = { + pageAlias: string; + framePath: string[]; }; - -type FrameDescriptionChildFrame = { - isMainFrame: false; - selectorsChain: string[]; -}; - -export type FrameDescription = { pageAlias: string } & (FrameDescriptionMainFrame | FrameDescriptionChildFrame); diff --git a/tests/library/inspector/cli-codegen-3.spec.ts b/tests/library/inspector/cli-codegen-3.spec.ts index 424b2bacfe..6828576456 100644 --- a/tests/library/inspector/cli-codegen-3.spec.ts +++ b/tests/library/inspector/cli-codegen-3.spec.ts @@ -120,20 +120,20 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).Nth(1).ClickAsy frameHello1.click('text=Hello1'), ]); - expect(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('#frame1').getByText('Hello1').click();`); + expect.soft(sources.get('JavaScript')!.text).toContain(` + await page.locator('#frame1').contentFrame().getByText('Hello1').click();`); - expect(sources.get('Java')!.text).toContain(` - page.frameLocator("#frame1").getByText("Hello1").click();`); + expect.soft(sources.get('Java')!.text).toContain(` + page.locator("#frame1").contentFrame().getByText("Hello1").click();`); - expect(sources.get('Python')!.text).toContain(` - page.frame_locator("#frame1").get_by_text("Hello1").click()`); + expect.soft(sources.get('Python')!.text).toContain(` + page.locator("#frame1").content_frame().get_by_text("Hello1").click()`); - expect(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("#frame1").get_by_text("Hello1").click()`); + expect.soft(sources.get('Python Async')!.text).toContain(` + await page.locator("#frame1").content_frame().get_by_text("Hello1").click()`); - expect(sources.get('C#')!.text).toContain(` -await page.FrameLocator("#frame1").GetByText("Hello1").ClickAsync();`); + expect.soft(sources.get('C#')!.text).toContain(` +await page.Locator("#frame1").ContentFrame().GetByText("Hello1").ClickAsync();`); [sources] = await Promise.all([ @@ -142,19 +142,19 @@ await page.FrameLocator("#frame1").GetByText("Hello1").ClickAsync();`); ]); expect.soft(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('#frame1').frameLocator('iframe').getByText('Hello2').click();`); + await page.locator('#frame1').contentFrame().locator('iframe').contentFrame().getByText('Hello2').click();`); expect.soft(sources.get('Java')!.text).toContain(` - page.frameLocator("#frame1").frameLocator("iframe").getByText("Hello2").click();`); + page.locator("#frame1").contentFrame().locator("iframe").contentFrame().getByText("Hello2").click();`); expect.soft(sources.get('Python')!.text).toContain(` - page.frame_locator("#frame1").frame_locator("iframe").get_by_text("Hello2").click()`); + page.locator("#frame1").content_frame().locator("iframe").content_frame().get_by_text("Hello2").click()`); expect.soft(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("#frame1").frame_locator("iframe").get_by_text("Hello2").click()`); + await page.locator("#frame1").content_frame().locator("iframe").content_frame().get_by_text("Hello2").click()`); expect.soft(sources.get('C#')!.text).toContain(` -await page.FrameLocator("#frame1").FrameLocator("iframe").GetByText("Hello2").ClickAsync();`); +await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().GetByText("Hello2").ClickAsync();`); [sources] = await Promise.all([ @@ -163,19 +163,19 @@ await page.FrameLocator("#frame1").FrameLocator("iframe").GetByText("Hello2").Cl ]); expect.soft(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('#frame1').frameLocator('iframe').frameLocator('iframe[name="one"]').getByText('HelloNameOne').click();`); + await page.locator('#frame1').contentFrame().locator('iframe').contentFrame().locator('iframe[name="one"]').contentFrame().getByText('HelloNameOne').click();`); expect.soft(sources.get('Java')!.text).toContain(` - page.frameLocator("#frame1").frameLocator("iframe").frameLocator("iframe[name=\\"one\\"]").getByText("HelloNameOne").click();`); + page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe[name=\\"one\\"]").contentFrame().getByText("HelloNameOne").click();`); expect.soft(sources.get('Python')!.text).toContain(` - page.frame_locator("#frame1").frame_locator("iframe").frame_locator("iframe[name=\\"one\\"]").get_by_text("HelloNameOne").click()`); + page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe[name=\\"one\\"]").content_frame().get_by_text("HelloNameOne").click()`); expect.soft(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("#frame1").frame_locator("iframe").frame_locator("iframe[name=\\"one\\"]").get_by_text("HelloNameOne").click()`); + await page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe[name=\\"one\\"]").content_frame().get_by_text("HelloNameOne").click()`); expect.soft(sources.get('C#')!.text).toContain(` -await page.FrameLocator("#frame1").FrameLocator("iframe").FrameLocator("iframe[name=\\"one\\"]").GetByText("HelloNameOne").ClickAsync();`); +await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Locator("iframe[name=\\"one\\"]").ContentFrame().GetByText("HelloNameOne").ClickAsync();`); [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'HelloNameAnonymous'), @@ -183,19 +183,19 @@ await page.FrameLocator("#frame1").FrameLocator("iframe").FrameLocator("iframe[n ]); expect.soft(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('#frame1').frameLocator('iframe').frameLocator('iframe >> nth=2').getByText('HelloNameAnonymous').click();`); + await page.locator('#frame1').contentFrame().locator('iframe').contentFrame().locator('iframe').nth(2).contentFrame().getByText('HelloNameAnonymous').click();`); expect.soft(sources.get('Java')!.text).toContain(` - page.frameLocator("#frame1").frameLocator("iframe").frameLocator("iframe >> nth=2").getByText("HelloNameAnonymous").click();`); + page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe").nth(2).contentFrame().getByText("HelloNameAnonymous").click();`); expect.soft(sources.get('Python')!.text).toContain(` - page.frame_locator("#frame1").frame_locator("iframe").frame_locator("iframe >> nth=2").get_by_text("HelloNameAnonymous").click()`); + page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe").nth(2).content_frame().get_by_text("HelloNameAnonymous").click()`); expect.soft(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("#frame1").frame_locator("iframe").frame_locator("iframe >> nth=2").get_by_text("HelloNameAnonymous").click()`); + await page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe").nth(2).content_frame().get_by_text("HelloNameAnonymous").click()`); expect.soft(sources.get('C#')!.text).toContain(` -await page.FrameLocator("#frame1").FrameLocator("iframe").FrameLocator("iframe >> nth=2").GetByText("HelloNameAnonymous").ClickAsync();`); +await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Locator("iframe").Nth(2).ContentFrame().GetByText("HelloNameAnonymous").ClickAsync();`); }); test('should generate frame locators with special characters in name attribute', async ({ page, openRecorder, server }) => { @@ -208,22 +208,22 @@ await page.FrameLocator("#frame1").FrameLocator("iframe").FrameLocator("iframe > }); const [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'Click me'), - page.frameLocator('iframe[name="foo"]').getByRole('button', { name: 'Click me' }).click(), + page.locator('iframe[name="foo"]').contentFrame().getByRole('button', { name: 'Click me' }).click(), ]); expect.soft(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('iframe[name="foo\\\\"]').getByRole('button', { name: 'Click me' }).click();`); + await page.locator('iframe[name="foo\\\\"]').contentFrame().getByRole('button', { name: 'Click me' }).click();`); expect.soft(sources.get('Java')!.text).toContain(` - page.frameLocator("iframe[name=\\"foo\\\\\\"]").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Click me")).click()`); + page.locator("iframe[name=\\"foo\\\\\\"]").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Click me")).click()`); expect.soft(sources.get('Python')!.text).toContain(` - page.frame_locator("iframe[name=\\"foo\\\\\\"]").get_by_role("button", name="Click me").click()`); + page.locator("iframe[name=\\"foo\\\\\\"]").content_frame().get_by_role("button", name="Click me").click()`); expect.soft(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("iframe[name=\\"foo\\\\\\"]").get_by_role("button", name="Click me").click()`); + await page.locator("iframe[name=\\"foo\\\\\\"]").content_frame().get_by_role("button", name="Click me").click()`); expect.soft(sources.get('C#')!.text).toContain(` -await page.FrameLocator("iframe[name=\\"foo\\\\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`); +await page.Locator("iframe[name=\\"foo\\\\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`); }); test('should generate frame locators with title attribute', async ({ page, openRecorder, server }) => { @@ -234,27 +234,27 @@ await page.FrameLocator("iframe[name=\\"foo\\\\\\"]") const [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'Click me'), - page.frameLocator('[title="hello world"]').getByRole('button', { name: 'Click me' }).click(), + page.locator('[title="hello world"]').contentFrame().getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript')!.text).toContain( - `await page.frameLocator('iframe[title="hello world"]').getByRole('button', { name: 'Click me' }).click();` + expect.soft(sources.get('JavaScript')!.text).toContain( + `await page.locator('iframe[title="hello world"]').contentFrame().getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java')!.text).toContain( - `page.frameLocator(\"iframe[title=\\\"hello world\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` + expect.soft(sources.get('Java')!.text).toContain( + `page.locator(\"iframe[title=\\\"hello world\\\"]\").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python')!.text).toContain( - `page.frame_locator(\"iframe[title=\\\"hello world\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` + expect.soft(sources.get('Python')!.text).toContain( + `page.locator(\"iframe[title=\\\"hello world\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async')!.text).toContain( - `await page.frame_locator("iframe[title=\\\"hello world\\\"]").get_by_role("button", name="Click me").click()` + expect.soft(sources.get('Python Async')!.text).toContain( + `await page.locator("iframe[title=\\\"hello world\\\"]").content_frame().get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#')!.text).toContain( - `await page.FrameLocator("iframe[title=\\\"hello world\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` + expect.soft(sources.get('C#')!.text).toContain( + `await page.Locator("iframe[title=\\\"hello world\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -266,27 +266,27 @@ await page.FrameLocator("iframe[name=\\"foo\\\\\\"]") const [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'Click me'), - page.frameLocator('[name="hello world"]').getByRole('button', { name: 'Click me' }).click(), + page.locator('[name="hello world"]').contentFrame().getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript')!.text).toContain( - `await page.frameLocator('iframe[name="hello world"]').getByRole('button', { name: 'Click me' }).click();` + expect.soft(sources.get('JavaScript')!.text).toContain( + `await page.locator('iframe[name="hello world"]').contentFrame().getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java')!.text).toContain( - `page.frameLocator(\"iframe[name=\\\"hello world\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` + expect.soft(sources.get('Java')!.text).toContain( + `page.locator(\"iframe[name=\\\"hello world\\\"]\").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python')!.text).toContain( - `page.frame_locator(\"iframe[name=\\\"hello world\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` + expect.soft(sources.get('Python')!.text).toContain( + `page.locator(\"iframe[name=\\\"hello world\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async')!.text).toContain( - `await page.frame_locator("iframe[name=\\\"hello world\\\"]").get_by_role("button", name="Click me").click()` + expect.soft(sources.get('Python Async')!.text).toContain( + `await page.locator("iframe[name=\\\"hello world\\\"]").content_frame().get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#')!.text).toContain( - `await page.FrameLocator("iframe[name=\\\"hello world\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` + expect.soft(sources.get('C#')!.text).toContain( + `await page.Locator("iframe[name=\\\"hello world\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -298,27 +298,27 @@ await page.FrameLocator("iframe[name=\\"foo\\\\\\"]") const [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'Click me'), - page.frameLocator('[id="hello-world"]').getByRole('button', { name: 'Click me' }).click(), + page.locator('[id="hello-world"]').contentFrame().getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript')!.text).toContain( - `await page.frameLocator('#hello-world').getByRole('button', { name: 'Click me' }).click();` + expect.soft(sources.get('JavaScript')!.text).toContain( + `await page.locator('#hello-world').contentFrame().getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java')!.text).toContain( - `page.frameLocator(\"#hello-world\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` + expect.soft(sources.get('Java')!.text).toContain( + `page.locator(\"#hello-world\").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python')!.text).toContain( - `page.frame_locator(\"#hello-world\").get_by_role(\"button\", name=\"Click me\").click()` + expect.soft(sources.get('Python')!.text).toContain( + `page.locator(\"#hello-world\").content_frame().get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async')!.text).toContain( - `await page.frame_locator("#hello-world").get_by_role("button", name="Click me").click()` + expect.soft(sources.get('Python Async')!.text).toContain( + `await page.locator("#hello-world").content_frame().get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#')!.text).toContain( - `await page.FrameLocator("#hello-world").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` + expect.soft(sources.get('C#')!.text).toContain( + `await page.Locator("#hello-world").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -330,27 +330,27 @@ await page.FrameLocator("iframe[name=\\"foo\\\\\\"]") const [sources] = await Promise.all([ recorder.waitForOutput('JavaScript', 'my-testid'), - page.frameLocator('iframe[data-testid="my-testid"]').getByRole('button', { name: 'Click me' }).click(), + page.locator('iframe[data-testid="my-testid"]').contentFrame().getByRole('button', { name: 'Click me' }).click(), ]); - expect(sources.get('JavaScript')!.text).toContain( - `await page.frameLocator('[data-testid="my-testid"]').getByRole('button', { name: 'Click me' }).click();` + expect.soft(sources.get('JavaScript')!.text).toContain( + `await page.locator('[data-testid="my-testid"]').contentFrame().getByRole('button', { name: 'Click me' }).click();` ); - expect(sources.get('Java')!.text).toContain( - `page.frameLocator(\"[data-testid=\\\"my-testid\\\"]\").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` + expect.soft(sources.get('Java')!.text).toContain( + `page.locator(\"[data-testid=\\\"my-testid\\\"]\").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName(\"Click me\")).click();` ); - expect(sources.get('Python')!.text).toContain( - `page.frame_locator(\"[data-testid=\\\"my-testid\\\"]\").get_by_role(\"button\", name=\"Click me\").click()` + expect.soft(sources.get('Python')!.text).toContain( + `page.locator(\"[data-testid=\\\"my-testid\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()` ); - expect(sources.get('Python Async')!.text).toContain( - `await page.frame_locator("[data-testid=\\\"my-testid\\\"]").get_by_role("button", name="Click me").click()` + expect.soft(sources.get('Python Async')!.text).toContain( + `await page.locator("[data-testid=\\\"my-testid\\\"]").content_frame().get_by_role("button", name="Click me").click()` ); - expect(sources.get('C#')!.text).toContain( - `await page.FrameLocator("[data-testid=\\\"my-testid\\\"]").GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` + expect.soft(sources.get('C#')!.text).toContain( + `await page.Locator("[data-testid=\\\"my-testid\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();` ); }); @@ -365,19 +365,19 @@ await page.FrameLocator("iframe[name=\\"foo\\\\\\"]") ]); expect.soft(sources.get('JavaScript')!.text).toContain(` - await page.frameLocator('#frame1').getByRole('button', { name: 'Submit' }).click();`); + await page.locator('#frame1').contentFrame().getByRole('button', { name: 'Submit' }).click();`); expect.soft(sources.get('Java')!.text).toContain(` - page.frameLocator("#frame1").getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Submit")).click();`); + page.locator("#frame1").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Submit")).click();`); expect.soft(sources.get('Python')!.text).toContain(` - page.frame_locator("#frame1").get_by_role("button", name="Submit").click()`); + page.locator("#frame1").content_frame().get_by_role("button", name="Submit").click()`); expect.soft(sources.get('Python Async')!.text).toContain(` - await page.frame_locator("#frame1").get_by_role("button", name="Submit").click()`); + await page.locator("#frame1").content_frame().get_by_role("button", name="Submit").click()`); expect.soft(sources.get('C#')!.text).toContain(` -await page.FrameLocator("#frame1").GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`); +await page.Locator("#frame1").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`); }); test('should generate getByTestId', async ({ page, openRecorder }) => {