Skip to content

Commit

Permalink
test: add handling for local frame becoming OOPIF
Browse files Browse the repository at this point in the history
  • Loading branch information
OrKoN committed Mar 9, 2022
1 parent 61844c2 commit bc6a1b9
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 27 deletions.
72 changes: 45 additions & 27 deletions src/PuppeteerRunnerExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,18 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
}
}

#getTimeoutForStep(step: Step, flow: UserFlow): number {
return step.timeout || flow.timeout || this.timeout;
}

async runStep(step: Step, flow: UserFlow): Promise<void> {
const timeout = step.timeout || this.timeout;
const timeout = this.#getTimeoutForStep(step, flow);
const page = this.page;
const browser = this.browser;
const waitForVisible = true;

const targetPage = await getTargetPageForStep(browser, page, step, timeout);
let targetFrame: Frame | null = null;

if (!targetPage && step.target) {
const frames = page.frames();
for (const f of frames) {
Expand All @@ -63,21 +67,35 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
targetFrame = await page.waitForFrame(step.target, { timeout });
}
}
const pageOrFrame = targetPage || targetFrame;
if (!pageOrFrame) {
const targetPageOrFrame = targetFrame || targetPage;
if (!targetPageOrFrame) {
throw new Error('Target is not found for step: ' + JSON.stringify(step));
}
await this.#ensureAutomationEmulatation(targetPageOrFrame);
const localFrame = await getFrame(targetPageOrFrame, step);
await this.runStepInFrame(
step,
page,
targetPageOrFrame,
localFrame,
timeout
);
}

await this.#ensureAutomationEmulatation(pageOrFrame);

const frame = await getFrame(pageOrFrame, step);

const assertedEventsPromise = waitForEvents(pageOrFrame, step, timeout);
async runStepInFrame(
step: Step,
mainPage: Page,
targetPageOrFrame: Page | Frame,
localFrame: Frame,
timeout: number
): Promise<void> {
const waitForVisible = true;
const assertedEventsPromise = waitForEvents(localFrame, step, timeout);

switch (step.type) {
case 'click':
{
const element = await waitForSelectors(step.selectors, frame, {
const element = await waitForSelectors(step.selectors, localFrame, {
timeout,
visible: waitForVisible,
});
Expand All @@ -96,31 +114,31 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
break;
case 'emulateNetworkConditions':
{
await page.emulateNetworkConditions(step);
await mainPage.emulateNetworkConditions(step);
}
break;
case 'keyDown':
{
await page.keyboard.down(step.key);
await page.waitForTimeout(100);
await mainPage.keyboard.down(step.key);
await mainPage.waitForTimeout(100);
}
break;
case 'keyUp':
{
await page.keyboard.up(step.key);
await page.waitForTimeout(100);
await mainPage.keyboard.up(step.key);
await mainPage.waitForTimeout(100);
}
break;
case 'close':
{
if ('close' in pageOrFrame) {
await pageOrFrame.close();
if ('close' in targetPageOrFrame) {
await targetPageOrFrame.close();
}
}
break;
case 'change':
{
const element = await waitForSelectors(step.selectors, frame, {
const element = await waitForSelectors(step.selectors, localFrame, {
timeout,
visible: waitForVisible,
});
Expand Down Expand Up @@ -164,14 +182,14 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
}
break;
case 'setViewport': {
if ('setViewport' in pageOrFrame) {
await pageOrFrame.setViewport(step);
if ('setViewport' in targetPageOrFrame) {
await targetPageOrFrame.setViewport(step);
}
break;
}
case 'scroll': {
if ('selectors' in step) {
const element = await waitForSelectors(step.selectors, frame, {
const element = await waitForSelectors(step.selectors, localFrame, {
timeout,
visible: waitForVisible,
});
Expand All @@ -187,7 +205,7 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
);
await element.dispose();
} else {
await frame.evaluate(
await localFrame.evaluate(
(x, y) => {
/* c8 ignore next 1 */
window.scroll(x, y);
Expand All @@ -199,12 +217,12 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
break;
}
case 'navigate': {
await frame.goto(step.url);
await localFrame.goto(step.url);
break;
}
case 'waitForElement': {
try {
await waitForElement(step, frame, timeout);
await waitForElement(step, localFrame, timeout);
} catch (err) {
if ((err as Error).message === 'Timed out') {
throw new Error(
Expand All @@ -217,7 +235,7 @@ export class PuppeteerRunnerExtension extends RunnerExtension {
break;
}
case 'waitForExpression': {
await frame.waitForFunction(step.expression, {
await localFrame.waitForFunction(step.expression, {
timeout,
});
break;
Expand Down Expand Up @@ -276,7 +294,7 @@ async function getTargetPageForStep(
}

async function waitForEvents(
targetPage: Page | Frame,
pageOrFrame: Page | Frame,
step: Step,
timeout: number
): Promise<void> {
Expand All @@ -286,7 +304,7 @@ async function waitForEvents(
switch (event.type) {
case 'navigation': {
promises.push(
targetPage.waitForNavigation({
pageOrFrame.waitForNavigation({
timeout,
})
);
Expand Down
23 changes: 23 additions & 0 deletions test/resources/local-iframe1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
Copyright 2022 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<h1>iframe 1</h1>
<script>
function navigate() {
const url = new URL('./iframe2.html', document.location);
window.location.href = url.toString().replace('localhost', 'oopifdomain');
}
</script>
<button onclick="navigate()">To iframe 2</button>
17 changes: 17 additions & 0 deletions test/resources/local-to-oopif.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--
Copyright 2022 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<h1>Navigation in local frame leading to an OOPIF</h1>
<iframe src="local-iframe1.html">
43 changes: 43 additions & 0 deletions test/runner_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,4 +752,47 @@ describe('Runner', () => {
.find((frame) => frame.url() === `${OOPIF_PREFIX}/iframe2.html`);
assert.ok(frame, 'Frame that the target page navigated to is not found');
});

it('should replay navigations from local from to OOPIF', async () => {
const runner = await createRunner(
{
title: 'Test Recording',
timeout: 3000,
steps: [
{
type: 'navigate',
url: `${HTTP_PREFIX}/local-to-oopif.html`,
assertedEvents: [
{
title: '',
type: 'navigation',
url: `${HTTP_PREFIX}/local-to-oopif.html`,
},
],
},
{
type: 'click',
frame: [0],
selectors: [['aria/To iframe 2']],
offsetX: 1,
offsetY: 1,
// TODO(alexrudenko): make the navigation assertions work.
// assertedEvents: [
// {
// type: 'navigation',
// title: '',
// url: `${OOPIF_PREFIX}/iframe2.html`,
// },
// ],
},
],
},
new PuppeteerRunnerExtension(browser, page)
);
await runner.run();
const frame = page.waitForFrame(
(frame) => frame.url() === `${OOPIF_PREFIX}/iframe2.html`
);
assert.ok(frame, 'Frame that the target page navigated to is not found');
});
});

0 comments on commit bc6a1b9

Please sign in to comment.