mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(firefox): implement missing launcher options (#4036)
This patch implements `puppeteer.defaultArgs()` and also missing options, such as `ignoreDefaultArgs`.
This commit is contained in:
parent
719ee5af3d
commit
03c542a6c1
@ -32,6 +32,11 @@ const removeFolderAsync = util.promisify(removeFolder);
|
|||||||
|
|
||||||
const FIREFOX_PROFILE_PATH = path.join(os.tmpdir(), 'puppeteer_firefox_profile-');
|
const FIREFOX_PROFILE_PATH = path.join(os.tmpdir(), 'puppeteer_firefox_profile-');
|
||||||
|
|
||||||
|
const DEFAULT_ARGS = [
|
||||||
|
'-no-remote',
|
||||||
|
'-foreground',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -41,15 +46,34 @@ class Launcher {
|
|||||||
this._preferredRevision = preferredRevision;
|
this._preferredRevision = preferredRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultArgs(options = {}) {
|
||||||
|
const {
|
||||||
|
headless = true,
|
||||||
|
args = [],
|
||||||
|
userDataDir = null,
|
||||||
|
} = options;
|
||||||
|
const firefoxArguments = [...DEFAULT_ARGS];
|
||||||
|
if (userDataDir)
|
||||||
|
firefoxArguments.push('-profile', userDataDir);
|
||||||
|
if (headless)
|
||||||
|
firefoxArguments.push('-headless');
|
||||||
|
firefoxArguments.push(...args);
|
||||||
|
if (args.every(arg => arg.startsWith('-')))
|
||||||
|
firefoxArguments.push('about:blank');
|
||||||
|
return firefoxArguments;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @return {!Promise<!Browser>}
|
* @return {!Promise<!Browser>}
|
||||||
*/
|
*/
|
||||||
async launch(options = {}) {
|
async launch(options = {}) {
|
||||||
const {
|
const {
|
||||||
|
ignoreDefaultArgs = false,
|
||||||
args = [],
|
args = [],
|
||||||
dumpio = false,
|
dumpio = false,
|
||||||
executablePath = this.executablePath(),
|
executablePath = null,
|
||||||
|
env = process.env,
|
||||||
handleSIGHUP = true,
|
handleSIGHUP = true,
|
||||||
handleSIGINT = true,
|
handleSIGINT = true,
|
||||||
handleSIGTERM = true,
|
handleSIGTERM = true,
|
||||||
@ -57,25 +81,36 @@ class Launcher {
|
|||||||
headless = true,
|
headless = true,
|
||||||
defaultViewport = {width: 800, height: 600},
|
defaultViewport = {width: 800, height: 600},
|
||||||
slowMo = 0,
|
slowMo = 0,
|
||||||
|
timeout = 30000,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const firefoxArguments = args.slice();
|
const firefoxArguments = [];
|
||||||
firefoxArguments.push('-no-remote');
|
if (!ignoreDefaultArgs)
|
||||||
|
firefoxArguments.push(...this.defaultArgs(options));
|
||||||
|
else if (Array.isArray(ignoreDefaultArgs))
|
||||||
|
firefoxArguments.push(...this.defaultArgs(options).filter(arg => !ignoreDefaultArgs.includes(arg)));
|
||||||
|
else
|
||||||
|
firefoxArguments.push(...args);
|
||||||
|
|
||||||
|
if (!firefoxArguments.includes('-juggler'))
|
||||||
firefoxArguments.push('-juggler', '0');
|
firefoxArguments.push('-juggler', '0');
|
||||||
firefoxArguments.push('-foreground');
|
|
||||||
if (headless)
|
|
||||||
firefoxArguments.push('-headless');
|
|
||||||
let temporaryProfileDir = null;
|
let temporaryProfileDir = null;
|
||||||
if (!firefoxArguments.some(arg => arg.startsWith('-profile') || arg.startsWith('--profile'))) {
|
if (!firefoxArguments.includes('-profile') && !firefoxArguments.includes('--profile')) {
|
||||||
temporaryProfileDir = await mkdtempAsync(FIREFOX_PROFILE_PATH);
|
temporaryProfileDir = await mkdtempAsync(FIREFOX_PROFILE_PATH);
|
||||||
firefoxArguments.push(`-profile`, temporaryProfileDir);
|
firefoxArguments.push(`-profile`, temporaryProfileDir);
|
||||||
}
|
}
|
||||||
if (firefoxArguments.every(arg => arg.startsWith('--') || arg.startsWith('-')))
|
|
||||||
firefoxArguments.push('about:blank');
|
|
||||||
|
|
||||||
|
let firefoxExecutable = executablePath;
|
||||||
|
if (!firefoxExecutable) {
|
||||||
|
const {missingText, executablePath} = this._resolveExecutablePath();
|
||||||
|
if (missingText)
|
||||||
|
throw new Error(missingText);
|
||||||
|
firefoxExecutable = executablePath;
|
||||||
|
}
|
||||||
const stdio = ['pipe', 'pipe', 'pipe'];
|
const stdio = ['pipe', 'pipe', 'pipe'];
|
||||||
const firefoxProcess = childProcess.spawn(
|
const firefoxProcess = childProcess.spawn(
|
||||||
executablePath,
|
firefoxExecutable,
|
||||||
firefoxArguments,
|
firefoxArguments,
|
||||||
{
|
{
|
||||||
// On non-windows platforms, `detached: false` makes child process a leader of a new
|
// On non-windows platforms, `detached: false` makes child process a leader of a new
|
||||||
@ -85,9 +120,9 @@ class Launcher {
|
|||||||
stdio,
|
stdio,
|
||||||
// On linux Juggler ships the libstdc++ it was linked against.
|
// On linux Juggler ships the libstdc++ it was linked against.
|
||||||
env: os.platform() === 'linux' ? {
|
env: os.platform() === 'linux' ? {
|
||||||
...process.env,
|
...env,
|
||||||
LD_LIBRARY_PATH: `${path.dirname(executablePath)}:${process.env.LD_LIBRARY_PATH}`,
|
LD_LIBRARY_PATH: `${path.dirname(firefoxExecutable)}:${process.env.LD_LIBRARY_PATH}`,
|
||||||
} : process.env,
|
} : env,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -115,16 +150,16 @@ class Launcher {
|
|||||||
if (handleSIGINT)
|
if (handleSIGINT)
|
||||||
listeners.push(helper.addEventListener(process, 'SIGINT', () => { killFirefox(); process.exit(130); }));
|
listeners.push(helper.addEventListener(process, 'SIGINT', () => { killFirefox(); process.exit(130); }));
|
||||||
if (handleSIGTERM)
|
if (handleSIGTERM)
|
||||||
listeners.push(helper.addEventListener(process, 'SIGTERM', killFirefox));
|
listeners.push(helper.addEventListener(process, 'SIGTERM', gracefullyCloseFirefox));
|
||||||
if (handleSIGHUP)
|
if (handleSIGHUP)
|
||||||
listeners.push(helper.addEventListener(process, 'SIGHUP', killFirefox));
|
listeners.push(helper.addEventListener(process, 'SIGHUP', gracefullyCloseFirefox));
|
||||||
/** @type {?Connection} */
|
/** @type {?Connection} */
|
||||||
let connection = null;
|
let connection = null;
|
||||||
try {
|
try {
|
||||||
const url = await waitForWSEndpoint(firefoxProcess, 30000);
|
const url = await waitForWSEndpoint(firefoxProcess, timeout);
|
||||||
const transport = await WebSocketTransport.create(url);
|
const transport = await WebSocketTransport.create(url);
|
||||||
connection = new Connection(url, transport, slowMo);
|
connection = new Connection(url, transport, slowMo);
|
||||||
const browser = await Browser.create(connection, defaultViewport, firefoxProcess, killFirefox);
|
const browser = await Browser.create(connection, defaultViewport, firefoxProcess, gracefullyCloseFirefox);
|
||||||
if (ignoreHTTPSErrors)
|
if (ignoreHTTPSErrors)
|
||||||
await connection.send('Browser.setIgnoreHTTPSErrors', {enabled: true});
|
await connection.send('Browser.setIgnoreHTTPSErrors', {enabled: true});
|
||||||
await browser.waitForTarget(t => t.type() === 'page');
|
await browser.waitForTarget(t => t.type() === 'page');
|
||||||
@ -134,6 +169,19 @@ class Launcher {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gracefullyCloseFirefox() {
|
||||||
|
helper.removeEventListeners(listeners);
|
||||||
|
if (temporaryProfileDir) {
|
||||||
|
killFirefox();
|
||||||
|
} else if (connection) {
|
||||||
|
connection.send('Browser.close').catch(error => {
|
||||||
|
debugError(error);
|
||||||
|
killFirefox();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return waitForFirefoxToClose;
|
||||||
|
}
|
||||||
|
|
||||||
// This method has to be sync to be used as 'exit' event handler.
|
// This method has to be sync to be used as 'exit' event handler.
|
||||||
function killFirefox() {
|
function killFirefox() {
|
||||||
helper.removeEventListeners(listeners);
|
helper.removeEventListeners(listeners);
|
||||||
@ -179,9 +227,14 @@ class Launcher {
|
|||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
executablePath() {
|
executablePath() {
|
||||||
|
return this._resolveExecutablePath().executablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
_resolveExecutablePath() {
|
||||||
const browserFetcher = new BrowserFetcher(this._projectRoot, { product: 'firefox' });
|
const browserFetcher = new BrowserFetcher(this._projectRoot, { product: 'firefox' });
|
||||||
const revisionInfo = browserFetcher.revisionInfo(this._preferredRevision);
|
const revisionInfo = browserFetcher.revisionInfo(this._preferredRevision);
|
||||||
return revisionInfo.executablePath;
|
const missingText = !revisionInfo.local ? `Firefox revision is not downloaded. Run "npm install" or "yarn install"` : null;
|
||||||
|
return {executablePath: revisionInfo.executablePath, missingText};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ class NavigationWatchdog {
|
|||||||
|
|
||||||
const check = this._checkNavigationComplete.bind(this);
|
const check = this._checkNavigationComplete.bind(this);
|
||||||
this._eventListeners = [
|
this._eventListeners = [
|
||||||
|
helper.addEventListener(session, Events.JugglerSession.Disconnected, () => this._resolveCallback(new Error('Navigation failed because browser has disconnected!'))),
|
||||||
helper.addEventListener(session, 'Page.eventFired', check),
|
helper.addEventListener(session, 'Page.eventFired', check),
|
||||||
helper.addEventListener(session, 'Page.frameAttached', check),
|
helper.addEventListener(session, 'Page.frameAttached', check),
|
||||||
helper.addEventListener(session, 'Page.frameDetached', check),
|
helper.addEventListener(session, 'Page.frameDetached', check),
|
||||||
|
@ -26,6 +26,10 @@ class Puppeteer {
|
|||||||
executablePath() {
|
executablePath() {
|
||||||
return this._launcher.executablePath();
|
return this._launcher.executablePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultArgs(options) {
|
||||||
|
return this._launcher.defaultArgs(options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {Puppeteer};
|
module.exports = {Puppeteer};
|
||||||
|
@ -57,8 +57,8 @@ pref("browser.startup.homepage_override.mstone", "ignore");
|
|||||||
// Disable browser animations (tabs, fullscreen, sliding alerts)
|
// Disable browser animations (tabs, fullscreen, sliding alerts)
|
||||||
pref("toolkit.cosmeticAnimations.enabled", false);
|
pref("toolkit.cosmeticAnimations.enabled", false);
|
||||||
|
|
||||||
// Do not close the window when the last tab gets closed
|
// Close the window when the last tab gets closed
|
||||||
pref("browser.tabs.closeWindowWithLastTab", false);
|
pref("browser.tabs.closeWindowWithLastTab", true);
|
||||||
|
|
||||||
// Do not allow background tabs to be zombified on Android, otherwise for
|
// Do not allow background tabs to be zombified on Android, otherwise for
|
||||||
// tests that open additional tabs, the test harness tab itself might get
|
// tests that open additional tabs, the test harness tab itself might get
|
||||||
|
@ -174,32 +174,13 @@ class Launcher {
|
|||||||
connection = new Connection('', transport, slowMo);
|
connection = new Connection('', transport, slowMo);
|
||||||
}
|
}
|
||||||
const browser = await Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, chromeProcess, gracefullyCloseChrome);
|
const browser = await Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, chromeProcess, gracefullyCloseChrome);
|
||||||
await ensureInitialPage(browser);
|
await browser.waitForTarget(t => t.type() === 'page');
|
||||||
return browser;
|
return browser;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
killChrome();
|
killChrome();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {!Browser} browser
|
|
||||||
*/
|
|
||||||
async function ensureInitialPage(browser) {
|
|
||||||
// Wait for initial page target to be created.
|
|
||||||
if (browser.targets().find(target => target.type() === 'page'))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let initialPageCallback;
|
|
||||||
const initialPagePromise = new Promise(resolve => initialPageCallback = resolve);
|
|
||||||
const listeners = [helper.addEventListener(browser, 'targetcreated', target => {
|
|
||||||
if (target.type() === 'page')
|
|
||||||
initialPageCallback();
|
|
||||||
})];
|
|
||||||
|
|
||||||
await initialPagePromise;
|
|
||||||
helper.removeEventListeners(listeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +24,7 @@ const statAsync = helper.promisify(fs.stat);
|
|||||||
const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');
|
const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
|
||||||
module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, puppeteer}) {
|
module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, puppeteer, CHROME}) {
|
||||||
const {describe, xdescribe, fdescribe, describe_fails_ffox} = testRunner;
|
const {describe, xdescribe, fdescribe, describe_fails_ffox} = testRunner;
|
||||||
const {it, fit, xit, it_fails_ffox} = testRunner;
|
const {it, fit, xit, it_fails_ffox} = testRunner;
|
||||||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||||
@ -59,7 +59,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
await rmAsync(downloadsFolder);
|
await rmAsync(downloadsFolder);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe_fails_ffox('Browser.disconnect', function() {
|
describe('Browser.disconnect', function() {
|
||||||
it('should reject navigation when browser closes', async({server}) => {
|
it('should reject navigation when browser closes', async({server}) => {
|
||||||
server.setRoute('/one-style.css', () => {});
|
server.setRoute('/one-style.css', () => {});
|
||||||
const browser = await puppeteer.launch(defaultBrowserOptions);
|
const browser = await puppeteer.launch(defaultBrowserOptions);
|
||||||
@ -80,7 +80,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
const watchdog = page.waitForSelector('div', {timeout: 60000}).catch(e => e);
|
const watchdog = page.waitForSelector('div', {timeout: 60000}).catch(e => e);
|
||||||
await remote.disconnect();
|
await remote.disconnect();
|
||||||
const error = await watchdog;
|
const error = await watchdog;
|
||||||
expect(error.message).toBe('Protocol error (Runtime.callFunctionOn): Session closed. Most likely the page has been closed.');
|
expect(error.message).toContain('Protocol error');
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -94,13 +94,13 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
await neverResolves;
|
await neverResolves;
|
||||||
expect(error.message).toContain('Protocol error');
|
expect(error.message).toContain('Protocol error');
|
||||||
});
|
});
|
||||||
it_fails_ffox('should reject if executable path is invalid', async({server}) => {
|
it('should reject if executable path is invalid', async({server}) => {
|
||||||
let waitError = null;
|
let waitError = null;
|
||||||
const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'});
|
const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'});
|
||||||
await puppeteer.launch(options).catch(e => waitError = e);
|
await puppeteer.launch(options).catch(e => waitError = e);
|
||||||
expect(waitError.message.startsWith('Failed to launch chrome! spawn random-invalid-path ENOENT')).toBe(true);
|
expect(waitError.message).toContain('Failed to launch');
|
||||||
});
|
});
|
||||||
it_fails_ffox('userDataDir option', async({server}) => {
|
it('userDataDir option', async({server}) => {
|
||||||
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
||||||
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
||||||
const browser = await puppeteer.launch(options);
|
const browser = await puppeteer.launch(options);
|
||||||
@ -112,10 +112,21 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
||||||
await rmAsync(userDataDir).catch(e => {});
|
await rmAsync(userDataDir).catch(e => {});
|
||||||
});
|
});
|
||||||
it_fails_ffox('userDataDir argument', async({server}) => {
|
it('userDataDir argument', async({server}) => {
|
||||||
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
||||||
const options = Object.assign({}, defaultBrowserOptions);
|
const options = Object.assign({}, defaultBrowserOptions);
|
||||||
options.args = [`--user-data-dir=${userDataDir}`].concat(options.args || []);
|
if (CHROME) {
|
||||||
|
options.args = [
|
||||||
|
...(defaultBrowserOptions.args || []),
|
||||||
|
`--user-data-dir=${userDataDir}`
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
options.args = [
|
||||||
|
...(defaultBrowserOptions.args || []),
|
||||||
|
`-profile`,
|
||||||
|
userDataDir,
|
||||||
|
];
|
||||||
|
}
|
||||||
const browser = await puppeteer.launch(options);
|
const browser = await puppeteer.launch(options);
|
||||||
expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0);
|
expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
@ -123,7 +134,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
||||||
await rmAsync(userDataDir).catch(e => {});
|
await rmAsync(userDataDir).catch(e => {});
|
||||||
});
|
});
|
||||||
it_fails_ffox('userDataDir option should restore state', async({server}) => {
|
it('userDataDir option should restore state', async({server}) => {
|
||||||
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
||||||
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
||||||
const browser = await puppeteer.launch(options);
|
const browser = await puppeteer.launch(options);
|
||||||
@ -140,7 +151,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
||||||
await rmAsync(userDataDir).catch(e => {});
|
await rmAsync(userDataDir).catch(e => {});
|
||||||
});
|
});
|
||||||
it_fails_ffox('userDataDir option should restore cookies', async({server}) => {
|
it('userDataDir option should restore cookies', async({server}) => {
|
||||||
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
const userDataDir = await mkdtempAsync(TMP_FOLDER);
|
||||||
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
const options = Object.assign({userDataDir}, defaultBrowserOptions);
|
||||||
const browser = await puppeteer.launch(options);
|
const browser = await puppeteer.launch(options);
|
||||||
@ -157,11 +168,18 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
// This might throw. See https://github.com/GoogleChrome/puppeteer/issues/2778
|
||||||
await rmAsync(userDataDir).catch(e => {});
|
await rmAsync(userDataDir).catch(e => {});
|
||||||
});
|
});
|
||||||
it_fails_ffox('should return the default chrome arguments', async() => {
|
it('should return the default arguments', async() => {
|
||||||
|
if (CHROME) {
|
||||||
expect(puppeteer.defaultArgs()).toContain('--no-first-run');
|
expect(puppeteer.defaultArgs()).toContain('--no-first-run');
|
||||||
expect(puppeteer.defaultArgs()).toContain('--headless');
|
expect(puppeteer.defaultArgs()).toContain('--headless');
|
||||||
expect(puppeteer.defaultArgs({headless: false})).not.toContain('--headless');
|
expect(puppeteer.defaultArgs({headless: false})).not.toContain('--headless');
|
||||||
expect(puppeteer.defaultArgs({userDataDir: 'foo'})).toContain('--user-data-dir=foo');
|
expect(puppeteer.defaultArgs({userDataDir: 'foo'})).toContain('--user-data-dir=foo');
|
||||||
|
} else {
|
||||||
|
expect(puppeteer.defaultArgs()).toContain('-headless');
|
||||||
|
expect(puppeteer.defaultArgs({headless: false})).not.toContain('-headless');
|
||||||
|
expect(puppeteer.defaultArgs({userDataDir: 'foo'})).toContain('-profile');
|
||||||
|
expect(puppeteer.defaultArgs({userDataDir: 'foo'})).toContain('foo');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
it('should dump browser process stderr', async({server}) => {
|
it('should dump browser process stderr', async({server}) => {
|
||||||
const dumpioTextToLog = 'MAGIC_DUMPIO_TEST';
|
const dumpioTextToLog = 'MAGIC_DUMPIO_TEST';
|
||||||
@ -196,34 +214,6 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
process.kill(res.pid);
|
process.kill(res.pid);
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
});
|
});
|
||||||
it_fails_ffox('should support the pipe option', async() => {
|
|
||||||
const options = Object.assign({pipe: true}, defaultBrowserOptions);
|
|
||||||
const browser = await puppeteer.launch(options);
|
|
||||||
expect((await browser.pages()).length).toBe(1);
|
|
||||||
expect(browser.wsEndpoint()).toBe('');
|
|
||||||
const page = await browser.newPage();
|
|
||||||
expect(await page.evaluate('11 * 11')).toBe(121);
|
|
||||||
await page.close();
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
it_fails_ffox('should support the pipe argument', async() => {
|
|
||||||
const options = Object.assign({}, defaultBrowserOptions);
|
|
||||||
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
|
||||||
const browser = await puppeteer.launch(options);
|
|
||||||
expect(browser.wsEndpoint()).toBe('');
|
|
||||||
const page = await browser.newPage();
|
|
||||||
expect(await page.evaluate('11 * 11')).toBe(121);
|
|
||||||
await page.close();
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
it_fails_ffox('should fire "disconnected" when closing with pipe', async() => {
|
|
||||||
const options = Object.assign({pipe: true}, defaultBrowserOptions);
|
|
||||||
const browser = await puppeteer.launch(options);
|
|
||||||
const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve));
|
|
||||||
// Emulate user exiting browser.
|
|
||||||
browser.process().kill();
|
|
||||||
await disconnectedEventPromise;
|
|
||||||
});
|
|
||||||
it('should work with no default arguments', async() => {
|
it('should work with no default arguments', async() => {
|
||||||
const options = Object.assign({}, defaultBrowserOptions);
|
const options = Object.assign({}, defaultBrowserOptions);
|
||||||
options.ignoreDefaultArgs = true;
|
options.ignoreDefaultArgs = true;
|
||||||
@ -233,7 +223,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
await page.close();
|
await page.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
it_fails_ffox('should filter out ignored default arguments', async() => {
|
it('should filter out ignored default arguments', async() => {
|
||||||
// Make sure we launch with `--enable-automation` by default.
|
// Make sure we launch with `--enable-automation` by default.
|
||||||
const defaultArgs = puppeteer.defaultArgs();
|
const defaultArgs = puppeteer.defaultArgs();
|
||||||
const browser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
const browser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
||||||
@ -253,15 +243,14 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
it_fails_ffox('should have custom url when launching browser', async function({server}) {
|
it_fails_ffox('should have custom url when launching browser', async function({server}) {
|
||||||
const customUrl = server.PREFIX + '/empty.html';
|
|
||||||
const options = Object.assign({}, defaultBrowserOptions);
|
const options = Object.assign({}, defaultBrowserOptions);
|
||||||
options.args = [customUrl].concat(options.args || []);
|
options.args = [server.EMPTY_PAGE].concat(options.args || []);
|
||||||
const browser = await puppeteer.launch(options);
|
const browser = await puppeteer.launch(options);
|
||||||
const pages = await browser.pages();
|
const pages = await browser.pages();
|
||||||
expect(pages.length).toBe(1);
|
expect(pages.length).toBe(1);
|
||||||
if (pages[0].url() !== customUrl)
|
if (pages[0].url() !== server.EMPTY_PAGE)
|
||||||
await pages[0].waitForNavigation();
|
await pages[0].waitForNavigation();
|
||||||
expect(pages[0].url()).toBe(customUrl);
|
expect(pages[0].url()).toBe(server.EMPTY_PAGE);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
it('should set the default viewport', async() => {
|
it('should set the default viewport', async() => {
|
||||||
@ -300,6 +289,85 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// "browserURL" is a chrome-only option.
|
||||||
|
(CHROME ? describe : xdescribe)('|browserURL| option', function() {
|
||||||
|
it('should be able to connect using browserUrl, with and without trailing slash', async({server}) => {
|
||||||
|
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
||||||
|
args: ['--remote-debugging-port=21222']
|
||||||
|
}));
|
||||||
|
const browserURL = 'http://127.0.0.1:21222';
|
||||||
|
|
||||||
|
const browser1 = await puppeteer.connect({browserURL});
|
||||||
|
const page1 = await browser1.newPage();
|
||||||
|
expect(await page1.evaluate(() => 7 * 8)).toBe(56);
|
||||||
|
browser1.disconnect();
|
||||||
|
|
||||||
|
const browser2 = await puppeteer.connect({browserURL: browserURL + '/'});
|
||||||
|
const page2 = await browser2.newPage();
|
||||||
|
expect(await page2.evaluate(() => 8 * 7)).toBe(56);
|
||||||
|
browser2.disconnect();
|
||||||
|
originalBrowser.close();
|
||||||
|
});
|
||||||
|
it('should throw when using both browserWSEndpoint and browserURL', async({server}) => {
|
||||||
|
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
||||||
|
args: ['--remote-debugging-port=21222']
|
||||||
|
}));
|
||||||
|
const browserURL = 'http://127.0.0.1:21222';
|
||||||
|
|
||||||
|
let error = null;
|
||||||
|
await puppeteer.connect({browserURL, browserWSEndpoint: originalBrowser.wsEndpoint()}).catch(e => error = e);
|
||||||
|
expect(error.message).toContain('Exactly one of browserWSEndpoint, browserURL or transport');
|
||||||
|
|
||||||
|
originalBrowser.close();
|
||||||
|
});
|
||||||
|
it('should throw when trying to connect to non-existing browser', async({server}) => {
|
||||||
|
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
||||||
|
args: ['--remote-debugging-port=21222']
|
||||||
|
}));
|
||||||
|
const browserURL = 'http://127.0.0.1:32333';
|
||||||
|
|
||||||
|
let error = null;
|
||||||
|
await puppeteer.connect({browserURL}).catch(e => error = e);
|
||||||
|
if (CHROME)
|
||||||
|
expect(error.message).toContain('Failed to fetch browser webSocket url from');
|
||||||
|
else
|
||||||
|
expect(error.message).toContain('Invalid URL');
|
||||||
|
|
||||||
|
originalBrowser.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// "pipe" is a chrome-only feature.
|
||||||
|
(CHROME ? describe : xdescribe)('|pipe| option', function() {
|
||||||
|
it('should support the pipe option', async() => {
|
||||||
|
const options = Object.assign({pipe: true}, defaultBrowserOptions);
|
||||||
|
const browser = await puppeteer.launch(options);
|
||||||
|
expect((await browser.pages()).length).toBe(1);
|
||||||
|
expect(browser.wsEndpoint()).toBe('');
|
||||||
|
const page = await browser.newPage();
|
||||||
|
expect(await page.evaluate('11 * 11')).toBe(121);
|
||||||
|
await page.close();
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
it('should support the pipe argument', async() => {
|
||||||
|
const options = Object.assign({}, defaultBrowserOptions);
|
||||||
|
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
||||||
|
const browser = await puppeteer.launch(options);
|
||||||
|
expect(browser.wsEndpoint()).toBe('');
|
||||||
|
const page = await browser.newPage();
|
||||||
|
expect(await page.evaluate('11 * 11')).toBe(121);
|
||||||
|
await page.close();
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
it('should fire "disconnected" when closing with pipe', async() => {
|
||||||
|
const options = Object.assign({pipe: true}, defaultBrowserOptions);
|
||||||
|
const browser = await puppeteer.launch(options);
|
||||||
|
const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve));
|
||||||
|
// Emulate user exiting browser.
|
||||||
|
browser.process().kill();
|
||||||
|
await disconnectedEventPromise;
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('Puppeteer.connect', function() {
|
describe('Puppeteer.connect', function() {
|
||||||
it('should be able to connect multiple times to the same browser', async({server}) => {
|
it('should be able to connect multiple times to the same browser', async({server}) => {
|
||||||
const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
|
const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
|
||||||
@ -359,47 +427,6 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
expect(await restoredPage.evaluate(() => 7 * 8)).toBe(56);
|
expect(await restoredPage.evaluate(() => 7 * 8)).toBe(56);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
it_fails_ffox('should be able to connect using browserUrl, with and without trailing slash', async({server}) => {
|
|
||||||
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
|
||||||
args: ['--remote-debugging-port=21222']
|
|
||||||
}));
|
|
||||||
const browserURL = 'http://127.0.0.1:21222';
|
|
||||||
|
|
||||||
const browser1 = await puppeteer.connect({browserURL});
|
|
||||||
const page1 = await browser1.newPage();
|
|
||||||
expect(await page1.evaluate(() => 7 * 8)).toBe(56);
|
|
||||||
browser1.disconnect();
|
|
||||||
|
|
||||||
const browser2 = await puppeteer.connect({browserURL: browserURL + '/'});
|
|
||||||
const page2 = await browser2.newPage();
|
|
||||||
expect(await page2.evaluate(() => 8 * 7)).toBe(56);
|
|
||||||
browser2.disconnect();
|
|
||||||
originalBrowser.close();
|
|
||||||
});
|
|
||||||
it_fails_ffox('should throw when using both browserWSEndpoint and browserURL', async({server}) => {
|
|
||||||
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
|
||||||
args: ['--remote-debugging-port=21222']
|
|
||||||
}));
|
|
||||||
const browserURL = 'http://127.0.0.1:21222';
|
|
||||||
|
|
||||||
let error = null;
|
|
||||||
await puppeteer.connect({browserURL, browserWSEndpoint: originalBrowser.wsEndpoint()}).catch(e => error = e);
|
|
||||||
expect(error.message).toContain('Exactly one of browserWSEndpoint, browserURL or transport');
|
|
||||||
|
|
||||||
originalBrowser.close();
|
|
||||||
});
|
|
||||||
it_fails_ffox('should throw when trying to connect to non-existing browser', async({server}) => {
|
|
||||||
const originalBrowser = await puppeteer.launch(Object.assign({}, defaultBrowserOptions, {
|
|
||||||
args: ['--remote-debugging-port=21222']
|
|
||||||
}));
|
|
||||||
const browserURL = 'http://127.0.0.1:32333';
|
|
||||||
|
|
||||||
let error = null;
|
|
||||||
await puppeteer.connect({browserURL}).catch(e => error = e);
|
|
||||||
expect(error.message).toContain('Failed to fetch browser webSocket url from');
|
|
||||||
|
|
||||||
originalBrowser.close();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
describe('Puppeteer.executablePath', function() {
|
describe('Puppeteer.executablePath', function() {
|
||||||
it('should work', async({server}) => {
|
it('should work', async({server}) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user