chore: add test configuration options for running tests against multiple products (#5964)

* chore: remove "Extracting..." log message

Fixes #5741.

* test: support extra Launcher options and skips

The extra Launcher options and skipping conditions enable
unit tests to be run more easily by third-parties, e.g.
browser vendors that are interested in Puppeteer support.

Extra Launcher options were previously removed as part of
switching away from the custom test harness.

* test: enable more tests for Firefox
This commit is contained in:
Maja Frydrychowicz 2020-06-12 09:55:51 -04:00 committed by Mathias Bynens
parent 5c91dfbf3f
commit 3d56a9e76f
20 changed files with 337 additions and 370 deletions

View File

@ -429,9 +429,6 @@ function extractTar(tarPath: string, folderPath: string): Promise<unknown> {
tarStream.on('error', reject);
tarStream.on('finish', fulfill);
const readStream = fs.createReadStream(tarPath);
readStream.on('data', () => {
process.stdout.write('\rExtracting...');
});
readStream.pipe(bzip()).pipe(tarStream);
});
}

View File

@ -24,11 +24,14 @@ If your test needs a Puppeteer page and context, you can use the `setupTestPageA
The best place to look is an existing test to see how they use the helpers.
## Skipping tests for Firefox
## Skipping tests in specific conditions
Tests that are not expected to pass in Firefox can be skipped. You can skip an individual test by using `itFailsFirefox` rather than `it`. Similarly you can skip a describe block with `describeFailsFirefox`.
There is also `describeChromeOnly` which will only execute the test if running in Chromium. Note that this is different from `describeFailsFirefox`: the goal is to get any `FailsFirefox` calls passing in Firefox, whereas `describeChromeOnly` should be used to test behaviour that will only ever apply in Chromium.
There is also `describeChromeOnly` and `itChromeOnly` which will only execute the test if running in Chromium. Note that this is different from `describeFailsFirefox`: the goal is to get any `FailsFirefox` calls passing in Firefox, whereas `describeChromeOnly` should be used to test behaviour that will only ever apply in Chromium.
There are also tests that assume a normal install flow, with browser binaries ending up in `.local-<browser>`, for example. Such tests are skipped with
`itOnlyRegularInstall` which checks `BINARY` and `PUPPETEER_ALT_INSTALL` environment variables.
[Mocha]: https://mochajs.org/
[Expect]: https://www.npmjs.com/package/expect

View File

@ -20,7 +20,7 @@ const utils = require('./utils');
describe('BrowserContext', function () {
setupTestBrowserHooks();
itFailsFirefox('should have default context', async () => {
it('should have default context', async () => {
const { browser } = getTestState();
expect(browser.browserContexts().length).toEqual(1);
const defaultContext = browser.browserContexts()[0];
@ -30,7 +30,7 @@ describe('BrowserContext', function () {
expect(browser.defaultBrowserContext()).toBe(defaultContext);
expect(error.message).toContain('cannot be closed');
});
itFailsFirefox('should create new incognito context', async () => {
it('should create new incognito context', async () => {
const { browser } = getTestState();
expect(browser.browserContexts().length).toBe(1);
@ -41,22 +41,19 @@ describe('BrowserContext', function () {
await context.close();
expect(browser.browserContexts().length).toBe(1);
});
itFailsFirefox(
'should close all belonging targets once closing context',
async () => {
const { browser } = getTestState();
it('should close all belonging targets once closing context', async () => {
const { browser } = getTestState();
expect((await browser.pages()).length).toBe(1);
expect((await browser.pages()).length).toBe(1);
const context = await browser.createIncognitoBrowserContext();
await context.newPage();
expect((await browser.pages()).length).toBe(2);
expect((await context.pages()).length).toBe(1);
const context = await browser.createIncognitoBrowserContext();
await context.newPage();
expect((await browser.pages()).length).toBe(2);
expect((await context.pages()).length).toBe(1);
await context.close();
expect((await browser.pages()).length).toBe(1);
}
);
await context.close();
expect((await browser.pages()).length).toBe(1);
});
itFailsFirefox('window.open should use parent tab context', async () => {
const { browser, server } = getTestState();

View File

@ -32,7 +32,7 @@ describe('Page.click', function () {
await page.click('button');
expect(await page.evaluate(() => result)).toBe('Clicked');
});
itFailsFirefox('should click svg', async () => {
it('should click svg', async () => {
const { page } = getTestState();
await page.setContent(`
@ -55,12 +55,10 @@ describe('Page.click', function () {
}
);
// @see https://github.com/puppeteer/puppeteer/issues/4281
itFailsFirefox(
'should click on a span with an inline element inside',
async () => {
const { page } = getTestState();
it('should click on a span with an inline element inside', async () => {
const { page } = getTestState();
await page.setContent(`
await page.setContent(`
<style>
span::before {
content: 'q';
@ -68,10 +66,9 @@ describe('Page.click', function () {
</style>
<span onclick='javascript:window.CLICKED=42'></span>
`);
await page.click('span');
expect(await page.evaluate(() => window.CLICKED)).toBe(42);
}
);
await page.click('span');
expect(await page.evaluate(() => window.CLICKED)).toBe(42);
});
it('should not throw UnhandledPromiseRejection when page closes', async () => {
const { page } = getTestState();
@ -98,12 +95,10 @@ describe('Page.click', function () {
await Promise.all([page.click('a'), page.waitForNavigation()]);
expect(page.url()).toBe(server.PREFIX + '/wrappedlink.html#clicked');
});
itFailsFirefox(
'should click when one of inline box children is outside of viewport',
async () => {
const { page } = getTestState();
it('should click when one of inline box children is outside of viewport', async () => {
const { page } = getTestState();
await page.setContent(`
await page.setContent(`
<style>
i {
position: absolute;
@ -112,10 +107,9 @@ describe('Page.click', function () {
</style>
<span onclick='javascript:window.CLICKED = 42;'><i>woof</i><b>doggo</b></span>
`);
await page.click('span');
expect(await page.evaluate(() => window.CLICKED)).toBe(42);
}
);
await page.click('span');
expect(await page.evaluate(() => window.CLICKED)).toBe(42);
});
it('should select the text by triple clicking', async () => {
const { page, server } = getTestState();
@ -244,7 +238,7 @@ describe('Page.click', function () {
)
).toBe('clicked');
});
itFailsFirefox('should double click the button', async () => {
it('should double click the button', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/button.html');
@ -290,7 +284,7 @@ describe('Page.click', function () {
).toBe('context menu');
});
// @see https://github.com/puppeteer/puppeteer/issues/206
itFailsFirefox('should click links which cause navigation', async () => {
it('should click links which cause navigation', async () => {
const { page, server } = getTestState();
await page.setContent(`<a href="${server.EMPTY_PAGE}">empty.html</a>`);

View File

@ -220,21 +220,18 @@ describe('Cookie specs', () => {
})
).toEqual(['foo=bar', 'password=123456']);
});
itFailsFirefox(
'should have |expires| set to |-1| for session cookies',
async () => {
const { page, server } = getTestState();
it('should have |expires| set to |-1| for session cookies', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
await page.setCookie({
name: 'password',
value: '123456',
});
const cookies = await page.cookies();
expect(cookies[0].session).toBe(true);
expect(cookies[0].expires).toBe(-1);
}
);
await page.goto(server.EMPTY_PAGE);
await page.setCookie({
name: 'password',
value: '123456',
});
const cookies = await page.cookies();
expect(cookies[0].session).toBe(true);
expect(cookies[0].expires).toBe(-1);
});
itFailsFirefox('should set cookie with reasonable defaults', async () => {
const { page, server } = getTestState();
@ -348,22 +345,19 @@ describe('Cookie specs', () => {
expect(cookie.secure).toBe(true);
}
);
itFailsFirefox(
'should be able to set unsecure cookie for HTTP website',
async () => {
const { page, server } = getTestState();
it('should be able to set unsecure cookie for HTTP website', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
const HTTP_URL = 'http://example.com';
await page.setCookie({
url: HTTP_URL,
name: 'foo',
value: 'bar',
});
const [cookie] = await page.cookies(HTTP_URL);
expect(cookie.secure).toBe(false);
}
);
await page.goto(server.EMPTY_PAGE);
const HTTP_URL = 'http://example.com';
await page.setCookie({
url: HTTP_URL,
name: 'foo',
value: 'bar',
});
const [cookie] = await page.cookies(HTTP_URL);
expect(cookie.secure).toBe(false);
});
itFailsFirefox('should set a cookie on a different domain', async () => {
const { page, server } = getTestState();

View File

@ -233,7 +233,7 @@ describe('ElementHandle specs', function () {
'Node is either not visible or not an HTMLElement'
);
});
itFailsFirefox('should throw for <br> elements', async () => {
it('should throw for <br> elements', async () => {
const { page } = getTestState();
await page.setContent('hello<br>goodbye');

View File

@ -127,7 +127,7 @@ describe('Emulation', () => {
'iPhone'
);
});
it('should support clicking', async () => {
itFailsFirefox('should support clicking', async () => {
const { page, server } = getTestState();
await page.emulate(iPhone);

View File

@ -35,31 +35,31 @@ describe('Evaluation specs', function () {
const result = await page.evaluate(() => 7 * 3);
expect(result).toBe(21);
});
(bigint ? itFailsFirefox : xit)('should transfer BigInt', async () => {
(bigint ? it : xit)('should transfer BigInt', async () => {
const { page } = getTestState();
const result = await page.evaluate((a) => a, BigInt(42));
expect(result).toBe(BigInt(42));
});
itFailsFirefox('should transfer NaN', async () => {
it('should transfer NaN', async () => {
const { page } = getTestState();
const result = await page.evaluate((a) => a, NaN);
expect(Object.is(result, NaN)).toBe(true);
});
itFailsFirefox('should transfer -0', async () => {
it('should transfer -0', async () => {
const { page } = getTestState();
const result = await page.evaluate((a) => a, -0);
expect(Object.is(result, -0)).toBe(true);
});
itFailsFirefox('should transfer Infinity', async () => {
it('should transfer Infinity', async () => {
const { page } = getTestState();
const result = await page.evaluate((a) => a, Infinity);
expect(Object.is(result, Infinity)).toBe(true);
});
itFailsFirefox('should transfer -Infinity', async () => {
it('should transfer -Infinity', async () => {
const { page } = getTestState();
const result = await page.evaluate((a) => a, -Infinity);
@ -202,31 +202,31 @@ describe('Evaluation specs', function () {
expect(result).not.toBe(object);
expect(result).toEqual(object);
});
(bigint ? itFailsFirefox : xit)('should return BigInt', async () => {
(bigint ? it : xit)('should return BigInt', async () => {
const { page } = getTestState();
const result = await page.evaluate(() => BigInt(42));
expect(result).toBe(BigInt(42));
});
itFailsFirefox('should return NaN', async () => {
it('should return NaN', async () => {
const { page } = getTestState();
const result = await page.evaluate(() => NaN);
expect(Object.is(result, NaN)).toBe(true);
});
itFailsFirefox('should return -0', async () => {
it('should return -0', async () => {
const { page } = getTestState();
const result = await page.evaluate(() => -0);
expect(Object.is(result, -0)).toBe(true);
});
itFailsFirefox('should return Infinity', async () => {
it('should return Infinity', async () => {
const { page } = getTestState();
const result = await page.evaluate(() => Infinity);
expect(Object.is(result, Infinity)).toBe(true);
});
itFailsFirefox('should return -Infinity', async () => {
it('should return -Infinity', async () => {
const { page } = getTestState();
const result = await page.evaluate(() => -Infinity);
@ -298,7 +298,7 @@ describe('Evaluation specs', function () {
const result = await page.evaluate('2 + 5;\n// do some math!');
expect(result).toBe(7);
});
itFailsFirefox('should accept element handle as an argument', async () => {
it('should accept element handle as an argument', async () => {
const { page } = getTestState();
await page.setContent('<section>42</section>');
@ -306,22 +306,19 @@ describe('Evaluation specs', function () {
const text = await page.evaluate((e) => e.textContent, element);
expect(text).toBe('42');
});
itFailsFirefox(
'should throw if underlying element was disposed',
async () => {
const { page } = getTestState();
it('should throw if underlying element was disposed', async () => {
const { page } = getTestState();
await page.setContent('<section>39</section>');
const element = await page.$('section');
expect(element).toBeTruthy();
await element.dispose();
let error = null;
await page
.evaluate((e) => e.textContent, element)
.catch((error_) => (error = error_));
expect(error.message).toContain('JSHandle is disposed');
}
);
await page.setContent('<section>39</section>');
const element = await page.$('section');
expect(element).toBeTruthy();
await element.dispose();
let error = null;
await page
.evaluate((e) => e.textContent, element)
.catch((error_) => (error = error_));
expect(error.message).toContain('JSHandle is disposed');
});
itFailsFirefox(
'should throw if elementHandles are from other frames',
async () => {
@ -376,17 +373,14 @@ describe('Evaluation specs', function () {
expect(result).toEqual([42]);
}
);
itFailsFirefox(
'should transfer 100Mb of data from page to node.js',
async function () {
const { page } = getTestState();
it('should transfer 100Mb of data from page to node.js', async function () {
const { page } = getTestState();
const a = await page.evaluate(() =>
Array(100 * 1024 * 1024 + 1).join('a')
);
expect(a.length).toBe(100 * 1024 * 1024);
}
);
const a = await page.evaluate(() =>
Array(100 * 1024 * 1024 + 1).join('a')
);
expect(a.length).toBe(100 * 1024 * 1024);
});
it('should throw error with detailed information on exception inside promise ', async () => {
const { page } = getTestState();

View File

@ -20,7 +20,7 @@ const { getTestState } = require('./mocha-utils');
const path = require('path');
describe('Fixtures', function () {
itFailsFirefox('dumpio option should work with pipe option ', async () => {
itChromeOnly('dumpio option should work with pipe option ', async () => {
const { defaultBrowserOptions, puppeteerPath } = getTestState();
let dumpioData = '';

View File

@ -17,7 +17,7 @@
const expect = require('expect');
const { getTestState } = require('./mocha-utils');
describeFailsFirefox('ignoreHTTPSErrors', function () {
describe('ignoreHTTPSErrors', function () {
/* Note that this test creates its own browser rather than use
* the one provided by the test set-up as we need one
* with ignoreHTTPSErrors set to true
@ -51,7 +51,7 @@ describeFailsFirefox('ignoreHTTPSErrors', function () {
page = null;
});
describe('Response.securityDetails', function () {
describeFailsFirefox('Response.securityDetails', function () {
it('should work', async () => {
const { httpsServer } = getTestState();
@ -105,7 +105,7 @@ describeFailsFirefox('ignoreHTTPSErrors', function () {
expect(error).toBe(null);
expect(response.ok()).toBe(true);
});
it('should work with request interception', async () => {
itFailsFirefox('should work with request interception', async () => {
const { httpsServer } = getTestState();
await page.setRequestInterception(true);
@ -113,7 +113,7 @@ describeFailsFirefox('ignoreHTTPSErrors', function () {
const response = await page.goto(httpsServer.EMPTY_PAGE);
expect(response.status()).toBe(200);
});
it('should work with mixed content', async () => {
itFailsFirefox('should work with mixed content', async () => {
const { server, httpsServer } = getTestState();
httpsServer.setRoute('/mixedcontent.html', (req, res) => {

View File

@ -179,7 +179,7 @@ describe('JSHandle', function () {
const element = aHandle.asElement();
expect(element).toBeFalsy();
});
itFailsFirefox('should return ElementHandle for TextNodes', async () => {
it('should return ElementHandle for TextNodes', async () => {
const { page } = getTestState();
await page.setContent('<div>ee!</div>');
@ -195,7 +195,7 @@ describe('JSHandle', function () {
)
);
});
itFailsFirefox('should work with nullified Node', async () => {
it('should work with nullified Node', async () => {
const { page } = getTestState();
await page.setContent('<section>test</section>');

View File

@ -125,7 +125,7 @@ describe('Keyboard', function () {
await page.evaluate(() => document.querySelector('textarea').value)
).toBe('嗨a');
});
itFailsFirefox('should report shiftKey', async () => {
it('should report shiftKey', async () => {
const { page, server } = getTestState();
await page.goto(server.PREFIX + '/input/keyboard.html');

View File

@ -28,6 +28,8 @@ const expect = require('expect');
const { getTestState } = require('./mocha-utils');
describe('Launcher specs', function () {
if (getTestState().isFirefox) this.timeout(30 * 1000);
describe('Puppeteer', function () {
describe('BrowserFetcher', function () {
it('should download and extract chrome linux binary', async () => {
@ -327,7 +329,7 @@ describe('Launcher specs', function () {
if (isChrome) expect(puppeteer.product).toBe('chrome');
else if (isFirefox) expect(puppeteer.product).toBe('firefox');
});
itFailsFirefox('should work with no default arguments', async () => {
it('should work with no default arguments', async () => {
const { defaultBrowserOptions, puppeteer } = getTestState();
const options = Object.assign({}, defaultBrowserOptions);
options.ignoreDefaultArgs = true;
@ -337,25 +339,22 @@ describe('Launcher specs', function () {
await page.close();
await browser.close();
});
itFailsFirefox(
'should filter out ignored default arguments',
async () => {
const { defaultBrowserOptions, puppeteer } = getTestState();
// Make sure we launch with `--enable-automation` by default.
const defaultArgs = puppeteer.defaultArgs();
const browser = await puppeteer.launch(
Object.assign({}, defaultBrowserOptions, {
// Ignore first and third default argument.
ignoreDefaultArgs: [defaultArgs[0], defaultArgs[2]],
})
);
const spawnargs = browser.process().spawnargs;
expect(spawnargs.indexOf(defaultArgs[0])).toBe(-1);
expect(spawnargs.indexOf(defaultArgs[1])).not.toBe(-1);
expect(spawnargs.indexOf(defaultArgs[2])).toBe(-1);
await browser.close();
}
);
it('should filter out ignored default arguments', async () => {
const { defaultBrowserOptions, puppeteer } = getTestState();
// Make sure we launch with `--enable-automation` by default.
const defaultArgs = puppeteer.defaultArgs();
const browser = await puppeteer.launch(
Object.assign({}, defaultBrowserOptions, {
// Ignore first and third default argument.
ignoreDefaultArgs: [defaultArgs[0], defaultArgs[2]],
})
);
const spawnargs = browser.process().spawnargs;
expect(spawnargs.indexOf(defaultArgs[0])).toBe(-1);
expect(spawnargs.indexOf(defaultArgs[1])).not.toBe(-1);
expect(spawnargs.indexOf(defaultArgs[2])).toBe(-1);
await browser.close();
});
it('should have default URL when launching browser', async function () {
const { defaultBrowserOptions, puppeteer } = getTestState();
const browser = await puppeteer.launch(defaultBrowserOptions);
@ -403,24 +402,21 @@ describe('Launcher specs', function () {
expect(page.viewport()).toBe(null);
await browser.close();
});
itFailsFirefox(
'should take fullPage screenshots when defaultViewport is null',
async () => {
const { server, puppeteer, defaultBrowserOptions } = getTestState();
it('should take fullPage screenshots when defaultViewport is null', async () => {
const { server, puppeteer, defaultBrowserOptions } = getTestState();
const options = Object.assign({}, defaultBrowserOptions, {
defaultViewport: null,
});
const browser = await puppeteer.launch(options);
const page = await browser.newPage();
await page.goto(server.PREFIX + '/grid.html');
const screenshot = await page.screenshot({
fullPage: true,
});
expect(screenshot).toBeInstanceOf(Buffer);
await browser.close();
}
);
const options = Object.assign({}, defaultBrowserOptions, {
defaultViewport: null,
});
const browser = await puppeteer.launch(options);
const page = await browser.newPage();
await page.goto(server.PREFIX + '/grid.html');
const screenshot = await page.screenshot({
fullPage: true,
});
expect(screenshot).toBeInstanceOf(Buffer);
await browser.close();
});
});
describe('Puppeteer.launch', function () {
@ -437,7 +433,7 @@ describe('Launcher specs', function () {
puppeteer._productName = productName;
});
it('should be able to launch Chrome', async () => {
itOnlyRegularInstall('should be able to launch Chrome', async () => {
const { puppeteer } = getTestState();
const browser = await puppeteer.launch({ product: 'chrome' });
const userAgent = await browser.userAgent();
@ -507,7 +503,7 @@ describe('Launcher specs', function () {
remoteBrowser.close(),
]);
});
itFailsFirefox('should support ignoreHTTPSErrors option', async () => {
it('should support ignoreHTTPSErrors option', async () => {
const {
httpsServer,
puppeteer,
@ -586,7 +582,7 @@ describe('Launcher specs', function () {
);
});
describe('Puppeteer.executablePath', function () {
itFailsFirefox('should work', async () => {
itOnlyRegularInstall('should work', async () => {
const { puppeteer } = getTestState();
const executablePath = puppeteer.executablePath();

View File

@ -53,17 +53,32 @@ exports.getTestState = () => state;
const product =
process.env.PRODUCT || process.env.PUPPETEER_PRODUCT || 'Chromium';
const alternativeInstall = process.env.PUPPETEER_ALT_INSTALL || false;
const isHeadless =
(process.env.HEADLESS || 'true').trim().toLowerCase() === 'true';
const isFirefox = product === 'firefox';
const isChrome = product === 'Chromium';
const defaultBrowserOptions = {
handleSIGINT: false,
executablePath: process.env.BINARY,
slowMo: false,
headless: isHeadless,
dumpio: !!process.env.DUMPIO,
};
let extraLaunchOptions = {};
try {
extraLaunchOptions = JSON.parse(process.env.EXTRA_LAUNCH_OPTIONS || '{}');
} catch (error) {
console.warn(
`Error parsing EXTRA_LAUNCH_OPTIONS: ${error.message}. Skipping.`
);
}
const defaultBrowserOptions = Object.assign(
{
handleSIGINT: false,
executablePath: process.env.BINARY,
slowMo: false,
headless: isHeadless,
dumpio: !!process.env.DUMPIO,
},
extraLaunchOptions
);
(async () => {
if (defaultBrowserOptions.executablePath) {
@ -97,6 +112,16 @@ global.itFailsFirefox = (...args) => {
else return it(...args);
};
global.itChromeOnly = (...args) => {
if (isChrome) return it(...args);
else return xit(...args);
};
global.itOnlyRegularInstall = (...args) => {
if (alternativeInstall || process.env.BINARY) return xit(...args);
else return it(...args);
};
global.itFailsWindowsUntilDate = (date, ...args) => {
if (os.platform() === 'win32' && Date.now() < date) {
// we are within the deferred time so skip the test
@ -120,7 +145,10 @@ if (process.env.COVERAGE) trackCoverage();
console.log(
`Running unit tests with:
-> product: ${product}
-> binary: ${path.relative(process.cwd(), puppeteer.executablePath())}`
-> binary: ${
defaultBrowserOptions.executablePath ||
path.relative(process.cwd(), puppeteer.executablePath())
}`
);
exports.setupTestBrowserHooks = () => {

View File

@ -57,15 +57,12 @@ describe('navigation', function () {
const response = await page.goto('about:blank');
expect(response).toBe(null);
});
itFailsFirefox(
'should return response when page changes its URL after load',
async () => {
const { page, server } = getTestState();
it('should return response when page changes its URL after load', async () => {
const { page, server } = getTestState();
const response = await page.goto(server.PREFIX + '/historyapi.html');
expect(response.status()).toBe(200);
}
);
const response = await page.goto(server.PREFIX + '/historyapi.html');
expect(response.status()).toBe(200);
});
it('should work with subframes return 204', async () => {
const { page, server } = getTestState();
@ -88,34 +85,28 @@ describe('navigation', function () {
if (isChrome) expect(error.message).toContain('net::ERR_ABORTED');
else expect(error.message).toContain('NS_BINDING_ABORTED');
});
itFailsFirefox(
'should navigate to empty page with domcontentloaded',
async () => {
const { page, server } = getTestState();
it('should navigate to empty page with domcontentloaded', async () => {
const { page, server } = getTestState();
const response = await page.goto(server.EMPTY_PAGE, {
waitUntil: 'domcontentloaded',
});
expect(response.status()).toBe(200);
}
);
itFailsFirefox(
'should work when page calls history API in beforeunload',
async () => {
const { page, server } = getTestState();
const response = await page.goto(server.EMPTY_PAGE, {
waitUntil: 'domcontentloaded',
});
expect(response.status()).toBe(200);
});
it('should work when page calls history API in beforeunload', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => {
window.addEventListener(
'beforeunload',
() => history.replaceState(null, 'initial', window.location.href),
false
);
});
const response = await page.goto(server.PREFIX + '/grid.html');
expect(response.status()).toBe(200);
}
);
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => {
window.addEventListener(
'beforeunload',
() => history.replaceState(null, 'initial', window.location.href),
false
);
});
const response = await page.goto(server.PREFIX + '/grid.html');
expect(response.status()).toBe(200);
});
itFailsFirefox(
'should navigate to empty page with networkidle0',
async () => {
@ -179,22 +170,18 @@ describe('navigation', function () {
expect(requests[0]).toBe('request');
expect(requests[1]).toBe('requestfailed');
});
itFailsFirefox(
'should fail when navigating to bad SSL after redirects',
async () => {
const { page, server, httpsServer, isChrome } = getTestState();
it('should fail when navigating to bad SSL after redirects', async () => {
const { page, server, httpsServer, isChrome } = getTestState();
server.setRedirect('/redirect/1.html', '/redirect/2.html');
server.setRedirect('/redirect/2.html', '/empty.html');
let error = null;
await page
.goto(httpsServer.PREFIX + '/redirect/1.html')
.catch((error_) => (error = error_));
if (isChrome)
expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE);
else expect(error.message).toContain('SSL_ERROR_UNKNOWN');
}
);
server.setRedirect('/redirect/1.html', '/redirect/2.html');
server.setRedirect('/redirect/2.html', '/empty.html');
let error = null;
await page
.goto(httpsServer.PREFIX + '/redirect/1.html')
.catch((error_) => (error = error_));
if (isChrome) expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE);
else expect(error.message).toContain('SSL_ERROR_UNKNOWN');
});
it('should throw if networkidle is passed as an option', async () => {
const { page, server } = getTestState();
@ -206,20 +193,17 @@ describe('navigation', function () {
'"networkidle" option is no longer supported'
);
});
itFailsFirefox(
'should fail when main resources failed to load',
async () => {
const { page, isChrome } = getTestState();
it('should fail when main resources failed to load', async () => {
const { page, isChrome } = getTestState();
let error = null;
await page
.goto('http://localhost:44123/non-existing-url')
.catch((error_) => (error = error_));
if (isChrome)
expect(error.message).toContain('net::ERR_CONNECTION_REFUSED');
else expect(error.message).toContain('NS_ERROR_CONNECTION_REFUSED');
}
);
let error = null;
await page
.goto('http://localhost:44123/non-existing-url')
.catch((error_) => (error = error_));
if (isChrome)
expect(error.message).toContain('net::ERR_CONNECTION_REFUSED');
else expect(error.message).toContain('NS_ERROR_CONNECTION_REFUSED');
});
it('should fail when exceeding maximum navigation timeout', async () => {
const { page, server, puppeteer } = getTestState();
@ -284,7 +268,7 @@ describe('navigation', function () {
expect(error).toBe(null);
expect(loaded).toBe(true);
});
itFailsFirefox('should work when navigating to valid url', async () => {
it('should work when navigating to valid url', async () => {
const { page, server } = getTestState();
const response = await page.goto(server.EMPTY_PAGE);
@ -296,26 +280,23 @@ describe('navigation', function () {
const response = await page.goto('data:text/html,hello');
expect(response.ok()).toBe(true);
});
itFailsFirefox('should work when navigating to 404', async () => {
it('should work when navigating to 404', async () => {
const { page, server } = getTestState();
const response = await page.goto(server.PREFIX + '/not-found');
expect(response.ok()).toBe(false);
expect(response.status()).toBe(404);
});
itFailsFirefox(
'should return last response in redirect chain',
async () => {
const { page, server } = getTestState();
it('should return last response in redirect chain', async () => {
const { page, server } = getTestState();
server.setRedirect('/redirect/1.html', '/redirect/2.html');
server.setRedirect('/redirect/2.html', '/redirect/3.html');
server.setRedirect('/redirect/3.html', server.EMPTY_PAGE);
const response = await page.goto(server.PREFIX + '/redirect/1.html');
expect(response.ok()).toBe(true);
expect(response.url()).toBe(server.EMPTY_PAGE);
}
);
server.setRedirect('/redirect/1.html', '/redirect/2.html');
server.setRedirect('/redirect/2.html', '/redirect/3.html');
server.setRedirect('/redirect/3.html', server.EMPTY_PAGE);
const response = await page.goto(server.PREFIX + '/redirect/1.html');
expect(response.ok()).toBe(true);
expect(response.url()).toBe(server.EMPTY_PAGE);
});
itFailsFirefox(
'should wait for network idle to succeed navigation',
async () => {
@ -401,22 +382,19 @@ describe('navigation', function () {
process.removeListener('warning', warningHandler);
expect(warning).toBe(null);
});
itFailsFirefox(
'should not leak listeners during bad navigation',
async () => {
const { page } = getTestState();
it('should not leak listeners during bad navigation', async () => {
const { page } = getTestState();
let warning = null;
const warningHandler = (w) => (warning = w);
process.on('warning', warningHandler);
for (let i = 0; i < 20; ++i)
await page.goto('asdf').catch((error) => {
/* swallow navigation error */
});
process.removeListener('warning', warningHandler);
expect(warning).toBe(null);
}
);
let warning = null;
const warningHandler = (w) => (warning = w);
process.on('warning', warningHandler);
for (let i = 0; i < 20; ++i)
await page.goto('asdf').catch((error) => {
/* swallow navigation error */
});
process.removeListener('warning', warningHandler);
expect(warning).toBe(null);
});
it('should not leak listeners during navigation of 11 pages', async () => {
const { context, server } = getTestState();
@ -467,28 +445,25 @@ describe('navigation', function () {
expect(requests[0].url()).toBe(server.EMPTY_PAGE);
}
);
itFailsFirefox('should work with self requesting page', async () => {
it('should work with self requesting page', async () => {
const { page, server } = getTestState();
const response = await page.goto(server.PREFIX + '/self-request.html');
expect(response.status()).toBe(200);
expect(response.url()).toContain('self-request.html');
});
itFailsFirefox(
'should fail when navigating and show the url at the error message',
async () => {
const { page, httpsServer } = getTestState();
it('should fail when navigating and show the url at the error message', async () => {
const { page, httpsServer } = getTestState();
const url = httpsServer.PREFIX + '/redirect/1.html';
let error = null;
try {
await page.goto(url);
} catch (error_) {
error = error_;
}
expect(error.message).toContain(url);
const url = httpsServer.PREFIX + '/redirect/1.html';
let error = null;
try {
await page.goto(url);
} catch (error_) {
error = error_;
}
);
expect(error.message).toContain(url);
});
itFailsFirefox('should send referer', async () => {
const { page, server } = getTestState();
@ -644,7 +619,7 @@ describe('navigation', function () {
);
});
describeFailsFirefox('Page.goBack', function () {
describe('Page.goBack', function () {
it('should work', async () => {
const { page, server } = getTestState();
@ -662,7 +637,7 @@ describe('navigation', function () {
response = await page.goForward();
expect(response).toBe(null);
});
it('should work with HistoryAPI', async () => {
itFailsFirefox('should work with HistoryAPI', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);

View File

@ -40,7 +40,7 @@ describe('network', function () {
await page.goto(server.EMPTY_PAGE);
expect(requests.length).toBe(1);
});
itFailsFirefox('should fire for iframes', async () => {
it('should fire for iframes', async () => {
const { page, server } = getTestState();
const requests = [];
@ -110,7 +110,7 @@ describe('network', function () {
});
});
describeFailsFirefox('Request.headers', function () {
describe('Request.headers', function () {
it('should work', async () => {
const { page, server, isChrome } = getTestState();
@ -122,7 +122,7 @@ describe('network', function () {
});
});
describeFailsFirefox('Response.headers', function () {
describe('Response.headers', function () {
it('should work', async () => {
const { page, server } = getTestState();
@ -325,7 +325,7 @@ describe('network', function () {
});
});
describeFailsFirefox('Response.statusText', function () {
describe('Response.statusText', function () {
it('should work', async () => {
const { page, server } = getTestState();

View File

@ -694,7 +694,7 @@ describe('Page', function () {
});
describe('Page.waitForResponse', function () {
itFailsFirefox('should work', async () => {
it('should work', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
@ -727,7 +727,7 @@ describe('Page', function () {
.catch((error_) => (error = error_));
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
});
itFailsFirefox('should work with predicate', async () => {
it('should work with predicate', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
@ -743,7 +743,7 @@ describe('Page', function () {
]);
expect(response.url()).toBe(server.PREFIX + '/digits/2.png');
});
itFailsFirefox('should work with no timeout', async () => {
it('should work with no timeout', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
@ -909,7 +909,7 @@ describe('Page', function () {
]);
expect(request.headers['user-agent']).toBe('foobar');
});
itFailsFirefox('should work for subframes', async () => {
it('should work for subframes', async () => {
const { page, server } = getTestState();
expect(await page.evaluate(() => navigator.userAgent)).toContain(
@ -936,7 +936,7 @@ describe('Page', function () {
});
});
describeFailsFirefox('Page.setContent', function () {
describe('Page.setContent', function () {
const expectedOutput =
'<html><head></head><body><div>hello</div></body></html>';
it('should work', async () => {
@ -1321,7 +1321,7 @@ describe('Page', function () {
expect(styleContent).toContain(path.join('assets', 'injectedstyle.css'));
});
itFailsFirefox('should work with content', async () => {
it('should work with content', async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
@ -1433,7 +1433,7 @@ describe('Page', function () {
});
describe('printing to PDF', function () {
itFailsFirefox('can print to PDF and save to file', async () => {
it('can print to PDF and save to file', async () => {
// Printing to pdf is currently only supported in headless
const { isHeadless, page } = getTestState();
@ -1591,7 +1591,7 @@ describe('Page', function () {
)
).toEqual(true);
});
itFailsFirefox('should throw if passed in non-strings', async () => {
it('should throw if passed in non-strings', async () => {
const { page } = getTestState();
await page.setContent('<select><option value="12"/></select>');

View File

@ -23,7 +23,7 @@ const {
describe('querySelector', function () {
setupTestBrowserHooks();
setupTestPageAndContextHooks();
describeFailsFirefox('Page.$eval', function () {
describe('Page.$eval', function () {
it('should work', async () => {
const { page } = getTestState();
@ -67,7 +67,7 @@ describe('querySelector', function () {
});
});
describeFailsFirefox('Page.$$eval', function () {
describe('Page.$$eval', function () {
it('should work', async () => {
const { page } = getTestState();
@ -79,7 +79,7 @@ describe('querySelector', function () {
});
});
describeFailsFirefox('Page.$', function () {
describe('Page.$', function () {
it('should query existing element', async () => {
const { page } = getTestState();
@ -96,7 +96,7 @@ describe('querySelector', function () {
});
describe('Page.$$', function () {
itFailsFirefox('should query existing elements', async () => {
it('should query existing elements', async () => {
const { page } = getTestState();
await page.setContent('<div>A</div><br/><div>B</div>');
@ -116,7 +116,7 @@ describe('querySelector', function () {
});
});
describeFailsFirefox('Path.$x', function () {
describe('Path.$x', function () {
it('should query existing element', async () => {
const { page } = getTestState();
@ -155,7 +155,7 @@ describe('querySelector', function () {
expect(content).toBe('A');
});
itFailsFirefox('should return null for non-existing element', async () => {
it('should return null for non-existing element', async () => {
const { page } = getTestState();
await page.setContent(
@ -166,7 +166,7 @@ describe('querySelector', function () {
expect(second).toBe(null);
});
});
describeFailsFirefox('ElementHandle.$eval', function () {
describe('ElementHandle.$eval', function () {
it('should work', async () => {
const { page } = getTestState();
@ -204,7 +204,7 @@ describe('querySelector', function () {
);
});
});
describeFailsFirefox('ElementHandle.$$eval', function () {
describe('ElementHandle.$$eval', function () {
it('should work', async () => {
const { page } = getTestState();
@ -246,7 +246,7 @@ describe('querySelector', function () {
});
});
describeFailsFirefox('ElementHandle.$$', function () {
describe('ElementHandle.$$', function () {
it('should query existing elements', async () => {
const { page } = getTestState();
@ -289,7 +289,7 @@ describe('querySelector', function () {
expect(content).toBe('A');
});
itFailsFirefox('should return null for non-existing element', async () => {
it('should return null for non-existing element', async () => {
const { page } = getTestState();
await page.setContent(

View File

@ -177,7 +177,7 @@ describe('Screenshots', function () {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
});
itFailsFirefox('should take into account padding and border', async () => {
it('should take into account padding and border', async () => {
const { page } = getTestState();
await page.setViewport({ width: 500, height: 500 });
@ -196,14 +196,12 @@ describe('Screenshots', function () {
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-padding-border.png');
});
itFailsFirefox(
'should capture full element when larger than viewport',
async () => {
const { page } = getTestState();
it('should capture full element when larger than viewport', async () => {
const { page } = getTestState();
await page.setViewport({ width: 500, height: 500 });
await page.setViewport({ width: 500, height: 500 });
await page.setContent(`
await page.setContent(`
something above
<style>
div.to-screenshot {
@ -218,21 +216,20 @@ describe('Screenshots', function () {
</style>
<div class="to-screenshot"></div>
`);
const elementHandle = await page.$('div.to-screenshot');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden(
'screenshot-element-larger-than-viewport.png'
);
const elementHandle = await page.$('div.to-screenshot');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden(
'screenshot-element-larger-than-viewport.png'
);
expect(
await page.evaluate(() => ({
w: window.innerWidth,
h: window.innerHeight,
}))
).toEqual({ w: 500, h: 500 });
}
);
itFailsFirefox('should scroll element into view', async () => {
expect(
await page.evaluate(() => ({
w: window.innerWidth,
h: window.innerHeight,
}))
).toEqual({ w: 500, h: 500 });
});
it('should scroll element into view', async () => {
const { page } = getTestState();
await page.setViewport({ width: 500, height: 500 });
@ -287,30 +284,24 @@ describe('Screenshots', function () {
'Node is either not visible or not an HTMLElement'
);
});
itFailsFirefox(
'should not hang with zero width/height element',
async () => {
const { page } = getTestState();
it('should not hang with zero width/height element', async () => {
const { page } = getTestState();
await page.setContent('<div style="width: 50px; height: 0"></div>');
const div = await page.$('div');
const error = await div.screenshot().catch((error_) => error_);
expect(error.message).toBe('Node has 0 height.');
}
);
itFailsFirefox(
'should work for an element with fractional dimensions',
async () => {
const { page } = getTestState();
await page.setContent('<div style="width: 50px; height: 0"></div>');
const div = await page.$('div');
const error = await div.screenshot().catch((error_) => error_);
expect(error.message).toBe('Node has 0 height.');
});
it('should work for an element with fractional dimensions', async () => {
const { page } = getTestState();
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');
}
);
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');
});
itFailsFirefox('should work for an element with an offset', async () => {
const { page } = getTestState();

View File

@ -27,7 +27,7 @@ describe('waittask specs', function () {
setupTestPageAndContextHooks();
describe('Page.waitFor', function () {
itFailsFirefox('should wait for selector', async () => {
it('should wait for selector', async () => {
const { page, server } = getTestState();
let found = false;
@ -39,7 +39,7 @@ describe('waittask specs', function () {
expect(found).toBe(true);
});
itFailsFirefox('should wait for an xpath', async () => {
it('should wait for an xpath', async () => {
const { page, server } = getTestState();
let found = false;
@ -50,19 +50,14 @@ describe('waittask specs', function () {
await waitFor;
expect(found).toBe(true);
});
itFailsFirefox(
'should not allow you to select an element with single slash xpath',
async () => {
const { page } = getTestState();
it('should not allow you to select an element with single slash xpath', async () => {
const { page } = getTestState();
await page.setContent(`<div>some text</div>`);
let error = null;
await page
.waitFor('/html/body/div')
.catch((error_) => (error = error_));
expect(error).toBeTruthy();
}
);
await page.setContent(`<div>some text</div>`);
let error = null;
await page.waitFor('/html/body/div').catch((error_) => (error = error_));
expect(error).toBeTruthy();
});
it('should timeout', async () => {
const { page } = getTestState();
@ -255,7 +250,7 @@ describe('waittask specs', function () {
expect(await page.waitForFunction(() => window)).toBeTruthy();
});
itFailsFirefox('should accept ElementHandle arguments', async () => {
it('should accept ElementHandle arguments', async () => {
const { page } = getTestState();
await page.setContent('<div></div>');
@ -330,7 +325,7 @@ describe('waittask specs', function () {
});
});
describeFailsFirefox('Frame.waitForSelector', function () {
describe('Frame.waitForSelector', function () {
const addElement = (tag) =>
document.body.appendChild(document.createElement(tag));
@ -344,7 +339,7 @@ describe('waittask specs', function () {
await frame.waitForSelector('div');
});
it('should work with removed MutationObserver', async () => {
itFailsFirefox('should work with removed MutationObserver', async () => {
const { page } = getTestState();
await page.evaluate(() => delete window.MutationObserver);
@ -385,20 +380,23 @@ describe('waittask specs', function () {
await watchdog;
});
it('Page.waitForSelector is shortcut for main frame', async () => {
const { page, server } = getTestState();
itFailsFirefox(
'Page.waitForSelector is shortcut for main frame',
async () => {
const { page, server } = getTestState();
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
const otherFrame = page.frames()[1];
const watchdog = page.waitForSelector('div');
await otherFrame.evaluate(addElement, 'div');
await page.evaluate(addElement, 'div');
const eHandle = await watchdog;
expect(eHandle.executionContext().frame()).toBe(page.mainFrame());
});
await page.goto(server.EMPTY_PAGE);
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
const otherFrame = page.frames()[1];
const watchdog = page.waitForSelector('div');
await otherFrame.evaluate(addElement, 'div');
await page.evaluate(addElement, 'div');
const eHandle = await watchdog;
expect(eHandle.executionContext().frame()).toBe(page.mainFrame());
}
);
it('should run in specified frame', async () => {
itFailsFirefox('should run in specified frame', async () => {
const { page, server } = getTestState();
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -412,7 +410,7 @@ describe('waittask specs', function () {
expect(eHandle.executionContext().frame()).toBe(frame2);
});
it('should throw when frame is detached', async () => {
itFailsFirefox('should throw when frame is detached', async () => {
const { page, server } = getTestState();
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -580,7 +578,7 @@ describe('waittask specs', function () {
);
expect(await waitForSelector).toBe(true);
});
itFailsFirefox('should return the element handle', async () => {
it('should return the element handle', async () => {
const { page } = getTestState();
const waitForSelector = page.waitForSelector('.zombo');
@ -600,7 +598,7 @@ describe('waittask specs', function () {
});
});
describeFailsFirefox('Frame.waitForXPath', function () {
describe('Frame.waitForXPath', function () {
const addElement = (tag) =>
document.body.appendChild(document.createElement(tag));
@ -628,7 +626,7 @@ describe('waittask specs', function () {
);
expect(error).toBeInstanceOf(puppeteer.errors.TimeoutError);
});
it('should run in specified frame', async () => {
itFailsFirefox('should run in specified frame', async () => {
const { page, server } = getTestState();
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
@ -641,7 +639,7 @@ describe('waittask specs', function () {
const eHandle = await waitForXPathPromise;
expect(eHandle.executionContext().frame()).toBe(frame2);
});
it('should throw when frame is detached', async () => {
itFailsFirefox('should throw when frame is detached', async () => {
const { page, server } = getTestState();
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE);