Skip to content

Commit

Permalink
fix: switchTo - within block (#3892)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
kobenguyent authored Oct 9, 2023
1 parent af97ec6 commit 1832ced
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
env:
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
- name: Install deps
run: npm install playwright@1.32.3 & npx playwright install-deps
run: npm install playwright@1.35.1 & npx playwright install-deps
- name: start a server
run: "php -S 127.0.0.1:8000 -t test/data/app &"
- name: run chromium tests
Expand Down
64 changes: 36 additions & 28 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -826,8 +826,9 @@ class Playwright extends Helper {

async _stopBrowser() {
this.withinLocator = null;
this._setPage(null);
await this._setPage(null);
this.context = null;
this.frame = null;
popupStore.clear();
await this.browser.close();
}
Expand Down Expand Up @@ -866,6 +867,7 @@ class Playwright extends Helper {
this.withinLocator = null;
this.context = await this.page;
this.contextLocator = null;
this.frame = null;
}

_extractDataFromPerformanceTiming(timing, ...dataNames) {
Expand Down Expand Up @@ -1155,6 +1157,9 @@ class Playwright extends Helper {
*/
async _locate(locator) {
const context = await this.context || await this._getContext();

if (this.frame) return findElements(this.frame, locator);

return findElements(context, locator);
}

Expand Down Expand Up @@ -1881,11 +1886,11 @@ class Playwright extends Helper {
* @returns {Promise<any>}
*/
async executeScript(fn, arg) {
let context = this.page;
if (this.context && this.context.constructor.name === 'Frame') {
context = this.context; // switching to iframe context
if (this.context && this.context.constructor.name === 'FrameLocator') {
// switching to iframe context
return this.context.locator(':root').evaluate(fn, arg);
}
return context.evaluate.apply(context, [fn, arg]);
return this.page.evaluate.apply(this.page, [fn, arg]);
}

/**
Expand Down Expand Up @@ -2407,7 +2412,7 @@ class Playwright extends Helper {
}

async _getContext() {
if (this.context && this.context.constructor.name === 'Frame') {
if (this.context && this.context.constructor.name === 'FrameLocator') {
return this.context;
}
return this.page;
Expand Down Expand Up @@ -2480,6 +2485,14 @@ class Playwright extends Helper {
}, [locator.value, text, $XPath.toString()], { timeout: waitTimeout });
}
} else {
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
if (this.frame) {
const { setTimeout } = require('timers/promises');
await setTimeout(waitTimeout);
waiter = await this.frame.locator(`:has-text('${text}')`).first().isVisible();
if (!waiter) throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec`);
return;
}
waiter = contextObject.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, text, { timeout: waitTimeout });
}
return waiter.catch((err) => {
Expand Down Expand Up @@ -2534,37 +2547,37 @@ class Playwright extends Helper {
}

if (locator >= 0 && locator < childFrames.length) {
this.context = childFrames[locator];
this.context = await this.page.frameLocator('iframe').nth(locator);
this.contextLocator = locator;
} else {
throw new Error('Element #invalidIframeSelector was not found by text|CSS|XPath');
}
return;
}
let contentFrame;

if (!locator) {
this.context = await this.page.frames()[0];
this.context = this.page;
this.contextLocator = null;
this.frame = null;
return;
}

// iframe by selector
const els = await this._locate(locator);
if (!els[0]) {
throw new Error(`Element ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
locator = buildLocatorString(new Locator(locator, 'css'));
const frame = await this._locateElement(locator);

if (!frame) {
throw new Error(`Frame ${JSON.stringify(locator)} was not found by text|CSS|XPath`);
}

// get content of the first iframe
locator = new Locator(locator, 'css');
if ((locator.frame && locator.frame === 'iframe') || locator.value.toLowerCase() === 'iframe') {
contentFrame = await this.page.frames()[1];
// get content of the iframe using its name
} else if (locator.value.toLowerCase().includes('name=')) {
const frameName = locator.value.split('=')[1].replace(/"/g, '').replaceAll(/]/g, '');
contentFrame = await this.page.frame(frameName);
if (this.frame) {
this.frame = await this.frame.frameLocator(locator);
} else {
this.frame = await this.page.frameLocator(locator);
}

const contentFrame = this.frame;

if (contentFrame) {
this.context = contentFrame;
this.contextLocator = null;
Expand Down Expand Up @@ -3339,13 +3352,9 @@ async function proceedSee(assertType, text, context, strict = false) {
let allText;

if (!context) {
let el = await this.context;
if (el && !el.getProperty) {
// Fallback to body
el = await this.page.$('body');
}
const el = await this.context;

allText = [await el.innerText()];
allText = [await el.locator('body').innerText()];
description = 'web application';
} else {
const locator = new Locator(context, 'css');
Expand Down Expand Up @@ -3518,8 +3527,7 @@ async function elementSelected(element) {
function isFrameLocator(locator) {
locator = new Locator(locator);
if (locator.isFrame()) {
const _locator = new Locator(locator.value);
return _locator.value;
return locator.value;
}
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"lint": "eslint bin/ examples/ lib/ test/ translations/ runok.js",
"lint-fix": "eslint bin/ examples/ lib/ test/ translations/ runok.js --fix",
"docs": "./runok.js docs",
"test:unit": "mocha test/unit --recursive --timeout 5000",
"test:runner": "mocha test/runner --recursive --timeout 5000",
"test:unit": "mocha test/unit --recursive --timeout 10000",
"test:runner": "mocha test/runner --recursive --timeout 10000",
"test": "npm run test:unit && npm run test:runner",
"test:appium-quick": "mocha test/helper/Appium_test.js --grep 'quick'",
"test:appium-other": "mocha test/helper/Appium_test.js --grep 'second'",
Expand Down
38 changes: 19 additions & 19 deletions test/acceptance/within_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,53 +47,53 @@ Scenario('within on iframe without iframe navigation @WebDriverIO @Puppeteer @Pl

Scenario('within on nested iframe without iframe navigation depth 2 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
I.amOnPage('/iframe_nested');
within({ frame: ['[name=wrapper]', '[name=content]'] }, async () => {
await I.fillField('rus', 'Updated');
await I.see('Sign in!');
within({ frame: ['[name=wrapper]', '[name=content]'] }, () => {
I.fillField('rus', 'Updated');
I.see('Sign in!');
});
I.see('Nested Iframe test');
I.dontSee('Sign in!');
});

Scenario('within on nested iframe depth 1 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
I.amOnPage('/iframe');
within({ frame: ['[name=content]'] }, async () => {
await I.fillField('rus', 'Updated');
await I.click('Sign in!');
await I.waitForText('Email Address');
within({ frame: ['[name=content]'] }, () => {
I.fillField('rus', 'Updated');
I.click('Sign in!');
I.waitForText('Email Address');
});
I.see('Iframe test');
I.dontSee('Email Address');
});

Scenario('within on nested iframe depth 2 @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
I.amOnPage('/iframe_nested');
within({ frame: ['[name=wrapper]', '[name=content]'] }, async () => {
await I.fillField('rus', 'Updated');
await I.click('Sign in!');
await I.see('Email Address');
within({ frame: ['[name=wrapper]', '[name=content]'] }, () => {
I.fillField('rus', 'Updated');
I.click('Sign in!');
I.see('Email Address');
});
I.see('Nested Iframe test');
I.dontSee('Email Address');
});

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

Scenario('within on nested iframe depth 2 and mixed class and xpath selector @WebDriverIO @Puppeteer @Playwright', ({ I }) => {
I.amOnPage('/iframe_nested');
within({ frame: ['.wrapperClass', '[name=content]'] }, async () => {
await I.fillField('rus', 'Updated');
await I.click('Sign in!');
await I.see('Email Address');
within({ frame: ['.wrapperClass', '[name=content]'] }, () => {
I.fillField('rus', 'Updated');
I.click('Sign in!');
I.see('Email Address');
});
I.see('Nested Iframe test');
I.dontSee('Email Address');
Expand Down
11 changes: 9 additions & 2 deletions test/data/app/controllers.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function GET() {
include __DIR__ . '/view/image.php';
}
}


class cookies {

Expand Down Expand Up @@ -177,6 +177,13 @@ public function GET()
}
}

class iframes {
public function GET()
{
include __DIR__.'/view/iframes.php';
}
}

class iframe_nested {
public function GET()
{
Expand Down Expand Up @@ -311,4 +318,4 @@ class basic_auth {
function GET() {
include __DIR__.'/view/basic_auth.php';
}
}
}
1 change: 1 addition & 0 deletions test/data/app/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
'/external_url' => 'external_url',
'/spinner' => 'spinner',
'/iframe' => 'iframe',
'/iframes' => 'iframes',
'/iframe_nested' => 'iframe_nested',
'/dynamic' => 'dynamic',
'/timeout' => 'timeout',
Expand Down
12 changes: 12 additions & 0 deletions test/data/app/view/iframes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<div class="box"><iframe name="content1" src="https://codecept.io" id="number-frame-5678" width="100%"> </iframe> </div>
<div class="box"><iframe name="content2" src="info" id="number-frame-1234" width="100%"/></div>

</body>
</html>
13 changes: 13 additions & 0 deletions test/helper/Playwright_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,19 @@ describe('Playwright', function () {
I.switchTo(null);
I.see('Iframe test');
});

it('should switch to iframe using css', () => {
I.amOnPage('/iframe');
I.switchTo('iframe#number-frame-1234');
I.see('Information');
I.see('Lots of valuable data here');
});

it('should switch to iframe using css when there are more than one iframes', () => {
I.amOnPage('/iframes');
I.switchTo('iframe#number-frame-1234');
I.see('Information');
});
});

describe('#seeInSource, #grabSource', () => {
Expand Down

0 comments on commit 1832ced

Please sign in to comment.