chore: roll test fixtures, replace trace w/ video (#4129)

This commit is contained in:
Pavel Feldman 2020-10-13 13:18:36 -07:00 committed by GitHub
parent a4474f6752
commit 9daedaca08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 149 additions and 154 deletions

View file

@ -186,8 +186,8 @@ jobs:
name: wire-${{ matrix.browser }}-linux-test-results
path: test-results
tracing_linux:
name: "Tracing Linux"
video_linux:
name: "Video Linux"
strategy:
fail-fast: false
matrix:
@ -207,13 +207,12 @@ jobs:
# XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR
# Wrap `npm run` in a subshell to redirect STDERR to file.
# Enable core dumps in the subshell.
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npx folio test/ --workers=1 --forbid-only --timeout=60000 --global-timeout=5400000 --retries=3 --reporter=dot,json"
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npx folio test/ --workers=1 --forbid-only --timeout=60000 --global-timeout=5400000 --retries=3 --reporter=dot,json -p video"
env:
BROWSER: ${{ matrix.browser }}
TRACING: true
FOLIO_JSON_OUTPUT_NAME: "test-results/report.json"
- uses: actions/upload-artifact@v1
if: ${{ always() }}
with:
name: tracing-${{ matrix.browser }}-linux-test-results
name: video-${{ matrix.browser }}-linux-test-results
path: test-results

View file

@ -139,15 +139,15 @@ it('should isolate send cookie header', async ({server, context, browser}) => {
}
});
it('should isolate cookies between launches', (test, parameters) => {
it('should isolate cookies between launches', test => {
test.slow();
}, async ({browserType, server, defaultBrowserOptions}) => {
const browser1 = await browserType.launch(defaultBrowserOptions);
}, async ({browserType, server, browserOptions}) => {
const browser1 = await browserType.launch(browserOptions);
const context1 = await browser1.newContext();
await context1.addCookies([{url: server.EMPTY_PAGE, name: 'cookie-in-context-1', value: 'value', expires: Date.now() / 1000 + 10000}]);
await browser1.close();
const browser2 = await browserType.launch(defaultBrowserOptions);
const browser2 = await browserType.launch(browserOptions);
const context2 = await browser2.newContext();
const cookies = await context2.cookies();
expect(cookies.length).toBe(0);

View file

@ -20,21 +20,21 @@ import { it, expect, describe } from './fixtures';
describe('lauch server', (suite, { wire }) => {
suite.skip(wire);
}, () => {
it('should work', async ({browserType, defaultBrowserOptions}) => {
const browserServer = await browserType.launchServer(defaultBrowserOptions);
it('should work', async ({browserType, browserOptions}) => {
const browserServer = await browserType.launchServer(browserOptions);
expect(browserServer.wsEndpoint()).not.toBe(null);
await browserServer.close();
});
it('should work with port', async ({browserType, defaultBrowserOptions, testWorkerIndex}) => {
const browserServer = await browserType.launchServer({ ...defaultBrowserOptions, port: 8800 + testWorkerIndex });
it('should work with port', async ({browserType, browserOptions, testWorkerIndex}) => {
const browserServer = await browserType.launchServer({ ...browserOptions, port: 8800 + testWorkerIndex });
expect(browserServer.wsEndpoint()).toContain(String(8800 + testWorkerIndex));
await browserServer.close();
});
it('should fire "close" event during kill', async ({browserType, defaultBrowserOptions}) => {
it('should fire "close" event during kill', async ({browserType, browserOptions}) => {
const order = [];
const browserServer = await browserType.launchServer(defaultBrowserOptions);
const browserServer = await browserType.launchServer(browserOptions);
const closedPromise = new Promise(f => browserServer.on('close', () => {
order.push('closed');
f();
@ -46,14 +46,14 @@ describe('lauch server', (suite, { wire }) => {
expect(order).toEqual(['closed', 'killed']);
});
it('should return child_process instance', async ({browserType, defaultBrowserOptions}) => {
const browserServer = await browserType.launchServer(defaultBrowserOptions);
it('should return child_process instance', async ({browserType, browserOptions}) => {
const browserServer = await browserType.launchServer(browserOptions);
expect(browserServer.process().pid).toBeGreaterThan(0);
await browserServer.close();
});
it('should fire close event', async ({browserType, defaultBrowserOptions}) => {
const browserServer = await browserType.launchServer(defaultBrowserOptions);
it('should fire close event', async ({browserType, browserOptions}) => {
const browserServer = await browserType.launchServer(browserOptions);
const [result] = await Promise.all([
// @ts-expect-error The signal parameter is not documented.
new Promise(f => browserServer.on('close', (exitCode, signal) => f({ exitCode, signal }))),

View file

@ -18,8 +18,8 @@
import path from 'path';
import { it, expect } from './fixtures';
it('should reject all promises when browser is closed', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch(defaultBrowserOptions);
it('should reject all promises when browser is closed', async ({browserType, browserOptions}) => {
const browser = await browserType.launch(browserOptions);
const page = await (await browser.newContext()).newPage();
let error = null;
const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e);
@ -29,54 +29,54 @@ it('should reject all promises when browser is closed', async ({browserType, def
expect(error.message).toContain('Protocol error');
});
it('should throw if userDataDir option is passed', async ({browserType, defaultBrowserOptions}) => {
it('should throw if userDataDir option is passed', async ({browserType, browserOptions}) => {
let waitError = null;
const options = Object.assign({}, defaultBrowserOptions, {userDataDir: 'random-path'});
const options = Object.assign({}, browserOptions, {userDataDir: 'random-path'});
await browserType.launch(options).catch(e => waitError = e);
expect(waitError.message).toContain('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
});
it('should throw if port option is passed', async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions, {port: 1234});
it('should throw if port option is passed', async ({browserType, browserOptions}) => {
const options = Object.assign({}, browserOptions, {port: 1234});
const error = await browserType.launch(options).catch(e => e);
expect(error.message).toContain('Cannot specify a port without launching as a server.');
});
it('should throw if port option is passed for persistent context', async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions, {port: 1234});
it('should throw if port option is passed for persistent context', async ({browserType, browserOptions}) => {
const options = Object.assign({}, browserOptions, {port: 1234});
const error = await browserType.launchPersistentContext('foo', options).catch(e => e);
expect(error.message).toContain('Cannot specify a port without launching as a server.');
});
it('should throw if page argument is passed', (test, { browserName }) => {
test.skip(browserName === 'firefox');
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
let waitError = null;
const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] });
const options = Object.assign({}, browserOptions, { args: ['http://example.com'] });
await browserType.launch(options).catch(e => waitError = e);
expect(waitError.message).toContain('can not specify page');
});
it('should reject if launched browser fails immediately', (test, parameters) => {
test.fixme(`I'm getting ENCONRESET on this one.`);
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')});
}, async ({browserType, browserOptions}) => {
const options = Object.assign({}, browserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')});
let waitError = null;
await browserType.launch(options).catch(e => waitError = e);
expect(waitError.message).toContain('== logs ==');
});
it('should reject if executable path is invalid', async ({browserType, defaultBrowserOptions}) => {
it('should reject if executable path is invalid', async ({browserType, browserOptions}) => {
let waitError = null;
const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'});
const options = Object.assign({}, browserOptions, {executablePath: 'random-invalid-path'});
await browserType.launch(options).catch(e => waitError = e);
expect(waitError.message).toContain('Failed to launch');
});
it('should handle timeout', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions}) => {
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
}, async ({browserType, browserOptions}) => {
const options = { ...browserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
const error = await browserType.launch(options).catch(e => e);
expect(error.message).toContain(`browserType.launch: Timeout 5000ms exceeded.`);
expect(error.message).toContain(`<launching>`);
@ -85,32 +85,32 @@ it('should handle timeout', (test, { wire }) => {
it('should handle exception', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
const e = new Error('Dummy');
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
const error = await browserType.launch(options).catch(e => e);
expect(error.message).toContain('Dummy');
});
it('should report launch log', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
const e = new Error('Dummy');
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 };
const error = await browserType.launch(options).catch(e => e);
expect(error.message).toContain('<launching>');
});
it('should accept objects as options', (test, parameters) => {
test.slow();
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
// @ts-expect-error process is not a real option.
const browser = await browserType.launch({ ...defaultBrowserOptions, process });
const browser = await browserType.launch({ ...browserOptions, process });
await browser.close();
});
it('should fire close event for all contexts', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch(defaultBrowserOptions);
it('should fire close event for all contexts', async ({browserType, browserOptions}) => {
const browser = await browserType.launch(browserOptions);
const context = await browser.newContext();
let closed = false;
context.on('close', () => closed = true);
@ -118,8 +118,8 @@ it('should fire close event for all contexts', async ({browserType, defaultBrows
expect(closed).toBe(true);
});
it('should be callable twice', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch(defaultBrowserOptions);
it('should be callable twice', async ({browserType, browserOptions}) => {
const browser = await browserType.launch(browserOptions);
await Promise.all([
browser.close(),
browser.close(),

View file

@ -118,7 +118,7 @@ it('should scope CDPSession handles', (test, { browserName }) => {
await expectScopeState(browserType, GOLDEN_PRECONDITION);
});
it('should scope browser handles', async ({browserType, defaultBrowserOptions}) => {
it('should scope browser handles', async ({browserType, browserOptions}) => {
const GOLDEN_PRECONDITION = {
_guid: '',
objects: [
@ -135,7 +135,7 @@ it('should scope browser handles', async ({browserType, defaultBrowserOptions})
};
await expectScopeState(browserType, GOLDEN_PRECONDITION);
const browser = await browserType.launch(defaultBrowserOptions);
const browser = await browserType.launch(browserOptions);
await browser.newContext();
await expectScopeState(browserType, {
_guid: '',
@ -161,8 +161,8 @@ it('should scope browser handles', async ({browserType, defaultBrowserOptions})
await expectScopeState(browserType, GOLDEN_PRECONDITION);
});
it('should work with the domain module', async ({ domain, browserType, defaultBrowserOptions }) => {
const browser = await browserType.launch(defaultBrowserOptions);
it('should work with the domain module', async ({ domain, browserType, browserOptions }) => {
const browser = await browserType.launch(browserOptions);
const page = await browser.newPage();
const result = await page.evaluate(() => 1 + 1);
expect(result).toBe(2);

View file

@ -20,8 +20,8 @@ import type { ChromiumBrowser, ChromiumBrowserContext } from '../..';
it('should throw with remote-debugging-pipe argument', (test, { browserName, wire }) => {
test.skip(wire || browserName !== 'chromium');
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions);
}, async ({browserType, browserOptions}) => {
const options = Object.assign({}, browserOptions);
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
const error = await browserType.launchServer(options).catch(e => e);
expect(error.message).toContain('Playwright manages remote debugging connection itself');
@ -29,8 +29,8 @@ it('should throw with remote-debugging-pipe argument', (test, { browserName, wir
it('should not throw with remote-debugging-port argument', (test, { browserName, wire }) => {
test.skip(wire || browserName !== 'chromium');
}, async ({browserType, defaultBrowserOptions}) => {
const options = Object.assign({}, defaultBrowserOptions);
}, async ({browserType, browserOptions}) => {
const options = Object.assign({}, browserOptions);
options.args = ['--remote-debugging-port=0'].concat(options.args || []);
const browser = await browserType.launchServer(options);
await browser.close();
@ -38,14 +38,14 @@ it('should not throw with remote-debugging-port argument', (test, { browserName,
it('should open devtools when "devtools: true" option is given', (test, { wire, browserName, platform}) => {
test.skip(browserName !== 'chromium' || wire || platform === 'win32');
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
let devtoolsCallback;
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
if (parsed.method === 'getPreferences')
devtoolsCallback();
};
const browser = await browserType.launch({...defaultBrowserOptions, headless: false, devtools: true, __testHookForDevTools} as any);
const browser = await browserType.launch({...browserOptions, headless: false, devtools: true, __testHookForDevTools} as any);
const context = await browser.newContext();
await Promise.all([
devtoolsPromise,
@ -56,10 +56,10 @@ it('should open devtools when "devtools: true" option is given', (test, { wire,
it('should return background pages', (test, { browserName }) => {
test.skip(browserName !== 'chromium');
}, async ({browserType, defaultBrowserOptions, createUserDataDir}) => {
}, async ({browserType, browserOptions, createUserDataDir}) => {
const userDataDir = await createUserDataDir();
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
const extensionOptions = {...defaultBrowserOptions,
const extensionOptions = {...browserOptions,
headless: false,
args: [
`--disable-extensions-except=${extensionPath}`,
@ -79,8 +79,8 @@ it('should return background pages', (test, { browserName }) => {
it('should not create pages automatically', (test, { browserName }) => {
test.skip(browserName !== 'chromium');
}, async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch(defaultBrowserOptions);
}, async ({browserType, browserOptions}) => {
const browser = await browserType.launch(browserOptions);
const browserSession = await (browser as ChromiumBrowser).newBrowserCDPSession();
const targets = [];
browserSession.on('Target.targetCreated', async ({targetInfo}) => {

View file

@ -17,10 +17,10 @@
import { folio } from '../fixtures';
const fixtures = folio.extend();
fixtures.browser.override(async ({browserType, defaultBrowserOptions}, run) => {
fixtures.browser.override(async ({browserType, browserOptions}, run) => {
const browser = await browserType.launch({
...defaultBrowserOptions,
args: (defaultBrowserOptions.args || []).concat(['--site-per-process'])
...browserOptions,
args: (browserOptions.args || []).concat(['--site-per-process'])
});
await run(browser);
await browser.close();
@ -240,10 +240,10 @@ describe('oopif', (suite, { browserName }) => {
expect(await page.evaluate(() => window['BUTTON_CLICKED'])).toBe(true);
});
it('should report google.com frame with headful', async ({browserType, defaultBrowserOptions, server}) => {
it('should report google.com frame with headful', async ({browserType, browserOptions, server}) => {
// @see https://github.com/GoogleChrome/puppeteer/issues/2548
// https://google.com is isolated by default in Chromium embedder.
const browser = await browserType.launch({...defaultBrowserOptions, headless: false});
const browser = await browserType.launch({...browserOptions, headless: false});
const page = await browser.newPage();
await page.goto(server.EMPTY_PAGE);
await page.route('**/*', route => {

View file

@ -79,9 +79,9 @@ it('should support extraHTTPHeaders option', (test, { browserName, platform, hea
it('should accept userDataDir', (test, { browserName }) => {
test.flaky(browserName === 'chromium');
}, async ({createUserDataDir, browserType, defaultBrowserOptions}) => {
}, async ({createUserDataDir, browserType, browserOptions}) => {
const userDataDir = await createUserDataDir();
const context = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
const context = await browserType.launchPersistentContext(userDataDir, browserOptions);
expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0);
await context.close();
expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0);
@ -89,22 +89,22 @@ it('should accept userDataDir', (test, { browserName }) => {
it('should restore state from userDataDir', (test, { browserName }) => {
test.slow();
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => {
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
const userDataDir = await createUserDataDir();
const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions);
const page = await browserContext.newPage();
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => localStorage.hey = 'hello');
await browserContext.close();
const browserContext2 = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
const browserContext2 = await browserType.launchPersistentContext(userDataDir, browserOptions);
const page2 = await browserContext2.newPage();
await page2.goto(server.EMPTY_PAGE);
expect(await page2.evaluate(() => localStorage.hey)).toBe('hello');
await browserContext2.close();
const userDataDir2 = await createUserDataDir();
const browserContext3 = await browserType.launchPersistentContext(userDataDir2, defaultBrowserOptions);
const browserContext3 = await browserType.launchPersistentContext(userDataDir2, browserOptions);
const page3 = await browserContext3.newPage();
await page3.goto(server.EMPTY_PAGE);
expect(await page3.evaluate(() => localStorage.hey)).not.toBe('hello');
@ -114,9 +114,9 @@ it('should restore state from userDataDir', (test, { browserName }) => {
it('should restore cookies from userDataDir', (test, { browserName }) => {
test.slow();
test.flaky(browserName === 'chromium');
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => {
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
const userDataDir = await createUserDataDir();
const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions);
const page = await browserContext.newPage();
await page.goto(server.EMPTY_PAGE);
const documentCookie = await page.evaluate(() => {
@ -126,14 +126,14 @@ it('should restore cookies from userDataDir', (test, { browserName }) => {
expect(documentCookie).toBe('doSomethingOnlyOnce=true');
await browserContext.close();
const browserContext2 = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions);
const browserContext2 = await browserType.launchPersistentContext(userDataDir, browserOptions);
const page2 = await browserContext2.newPage();
await page2.goto(server.EMPTY_PAGE);
expect(await page2.evaluate(() => document.cookie)).toBe('doSomethingOnlyOnce=true');
await browserContext2.close();
const userDataDir2 = await createUserDataDir();
const browserContext3 = await browserType.launchPersistentContext(userDataDir2, defaultBrowserOptions);
const browserContext3 = await browserType.launchPersistentContext(userDataDir2, browserOptions);
const page3 = await browserContext3.newPage();
await page3.goto(server.EMPTY_PAGE);
expect(await page3.evaluate(() => document.cookie)).not.toBe('doSomethingOnlyOnce=true');
@ -148,19 +148,19 @@ it('should have default URL when launching browser', async ({launchPersistent})
it('should throw if page argument is passed', (test, { browserName }) => {
test.skip(browserName === 'firefox');
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => {
const options = {...defaultBrowserOptions, args: [server.EMPTY_PAGE] };
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
const options = {...browserOptions, args: [server.EMPTY_PAGE] };
const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e);
expect(error.message).toContain('can not specify page');
});
it('should have passed URL when launching with ignoreDefaultArgs: true', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir, toImpl}) => {
}, async ({browserType, browserOptions, server, createUserDataDir, toImpl}) => {
const userDataDir = await createUserDataDir();
const args = toImpl(browserType)._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
const args = toImpl(browserType)._defaultArgs(browserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
const options = {
...defaultBrowserOptions,
...browserOptions,
args: [...args, server.EMPTY_PAGE],
ignoreDefaultArgs: true,
};
@ -175,17 +175,17 @@ it('should have passed URL when launching with ignoreDefaultArgs: true', (test,
it('should handle timeout', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions, createUserDataDir}) => {
const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
}, async ({browserType, browserOptions, createUserDataDir}) => {
const options = { ...browserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) };
const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e);
expect(error.message).toContain(`browserType.launchPersistentContext: Timeout 5000ms exceeded.`);
});
it('should handle exception', (test, { wire }) => {
test.skip(wire);
}, async ({browserType, defaultBrowserOptions, createUserDataDir}) => {
}, async ({browserType, browserOptions, createUserDataDir}) => {
const e = new Error('Dummy');
const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } };
const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; } };
const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e);
expect(error.message).toContain('Dummy');
});

View file

@ -344,8 +344,8 @@ describe('download event', () => {
expect(fs.existsSync(path2)).toBeFalsy();
});
it('should delete downloads on browser gone', async ({ server, browserType, defaultBrowserOptions }) => {
const browser = await browserType.launch(defaultBrowserOptions);
it('should delete downloads on browser gone', async ({ server, browserType, browserOptions }) => {
const browser = await browserType.launch(browserOptions);
const page = await browser.newPage({ acceptDownloads: true });
await page.setContent(`<a href="${server.PREFIX}/download">download</a>`);
const [ download1 ] = await Promise.all([

View file

@ -25,14 +25,14 @@ type TestState = {
};
const fixtures = folio.extend<{}, TestState>();
fixtures.downloadsBrowser.init(async ({ server, browserType, defaultBrowserOptions, testInfo }, test) => {
fixtures.downloadsBrowser.init(async ({ server, browserType, browserOptions, testInfo }, test) => {
server.setRoute('/download', (req, res) => {
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename=file.txt');
res.end(`Hello world`);
});
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
downloadsPath: testInfo.outputPath(''),
});
await test(browser);

View file

@ -17,9 +17,9 @@ import { it, expect } from '../fixtures';
it('should pass firefox user preferences', (test, { browserName }) => {
test.skip(browserName !== 'firefox');
}, async ({browserType, defaultBrowserOptions}) => {
}, async ({browserType, browserOptions}) => {
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
firefoxUserPrefs: {
'network.proxy.type': 1,
'network.proxy.http': '127.0.0.1',

View file

@ -72,13 +72,13 @@ fixtures.createUserDataDir.init(async ({ }, run) => {
await Promise.all(dirs.map(dir => removeFolderAsync(dir).catch(e => { })));
});
fixtures.launchPersistent.init(async ({ createUserDataDir, defaultBrowserOptions, browserType }, run) => {
fixtures.launchPersistent.init(async ({ createUserDataDir, browserOptions, browserType }, run) => {
let context;
async function launchPersistent(options) {
if (context)
throw new Error('can only launch one persitent context');
const userDataDir = await createUserDataDir();
context = await browserType.launchPersistentContext(userDataDir, { ...defaultBrowserOptions, ...options });
context = await browserType.launchPersistentContext(userDataDir, { ...browserOptions, ...options });
const page = context.pages()[0];
return { context, page };
}
@ -87,7 +87,7 @@ fixtures.launchPersistent.init(async ({ createUserDataDir, defaultBrowserOptions
await context.close();
});
fixtures.defaultBrowserOptions.override(async ({ browserName, headful, slowMo }, run) => {
fixtures.browserOptions.override(async ({ browserName, headful, slowMo }, run) => {
const executablePath = getExecutablePath(browserName);
if (executablePath)
console.error(`Using executable at ${executablePath}`);

View file

@ -16,8 +16,8 @@
import { it, expect } from './fixtures';
it('should have default url when launching browser', async ({browserType, defaultBrowserOptions, createUserDataDir}) => {
const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...defaultBrowserOptions, headless: false });
it('should have default url when launching browser', async ({browserType, browserOptions, createUserDataDir}) => {
const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...browserOptions, headless: false });
const urls = browserContext.pages().map(page => page.url());
expect(urls).toEqual(['about:blank']);
await browserContext.close();
@ -27,17 +27,17 @@ it('headless should be able to read cookies written by headful', (test, { browse
test.fail(platform === 'win32' && browserName === 'chromium');
test.flaky(browserName === 'firefox');
test.slow();
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => {
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
// see https://github.com/microsoft/playwright/issues/717
const userDataDir = await createUserDataDir();
// Write a cookie in headful chrome
const headfulContext = await browserType.launchPersistentContext(userDataDir, {...defaultBrowserOptions, headless: false});
const headfulContext = await browserType.launchPersistentContext(userDataDir, {...browserOptions, headless: false});
const headfulPage = await headfulContext.newPage();
await headfulPage.goto(server.EMPTY_PAGE);
await headfulPage.evaluate(() => document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT');
await headfulContext.close();
// Read the cookie from headless chrome
const headlessContext = await browserType.launchPersistentContext(userDataDir, {...defaultBrowserOptions, headless: true});
const headlessContext = await browserType.launchPersistentContext(userDataDir, {...browserOptions, headless: true});
const headlessPage = await headlessContext.newPage();
await headlessPage.goto(server.EMPTY_PAGE);
const cookie = await headlessPage.evaluate(() => document.cookie);
@ -47,8 +47,8 @@ it('headless should be able to read cookies written by headful', (test, { browse
it('should close browser with beforeunload page', (test, parameters) => {
test.slow();
}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => {
const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...defaultBrowserOptions, headless: false});
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...browserOptions, headless: false});
const page = await browserContext.newPage();
await page.goto(server.PREFIX + '/beforeunload.html');
// We have to interact with a page so that 'beforeunload' handlers
@ -57,8 +57,8 @@ it('should close browser with beforeunload page', (test, parameters) => {
await browserContext.close();
});
it('should not crash when creating second context', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
it('should not crash when creating second context', async ({browserType, browserOptions}) => {
const browser = await browserType.launch({...browserOptions, headless: false });
{
const browserContext = await browser.newContext();
await browserContext.newPage();
@ -72,8 +72,8 @@ 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 });
it('should click background tab', async ({browserType, browserOptions, server}) => {
const browser = await browserType.launch({...browserOptions, headless: false });
const page = await browser.newPage();
await page.setContent(`<button>Hello</button><a target=_blank href="${server.EMPTY_PAGE}">empty.html</a>`);
await page.click('a');
@ -81,16 +81,16 @@ it('should click background tab', async ({browserType, defaultBrowserOptions, se
await browser.close();
});
it('should close browser after context menu was triggered', async ({browserType, defaultBrowserOptions, server}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
it('should close browser after context menu was triggered', async ({browserType, browserOptions, server}) => {
const browser = await browserType.launch({...browserOptions, headless: false });
const page = await browser.newPage();
await page.goto(server.PREFIX + '/grid.html');
await page.click('body', {button: 'right'});
await browser.close();
});
it('should(not) block third party cookies', async ({browserType, defaultBrowserOptions, server, isChromium, isFirefox}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
it('should(not) block third party cookies', async ({browserType, browserOptions, server, isChromium, isFirefox}) => {
const browser = await browserType.launch({...browserOptions, headless: false });
const page = await browser.newPage();
await page.goto(server.EMPTY_PAGE);
await page.evaluate(src => {
@ -131,9 +131,9 @@ it('should(not) block third party cookies', async ({browserType, defaultBrowserO
it('should not override viewport size when passed null', (test, { browserName }) => {
test.fixme(browserName === 'webkit');
}, async function({browserType, defaultBrowserOptions, server}) {
}, async function({browserType, browserOptions, server}) {
// Our WebKit embedder does not respect window features.
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
const browser = await browserType.launch({...browserOptions, headless: false });
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
await page.goto(server.EMPTY_PAGE);
@ -150,8 +150,8 @@ it('should not override viewport size when passed null', (test, { browserName })
await browser.close();
});
it('Page.bringToFront should work', async ({browserType, defaultBrowserOptions}) => {
const browser = await browserType.launch({...defaultBrowserOptions, headless: false });
it('Page.bringToFront should work', async ({browserType, browserOptions}) => {
const browser = await browserType.launch({...browserOptions, headless: false });
const page1 = await browser.newPage();
await page1.setContent('Page1');
const page2 = await browser.newPage();

View file

@ -16,9 +16,9 @@
import { it, expect } from './fixtures';
it('should log', async ({browserType, defaultBrowserOptions}) => {
it('should log', async ({browserType, browserOptions}) => {
const log = [];
const browser = await browserType.launch({...defaultBrowserOptions, logger: {
const browser = await browserType.launch({...browserOptions, logger: {
log: (name, severity, message) => log.push({name, severity, message}),
isEnabled: (name, severity) => severity !== 'verbose'
}});
@ -30,9 +30,9 @@ it('should log', async ({browserType, defaultBrowserOptions}) => {
expect(log.filter(item => item.message.includes('browserType.launch succeeded')).length > 0).toBeTruthy();
});
it('should log context-level', async ({browserType, defaultBrowserOptions}) => {
it('should log context-level', async ({browserType, browserOptions}) => {
const log = [];
const browser = await browserType.launch(defaultBrowserOptions);
const browser = await browserType.launch(browserOptions);
const context = await browser.newContext({
logger: {
log: (name, severity, message) => log.push({name, severity, message}),

View file

@ -361,7 +361,6 @@ it('should not leak listeners during bad navigation', async ({page, server}) =>
});
it('should not leak listeners during navigation of 20 pages', (test, parameters) => {
test.flaky(parameters.trace, 'Flakes on tracing');
test.slow('We open 20 pages here');
}, async ({page, context, server}) => {
let warning = null;

View file

@ -23,7 +23,6 @@
import { config, folio as baseFolio } from 'folio';
import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from '../index';
import * as path from 'path';
export { expect, config } from 'folio';
// Test timeout for e2e tests is 30 seconds.
@ -43,8 +42,8 @@ type PlaywrightParameters = {
screenshotOnFailure: boolean;
// Slows down Playwright operations by the specified amount of milliseconds.
slowMo: number;
// Whether to record the execution trace.
trace: boolean;
// Whether to record videos for all tests.
video: boolean;
};
@ -57,7 +56,7 @@ type PlaywrightWorkerFixtures = {
// Browser type (Chromium / WebKit / Firefox)
browserType: BrowserType<Browser>;
// Default browserType.launch() options.
defaultBrowserOptions: LaunchOptions;
browserOptions: LaunchOptions;
// Browser instance, shared for the worker.
browser: Browser;
// True iff browserName is Chromium
@ -79,7 +78,7 @@ type PlaywrightWorkerFixtures = {
type PlaywrightTestFixtures = {
// Default browser.newContext() options.
defaultContextOptions: BrowserContextOptions;
contextOptions: BrowserContextOptions;
// Factory for creating a context with given additional options.
contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>;
// Context instance for test.
@ -94,9 +93,9 @@ fixtures.headful.initParameter('Whether to run tests headless or headful', proce
fixtures.platform.initParameter('Operating system', process.platform as ('win32' | 'linux' | 'darwin'));
fixtures.screenshotOnFailure.initParameter('Generate screenshot on failure', false);
fixtures.slowMo.initParameter('Slows down Playwright operations by the specified amount of milliseconds', 0);
fixtures.trace.initParameter('Whether to record the execution trace', !!process.env.TRACING);
fixtures.video.initParameter('Record videos while running tests', false);
fixtures.defaultBrowserOptions.init(async ({ headful, slowMo }, run) => {
fixtures.browserOptions.init(async ({ headful, slowMo }, run) => {
await run({
handleSIGINT: false,
slowMo,
@ -105,7 +104,7 @@ fixtures.defaultBrowserOptions.init(async ({ headful, slowMo }, run) => {
}, { scope: 'worker' });
fixtures.playwright.init(async ({ }, run) => {
const playwright = require('../index');
const playwright = require('playwright');
await run(playwright);
}, { scope: 'worker' });
@ -114,8 +113,8 @@ fixtures.browserType.init(async ({ playwright, browserName }, run) => {
await run(browserType);
}, { scope: 'worker' });
fixtures.browser.init(async ({ browserType, defaultBrowserOptions }, run) => {
const browser = await browserType.launch(defaultBrowserOptions);
fixtures.browser.init(async ({ browserType, browserOptions }, run) => {
const browser = await browserType.launch(browserOptions);
await run(browser);
await browser.close();
}, { scope: 'worker' });
@ -144,22 +143,20 @@ fixtures.isLinux.init(async ({ platform }, run) => {
await run(platform === 'linux');
}, { scope: 'worker' });
fixtures.defaultContextOptions.init(async ({ trace, testInfo }, run) => {
if (trace || testInfo.retry) {
fixtures.contextOptions.init(async ({ video, testInfo }, run) => {
if (video) {
await run({
_traceResourcesPath: path.join(config.outputDir, 'trace-resources'),
_tracePath: testInfo.outputPath('playwright.trace'),
videosPath: testInfo.outputPath(''),
} as any);
});
} else {
await run({});
}
});
fixtures.contextFactory.init(async ({ browser, defaultContextOptions, testInfo, screenshotOnFailure }, run) => {
fixtures.contextFactory.init(async ({ browser, contextOptions, testInfo, screenshotOnFailure }, run) => {
const contexts: BrowserContext[] = [];
async function contextFactory(options: BrowserContextOptions = {}) {
const context = await browser.newContext({ ...defaultContextOptions, ...options });
const context = await browser.newContext({ ...contextOptions, ...options });
contexts.push(context);
return context;
}

View file

@ -18,21 +18,21 @@ import { it, expect } from './fixtures';
import socks from 'socksv5';
it('should throw for bad server value', async ({browserType, defaultBrowserOptions}) => {
it('should throw for bad server value', async ({browserType, browserOptions}) => {
const error = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
// @ts-expect-error server must be a string
proxy: { server: 123 }
}).catch(e => e);
expect(error.message).toContain('proxy.server: expected string, got number');
});
it('should use proxy', async ({browserType, defaultBrowserOptions, server}) => {
it('should use proxy', async ({browserType, browserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: `localhost:${server.PORT}` }
});
const page = await browser.newPage();
@ -41,12 +41,12 @@ it('should use proxy', async ({browserType, defaultBrowserOptions, server}) => {
await browser.close();
});
it('should work with IP:PORT notion', async ({browserType, defaultBrowserOptions, server}) => {
it('should work with IP:PORT notion', async ({browserType, browserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: `127.0.0.1:${server.PORT}` }
});
const page = await browser.newPage();
@ -55,7 +55,7 @@ it('should work with IP:PORT notion', async ({browserType, defaultBrowserOptions
await browser.close();
});
it('should authenticate', async ({browserType, defaultBrowserOptions, server}) => {
it('should authenticate', async ({browserType, browserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
const auth = req.headers['proxy-authorization'];
if (!auth) {
@ -68,7 +68,7 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) =
}
});
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: `localhost:${server.PORT}`, username: 'user', password: 'secret' }
});
const page = await browser.newPage();
@ -79,7 +79,7 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) =
it('should exclude patterns', (test, { browserName, headful }) => {
test.flaky(browserName === 'chromium' && headful, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.');
}, async ({browserType, defaultBrowserOptions, server}) => {
}, async ({browserType, browserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
@ -88,7 +88,7 @@ it('should exclude patterns', (test, { browserName, headful }) => {
//
// @see https://gist.github.com/CollinChaffin/24f6c9652efb3d6d5ef2f5502720ef00
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: `localhost:${server.PORT}`, bypass: '1.non.existent.domain.for.the.test, 2.non.existent.domain.for.the.test, .another.test' }
});
@ -121,7 +121,7 @@ it('should exclude patterns', (test, { browserName, headful }) => {
it('should use socks proxy', (test, { browserName, platform }) => {
test.flaky(platform === 'darwin' && browserName === 'webkit', 'Intermittent page.goto: The network connection was lost error on bots');
}, async ({ browserType, defaultBrowserOptions, testWorkerIndex }) => {
}, async ({ browserType, browserOptions, testWorkerIndex }) => {
const server = socks.createServer((info, accept, deny) => {
let socket;
if ((socket = accept(true))) {
@ -143,7 +143,7 @@ it('should use socks proxy', (test, { browserName, platform }) => {
server.useAuth(socks.auth.None());
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: `socks5://localhost:${socksPort}` }
});
const page = await browser.newPage();
@ -153,9 +153,9 @@ it('should use socks proxy', (test, { browserName, platform }) => {
server.close();
});
it('does launch without a port', async ({ browserType, defaultBrowserOptions }) => {
it('does launch without a port', async ({ browserType, browserOptions }) => {
const browser = await browserType.launch({
...defaultBrowserOptions,
...browserOptions,
proxy: { server: 'http://localhost' }
});
await browser.close();

View file

@ -26,16 +26,16 @@ type ServerFixtures = {
};
const fixtures = base.extend<{}, ServerFixtures>();
fixtures.remoteServer.init(async ({ browserType, defaultBrowserOptions }, run) => {
fixtures.remoteServer.init(async ({ browserType, browserOptions }, run) => {
const remoteServer = new RemoteServer();
await remoteServer._start(browserType, defaultBrowserOptions);
await remoteServer._start(browserType, browserOptions);
await run(remoteServer);
await remoteServer.close();
});
fixtures.stallingRemoteServer.init(async ({ browserType, defaultBrowserOptions }, run) => {
fixtures.stallingRemoteServer.init(async ({ browserType, browserOptions }, run) => {
const remoteServer = new RemoteServer();
await remoteServer._start(browserType, defaultBrowserOptions, { stallOnClose: true });
await remoteServer._start(browserType, browserOptions, { stallOnClose: true });
await run(remoteServer);
await remoteServer.close();
});
@ -55,17 +55,17 @@ export class RemoteServer {
_didExit: boolean;
_wsEndpoint: string;
async _start(browserType: BrowserType<Browser>, defaultBrowserOptions: LaunchOptions, extraOptions?: { stallOnClose: boolean; }) {
async _start(browserType: BrowserType<Browser>, browserOptions: LaunchOptions, extraOptions?: { stallOnClose: boolean; }) {
this._output = new Map();
this._outputCallback = new Map();
this._didExit = false;
this._browserType = browserType;
const launchOptions = {...defaultBrowserOptions,
const launchOptions = {...browserOptions,
handleSIGINT: true,
handleSIGTERM: true,
handleSIGHUP: true,
executablePath: defaultBrowserOptions.executablePath || browserType.executablePath(),
executablePath: browserOptions.executablePath || browserType.executablePath(),
logger: undefined,
};
const options = {