Skip to content

Commit 1832ced

Browse files
authored
fix: switchTo - within block (#3892)
* fix: switchTo * fix: switch to * fix: failed acceptance tests * fix: within block * fix: within tests * fix: within tests * fix: within tests * fix: within block * fix within block * fix switchTo * fix: puppeteer test * fix: switchTo
1 parent af97ec6 commit 1832ced

File tree

8 files changed

+93
-52
lines changed

8 files changed

+93
-52
lines changed

Diff for: .github/workflows/playwright.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
env:
3838
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
3939
- name: Install deps
40-
run: npm install playwright@1.32.3 & npx playwright install-deps
40+
run: npm install playwright@1.35.1 & npx playwright install-deps
4141
- name: start a server
4242
run: "php -S 127.0.0.1:8000 -t test/data/app &"
4343
- name: run chromium tests

Diff for: lib/helper/Playwright.js

+36-28
Original file line numberDiff line numberDiff line change
@@ -826,8 +826,9 @@ class Playwright extends Helper {
826826

827827
async _stopBrowser() {
828828
this.withinLocator = null;
829-
this._setPage(null);
829+
await this._setPage(null);
830830
this.context = null;
831+
this.frame = null;
831832
popupStore.clear();
832833
await this.browser.close();
833834
}
@@ -866,6 +867,7 @@ class Playwright extends Helper {
866867
this.withinLocator = null;
867868
this.context = await this.page;
868869
this.contextLocator = null;
870+
this.frame = null;
869871
}
870872

871873
_extractDataFromPerformanceTiming(timing, ...dataNames) {
@@ -1155,6 +1157,9 @@ class Playwright extends Helper {
11551157
*/
11561158
async _locate(locator) {
11571159
const context = await this.context || await this._getContext();
1160+
1161+
if (this.frame) return findElements(this.frame, locator);
1162+
11581163
return findElements(context, locator);
11591164
}
11601165

@@ -1881,11 +1886,11 @@ class Playwright extends Helper {
18811886
* @returns {Promise<any>}
18821887
*/
18831888
async executeScript(fn, arg) {
1884-
let context = this.page;
1885-
if (this.context && this.context.constructor.name === 'Frame') {
1886-
context = this.context; // switching to iframe context
1889+
if (this.context && this.context.constructor.name === 'FrameLocator') {
1890+
// switching to iframe context
1891+
return this.context.locator(':root').evaluate(fn, arg);
18871892
}
1888-
return context.evaluate.apply(context, [fn, arg]);
1893+
return this.page.evaluate.apply(this.page, [fn, arg]);
18891894
}
18901895

18911896
/**
@@ -2407,7 +2412,7 @@ class Playwright extends Helper {
24072412
}
24082413

24092414
async _getContext() {
2410-
if (this.context && this.context.constructor.name === 'Frame') {
2415+
if (this.context && this.context.constructor.name === 'FrameLocator') {
24112416
return this.context;
24122417
}
24132418
return this.page;
@@ -2480,6 +2485,14 @@ class Playwright extends Helper {
24802485
}, [locator.value, text, $XPath.toString()], { timeout: waitTimeout });
24812486
}
24822487
} else {
2488+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2489+
if (this.frame) {
2490+
const { setTimeout } = require('timers/promises');
2491+
await setTimeout(waitTimeout);
2492+
waiter = await this.frame.locator(`:has-text('${text}')`).first().isVisible();
2493+
if (!waiter) throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec`);
2494+
return;
2495+
}
24832496
waiter = contextObject.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, text, { timeout: waitTimeout });
24842497
}
24852498
return waiter.catch((err) => {
@@ -2534,37 +2547,37 @@ class Playwright extends Helper {
25342547
}
25352548

25362549
if (locator >= 0 && locator < childFrames.length) {
2537-
this.context = childFrames[locator];
2550+
this.context = await this.page.frameLocator('iframe').nth(locator);
25382551
this.contextLocator = locator;
25392552
} else {
25402553
throw new Error('Element #invalidIframeSelector was not found by text|CSS|XPath');
25412554
}
25422555
return;
25432556
}
2544-
let contentFrame;
25452557

25462558
if (!locator) {
2547-
this.context = await this.page.frames()[0];
2559+
this.context = this.page;
25482560
this.contextLocator = null;
2561+
this.frame = null;
25492562
return;
25502563
}
25512564

25522565
// iframe by selector
2553-
const els = await this._locate(locator);
2554-
if (!els[0]) {
2555-
throw new Error(`Element ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
2566+
locator = buildLocatorString(new Locator(locator, 'css'));
2567+
const frame = await this._locateElement(locator);
2568+
2569+
if (!frame) {
2570+
throw new Error(`Frame ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
25562571
}
25572572

2558-
// get content of the first iframe
2559-
locator = new Locator(locator, 'css');
2560-
if ((locator.frame && locator.frame === 'iframe') || locator.value.toLowerCase() === 'iframe') {
2561-
contentFrame = await this.page.frames()[1];
2562-
// get content of the iframe using its name
2563-
} else if (locator.value.toLowerCase().includes('name=')) {
2564-
const frameName = locator.value.split('=')[1].replace(/"/g, '').replaceAll(/]/g, '');
2565-
contentFrame = await this.page.frame(frameName);
2573+
if (this.frame) {
2574+
this.frame = await this.frame.frameLocator(locator);
2575+
} else {
2576+
this.frame = await this.page.frameLocator(locator);
25662577
}
25672578

2579+
const contentFrame = this.frame;
2580+
25682581
if (contentFrame) {
25692582
this.context = contentFrame;
25702583
this.contextLocator = null;
@@ -3339,13 +3352,9 @@ async function proceedSee(assertType, text, context, strict = false) {
33393352
let allText;
33403353

33413354
if (!context) {
3342-
let el = await this.context;
3343-
if (el && !el.getProperty) {
3344-
// Fallback to body
3345-
el = await this.page.$('body');
3346-
}
3355+
const el = await this.context;
33473356

3348-
allText = [await el.innerText()];
3357+
allText = [await el.locator('body').innerText()];
33493358
description = 'web application';
33503359
} else {
33513360
const locator = new Locator(context, 'css');
@@ -3518,8 +3527,7 @@ async function elementSelected(element) {
35183527
function isFrameLocator(locator) {
35193528
locator = new Locator(locator);
35203529
if (locator.isFrame()) {
3521-
const _locator = new Locator(locator.value);
3522-
return _locator.value;
3530+
return locator.value;
35233531
}
35243532
return false;
35253533
}

Diff for: package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"lint": "eslint bin/ examples/ lib/ test/ translations/ runok.js",
4141
"lint-fix": "eslint bin/ examples/ lib/ test/ translations/ runok.js --fix",
4242
"docs": "./runok.js docs",
43-
"test:unit": "mocha test/unit --recursive --timeout 5000",
44-
"test:runner": "mocha test/runner --recursive --timeout 5000",
43+
"test:unit": "mocha test/unit --recursive --timeout 10000",
44+
"test:runner": "mocha test/runner --recursive --timeout 10000",
4545
"test": "npm run test:unit && npm run test:runner",
4646
"test:appium-quick": "mocha test/helper/Appium_test.js --grep 'quick'",
4747
"test:appium-other": "mocha test/helper/Appium_test.js --grep 'second'",

Diff for: test/acceptance/within_test.js

+19-19
Original file line numberDiff line numberDiff line change
@@ -47,53 +47,53 @@ Scenario('within on iframe without iframe navigation @WebDriverIO @Puppeteer @Pl
4747

4848
Scenario('within on nested iframe without iframe navigation depth 2 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
4949
I.amOnPage('/iframe_nested');
50-
within({ frame: ['[name=wrapper]', '[name=content]'] }, async () => {
51-
await I.fillField('rus', 'Updated');
52-
await I.see('Sign in!');
50+
within({ frame: ['[name=wrapper]', '[name=content]'] }, () => {
51+
I.fillField('rus', 'Updated');
52+
I.see('Sign in!');
5353
});
5454
I.see('Nested Iframe test');
5555
I.dontSee('Sign in!');
5656
});
5757

5858
Scenario('within on nested iframe depth 1 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
5959
I.amOnPage('/iframe');
60-
within({ frame: ['[name=content]'] }, async () => {
61-
await I.fillField('rus', 'Updated');
62-
await I.click('Sign in!');
63-
await I.waitForText('Email Address');
60+
within({ frame: ['[name=content]'] }, () => {
61+
I.fillField('rus', 'Updated');
62+
I.click('Sign in!');
63+
I.waitForText('Email Address');
6464
});
6565
I.see('Iframe test');
6666
I.dontSee('Email Address');
6767
});
6868

6969
Scenario('within on nested iframe depth 2 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
7070
I.amOnPage('/iframe_nested');
71-
within({ frame: ['[name=wrapper]', '[name=content]'] }, async () => {
72-
await I.fillField('rus', 'Updated');
73-
await I.click('Sign in!');
74-
await I.see('Email Address');
71+
within({ frame: ['[name=wrapper]', '[name=content]'] }, () => {
72+
I.fillField('rus', 'Updated');
73+
I.click('Sign in!');
74+
I.see('Email Address');
7575
});
7676
I.see('Nested Iframe test');
7777
I.dontSee('Email Address');
7878
});
7979

8080
Scenario('within on nested iframe depth 2 and mixed id and xpath selector @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
8181
I.amOnPage('/iframe_nested');
82-
within({ frame: ['#wrapperId', '[name=content]'] }, async () => {
83-
await I.fillField('rus', 'Updated');
84-
await I.click('Sign in!');
85-
await I.see('Email Address');
82+
within({ frame: ['#wrapperId', '[name=content]'] }, () => {
83+
I.fillField('rus', 'Updated');
84+
I.click('Sign in!');
85+
I.see('Email Address');
8686
});
8787
I.see('Nested Iframe test');
8888
I.dontSee('Email Address');
8989
});
9090

9191
Scenario('within on nested iframe depth 2 and mixed class and xpath selector @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
9292
I.amOnPage('/iframe_nested');
93-
within({ frame: ['.wrapperClass', '[name=content]'] }, async () => {
94-
await I.fillField('rus', 'Updated');
95-
await I.click('Sign in!');
96-
await I.see('Email Address');
93+
within({ frame: ['.wrapperClass', '[name=content]'] }, () => {
94+
I.fillField('rus', 'Updated');
95+
I.click('Sign in!');
96+
I.see('Email Address');
9797
});
9898
I.see('Nested Iframe test');
9999
I.dontSee('Email Address');

Diff for: test/data/app/controllers.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function GET() {
138138
include __DIR__ . '/view/image.php';
139139
}
140140
}
141-
141+
142142

143143
class cookies {
144144

@@ -177,6 +177,13 @@ public function GET()
177177
}
178178
}
179179

180+
class iframes {
181+
public function GET()
182+
{
183+
include __DIR__.'/view/iframes.php';
184+
}
185+
}
186+
180187
class iframe_nested {
181188
public function GET()
182189
{
@@ -311,4 +318,4 @@ class basic_auth {
311318
function GET() {
312319
include __DIR__.'/view/basic_auth.php';
313320
}
314-
}
321+
}

Diff for: test/data/app/index.php

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
'/external_url' => 'external_url',
4040
'/spinner' => 'spinner',
4141
'/iframe' => 'iframe',
42+
'/iframes' => 'iframes',
4243
'/iframe_nested' => 'iframe_nested',
4344
'/dynamic' => 'dynamic',
4445
'/timeout' => 'timeout',

Diff for: test/data/app/view/iframes.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5+
</head>
6+
<body>
7+
8+
<div class="box"><iframe name="content1" src="https://codecept.io" id="number-frame-5678" width="100%"> </iframe> </div>
9+
<div class="box"><iframe name="content2" src="info" id="number-frame-1234" width="100%"/></div>
10+
11+
</body>
12+
</html>

Diff for: test/helper/Playwright_test.js

+13
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,19 @@ describe('Playwright', function () {
335335
I.switchTo(null);
336336
I.see('Iframe test');
337337
});
338+
339+
it('should switch to iframe using css', () => {
340+
I.amOnPage('/iframe');
341+
I.switchTo('iframe#number-frame-1234');
342+
I.see('Information');
343+
I.see('Lots of valuable data here');
344+
});
345+
346+
it('should switch to iframe using css when there are more than one iframes', () => {
347+
I.amOnPage('/iframes');
348+
I.switchTo('iframe#number-frame-1234');
349+
I.see('Information');
350+
});
338351
});
339352

340353
describe('#seeInSource, #grabSource', () => {

0 commit comments

Comments
 (0)