chore(test): add blank lines (#3303)

This commit is contained in:
Pavel Feldman 2020-08-05 11:43:40 -07:00 committed by GitHub
parent b03b4a5566
commit 9280037d0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 183 additions and 0 deletions

View file

@ -26,6 +26,7 @@ it('should work', async({context, page, server}) => {
}]);
expect(await page.evaluate(() => document.cookie)).toEqual('password=123456');
});
it('should roundtrip cookie', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
// @see https://en.wikipedia.org/wiki/Year_2038_problem
@ -42,6 +43,7 @@ it('should roundtrip cookie', async({context, page, server}) => {
await context.addCookies(cookies);
expect(await context.cookies()).toEqual(cookies);
});
it('should send cookie header', async({server, context}) => {
let cookie = '';
server.setRoute('/empty.html', (req, res) => {
@ -53,6 +55,7 @@ it('should send cookie header', async({server, context}) => {
await page.goto(server.EMPTY_PAGE);
expect(cookie).toBe('cookie=value');
});
it('should isolate cookies in browser contexts', async({context, server, browser}) => {
const anotherContext = await browser.newContext();
await context.addCookies([{url: server.EMPTY_PAGE, name: 'isolatecookie', value: 'page1value'}]);
@ -68,6 +71,7 @@ it('should isolate cookies in browser contexts', async({context, server, browser
expect(cookies2[0].value).toBe('page2value');
await anotherContext.close();
});
it('should isolate session cookies', async({context, server, browser}) => {
server.setRoute('/setcookie.html', (req, res) => {
res.setHeader('Set-Cookie', 'session=value');
@ -93,6 +97,7 @@ it('should isolate session cookies', async({context, server, browser}) => {
await context2.close();
}
});
it('should isolate persistent cookies', async({context, server, browser}) => {
server.setRoute('/setcookie.html', (req, res) => {
res.setHeader('Set-Cookie', 'persistent=persistent-value; max-age=3600');
@ -112,6 +117,7 @@ it('should isolate persistent cookies', async({context, server, browser}) => {
expect(cookies2.length).toBe(0);
await context2.close();
});
it('should isolate send cookie header', async({server, context, browser}) => {
let cookie = [];
server.setRoute('/empty.html', (req, res) => {
@ -132,6 +138,7 @@ it('should isolate send cookie header', async({server, context, browser}) => {
await context.close();
}
});
it.slow()('should isolate cookies between launches', async({browserType, server, defaultBrowserOptions}) => {
const browser1 = await browserType.launch(defaultBrowserOptions);
const context1 = await browser1.newContext();
@ -144,6 +151,7 @@ it.slow()('should isolate cookies between launches', async({browserType, server,
expect(cookies.length).toBe(0);
await browser2.close();
});
it('should set multiple cookies', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.addCookies([{
@ -163,6 +171,7 @@ it('should set multiple cookies', async({context, page, server}) => {
'multiple-2=bar',
]);
});
it('should have |expires| set to |-1| for session cookies', async({context, server}) => {
await context.addCookies([{
url: server.EMPTY_PAGE,
@ -172,6 +181,7 @@ it('should have |expires| set to |-1| for session cookies', async({context, serv
const cookies = await context.cookies();
expect(cookies[0].expires).toBe(-1);
});
it('should set cookie with reasonable defaults', async({context, server}) => {
await context.addCookies([{
url: server.EMPTY_PAGE,
@ -190,6 +200,7 @@ it('should set cookie with reasonable defaults', async({context, server}) => {
sameSite: 'None',
}]);
});
it('should set a cookie with a path', async({context, page, server}) => {
await page.goto(server.PREFIX + '/grid.html');
await context.addCookies([{
@ -214,6 +225,7 @@ it('should set a cookie with a path', async({context, page, server}) => {
await page.goto(server.PREFIX + '/grid.html');
expect(await page.evaluate('document.cookie')).toBe('gridcookie=GRID');
});
it('should not set a cookie with blank page URL', async function({context, server}) {
let error = null;
try {
@ -228,6 +240,7 @@ it('should not set a cookie with blank page URL', async function({context, serve
`Blank page can not have cookie "example-cookie-blank"`
);
});
it('should not set a cookie on a data URL page', async function({context}) {
let error = null;
try {
@ -237,6 +250,7 @@ it('should not set a cookie on a data URL page', async function({context}) {
}
expect(error.message).toContain('Data URL page can not have cookie "example-cookie"');
});
it('should default to setting secure cookie for HTTPS websites', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
const SECURE_URL = 'https://example.com';
@ -248,6 +262,7 @@ it('should default to setting secure cookie for HTTPS websites', async({context,
const [cookie] = await context.cookies(SECURE_URL);
expect(cookie.secure).toBe(true);
});
it('should be able to set unsecure cookie for HTTP website', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
const HTTP_URL = 'http://example.com';
@ -259,6 +274,7 @@ it('should be able to set unsecure cookie for HTTP website', async({context, pag
const [cookie] = await context.cookies(HTTP_URL);
expect(cookie.secure).toBe(false);
});
it('should set a cookie on a different domain', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.addCookies([{
@ -278,6 +294,7 @@ it('should set a cookie on a different domain', async({context, page, server}) =
sameSite: 'None',
}]);
});
it('should set cookies for a frame', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
await context.addCookies([
@ -295,6 +312,7 @@ it('should set cookies for a frame', async({context, page, server}) => {
expect(await page.frames()[1].evaluate('document.cookie')).toBe('frame-cookie=value');
});
it('should(not) block third party cookies', async({context, page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.evaluate(src => {

View file

@ -158,6 +158,7 @@ it('should fire page lifecycle events', async function({browser, server}) {
]);
await context.close();
});
it.fail(WEBKIT)('should work with Shift-clicking', async({browser, server}) => {
// WebKit: Shift+Click does not open a new window.
const context = await browser.newContext();
@ -171,6 +172,7 @@ it.fail(WEBKIT)('should work with Shift-clicking', async({browser, server}) => {
expect(await popup.opener()).toBe(null);
await context.close();
});
it.fail(WEBKIT || FFOX)('should work with Ctrl-clicking', async({browser, server}) => {
// Firefox: reports an opener in this case.
// WebKit: Ctrl+Click does not open a new tab.

View file

@ -99,6 +99,7 @@ it('should delete downloads when context closes', async({downloadsBrowser, downl
expect(fs.existsSync(path)).toBeFalsy();
});
it('should report downloads in downloadsPath folder', async({downloadsBrowser, downloadsPath, server}) => {
const page = await downloadsBrowser.newPage({ acceptDownloads: true });
await page.setContent(`<a href="${server.PREFIX}/download">download</a>`);

View file

@ -25,6 +25,7 @@ it.fail(FFOX && !HEADLESS)('should work', async ({ page, server }) => {
const box = await elementHandle.boundingBox();
expect(box).toEqual({ x: 100, y: 50, width: 50, height: 50 });
});
it('should handle nested frames', async ({ page, server }) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.goto(server.PREFIX + '/frames/nested-frames.html');
@ -33,11 +34,13 @@ it('should handle nested frames', async ({ page, server }) => {
const box = await elementHandle.boundingBox();
expect(box).toEqual({ x: 24, y: 224, width: 268, height: 18 });
});
it('should return null for invisible elements', async ({ page, server }) => {
await page.setContent('<div style="display:none">hi</div>');
const element = await page.$('div');
expect(await element.boundingBox()).toBe(null);
});
it('should force a layout', async ({ page, server }) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.setContent('<div style="width: 100px; height: 100px">hello</div>');
@ -46,6 +49,7 @@ it('should force a layout', async ({ page, server }) => {
const box = await elementHandle.boundingBox();
expect(box).toEqual({ x: 8, y: 8, width: 100, height: 200 });
});
it('should work with SVG nodes', async ({ page, server }) => {
await page.setContent(`
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500">
@ -60,6 +64,7 @@ it('should work with SVG nodes', async ({ page, server }) => {
}, element);
expect(pwBoundingBox).toEqual(webBoundingBox);
});
it.skip(FFOX)('should work with page scale', async ({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 400, height: 400, isMobile: true } });
const page = await context.newPage();
@ -80,6 +85,7 @@ it.skip(FFOX)('should work with page scale', async ({ browser, server }) => {
expect(Math.round(box.height * 100)).toBe(20 * 100);
await context.close();
});
it('should work when inline box child is outside of viewport', async ({ page, server }) => {
await page.setContent(`
<style>

View file

@ -24,6 +24,7 @@ it('should work', async ({ page, server }) => {
await button.click();
expect(await page.evaluate(() => result)).toBe('Clicked');
});
it('should work with Node removed', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.evaluate(() => delete window['Node']);
@ -31,18 +32,21 @@ it('should work with Node removed', async ({ page, server }) => {
await button.click();
expect(await page.evaluate(() => result)).toBe('Clicked');
});
it('should work for Shadow DOM v1', async ({ page, server }) => {
await page.goto(server.PREFIX + '/shadow.html');
const buttonHandle = await page.evaluateHandle(() => button);
await buttonHandle.click();
expect(await page.evaluate(() => clicked)).toBe(true);
});
it('should work for TextNodes', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
const buttonTextNode = await page.evaluateHandle(() => document.querySelector('button').firstChild);
await buttonTextNode.click();
expect(await page.evaluate(() => result)).toBe('Clicked');
});
it('should throw for detached nodes', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
const button = await page.$('button');
@ -51,6 +55,7 @@ it('should throw for detached nodes', async ({ page, server }) => {
await button.click().catch(err => error = err);
expect(error.message).toContain('Element is not attached to the DOM');
});
it('should throw for hidden nodes with force', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
const button = await page.$('button');
@ -58,6 +63,7 @@ it('should throw for hidden nodes with force', async ({ page, server }) => {
const error = await button.click({ force: true }).catch(err => err);
expect(error.message).toContain('Element is not visible');
});
it('should throw for recursively hidden nodes with force', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
const button = await page.$('button');
@ -65,12 +71,14 @@ it('should throw for recursively hidden nodes with force', async ({ page, server
const error = await button.click({ force: true }).catch(err => err);
expect(error.message).toContain('Element is not visible');
});
it('should throw for <br> elements with force', async ({ page, server }) => {
await page.setContent('hello<br>goodbye');
const br = await page.$('br');
const error = await br.click({ force: true }).catch(err => err);
expect(error.message).toContain('Element is outside of the viewport');
});
it('should double click the button', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/button.html');
await page.evaluate(() => {

View file

@ -25,6 +25,7 @@ it('should work', async ({ page, server }) => {
const frame = await elementHandle.contentFrame();
expect(frame).toBe(page.frames()[1]);
});
it('should work for cross-process iframes', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.CROSS_PROCESS_PREFIX + '/empty.html');
@ -32,6 +33,7 @@ it('should work for cross-process iframes', async ({ page, server }) => {
const frame = await elementHandle.contentFrame();
expect(frame).toBe(page.frames()[1]);
});
it('should work for cross-frame evaluations', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -39,6 +41,7 @@ it('should work for cross-frame evaluations', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => window.top.document.querySelector('#frame1'));
expect(await elementHandle.contentFrame()).toBe(frame);
});
it('should return null for non-iframes', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -46,6 +49,7 @@ it('should return null for non-iframes', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document.body);
expect(await elementHandle.contentFrame()).toBe(null);
});
it('should return null for document.documentElement', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);

View file

@ -30,6 +30,7 @@ it('should have a nice preview', async ({ page, server }) => {
expect(String(text)).toBe('JSHandle@#text=Text,↵more text');
expect(String(check)).toBe('JSHandle@<input checked id="check" foo="bar"" type="checkbox"/>');
});
it('getAttribute should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const handle = await page.$('#outer');
@ -38,18 +39,21 @@ it('getAttribute should work', async ({ page, server }) => {
expect(await page.getAttribute('#outer', 'name')).toBe('value');
expect(await page.getAttribute('#outer', 'foo')).toBe(null);
});
it('innerHTML should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const handle = await page.$('#outer');
expect(await handle.innerHTML()).toBe('<div id="inner">Text,\nmore text</div>');
expect(await page.innerHTML('#outer')).toBe('<div id="inner">Text,\nmore text</div>');
});
it('innerText should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const handle = await page.$('#inner');
expect(await handle.innerText()).toBe('Text, more text');
expect(await page.innerText('#inner')).toBe('Text, more text');
});
it('innerText should throw', async ({ page, server }) => {
await page.setContent(`<svg>text</svg>`);
const error1 = await page.innerText('svg').catch(e => e);
@ -58,12 +62,14 @@ it('innerText should throw', async ({ page, server }) => {
const error2 = await handle.innerText().catch(e => e);
expect(error2.message).toContain('Not an HTMLElement');
});
it('textContent should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const handle = await page.$('#inner');
expect(await handle.textContent()).toBe('Text,\nmore text');
expect(await page.textContent('#inner')).toBe('Text,\nmore text');
});
it('textContent should be atomic', async ({ playwright, page }) => {
const createDummySelector = () => ({
create(root, target) { },
@ -86,6 +92,7 @@ it('textContent should be atomic', async ({ playwright, page }) => {
expect(tc).toBe('Hello');
expect(await page.evaluate(() => document.querySelector('div').textContent)).toBe('modified');
});
it('innerText should be atomic', async ({ playwright, page }) => {
const createDummySelector = () => ({
create(root, target) { },
@ -108,6 +115,7 @@ it('innerText should be atomic', async ({ playwright, page }) => {
expect(tc).toBe('Hello');
expect(await page.evaluate(() => document.querySelector('div').innerText)).toBe('modified');
});
it('innerHTML should be atomic', async ({ playwright, page }) => {
const createDummySelector = () => ({
create(root, target) { },
@ -130,6 +138,7 @@ it('innerHTML should be atomic', async ({ playwright, page }) => {
expect(tc).toBe('Hello<span>world</span>');
expect(await page.evaluate(() => document.querySelector('div').innerHTML)).toBe('modified');
});
it('getAttribute should be atomic', async ({ playwright, page }) => {
const createDummySelector = () => ({
create(root, target) { },

View file

@ -25,6 +25,7 @@ it('should work', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document.body);
expect(await elementHandle.ownerFrame()).toBe(frame);
});
it('should work for cross-process iframes', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.CROSS_PROCESS_PREFIX + '/empty.html');
@ -32,6 +33,7 @@ it('should work for cross-process iframes', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document.body);
expect(await elementHandle.ownerFrame()).toBe(frame);
});
it('should work for document', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -39,6 +41,7 @@ it('should work for document', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document);
expect(await elementHandle.ownerFrame()).toBe(frame);
});
it('should work for iframe elements', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -46,6 +49,7 @@ it('should work for iframe elements', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document.querySelector('#frame1'));
expect(await elementHandle.ownerFrame()).toBe(frame);
});
it('should work for cross-frame evaluations', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -53,6 +57,7 @@ it('should work for cross-frame evaluations', async ({ page, server }) => {
const elementHandle = await frame.evaluateHandle(() => document.querySelector('#frame1').contentWindow.document.body);
expect(await elementHandle.ownerFrame()).toBe(frame.childFrames()[0]);
});
it('should work for detached elements', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
const divHandle = await page.evaluateHandle(() => {
@ -67,6 +72,7 @@ it('should work for detached elements', async ({ page, server }) => {
});
expect(await divHandle.ownerFrame()).toBe(page.mainFrame());
});
it('should work for adopted elements', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE);
const [popup] = await Promise.all([

View file

@ -23,11 +23,13 @@ it('should work', async ({ page }) => {
await page.press('input', 'h');
expect(await page.$eval('input', input => input.value)).toBe('h');
});
it('should not select existing value', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' />`);
await page.press('input', 'w');
expect(await page.$eval('input', input => input.value)).toBe('whello');
});
it('should reset selection when not focused', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' /><div tabIndex=2>text</div>`);
await page.$eval('input', input => {
@ -38,6 +40,7 @@ it('should reset selection when not focused', async ({ page }) => {
await page.press('input', 'w');
expect(await page.$eval('input', input => input.value)).toBe('whello');
});
it('should not modify selection when focused', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' />`);
await page.$eval('input', input => {
@ -48,6 +51,7 @@ it('should not modify selection when focused', async ({ page }) => {
await page.press('input', 'w');
expect(await page.$eval('input', input => input.value)).toBe('hewo');
});
it('should work with number input', async ({ page }) => {
await page.setContent(`<input type='number' value=2 />`);
await page.press('input', '1');

View file

@ -30,6 +30,7 @@ it.skip(ffheadful)('should work', async({page, server}) => {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
});
it.skip(ffheadful)('should take into account padding and border', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
await page.setContent(`
@ -47,6 +48,7 @@ it.skip(ffheadful)('should take into account padding and border', async({page})
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-padding-border.png');
});
it.skip(ffheadful)('should capture full element when larger than viewport in parallel', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
@ -74,6 +76,7 @@ it.skip(ffheadful)('should capture full element when larger than viewport in par
await utils.verifyViewport(page, 500, 500);
});
it.skip(ffheadful)('should capture full element when larger than viewport', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
@ -100,6 +103,7 @@ it.skip(ffheadful)('should capture full element when larger than viewport', asyn
await utils.verifyViewport(page, 500, 500);
});
it.skip(ffheadful)('should scroll element into view', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
await page.setContent(`
@ -123,6 +127,7 @@ it.skip(ffheadful)('should scroll element into view', async({page}) => {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-scrolled-into-view.png');
});
it.skip(ffheadful)('should scroll 15000px into view', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
await page.setContent(`
@ -146,6 +151,7 @@ it.skip(ffheadful)('should scroll 15000px into view', async({page}) => {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-scrolled-into-view.png');
});
it.skip(ffheadful)('should work with a rotated element', async({page}) => {
await page.setViewportSize({width: 500, height: 500});
await page.setContent(`<div style="position:absolute;
@ -159,6 +165,7 @@ it.skip(ffheadful)('should work with a rotated element', async({page}) => {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-rotate.png');
});
it.skip(ffheadful)('should fail to screenshot a detached element', async({page, server}) => {
await page.setContent('<h1>remove this</h1>');
const elementHandle = await page.$('h1');
@ -166,6 +173,7 @@ it.skip(ffheadful)('should fail to screenshot a detached element', async({page,
const screenshotError = await elementHandle.screenshot().catch(error => error);
expect(screenshotError.message).toContain('Element is not attached to the DOM');
});
it.skip(ffheadful)('should timeout waiting for visible', async({page, server}) => {
await page.setContent('<div style="width: 50px; height: 0"></div>');
const div = await page.$('div');
@ -173,6 +181,7 @@ it.skip(ffheadful)('should timeout waiting for visible', async({page, server}) =
expect(error.message).toContain('elementHandle.screenshot: Timeout 3000ms exceeded');
expect(error.message).toContain('element is not visible');
});
it.skip(ffheadful)('should wait for visible', async({page, server}) => {
await page.setViewportSize({width: 500, height: 500});
await page.goto(server.PREFIX + '/grid.html');
@ -191,12 +200,14 @@ it.skip(ffheadful)('should wait for visible', async({page, server}) => {
const screenshot = await promise;
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
});
it.skip(ffheadful)('should work for an element with fractional dimensions', async({page}) => {
await page.setContent('<div style="width:48.51px;height:19.8px;border:1px solid black;"></div>');
const elementHandle = await page.$('div');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-fractional.png');
});
it.skip(FFOX)('should work with a mobile viewport', async({browser, server}) => {
const context = await browser.newContext({viewport: { width: 320, height: 480, isMobile: true }});
const page = await context.newPage();
@ -207,6 +218,7 @@ it.skip(FFOX)('should work with a mobile viewport', async({browser, server}) =>
expect(screenshot).toBeGolden('screenshot-element-mobile.png');
await context.close();
});
it.skip(FFOX)('should work with device scale factor', async({browser, server}) => {
const context = await browser.newContext({ viewport: { width: 320, height: 480 }, deviceScaleFactor: 2 });
const page = await context.newPage();
@ -217,12 +229,14 @@ it.skip(FFOX)('should work with device scale factor', async({browser, server}) =
expect(screenshot).toBeGolden('screenshot-element-mobile-dsf.png');
await context.close();
});
it.skip(ffheadful)('should work for an element with an offset', async({page}) => {
await page.setContent('<div style="position:absolute; top: 10.3px; left: 20.4px;width:50.3px;height:20.2px;border:1px solid black;"></div>');
const elementHandle = await page.$('div');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-fractional-offset.png');
});
it.skip(ffheadful)('should take screenshots when default viewport is null', async({server, browser}) => {
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
@ -241,6 +255,7 @@ it.skip(ffheadful)('should take screenshots when default viewport is null', asyn
expect(sizeBefore.height).toBe(sizeAfter.height);
await context.close();
});
it.skip(ffheadful)('should take fullPage screenshots when default viewport is null', async({server, browser}) => {
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
@ -256,6 +271,7 @@ it.skip(ffheadful)('should take fullPage screenshots when default viewport is nu
expect(sizeBefore.height).toBe(sizeAfter.height);
await context.close();
});
it.skip(ffheadful)('should restore default viewport after fullPage screenshot', async({ browser }) => {
const context = await browser.newContext({ viewport: { width: 456, height: 789 } });
const page = await context.newPage();
@ -265,6 +281,7 @@ it.skip(ffheadful)('should restore default viewport after fullPage screenshot',
await utils.verifyViewport(page, 456, 789);
await context.close();
});
it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot and exception', async({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
const page = await context.newPage();
@ -275,6 +292,7 @@ it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot
await utils.verifyViewport(page, 350, 360);
await context.close();
});
it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot and timeout', async({ browser, server }) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
const page = await context.newPage();
@ -288,6 +306,7 @@ it.skip(ffheadful || USES_HOOKS)('should restore viewport after page screenshot
await utils.verifyViewport(page, 400, 400);
await context.close();
});
it.skip(ffheadful)('should take element screenshot when default viewport is null and restore back', async({server, browser}) => {
const context = await browser.newContext({viewport: null});
const page = await context.newPage({ viewport: null });
@ -317,6 +336,7 @@ it.skip(ffheadful)('should take element screenshot when default viewport is null
expect(sizeBefore.height).toBe(sizeAfter.height);
await context.close();
});
it.skip(ffheadful || USES_HOOKS)('should restore viewport after element screenshot and exception', async({server, browser}) => {
const context = await browser.newContext({ viewport: { width: 350, height: 360 } });
const page = await context.newPage();
@ -328,6 +348,7 @@ it.skip(ffheadful || USES_HOOKS)('should restore viewport after element screensh
await utils.verifyViewport(page, 350, 360);
await context.close();
});
it.skip(ffheadful)('should wait for element to stop moving', async({page, server}) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.goto(server.PREFIX + '/grid.html');
@ -339,6 +360,7 @@ it.skip(ffheadful)('should wait for element to stop moving', async({page, server
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
});
it.skip(ffheadful)('should take screenshot of disabled button', async({page}) => {
await page.setViewportSize({ width: 500, height: 500 });
await page.setContent(`<button disabled>Click me</button>`);

View file

@ -34,6 +34,7 @@ it('should work', async ({ page, server }) => {
await page.evaluate(() => window.scrollTo(0, 0));
}
});
it('should throw for detached element', async ({ page, server }) => {
await page.setContent('<div>Hello</div>');
const div = await page.$('div');
@ -56,22 +57,27 @@ it('should wait for display:none to become visible', async ({ page, server }) =>
await page.setContent('<div style="display:none">Hello</div>');
await testWaiting(page, div => div.style.display = 'block');
});
it('should wait for display:contents to become visible', async ({ page, server }) => {
await page.setContent('<div style="display:contents">Hello</div>');
await testWaiting(page, div => div.style.display = 'block');
});
it('should wait for visibility:hidden to become visible', async ({ page, server }) => {
await page.setContent('<div style="visibility:hidden">Hello</div>');
await testWaiting(page, div => div.style.visibility = 'visible');
});
it('should wait for zero-sized element to become visible', async ({ page, server }) => {
await page.setContent('<div style="height:0">Hello</div>');
await testWaiting(page, div => div.style.height = '100px');
});
it('should wait for nested display:none to become visible', async ({ page, server }) => {
await page.setContent('<span style="display:none"><div>Hello</div></span>');
await testWaiting(page, div => div.parentElement.style.display = 'block');
});
it('should wait for element to stop moving', async ({ page, server }) => {
await page.setContent(`
<style>

View file

@ -30,6 +30,7 @@ it('should select textarea', async ({ page, server }) => {
expect(await page.evaluate(() => window.getSelection().toString())).toBe('some value');
}
});
it('should select input', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const input = await page.$('input');
@ -42,12 +43,14 @@ it('should select input', async ({ page, server }) => {
expect(await page.evaluate(() => window.getSelection().toString())).toBe('some value');
}
});
it('should select plain div', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const div = await page.$('div.plain');
await div.selectText();
expect(await page.evaluate(() => window.getSelection().toString())).toBe('Plain div');
});
it('should timeout waiting for invisible element', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
@ -55,6 +58,7 @@ it('should timeout waiting for invisible element', async ({ page, server }) => {
const error = await textarea.selectText({ timeout: 3000 }).catch(e => e);
expect(error.message).toContain('element is not visible');
});
it('should wait for visible', async ({ page, server }) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');

View file

@ -23,11 +23,13 @@ it('should work', async ({ page }) => {
await page.type('input', 'hello');
expect(await page.$eval('input', input => input.value)).toBe('hello');
});
it('should not select existing value', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' />`);
await page.type('input', 'world');
expect(await page.$eval('input', input => input.value)).toBe('worldhello');
});
it('should reset selection when not focused', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' /><div tabIndex=2>text</div>`);
await page.$eval('input', input => {
@ -38,6 +40,7 @@ it('should reset selection when not focused', async ({ page }) => {
await page.type('input', 'world');
expect(await page.$eval('input', input => input.value)).toBe('worldhello');
});
it('should not modify selection when focused', async ({ page }) => {
await page.setContent(`<input type='text' value='hello' />`);
await page.$eval('input', input => {
@ -48,6 +51,7 @@ it('should not modify selection when focused', async ({ page }) => {
await page.type('input', 'world');
expect(await page.$eval('input', input => input.value)).toBe('heworldo');
});
it('should work with number input', async ({ page }) => {
await page.setContent(`<input type='number' value=2 />`);
await page.type('input', '13');

View file

@ -24,26 +24,31 @@ it('should work with css selector', async({page, server}) => {
const divsCount = await page.$$eval('css=div', divs => divs.length);
expect(divsCount).toBe(3);
});
it('should work with text selector', async({page, server}) => {
await page.setContent('<div>hello</div><div>beautiful</div><div>beautiful</div><div>world!</div>');
const divsCount = await page.$$eval('text="beautiful"', divs => divs.length);
expect(divsCount).toBe(2);
});
it('should work with xpath selector', async({page, server}) => {
await page.setContent('<div>hello</div><div>beautiful</div><div>world!</div>');
const divsCount = await page.$$eval('xpath=/html/body/div', divs => divs.length);
expect(divsCount).toBe(3);
});
it('should auto-detect css selector', async({page, server}) => {
await page.setContent('<div>hello</div><div>beautiful</div><div>world!</div>');
const divsCount = await page.$$eval('div', divs => divs.length);
expect(divsCount).toBe(3);
});
it('should support >> syntax', async({page, server}) => {
await page.setContent('<div><span>hello</span></div><div>beautiful</div><div><span>wo</span><span>rld!</span></div><span>Not this one</span>');
const spansCount = await page.$$eval('css=div >> css=span', spans => spans.length);
expect(spansCount).toBe(3);
});
it('should support * capture', async({page, server}) => {
await page.setContent('<section><div><span>a</span></div></section><section><div><span>b</span></div></section>');
expect(await page.$$eval('*css=div >> "b"', els => els.length)).toBe(1);
@ -58,12 +63,14 @@ it('should support * capture', async({page, server}) => {
expect(await page.$$eval('*css=div >> "a"', els => els.length)).toBe(3);
expect(await page.$$eval('section >> *css=div >> "a"', els => els.length)).toBe(1);
});
it('should support * capture when multiple paths match', async({page, server}) => {
await page.setContent('<div><div><span></span></div></div><div></div>');
expect(await page.$$eval('*css=div >> span', els => els.length)).toBe(2);
await page.setContent('<div><div><span></span></div><span></span><span></span></div><div></div>');
expect(await page.$$eval('*css=div >> span', els => els.length)).toBe(2);
});
it('should return complex values', async({page, server}) => {
await page.setContent('<div>hello</div><div>beautiful</div><div>world!</div>');
const texts = await page.$$eval('css=div', divs => divs.map(div => div.textContent));

View file

@ -22,6 +22,7 @@ it('should work', async function({page, server}) {
await page.focus('#d1');
expect(await page.evaluate(() => document.activeElement.id)).toBe('d1');
});
it('should emit focus event', async function({page, server}) {
await page.setContent(`<div id=d1 tabIndex=0></div>`);
let focused = false;
@ -30,6 +31,7 @@ it('should emit focus event', async function({page, server}) {
await page.focus('#d1');
expect(focused).toBe(true);
});
it('should emit blur event', async function({page, server}) {
await page.setContent(`<div id=d1 tabIndex=0>DIV1</div><div id=d2 tabIndex=0>DIV2</div>`);
await page.focus('#d1');
@ -43,6 +45,7 @@ it('should emit blur event', async function({page, server}) {
expect(focused).toBe(true);
expect(blurred).toBe(true);
});
it('should traverse focus', async function({page}) {
await page.setContent(`<input id="i1"><input id="i2">`);
let focused = false;
@ -58,6 +61,7 @@ it('should traverse focus', async function({page}) {
expect(await page.$eval('#i1', e => e.value)).toBe('First');
expect(await page.$eval('#i2', e => e.value)).toBe('Last');
});
it('should traverse focus in all directions', async function({page}) {
await page.setContent(`<input value="1"><input value="2"><input value="3">`);
await page.keyboard.press('Tab');

View file

@ -28,6 +28,7 @@ it('should handle nested frames', async({page, server}) => {
' http://localhost:<PORT>/frames/frame.html (uno)',
]);
});
it('should send events when frames are manipulated dynamically', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
// validate frameattached events
@ -55,6 +56,7 @@ it('should send events when frames are manipulated dynamically', async({page, se
expect(detachedFrames.length).toBe(1);
expect(detachedFrames[0].isDetached()).toBe(true);
});
it('should send "framenavigated" when navigating on anchor URLs', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await Promise.all([
@ -63,12 +65,14 @@ it('should send "framenavigated" when navigating on anchor URLs', async({page, s
]);
expect(page.url()).toBe(server.EMPTY_PAGE + '#foo');
});
it('should persist mainFrame on cross-process navigation', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
const mainFrame = page.mainFrame();
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
expect(page.mainFrame() === mainFrame).toBeTruthy();
});
it('should not send attach/detach events for main frame', async({page, server}) => {
let hasEvents = false;
page.on('frameattached', frame => hasEvents = true);
@ -76,6 +80,7 @@ it('should not send attach/detach events for main frame', async({page, server})
await page.goto(server.EMPTY_PAGE);
expect(hasEvents).toBe(false);
});
it('should detach child frames on navigation', async({page, server}) => {
let attachedFrames = [];
let detachedFrames = [];
@ -96,6 +101,7 @@ it('should detach child frames on navigation', async({page, server}) => {
expect(detachedFrames.length).toBe(4);
expect(navigatedFrames.length).toBe(1);
});
it('should support framesets', async({page, server}) => {
let attachedFrames = [];
let detachedFrames = [];
@ -116,6 +122,7 @@ it('should support framesets', async({page, server}) => {
expect(detachedFrames.length).toBe(4);
expect(navigatedFrames.length).toBe(1);
});
it('should report frame from-inside shadow DOM', async({page, server}) => {
await page.goto(server.PREFIX + '/shadow.html');
await page.evaluate(async url => {
@ -127,6 +134,7 @@ it('should report frame from-inside shadow DOM', async({page, server}) => {
expect(page.frames().length).toBe(2);
expect(page.frames()[1].url()).toBe(server.EMPTY_PAGE);
});
it('should report frame.name()', async({page, server}) => {
await utils.attachFrame(page, 'theFrameId', server.EMPTY_PAGE);
await page.evaluate(url => {
@ -140,6 +148,7 @@ it('should report frame.name()', async({page, server}) => {
expect(page.frames()[1].name()).toBe('theFrameId');
expect(page.frames()[2].name()).toBe('theFrameName');
});
it('should report frame.parent()', async({page, server}) => {
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame2', server.EMPTY_PAGE);
@ -147,6 +156,7 @@ it('should report frame.parent()', async({page, server}) => {
expect(page.frames()[1].parentFrame()).toBe(page.mainFrame());
expect(page.frames()[2].parentFrame()).toBe(page.mainFrame());
});
it('should report different frame instance when frame re-attaches', async({page, server}) => {
const frame1 = await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
await page.evaluate(() => {
@ -161,6 +171,7 @@ it('should report different frame instance when frame re-attaches', async({page,
expect(frame2.isDetached()).toBe(false);
expect(frame1).not.toBe(frame2);
});
it.fail(FFOX)('should refuse to display x-frame-options:deny iframe', async({page, server}) => {
server.setRoute('/x-frame-options-deny.html', async (req, res) => {
res.setHeader('Content-Type', 'text/html');

View file

@ -29,6 +29,7 @@ it('should work', async({page, server, context}) => {
longitude: 10
});
});
it('should throw when invalid longitude', async({context}) => {
let error = null;
try {
@ -38,6 +39,7 @@ it('should throw when invalid longitude', async({context}) => {
}
expect(error.message).toContain('geolocation.longitude: precondition -180 <= LONGITUDE <= 180 failed.');
});
it('should isolate contexts', async({page, server, context, browser}) => {
await context.grantPermissions(['geolocation']);
await context.setGeolocation({longitude: 10, latitude: 10});
@ -68,6 +70,7 @@ it('should isolate contexts', async({page, server, context, browser}) => {
await context2.close();
});
it('should throw with missing latitude', async({context}) => {
let error = null;
try {
@ -77,6 +80,7 @@ it('should throw with missing latitude', async({context}) => {
}
expect(error.message).toContain('geolocation.latitude: expected number, got undefined');
});
it('should not modify passed default options object', async({browser}) => {
const geolocation = { longitude: 10, latitude: 10 };
const options = { geolocation };
@ -85,6 +89,7 @@ it('should not modify passed default options object', async({browser}) => {
expect(options.geolocation).toBe(geolocation);
await context.close();
});
it('should throw with missing longitude in default options', async({browser}) => {
let error = null;
try {
@ -95,6 +100,7 @@ it('should throw with missing longitude in default options', async({browser}) =>
}
expect(error.message).toContain('geolocation.longitude: expected number, got undefined');
});
it('should use context options', async({browser, server}) => {
const options = { geolocation: { longitude: 10, latitude: 10 }, permissions: ['geolocation'] };
const context = await browser.newContext(options);
@ -110,6 +116,7 @@ it('should use context options', async({browser, server}) => {
});
await context.close();
});
it('watchPosition should be notified', async({page, server, context}) => {
await context.grantPermissions(['geolocation']);
await page.goto(server.EMPTY_PAGE);
@ -135,6 +142,7 @@ it('watchPosition should be notified', async({page, server, context}) => {
expect(allMessages).toContain('lat=20 lng=30');
expect(allMessages).toContain('lat=40 lng=50');
});
it('should use context options for popup', async({page, context, server}) => {
await context.grantPermissions(['geolocation']);
await context.setGeolocation({ longitude: 10, latitude: 10 });

View file

@ -26,6 +26,7 @@ it('should have default url when launching browser', async ({browserType, defaul
await browserContext.close();
await removeUserDataDir(userDataDir);
});
it.fail(WIN && CHROMIUM).slow()('headless should be able to read cookies written by headful', async({browserType, defaultBrowserOptions, server}) => {
// see https://github.com/microsoft/playwright/issues/717
const userDataDir = await makeUserDataDir();
@ -45,6 +46,7 @@ it.fail(WIN && CHROMIUM).slow()('headless should be able to read cookies written
await removeUserDataDir(userDataDir);
expect(cookie).toBe('foo=true');
});
it.slow()('should close browser with beforeunload page', async({browserType, defaultBrowserOptions, server}) => {
const userDataDir = await makeUserDataDir();
const browserContext = await browserType.launchPersistentContext(userDataDir, {...defaultBrowserOptions, headless: false});
@ -56,6 +58,7 @@ it.slow()('should close browser with beforeunload page', async({browserType, def
await browserContext.close();
await removeUserDataDir(userDataDir);
});
it('should not crash when creating second context', async ({browserType, defaultBrowserOptions, server}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
{
@ -70,6 +73,7 @@ it('should not crash when creating second context', async ({browserType, default
}
await browser.close();
});
it('should click background tab', async({browserType, defaultBrowserOptions, server}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const page = await browser.newPage();
@ -78,6 +82,7 @@ it('should click background tab', async({browserType, defaultBrowserOptions, ser
await page.click('button');
await browser.close();
});
it('should close browser after context menu was triggered', async({browserType, defaultBrowserOptions, server}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const page = await browser.newPage();
@ -85,6 +90,7 @@ it('should close browser after context menu was triggered', async({browserType,
await page.click('body', {button: 'right'});
await browser.close();
});
it('should(not) block third party cookies', async({browserType, defaultBrowserOptions, server}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const page = await browser.newPage();
@ -124,6 +130,7 @@ it('should(not) block third party cookies', async({browserType, defaultBrowserOp
}
await browser.close();
});
it.fail(WEBKIT)('should not override viewport size when passed null', async function({browserType, defaultBrowserOptions, server}) {
// Our WebKit embedder does not respect window features.
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
@ -142,6 +149,7 @@ it.fail(WEBKIT)('should not override viewport size when passed null', async func
await context.close();
await browser.close();
});
it('Page.bringToFront should work', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const page1 = await browser.newPage();

View file

@ -26,6 +26,7 @@ it('should work', async({browser, httpsServer}) => {
expect(response.ok()).toBe(true);
await context.close();
});
it('should isolate contexts', async({browser, httpsServer}) => {
{
let error = null;
@ -45,6 +46,7 @@ it('should isolate contexts', async({browser, httpsServer}) => {
await context.close();
}
});
it('should work with mixed content', async({browser, server, httpsServer}) => {
httpsServer.setRoute('/mixedcontent.html', (req, res) => {
res.end(`<iframe src=${server.EMPTY_PAGE}></iframe>`);
@ -59,6 +61,7 @@ it('should work with mixed content', async({browser, server, httpsServer}) => {
expect(await page.frames()[1].evaluate('2 + 3')).toBe(5);
await context.close();
});
it('should work with WebSocket', async({browser, httpsServer}) => {
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
@ -73,6 +76,7 @@ it('should work with WebSocket', async({browser, httpsServer}) => {
expect(value).toBe('incoming');
await context.close();
});
it('should fail with WebSocket if not ignored', async({browser, httpsServer}) => {
const context = await browser.newContext();
const page = await context.newPage();

View file

@ -29,6 +29,7 @@ it('should type into a textarea', async ({page, server}) => {
await page.keyboard.type(text);
expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe(text);
});
it('should move with the arrow keys', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.type('textarea', 'Hello World!');
@ -44,6 +45,7 @@ it('should move with the arrow keys', async ({page, server}) => {
await page.keyboard.press('Backspace');
expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('Hello World!');
});
it('should send a character with ElementHandle.press', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
@ -55,6 +57,7 @@ it('should send a character with ElementHandle.press', async ({page, server}) =>
await textarea.press('b');
expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('a');
});
it('should send a character with sendCharacter', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.focus('textarea');
@ -64,6 +67,7 @@ it('should send a character with sendCharacter', async ({page, server}) => {
await page.keyboard.insertText('a');
expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('嗨a');
});
it('insertText should only emit input event', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.focus('textarea');
@ -79,6 +83,7 @@ it('insertText should only emit input event', async ({page, server}) => {
await page.keyboard.insertText('hello world');
expect(await events.jsonValue()).toEqual(['input']);
});
it.fail(FFOX && MAC)('should report shiftKey', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
const keyboard = page.keyboard;
@ -99,6 +104,7 @@ it.fail(FFOX && MAC)('should report shiftKey', async ({page, server}) => {
expect(await page.evaluate(() => getResult())).toBe('Keyup: ' + modifierKey + ' ' + modifierKey + 'Left ' + codeForKey[modifierKey] + ' []');
}
});
it('should report multiple modifiers', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
const keyboard = page.keyboard;
@ -115,6 +121,7 @@ it('should report multiple modifiers', async ({page, server}) => {
await keyboard.up('Alt');
expect(await page.evaluate(() => getResult())).toBe('Keyup: Alt AltLeft 18 []');
});
it('should send proper codes while typing', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.type('!');
@ -128,6 +135,7 @@ it('should send proper codes while typing', async ({page, server}) => {
'Keypress: ^ Digit6 94 94 []',
'Keyup: ^ Digit6 54 []'].join('\n'));
});
it('should send proper codes while typing with shift', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
const keyboard = page.keyboard;
@ -140,6 +148,7 @@ it('should send proper codes while typing with shift', async ({page, server}) =>
'Keyup: ~ Backquote 192 [Shift]'].join('\n'));
await keyboard.up('Shift');
});
it('should not type canceled events', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.focus('textarea');
@ -156,6 +165,7 @@ it('should not type canceled events', async ({page, server}) => {
await page.keyboard.type('Hello World!');
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('He Wrd!');
});
it('should press plus', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.press('+');
@ -164,6 +174,7 @@ it('should press plus', async ({page, server}) => {
'Keypress: + Equal 43 43 []', // 126 is ~ charCode
'Keyup: + Equal 187 []'].join('\n'));
});
it('should press shift plus', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.press('Shift++');
@ -174,6 +185,7 @@ it('should press shift plus', async ({page, server}) => {
'Keyup: + Equal 187 [Shift]',
'Keyup: Shift ShiftLeft 16 []'].join('\n'));
});
it('should support plus-separated modifiers', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.press('Shift+~');
@ -184,6 +196,7 @@ it('should support plus-separated modifiers', async ({page, server}) => {
'Keyup: ~ Backquote 192 [Shift]',
'Keyup: Shift ShiftLeft 16 []'].join('\n'));
});
it('should support multiple plus-separated modifiers', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.press('Control+Shift+~');
@ -195,6 +208,7 @@ it('should support multiple plus-separated modifiers', async ({page, server}) =>
'Keyup: Shift ShiftLeft 16 [Control]',
'Keyup: Control ControlLeft 17 []'].join('\n'));
});
it('should shift raw codes', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/keyboard.html');
await page.keyboard.press('Shift+Digit3');
@ -205,6 +219,7 @@ it('should shift raw codes', async ({page, server}) => {
'Keyup: # Digit3 51 [Shift]',
'Keyup: Shift ShiftLeft 16 []'].join('\n'));
});
it('should specify repeat property', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.focus('textarea');
@ -223,6 +238,7 @@ it('should specify repeat property', async ({page, server}) => {
await page.keyboard.down('a');
expect(await lastEvent.evaluate(e => e.repeat)).toBe(false);
});
it('should type all kinds of characters', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.focus('textarea');
@ -230,6 +246,7 @@ it('should type all kinds of characters', async ({page, server}) => {
await page.keyboard.type(text);
expect(await page.$eval('textarea', t => t.value)).toBe(text);
});
it('should specify location', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const lastEvent = await captureLastKeydown(page);
@ -247,6 +264,7 @@ it('should specify location', async ({page, server}) => {
await textarea.press('NumpadSubtract');
expect(await lastEvent.evaluate(e => e.location)).toBe(3);
});
it('should press Enter', async ({page, server}) => {
await page.setContent('<textarea></textarea>');
await page.focus('textarea');
@ -266,6 +284,7 @@ it('should press Enter', async ({page, server}) => {
await page.$eval('textarea', t => t.value = '');
}
});
it('should throw on unknown keys', async ({page, server}) => {
let error = await page.keyboard.press('NotARealKey').catch(e => e);
expect(error.message).toBe('Unknown key: "NotARealKey"');
@ -276,11 +295,13 @@ it('should throw on unknown keys', async ({page, server}) => {
error = await page.keyboard.press('😊').catch(e => e);
expect(error && error.message).toBe('Unknown key: "😊"');
});
it('should type emoji', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
await page.type('textarea', '👹 Tokyo street Japan 🇯🇵');
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('👹 Tokyo street Japan 🇯🇵');
});
it('should type emoji into an iframe', async ({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'emoji-test', server.PREFIX + '/input/textarea.html');
@ -289,6 +310,7 @@ it('should type emoji into an iframe', async ({page, server}) => {
await textarea.type('👹 Tokyo street Japan 🇯🇵');
expect(await frame.$eval('textarea', textarea => textarea.value)).toBe('👹 Tokyo street Japan 🇯🇵');
});
it('should handle selectAll', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
@ -300,6 +322,7 @@ it('should handle selectAll', async ({page, server}) => {
await page.keyboard.press('Backspace');
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('');
});
it('should be able to prevent selectAll', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
@ -317,6 +340,7 @@ it('should be able to prevent selectAll', async ({page, server}) => {
await page.keyboard.press('Backspace');
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some tex');
});
it.skip(!MAC)('should support MacOS shortcuts', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/textarea.html');
const textarea = await page.$('textarea');
@ -326,6 +350,7 @@ it.skip(!MAC)('should support MacOS shortcuts', async ({page, server}) => {
await page.keyboard.press('Backspace');
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some ');
});
it('should press the meta key', async ({page}) => {
const lastEvent = await captureLastKeydown(page);
await page.keyboard.press('Meta');
@ -346,6 +371,7 @@ it('should press the meta key', async ({page}) => {
expect(metaKey).toBe(true);
});
it('should work after a cross origin navigation', async ({page, server}) => {
await page.goto(server.PREFIX + '/empty.html');
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
@ -374,6 +400,7 @@ it.skip(!WEBKIT)('should expose keyIdentifier in webkit', async ({page, server})
expect(await lastEvent.evaluate(e => e.keyIdentifier)).toBe(keyIdentifier);
}
});
it('should scroll with PageDown', async ({page, server}) => {
await page.goto(server.PREFIX + '/input/scrollable.html');
// A click is required for WebKit to send the event into the body.

View file

@ -31,6 +31,7 @@ it('should log', async({browserType, defaultBrowserOptions}) => {
expect(log.filter(item => item.message.includes('browserType.launch started')).length > 0).toBeTruthy();
expect(log.filter(item => item.message.includes('browserType.launch succeeded')).length > 0).toBeTruthy();
});
it('should log context-level', async({browserType, defaultBrowserOptions}) => {
const log = [];
const browser = await browserType.launch(defaultBrowserOptions);

View file

@ -26,20 +26,24 @@ it('should evaluate before anything else on the page', async ({ page, server })
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window.result)).toBe(123);
});
it('should work with a path', async ({ page, server }) => {
await page.addInitScript({ path: path.join(__dirname, 'assets/injectedfile.js') });
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window.result)).toBe(123);
});
it('should work with content', async ({ page, server }) => {
await page.addInitScript({ content: 'window.injected = 123' });
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window.result)).toBe(123);
});
it('should throw without path and content', async ({ page, server }) => {
const error = await page.addInitScript({ foo: 'bar' }).catch(e => e);
expect(error.message).toContain('Either path or content property must be present');
});
it('should work with browser context scripts', async ({ browser, server }) => {
const context = await browser.newContext();
await context.addInitScript(() => window.temp = 123);
@ -49,6 +53,7 @@ it('should work with browser context scripts', async ({ browser, server }) => {
expect(await page.evaluate(() => window.result)).toBe(123);
await context.close();
});
it('should work with browser context scripts with a path', async ({ browser, server }) => {
const context = await browser.newContext();
await context.addInitScript({ path: path.join(__dirname, 'assets/injectedfile.js') });
@ -57,6 +62,7 @@ it('should work with browser context scripts with a path', async ({ browser, ser
expect(await page.evaluate(() => window.result)).toBe(123);
await context.close();
});
it('should work with browser context scripts for already created pages', async ({ browser, server }) => {
const context = await browser.newContext();
const page = await context.newPage();
@ -66,6 +72,7 @@ it('should work with browser context scripts for already created pages', async (
expect(await page.evaluate(() => window.result)).toBe(123);
await context.close();
});
it('should support multiple scripts', async ({ page, server }) => {
await page.addInitScript(function () {
window.script1 = 1;
@ -77,6 +84,7 @@ it('should support multiple scripts', async ({ page, server }) => {
expect(await page.evaluate(() => window.script1)).toBe(1);
expect(await page.evaluate(() => window.script2)).toBe(2);
});
it('should work with CSP', async ({ page, server }) => {
server.setCSP('/empty.html', 'script-src ' + server.PREFIX);
await page.addInitScript(function () {
@ -89,6 +97,7 @@ it('should work with CSP', async ({ page, server }) => {
await page.addScriptTag({ content: 'window.e = 10;' }).catch(e => void e);
expect(await page.evaluate(() => window.e)).toBe(undefined);
});
it('should work after a cross origin navigation', async ({ page, server }) => {
await page.goto(server.CROSS_PROCESS_PREFIX);
await page.addInitScript(function () {

View file

@ -29,6 +29,7 @@ it('Page.workers', async function({page, server}) {
await page.goto(server.EMPTY_PAGE);
expect(page.workers().length).toBe(0);
});
it('should emit created and destroyed events', async function({page}) {
const workerCreatedPromise = page.waitForEvent('worker');
const workerObj = await page.evaluateHandle(() => new Worker(URL.createObjectURL(new Blob(['1'], {type: 'application/javascript'}))));
@ -40,6 +41,7 @@ it('should emit created and destroyed events', async function({page}) {
const error = await workerThisObj.getProperty('self').catch(error => error);
expect(error.message).toContain('Most likely the worker has been closed.');
});
it('should report console logs', async function({page}) {
const [message] = await Promise.all([
page.waitForEvent('console'),
@ -47,6 +49,7 @@ it('should report console logs', async function({page}) {
]);
expect(message.text()).toBe('1');
});
it('should have JSHandles for console logs', async function({page}) {
const logPromise = new Promise(x => page.on('console', x));
await page.evaluate(() => new Worker(URL.createObjectURL(new Blob(['console.log(1,2,3,this)'], {type: 'application/javascript'}))));
@ -55,12 +58,14 @@ it('should have JSHandles for console logs', async function({page}) {
expect(log.args().length).toBe(4);
expect(await (await log.args()[3].getProperty('origin')).jsonValue()).toBe('null');
});
it('should evaluate', async function({page}) {
const workerCreatedPromise = page.waitForEvent('worker');
await page.evaluate(() => new Worker(URL.createObjectURL(new Blob(['console.log(1)'], {type: 'application/javascript'}))));
const worker = await workerCreatedPromise;
expect(await worker.evaluate('1+1')).toBe(2);
});
it('should report errors', async function({page}) {
const errorPromise = new Promise(x => page.on('pageerror', x));
await page.evaluate(() => new Worker(URL.createObjectURL(new Blob([`
@ -73,6 +78,7 @@ it('should report errors', async function({page}) {
const errorLog = await errorPromise;
expect(errorLog.message).toContain('this is my error');
});
it('should clear upon navigation', async function({server, page}) {
await page.goto(server.EMPTY_PAGE);
const workerCreatedPromise = page.waitForEvent('worker');
@ -85,6 +91,7 @@ it('should clear upon navigation', async function({server, page}) {
expect(destroyed).toBe(true);
expect(page.workers().length).toBe(0);
});
it('should clear upon cross-process navigation', async function({server, page}) {
await page.goto(server.EMPTY_PAGE);
const workerCreatedPromise = page.waitForEvent('worker');
@ -97,6 +104,7 @@ it('should clear upon cross-process navigation', async function({server, page})
expect(destroyed).toBe(true);
expect(page.workers().length).toBe(0);
});
it('should report network activity', async function({page, server}) {
const [worker] = await Promise.all([
page.waitForEvent('worker'),
@ -112,6 +120,7 @@ it('should report network activity', async function({page, server}) {
expect(response.request()).toBe(request);
expect(response.ok()).toBe(true);
});
it('should report network activity on worker creation', async function({page, server}) {
// Chromium needs waitForDebugger enabled for this one.
await page.goto(server.EMPTY_PAGE);
@ -127,6 +136,7 @@ it('should report network activity on worker creation', async function({page, se
expect(response.request()).toBe(request);
expect(response.ok()).toBe(true);
});
it('should format number using context locale', async({browser, server}) => {
const context = await browser.newContext({ locale: 'ru-RU' });
const page = await context.newPage();