test: organize tests to not depend on context (#5878)

This commit is contained in:
Pavel Feldman 2021-03-19 07:20:35 +08:00 committed by GitHub
parent 5c753b763f
commit 16bf462e4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 214 additions and 204 deletions

View file

@ -17,45 +17,34 @@
import { it, expect } from './fixtures';
it('should reject all promises when page is closed', async ({context}) => {
const newPage = await context.newPage();
it('should reject all promises when page is closed', async ({page}) => {
let error = null;
await Promise.all([
newPage.evaluate(() => new Promise(r => {})).catch(e => error = e),
newPage.close(),
page.evaluate(() => new Promise(r => {})).catch(e => error = e),
page.close(),
]);
expect(error.message).toContain('Protocol error');
});
it('should not be visible in context.pages', async ({context}) => {
const newPage = await context.newPage();
expect(context.pages()).toContain(newPage);
await newPage.close();
expect(context.pages()).not.toContain(newPage);
it('should set the page close state', async ({page}) => {
expect(page.isClosed()).toBe(false);
await page.close();
expect(page.isClosed()).toBe(true);
});
it('should set the page close state', async ({context}) => {
const newPage = await context.newPage();
expect(newPage.isClosed()).toBe(false);
await newPage.close();
expect(newPage.isClosed()).toBe(true);
});
it('should pass page to close event', async ({context}) => {
const newPage = await context.newPage();
it('should pass page to close event', async ({page}) => {
const [closedPage] = await Promise.all([
newPage.waitForEvent('close'),
newPage.close()
page.waitForEvent('close'),
page.close()
]);
expect(closedPage).toBe(newPage);
expect(closedPage).toBe(page);
});
it('should terminate network waiters', async ({context, server}) => {
const newPage = await context.newPage();
it('should terminate network waiters', async ({page, server}) => {
const results = await Promise.all([
newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e),
newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e),
newPage.close()
page.waitForRequest(server.EMPTY_PAGE).catch(e => e),
page.waitForResponse(server.EMPTY_PAGE).catch(e => e),
page.close()
]);
for (let i = 0; i < 2; i++) {
const message = results[i].message;
@ -64,16 +53,15 @@ it('should terminate network waiters', async ({context, server}) => {
}
});
it('should be callable twice', async ({context}) => {
const newPage = await context.newPage();
it('should be callable twice', async ({page}) => {
await Promise.all([
newPage.close(),
newPage.close(),
page.close(),
page.close(),
]);
await newPage.close();
await page.close();
});
it('should fire load when expected', async ({page, server}) => {
it('should fire load when expected', async ({page}) => {
await Promise.all([
page.goto('about:blank'),
page.waitForEvent('load'),
@ -109,13 +97,13 @@ it('should return null if parent page has been closed', async ({page}) => {
expect(opener).toBe(null);
});
it('should fire domcontentloaded when expected', async ({page, server}) => {
it('should fire domcontentloaded when expected', async ({page}) => {
const navigatedPromise = page.goto('about:blank');
await page.waitForEvent('domcontentloaded');
await navigatedPromise;
});
it('should pass self as argument to domcontentloaded event', async ({page, server}) => {
it('should pass self as argument to domcontentloaded event', async ({page}) => {
const [eventArg] = await Promise.all([
new Promise(f => page.on('domcontentloaded', f)),
page.goto('about:blank')
@ -123,7 +111,7 @@ it('should pass self as argument to domcontentloaded event', async ({page, serve
expect(eventArg).toBe(page);
});
it('should pass self as argument to load event', async ({page, server}) => {
it('should pass self as argument to load event', async ({page}) => {
const [eventArg] = await Promise.all([
new Promise(f => page.on('load', f)),
page.goto('about:blank')
@ -131,7 +119,7 @@ it('should pass self as argument to load event', async ({page, server}) => {
expect(eventArg).toBe(page);
});
it('should fail with error upon disconnect', async ({page, server}) => {
it('should fail with error upon disconnect', async ({page}) => {
let error;
const waitForPromise = page.waitForEvent('download').catch(e => error = e);
await page.close();
@ -159,7 +147,7 @@ it('page.title should return the page title', async ({page, server}) => {
expect(await page.title()).toBe('Woof-Woof');
});
it('page.close should work with window.close', async function({ page, context, server }) {
it('page.close should work with window.close', async function({ page }) {
const newPagePromise = page.waitForEvent('popup');
await page.evaluate(() => window['newPage'] = window.open('about:blank'));
const newPage = await newPagePromise;
@ -168,18 +156,13 @@ it('page.close should work with window.close', async function({ page, context, s
await closedPromise;
});
it('page.close should work with page.close', async function({ page, context, server }) {
const newPage = await context.newPage();
const closedPromise = new Promise(x => newPage.on('close', x));
await newPage.close();
it('page.close should work with page.close', async function({ page }) {
const closedPromise = new Promise(x => page.on('close', x));
await page.close();
await closedPromise;
});
it('page.context should return the correct instance', async function({page, context}) {
expect(page.context()).toBe(context);
});
it('page.frame should respect name', async function({page, server}) {
it('page.frame should respect name', async function({page}) {
await page.setContent(`<iframe name=target></iframe>`);
expect(page.frame({ name: 'bogus' })).toBe(null);
const frame = page.frame({ name: 'target' });
@ -233,7 +216,7 @@ it('page.press should work', async ({page, server}) => {
expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('a');
});
it('page.press should work for Enter', async ({page, server}) => {
it('page.press should work for Enter', async ({page}) => {
await page.setContent(`<input onkeypress="console.log('press')"></input>`);
const messages = [];
page.on('console', message => messages.push(message));
@ -247,13 +230,3 @@ it('frame.press should work', async ({page, server}) => {
await frame.press('textarea', 'a');
expect(await frame.evaluate(() => document.querySelector('textarea').value)).toBe('a');
});
it('frame.focus should work multiple times', async ({ context, server }) => {
const page1 = await context.newPage();
const page2 = await context.newPage();
for (const page of [page1, page2]) {
await page.setContent(`<button id="foo" onfocus="window.gotFocus=true"></button>`);
await page.focus('#foo');
expect(await page.evaluate(() => !!window['gotFocus'])).toBe(true);
}
});

View file

@ -20,7 +20,7 @@ declare const renderComponent;
declare const e;
declare const MyButton;
it('should report that selector does not match anymore', (test, parameters) => {
it('should report that selector does not match anymore', test => {
test.fail(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -41,7 +41,7 @@ it('should report that selector does not match anymore', (test, parameters) => {
expect(error.message).toContain('element does not match the selector anymore');
});
it('should not retarget the handle when element is recycled', (test, parameters) => {
it('should not retarget the handle when element is recycled', test => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -70,7 +70,7 @@ it('should timeout when click opens alert', async ({page, server}) => {
await dialog.dismiss();
});
it('should retarget when element is recycled during hit testing', (test, parameters) => {
it('should retarget when element is recycled during hit testing', test => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');
@ -87,7 +87,7 @@ it('should retarget when element is recycled during hit testing', (test, paramet
expect(await page.evaluate('window.button2')).toBe(undefined);
});
it('should retarget when element is recycled before enabled check', (test, parameters) => {
it('should retarget when element is recycled before enabled check', test => {
test.fixme(true);
}, async ({page, server}) => {
await page.goto(server.PREFIX + '/react.html');

View file

@ -27,7 +27,7 @@ it('should avoid side effects after timeout', (test, { mode }) => {
expect(error.message).toContain('page.click: Timeout 2000ms exceeded.');
});
it('should timeout waiting for button to be enabled', async ({page, server}) => {
it('should timeout waiting for button to be enabled', async ({page}) => {
await page.setContent('<button onclick="javascript:window.__CLICKED=true;" disabled><span>Click target</span></button>');
const error = await page.click('text=Click target', { timeout: 3000 }).catch(e => e);
expect(await page.evaluate('window.__CLICKED')).toBe(undefined);

View file

@ -47,7 +47,7 @@ it('should click the button if window.Node is removed', async ({page, server}) =
});
// @see https://github.com/GoogleChrome/puppeteer/issues/4281
it('should click on a span with an inline element inside', async ({page, server}) => {
it('should click on a span with an inline element inside', async ({page}) => {
await page.setContent(`
<style>
span::before {
@ -60,17 +60,14 @@ it('should click on a span with an inline element inside', async ({page, server}
expect(await page.evaluate('CLICKED')).toBe(42);
});
it('should not throw UnhandledPromiseRejection when page closes', async ({browser, server}) => {
const context = await browser.newContext();
const page = await context.newPage();
it('should not throw UnhandledPromiseRejection when page closes', async ({page}) => {
await Promise.all([
page.close(),
page.mouse.click(1, 2),
]).catch(e => {});
await context.close();
});
it('should click the 1x1 div', async ({page, server}) => {
it('should click the 1x1 div', async ({page}) => {
await page.setContent(`<div style="width: 1px; height: 1px;" onclick="window.__clicked = true"></div>`);
await page.click('div');
expect(await page.evaluate('window.__clicked')).toBe(true);
@ -92,19 +89,7 @@ it('should click the button after a cross origin navigation ', async ({page, ser
expect(await page.evaluate('result')).toBe('Clicked');
});
it('should click with disabled javascript', async ({browser, server}) => {
const context = await browser.newContext({ javaScriptEnabled: false });
const page = await context.newPage();
await page.goto(server.PREFIX + '/wrappedlink.html');
await Promise.all([
page.click('a'),
page.waitForNavigation()
]);
expect(page.url()).toBe(server.PREFIX + '/wrappedlink.html#clicked');
await context.close();
});
it('should click when one of inline box children is outside of viewport', async ({page, server}) => {
it('should click when one of inline box children is outside of viewport', async ({page}) => {
await page.setContent(`
<style>
i {
@ -248,17 +233,6 @@ it('should click on checkbox label and toggle', async ({page, server}) => {
expect(await page.evaluate(() => window['result'].check)).toBe(false);
});
it('should not hang with touch-enabled viewports', async ({browser, playwright}) => {
// @see https://github.com/GoogleChrome/puppeteer/issues/161
const { viewport, hasTouch } = playwright.devices['iPhone 6'];
const context = await browser.newContext({ viewport, hasTouch });
const page = await context.newPage();
await page.mouse.down();
await page.mouse.move(100, 10);
await page.mouse.up();
await context.close();
});
it('should scroll and click the button', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/scrollable.html');
await page.click('#button-5');
@ -375,19 +349,6 @@ it('should click the button behind sticky header', async ({page}) => {
expect(await page.evaluate(() => window['__clicked'])).toBe(true);
});
it('should click the button with deviceScaleFactor set', async ({browser, server}) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, deviceScaleFactor: 5 });
const page = await context.newPage();
expect(await page.evaluate(() => window.devicePixelRatio)).toBe(5);
await page.setContent('<div style="width:100px;height:100px">spacer</div>');
await attachFrame(page, 'button-test', server.PREFIX + '/input/button.html');
const frame = page.frames()[1];
const button = await frame.$('button');
await button.click();
expect(await frame.evaluate(() => window['result'])).toBe('Clicked');
await context.close();
});
it('should click the button with px border with offset', async ({page, server, isWebKit}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => button.style.borderWidth = '8px');
@ -440,32 +401,6 @@ it('should click a button in scrolling container with offset', async ({page, ser
expect(await page.evaluate('offsetY')).toBe(isWebKit ? 1910 + 8 : 1910);
});
it('should click the button with offset with page scale', (test, { browserName }) => {
test.skip(browserName === 'firefox');
}, async ({browser, server, isWebKit, isChromium, headful}) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true });
const page = await context.newPage();
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => {
button.style.borderWidth = '8px';
document.body.style.margin = '0';
});
await page.click('button', { position: { x: 20, y: 10 } });
expect(await page.evaluate('result')).toBe('Clicked');
const round = x => Math.round(x + 0.01);
let expected = { x: 28, y: 18 }; // 20;10 + 8px of border in each direction
if (isWebKit) {
// WebKit rounds up during css -> dip -> css conversion.
expected = { x: 29, y: 19 };
} else if (isChromium && !headful) {
// Headless Chromium rounds down during css -> dip -> css conversion.
expected = { x: 27, y: 18 };
}
expect(round(await page.evaluate('pageX'))).toBe(expected.x);
expect(round(await page.evaluate('pageY'))).toBe(expected.y);
await context.close();
});
it('should wait for stable position', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => {
@ -534,7 +469,7 @@ it('should fail when obscured and not waiting for hit target', async ({page, ser
expect(await page.evaluate(() => window['result'])).toBe('Was not clicked');
});
it('should wait for button to be enabled', async ({page, server}) => {
it('should wait for button to be enabled', async ({page}) => {
await page.setContent('<button onclick="javascript:window.__CLICKED=true;" disabled><span>Click target</span></button>');
let done = false;
const clickPromise = page.click('text=Click target').then(() => done = true);
@ -546,7 +481,7 @@ it('should wait for button to be enabled', async ({page, server}) => {
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should wait for input to be enabled', async ({page, server}) => {
it('should wait for input to be enabled', async ({page}) => {
await page.setContent('<input onclick="javascript:window.__CLICKED=true;" disabled>');
let done = false;
const clickPromise = page.click('input').then(() => done = true);
@ -558,7 +493,7 @@ it('should wait for input to be enabled', async ({page, server}) => {
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should wait for select to be enabled', async ({page, server}) => {
it('should wait for select to be enabled', async ({page}) => {
await page.setContent('<select onclick="javascript:window.__CLICKED=true;" disabled><option selected>Hello</option></select>');
let done = false;
const clickPromise = page.click('select').then(() => done = true);
@ -570,25 +505,25 @@ it('should wait for select to be enabled', async ({page, server}) => {
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should click disabled div', async ({page, server}) => {
it('should click disabled div', async ({page}) => {
await page.setContent('<div onclick="javascript:window.__CLICKED=true;" disabled>Click target</div>');
await page.click('text=Click target');
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should climb dom for inner label with pointer-events:none', async ({page, server}) => {
it('should climb dom for inner label with pointer-events:none', async ({page}) => {
await page.setContent('<button onclick="javascript:window.__CLICKED=true;"><label style="pointer-events:none">Click target</label></button>');
await page.click('text=Click target');
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should climb up to [role=button]', async ({page, server}) => {
it('should climb up to [role=button]', async ({page}) => {
await page.setContent('<div role=button onclick="javascript:window.__CLICKED=true;"><div style="pointer-events:none"><span><div>Click target</div></span></div>');
await page.click('text=Click target');
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should wait for BUTTON to be clickable when it has pointer-events:none', async ({page, server}) => {
it('should wait for BUTTON to be clickable when it has pointer-events:none', async ({page}) => {
await page.setContent('<button onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></button>');
let done = false;
const clickPromise = page.click('text=Click target').then(() => done = true);
@ -600,7 +535,7 @@ it('should wait for BUTTON to be clickable when it has pointer-events:none', asy
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should wait for LABEL to be clickable when it has pointer-events:none', async ({page, server}) => {
it('should wait for LABEL to be clickable when it has pointer-events:none', async ({page}) => {
await page.setContent('<label onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></label>');
const clickPromise = page.click('text=Click target');
// Do a few roundtrips to the page.
@ -682,7 +617,7 @@ it('should retry when element detaches after animation', async ({page, server})
expect(await page.evaluate('clicked')).toBe(true);
});
it('should retry when element is animating from outside the viewport', async ({page, server}) => {
it('should retry when element is animating from outside the viewport', async ({page}) => {
await page.setContent(`<style>
@keyframes move {
from { left: -300px; }
@ -710,7 +645,7 @@ it('should retry when element is animating from outside the viewport', async ({p
expect(await page.evaluate('clicked')).toBe(true);
});
it('should fail when element is animating from outside the viewport with force', async ({page, server}) => {
it('should fail when element is animating from outside the viewport with force', async ({page}) => {
await page.setContent(`<style>
@keyframes move {
from { left: -300px; }
@ -739,7 +674,7 @@ it('should fail when element is animating from outside the viewport with force',
expect(error.message).toContain('Element is outside of the viewport');
});
it('should dispatch microtasks in order', async ({page, server}) => {
it('should dispatch microtasks in order', async ({page}) => {
await page.setContent(`
<button id=button>Click me</button>
<script>
@ -769,7 +704,7 @@ it('should click the button when window.innerWidth is corrupted', async ({page,
expect(await page.evaluate('result')).toBe('Clicked');
});
it('should click zero-sized input by label', async ({page, server}) => {
it('should click zero-sized input by label', async ({page}) => {
await page.setContent(`
<label>
Click me

View file

@ -40,7 +40,7 @@ it('should dispatch click svg', async ({page}) => {
expect(await page.evaluate(() => window['__CLICKED'])).toBe(42);
});
it('should dispatch click on a span with an inline element inside', async ({page, server}) => {
it('should dispatch click on a span with an inline element inside', async ({page}) => {
await page.setContent(`
<style>
span::before {
@ -69,7 +69,7 @@ it('should dispatch click after a cross origin navigation ', async ({page, serve
expect(await page.evaluate(() => window['result'])).toBe('Clicked');
});
it('should not fail when element is blocked on hover', async ({page, server}) => {
it('should not fail when element is blocked on hover', async ({page}) => {
await page.setContent(`<style>
container { display: block; position: relative; width: 200px; height: 50px; }
div, button { position: absolute; left: 0; top: 0; bottom: 0; right: 0; }

View file

@ -20,7 +20,7 @@ import { attachFrame } from './utils';
describe('Drag and drop', (test, {browserName}) => {
test.fixme(browserName === 'chromium');
}, () => {
it('should work', async ({server, page, context}) => {
it('should work', async ({page, server}) => {
await page.goto(server.PREFIX + '/drag-n-drop.html');
await page.hover('#source');
await page.mouse.down();
@ -123,8 +123,7 @@ describe('Drag and drop', (test, {browserName}) => {
test.fixme(browserName === 'chromium', 'Chromium doesn\'t let users set dropEffect on our fake data transfer');
test.fixme(browserName === 'webkit' && platform !== 'linux', 'WebKit doesn\'t handle the drop effect correctly outside of linux.');
test.fixme(browserName === 'firefox');
}, async ({context}) => {
const page = await context.newPage();
}, async ({page}) => {
expect(await testIfDropped('copy', 'copy')).toBe(true);
expect(await testIfDropped('copy', 'move')).toBe(false);
expect(await testIfDropped('all', 'link')).toBe(true);

View file

@ -18,7 +18,7 @@
import { it, expect } from './fixtures';
import { attachFrame } from './utils';
it('should emulate type', async ({page, server}) => {
it('should emulate type', async ({page}) => {
expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(false);
await page.emulateMedia({ media: 'print' });
@ -32,14 +32,14 @@ it('should emulate type', async ({page, server}) => {
expect(await page.evaluate(() => matchMedia('print').matches)).toBe(false);
});
it('should throw in case of bad media argument', async ({page, server}) => {
it('should throw in case of bad media argument', async ({page}) => {
let error = null;
// @ts-expect-error 'bad' is not a valid media type
await page.emulateMedia({ media: 'bad'}).catch(e => error = e);
expect(error.message).toContain('media: expected one of (screen|print|null)');
});
it('should emulate scheme work', async ({page, server}) => {
it('should emulate scheme work', async ({page}) => {
await page.emulateMedia({ colorScheme: 'light' });
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
@ -48,7 +48,7 @@ it('should emulate scheme work', async ({page, server}) => {
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
});
it('should default to light', async ({page, server}) => {
it('should default to light', async ({page}) => {
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false);
@ -61,7 +61,7 @@ it('should default to light', async ({page, server}) => {
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(true);
});
it('should throw in case of bad colorScheme argument', async ({page, server}) => {
it('should throw in case of bad colorScheme argument', async ({page}) => {
let error = null;
// @ts-expect-error 'bad' is not a valid media type
await page.emulateMedia({ colorScheme: 'bad' }).catch(e => error = e);

View file

@ -17,24 +17,24 @@
import { it, expect } from './fixtures';
it('should work', async ({page, server}) => {
it('should work', async ({page}) => {
const windowHandle = await page.evaluateHandle(() => window);
expect(windowHandle).toBeTruthy();
});
it('should accept object handle as an argument', async ({page, server}) => {
it('should accept object handle as an argument', async ({page}) => {
const navigatorHandle = await page.evaluateHandle(() => navigator);
const text = await page.evaluate(e => e.userAgent, navigatorHandle);
expect(text).toContain('Mozilla');
});
it('should accept object handle to primitive types', async ({page, server}) => {
it('should accept object handle to primitive types', async ({page}) => {
const aHandle = await page.evaluateHandle(() => 5);
const isFive = await page.evaluate(e => Object.is(e, 5), aHandle);
expect(isFive).toBeTruthy();
});
it('should accept nested handle', async ({page, server}) => {
it('should accept nested handle', async ({page}) => {
const foo = await page.evaluateHandle(() => ({ x: 1, y: 'foo' }));
const result = await page.evaluate(({ foo }) => {
return foo;
@ -42,7 +42,7 @@ it('should accept nested handle', async ({page, server}) => {
expect(result).toEqual({ x: 1, y: 'foo' });
});
it('should accept nested window handle', async ({page, server}) => {
it('should accept nested window handle', async ({page}) => {
const foo = await page.evaluateHandle(() => window);
const result = await page.evaluate(({ foo }) => {
return foo === window;
@ -50,7 +50,7 @@ it('should accept nested window handle', async ({page, server}) => {
expect(result).toBe(true);
});
it('should accept multiple nested handles', async ({page, server}) => {
it('should accept multiple nested handles', async ({page}) => {
const foo = await page.evaluateHandle(() => ({ x: 1, y: 'foo' }));
const bar = await page.evaluateHandle(() => 5);
const baz = await page.evaluateHandle(() => (['baz']));
@ -63,29 +63,29 @@ it('should accept multiple nested handles', async ({page, server}) => {
});
});
it('should throw for circular objects', async ({page, server}) => {
it('should throw for circular objects', async ({page}) => {
const a = { x: 1 };
a['y'] = a;
const error = await page.evaluate(x => x, a).catch(e => e);
expect(error.message).toContain('Argument is a circular structure');
});
it('should accept same handle multiple times', async ({page, server}) => {
it('should accept same handle multiple times', async ({page}) => {
const foo = await page.evaluateHandle(() => 1);
expect(await page.evaluate(x => x, { foo, bar: [foo], baz: { foo }})).toEqual({ foo: 1, bar: [1], baz: { foo: 1 } });
});
it('should accept same nested object multiple times', async ({page, server}) => {
it('should accept same nested object multiple times', async ({page}) => {
const foo = { x: 1 };
expect(await page.evaluate(x => x, { foo, bar: [foo], baz: { foo }})).toEqual({ foo: { x: 1 }, bar: [{ x: 1 }], baz: { foo: { x: 1 } } });
});
it('should accept object handle to unserializable value', async ({page, server}) => {
it('should accept object handle to unserializable value', async ({page}) => {
const aHandle = await page.evaluateHandle(() => Infinity);
expect(await page.evaluate(e => Object.is(e, Infinity), aHandle)).toBe(true);
});
it('should pass configurable args', async ({page, server}) => {
it('should pass configurable args', async ({page}) => {
const result = await page.evaluate(arg => {
if (arg.foo !== 42)
throw new Error('Not a 42');
@ -100,7 +100,7 @@ it('should pass configurable args', async ({page, server}) => {
expect(result).toEqual({});
});
it('should work with primitives', async ({page, server}) => {
it('should work with primitives', async ({page}) => {
const aHandle = await page.evaluateHandle(() => {
window['FOO'] = 123;
return window;

View file

@ -17,27 +17,27 @@
import { it, expect } from './fixtures';
it('should work', async ({ page, server }) => {
it('should work', async ({ page }) => {
const result = await page.evaluate(() => 7 * 3);
expect(result).toBe(21);
});
it('should transfer NaN', async ({ page, server }) => {
it('should transfer NaN', async ({ page }) => {
const result = await page.evaluate(a => a, NaN);
expect(Object.is(result, NaN)).toBe(true);
});
it('should transfer -0', async ({ page, server }) => {
it('should transfer -0', async ({ page }) => {
const result = await page.evaluate(a => a, -0);
expect(Object.is(result, -0)).toBe(true);
});
it('should transfer Infinity', async ({ page, server }) => {
it('should transfer Infinity', async ({ page }) => {
const result = await page.evaluate(a => a, Infinity);
expect(Object.is(result, Infinity)).toBe(true);
});
it('should transfer -Infinity', async ({ page, server }) => {
it('should transfer -Infinity', async ({ page }) => {
const result = await page.evaluate(a => a, -Infinity);
expect(Object.is(result, -Infinity)).toBe(true);
});
@ -83,17 +83,17 @@ it('should roundtrip promise to unserializable values', async ({ page }) => {
expect(result).toEqual(value);
});
it('should transfer arrays', async ({ page, server }) => {
it('should transfer arrays', async ({ page }) => {
const result = await page.evaluate(a => a, [1, 2, 3]);
expect(result).toEqual([1, 2, 3]);
});
it('should transfer arrays as arrays, not objects', async ({ page, server }) => {
it('should transfer arrays as arrays, not objects', async ({ page }) => {
const result = await page.evaluate(a => Array.isArray(a), [1, 2, 3]);
expect(result).toBe(true);
});
it('should transfer maps as empty objects', async ({ page, server }) => {
it('should transfer maps as empty objects', async ({ page }) => {
const result = await page.evaluate(a => a.x.constructor.name + ' ' + JSON.stringify(a.x), { x: new Map([[1, 2]]) });
expect(result).toBe('Object {}');
});
@ -108,7 +108,7 @@ it('should evaluate in the page context', async ({ page, server }) => {
expect(await page.evaluate('globalVar')).toBe(123);
});
it('should return undefined for objects with symbols', async ({ page, server }) => {
it('should return undefined for objects with symbols', async ({ page }) => {
expect(await page.evaluate(() => [Symbol('foo4')])).toEqual([undefined]);
expect(await page.evaluate(() => {
const a = {};
@ -120,7 +120,7 @@ it('should return undefined for objects with symbols', async ({ page, server })
})).toEqual({ foo: [{ a: undefined }] });
});
it('should work with function shorthands', async ({ page, server }) => {
it('should work with function shorthands', async ({ page }) => {
const a = {
sum([a, b]) { return a + b; },
async mult([a, b]) { return a * b; }
@ -129,12 +129,12 @@ it('should work with function shorthands', async ({ page, server }) => {
expect(await page.evaluate(a.mult, [2, 4])).toBe(8);
});
it('should work with unicode chars', async ({ page, server }) => {
it('should work with unicode chars', async ({ page }) => {
const result = await page.evaluate(a => a['中文字符'], { '中文字符': 42 });
expect(result).toBe(42);
});
it('should throw when evaluation triggers reload', async ({ page, server }) => {
it('should throw when evaluation triggers reload', async ({ page }) => {
let error = null;
await page.evaluate(() => {
location.reload();
@ -143,7 +143,7 @@ it('should throw when evaluation triggers reload', async ({ page, server }) => {
expect(error.message).toContain('navigation');
});
it('should await promise', async ({ page, server }) => {
it('should await promise', async ({ page }) => {
const result = await page.evaluate(() => Promise.resolve(8 * 7));
expect(result).toBe(56);
});
@ -167,7 +167,7 @@ it('should work right after a cross-origin navigation', async ({ page, server })
expect(await frameEvaluation).toBe(42);
});
it('should work from-inside an exposed function', async ({ page, server }) => {
it('should work from-inside an exposed function', async ({ page }) => {
// Setup inpage callback, which calls Page.evaluate
await page.exposeFunction('callController', async function(a, b) {
return await page.evaluate(({ a, b }) => a * b, { a, b });
@ -178,7 +178,7 @@ it('should work from-inside an exposed function', async ({ page, server }) => {
expect(result).toBe(27);
});
it('should reject promise with exception', async ({ page, server }) => {
it('should reject promise with exception', async ({ page }) => {
let error = null;
// @ts-ignore
await page.evaluate(() => not_existing_object.property).catch(e => error = e);
@ -186,48 +186,48 @@ it('should reject promise with exception', async ({ page, server }) => {
expect(error.message).toContain('not_existing_object');
});
it('should support thrown strings as error messages', async ({ page, server }) => {
it('should support thrown strings as error messages', async ({ page }) => {
let error = null;
await page.evaluate(() => { throw 'qwerty'; }).catch(e => error = e);
expect(error).toBeTruthy();
expect(error.message).toContain('qwerty');
});
it('should support thrown numbers as error messages', async ({ page, server }) => {
it('should support thrown numbers as error messages', async ({ page }) => {
let error = null;
await page.evaluate(() => { throw 100500; }).catch(e => error = e);
expect(error).toBeTruthy();
expect(error.message).toContain('100500');
});
it('should return complex objects', async ({ page, server }) => {
it('should return complex objects', async ({ page }) => {
const object = { foo: 'bar!' };
const result = await page.evaluate(a => a, object);
expect(result).not.toBe(object);
expect(result).toEqual(object);
});
it('should return NaN', async ({ page, server }) => {
it('should return NaN', async ({ page }) => {
const result = await page.evaluate(() => NaN);
expect(Object.is(result, NaN)).toBe(true);
});
it('should return -0', async ({ page, server }) => {
it('should return -0', async ({ page }) => {
const result = await page.evaluate(() => -0);
expect(Object.is(result, -0)).toBe(true);
});
it('should return Infinity', async ({ page, server }) => {
it('should return Infinity', async ({ page }) => {
const result = await page.evaluate(() => Infinity);
expect(Object.is(result, Infinity)).toBe(true);
});
it('should return -Infinity', async ({ page, server }) => {
it('should return -Infinity', async ({ page }) => {
const result = await page.evaluate(() => -Infinity);
expect(Object.is(result, -Infinity)).toBe(true);
});
it('should work with overwritten Promise', async ({ page, server }) => {
it('should work with overwritten Promise', async ({ page }) => {
await page.evaluate(() => {
const originalPromise = window.Promise;
class Promise2 {
@ -274,7 +274,7 @@ it('should work with overwritten Promise', async ({ page, server }) => {
expect(await page.evaluate(() => Promise.resolve(42))).toBe(42);
});
it('should throw when passed more than one parameter', async ({ page, server }) => {
it('should throw when passed more than one parameter', async ({ page }) => {
const expectThrow = async f => {
let error;
await f().catch(e => error = e);
@ -303,7 +303,7 @@ it('should throw when passed more than one parameter', async ({ page, server })
await expectThrow(() => frame.evaluate((a, b) => false, 1, 2));
});
it('should accept "undefined" as one of multiple parameters', async ({ page, server }) => {
it('should accept "undefined" as one of multiple parameters', async ({ page }) => {
const result = await page.evaluate(({ a, b }) => Object.is(a, undefined) && Object.is(b, 'foo'), { a: undefined, b: 'foo' });
expect(result).toBe(true);
});
@ -329,11 +329,11 @@ it('should properly serialize null fields', async ({ page }) => {
expect(await page.evaluate(() => ({ a: null }))).toEqual({ a: null });
});
it('should return undefined for non-serializable objects', async ({ page, server }) => {
it('should return undefined for non-serializable objects', async ({ page }) => {
expect(await page.evaluate(() => window)).toBe(undefined);
});
it('should fail for circular object', async ({ page, server }) => {
it('should fail for circular object', async ({ page }) => {
const result = await page.evaluate(() => {
const a = {} as any;
const b = { a };
@ -343,7 +343,7 @@ it('should fail for circular object', async ({ page, server }) => {
expect(result).toBe(undefined);
});
it('should be able to throw a tricky error', async ({ page, server }) => {
it('should be able to throw a tricky error', async ({ page }) => {
const windowHandle = await page.evaluateHandle(() => window);
const errorText = await windowHandle.jsonValue().catch(e => e.message);
const error = await page.evaluate(errorText => {
@ -352,29 +352,29 @@ it('should be able to throw a tricky error', async ({ page, server }) => {
expect(error.message).toContain(errorText);
});
it('should accept a string', async ({ page, server }) => {
it('should accept a string', async ({ page }) => {
const result = await page.evaluate('1 + 2');
expect(result).toBe(3);
});
it('should accept a string with semi colons', async ({ page, server }) => {
it('should accept a string with semi colons', async ({ page }) => {
const result = await page.evaluate('1 + 5;');
expect(result).toBe(6);
});
it('should accept a string with comments', async ({ page, server }) => {
it('should accept a string with comments', async ({ page }) => {
const result = await page.evaluate('2 + 5;\n// do some math!');
expect(result).toBe(7);
});
it('should accept element handle as an argument', async ({ page, server }) => {
it('should accept element handle as an argument', async ({ page }) => {
await page.setContent('<section>42</section>');
const element = await page.$('section');
const text = await page.evaluate(e => e.textContent, element);
expect(text).toBe('42');
});
it('should throw if underlying element was disposed', async ({ page, server }) => {
it('should throw if underlying element was disposed', async ({ page }) => {
await page.setContent('<section>39</section>');
const element = await page.$('section');
expect(element).toBeTruthy();
@ -384,7 +384,7 @@ it('should throw if underlying element was disposed', async ({ page, server }) =
expect(error.message).toContain('JSHandle is disposed');
});
it('should simulate a user gesture', async ({ page, server }) => {
it('should simulate a user gesture', async ({ page }) => {
const result = await page.evaluate(() => {
document.body.appendChild(document.createTextNode('test'));
document.execCommand('selectAll');
@ -393,7 +393,7 @@ it('should simulate a user gesture', async ({ page, server }) => {
expect(result).toBe(true);
});
it('should throw a nice error after a navigation', async ({ page, server }) => {
it('should throw a nice error after a navigation', async ({ page }) => {
const errorPromise = page.evaluate(() => new Promise(f => window['__resolve'] = f)).catch(e => e) as Promise<Error>;
await Promise.all([
page.waitForNavigation(),

View file

@ -18,7 +18,7 @@
import { it, expect } from './fixtures';
import util from 'util';
it('should work', async ({page, server}) => {
it('should work', async ({page}) => {
let message = null;
page.once('console', m => message = m);
await Promise.all([
@ -32,7 +32,7 @@ it('should work', async ({page, server}) => {
expect(await message.args()[2].jsonValue()).toEqual({foo: 'bar'});
});
it('should emit same log twice', async ({page, server}) => {
it('should emit same log twice', async ({page}) => {
const messages = [];
page.on('console', m => messages.push(m.text()));
await page.evaluate(() => { for (let i = 0; i < 2; ++i) console.log('hello'); });
@ -49,7 +49,7 @@ it('should use text() for inspection', async ({page}) => {
expect(text).toEqual('Hello world');
});
it('should work for different console API calls', async ({page, server}) => {
it('should work for different console API calls', async ({page}) => {
const messages = [];
page.on('console', msg => messages.push(msg));
// All console events will be reported before `page.evaluate` is finished.
@ -76,7 +76,7 @@ it('should work for different console API calls', async ({page, server}) => {
]);
});
it('should not fail for window object', async ({page, server}) => {
it('should not fail for window object', async ({page}) => {
let message = null;
page.once('console', msg => message = msg);
await Promise.all([

View file

@ -0,0 +1,103 @@
/**
* Copyright 2017 Google Inc. All rights reserved.
* Modifications copyright (c) Microsoft Corporation.
*
* 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
*
* http://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.
*/
import { it, expect } from './fixtures';
import { attachFrame } from './utils';
it('should not be visible in context.pages', async ({page, context}) => {
expect(context.pages()).toContain(page);
await page.close();
expect(context.pages()).not.toContain(page);
});
it('page.context should return the correct instance', async function({page, context}) {
expect(page.context()).toBe(context);
});
it('frame.focus should work multiple times', async ({ context }) => {
const page1 = await context.newPage();
const page2 = await context.newPage();
for (const page of [page1, page2]) {
await page.setContent(`<button id="foo" onfocus="window.gotFocus=true"></button>`);
await page.focus('#foo');
expect(await page.evaluate(() => !!window['gotFocus'])).toBe(true);
}
});
it('should click with disabled javascript', async ({browser, server}) => {
const context = await browser.newContext({ javaScriptEnabled: false });
const page = await context.newPage();
await page.goto(server.PREFIX + '/wrappedlink.html');
await Promise.all([
page.click('a'),
page.waitForNavigation()
]);
expect(page.url()).toBe(server.PREFIX + '/wrappedlink.html#clicked');
await context.close();
});
it('should not hang with touch-enabled viewports', async ({browser, playwright}) => {
// @see https://github.com/GoogleChrome/puppeteer/issues/161
const { viewport, hasTouch } = playwright.devices['iPhone 6'];
const context = await browser.newContext({ viewport, hasTouch });
const page = await context.newPage();
await page.mouse.down();
await page.mouse.move(100, 10);
await page.mouse.up();
await context.close();
});
it('should click the button with deviceScaleFactor set', async ({browser, server}) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, deviceScaleFactor: 5 });
const page = await context.newPage();
expect(await page.evaluate(() => window.devicePixelRatio)).toBe(5);
await page.setContent('<div style="width:100px;height:100px">spacer</div>');
await attachFrame(page, 'button-test', server.PREFIX + '/input/button.html');
const frame = page.frames()[1];
const button = await frame.$('button');
await button.click();
expect(await frame.evaluate(() => window['result'])).toBe('Clicked');
await context.close();
});
it('should click the button with offset with page scale', (test, { browserName }) => {
test.skip(browserName === 'firefox');
}, async ({browser, server, isWebKit, isChromium, headful}) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true });
const page = await context.newPage();
await page.goto(server.PREFIX + '/input/button.html');
await page.$eval('button', button => {
button.style.borderWidth = '8px';
document.body.style.margin = '0';
});
await page.click('button', { position: { x: 20, y: 10 } });
expect(await page.evaluate('result')).toBe('Clicked');
const round = x => Math.round(x + 0.01);
let expected = { x: 28, y: 18 }; // 20;10 + 8px of border in each direction
if (isWebKit) {
// WebKit rounds up during css -> dip -> css conversion.
expected = { x: 29, y: 19 };
} else if (isChromium && !headful) {
// Headless Chromium rounds down during css -> dip -> css conversion.
expected = { x: 27, y: 18 };
}
expect(round(await page.evaluate('pageX'))).toBe(expected.x);
expect(round(await page.evaluate('pageY'))).toBe(expected.y);
await context.close();
});