[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop the trace when multiple tabs are found. #639

Merged
merged 14 commits into from
Oct 28, 2016
Prev Previous commit
Next Next commit
Merge branch 'master' into sw/warn-tabs
  • Loading branch information
wardpeet committed Oct 25, 2016
commit fcf2b0b90924c97a8d18ee9234673beda636a641
244 changes: 1 addition & 243 deletions lighthouse-cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,246 +2,4 @@

'use strict'

const environment = require('../lighthouse-core/lib/environment.js');
if (!environment.checkNodeCompatibility()) {
console.warn('Compatibility error', 'Lighthouse requires node 5+ or 4 with --harmony');
process.exit(1);
}

const path = require('path');
const yargs = require('yargs');
const Printer = require('./printer');
const lighthouse = require('../lighthouse-core');
const assetSaver = require('../lighthouse-core/lib/asset-saver.js');
const ChromeLauncher = require('./chrome-launcher');

const perfOnlyConfig = require('../lighthouse-core/config/perf.json');

const cli = yargs
.help('help')
.version(() => require('../package').version)
.showHelpOnFail(false, 'Specify --help for available options')

.usage('$0 url')

// List of options
.group([
'verbose',
'quiet'
], 'Logging:')
.describe({
verbose: 'Displays verbose logging',
quiet: 'Displays no progress or debug logs'
})

.group([
'mobile',
'save-assets',
'save-artifacts',
'list-all-audits',
'list-trace-categories',
'config-path',
'perf'
], 'Configuration:')
.describe({
'mobile': 'Emulates a Nexus 5X',
'save-assets': 'Save the trace contents & screenshots to disk',
'save-artifacts': 'Save all gathered artifacts to disk',
'list-all-audits': 'Prints a list of all available audits and exits',
'list-trace-categories': 'Prints a list of all required trace categories and exits',
'config-path': 'The path to the config JSON.',
'perf': 'Use a performance-test-only configuration',
'skip-autolaunch': 'Skip autolaunch of chrome when accessing port 9222 fails',
'select-chrome': 'Choose chrome location to use when multiple installations are found',
})

.group([
'output',
'output-path'
], 'Output:')
.describe({
'output': 'Reporter for the results',
'output-path': `The file path to output the results
Example: --output-path=./lighthouse-results.html`
})

// boolean values
.boolean([
'save-assets',
'save-artifacts',
'list-all-audits',
'list-trace-categories',
'mobile',
'perf',
'skip-autolaunch',
'select-chrome',
'verbose',
'quiet',
'help'
])

.choices('output', Object.keys(Printer.OUTPUT_MODE))

// default values
.default('mobile', true)
.default('output', Printer.OUTPUT_MODE.pretty)
.default('output-path', 'stdout')
.check(argv => {
// Make sure lighthouse has been passed a url, or at least one of --list-all-audits
// or --list-trace-categories. If not, stop the program and ask for a url
if (!argv.listAllAudits && !argv.listTraceCategories && argv._.length === 0) {
throw new Error('Please provide a url');
}

return true;
})
.argv;

if (cli.listAllAudits) {
const audits = lighthouse
.getAuditList()
.map(i => {
return i.replace(/\.js$/, '');
});

process.stdout.write(JSON.stringify({audits}));
process.exit(0);
}

if (cli.listTraceCategories) {
const traceCategories = lighthouse.traceCategories;

process.stdout.write(JSON.stringify({traceCategories}));
process.exit(0);
}

const urls = cli._;
const outputMode = cli.output;
const outputPath = cli['output-path'];
const flags = cli;

let config = null;
if (cli.configPath) {
// Resolve the config file path relative to where cli was called.
cli.configPath = path.resolve(process.cwd(), cli.configPath);
config = require(cli.configPath);
} else if (cli.perf) {
config = perfOnlyConfig;
}

// set logging preferences
flags.logLevel = 'info';
if (cli.verbose) {
flags.logLevel = 'verbose';
} else if (cli.quiet) {
flags.logLevel = 'error';
}

const cleanup = {
fns: [],
register(fn) {
this.fns.push(fn);
},
doCleanup() {
return Promise.all(this.fns.map(c => c()));
}
};

function launchChromeAndRun(addresses) {
const launcher = new ChromeLauncher({
autoSelectChrome: !cli.selectChrome,
});

cleanup.register(() => launcher.kill());

return launcher
.isDebuggerReady()
.catch(() => {
console.log('Launching Chrome...');
return launcher.run();
})
.then(() => lighthouseRun(addresses))
.then(() => launcher.kill());
}

function lighthouseRun(addresses) {
// Process URLs once at a time
const address = addresses.shift();
if (!address) {
return;
}

return lighthouse(address, flags, config)
.then(results => Printer.write(results, outputMode, outputPath))
.then(results => {
if (outputMode !== 'html') {
const filename = './' + assetSaver.getFilenamePrefix({url: address}) + '.html';
Printer.write(results, 'html', filename);
}

return lighthouseRun(addresses);
})
.catch(err => {
if (err.code === 'ECONNREFUSED') {
showConnectionError();
} else if (err) {
showRuntimeError(err);
}
});
}

function showConnectionError() {
console.error('Unable to connect to Chrome');
console.error(
'If you\'re using lighthouse with --skip-autolaunch, ' +
'make sure you\'re running some other Chrome with a debugger.'
);
process.exit(1);
}

function showRuntimeError(err) {
console.error('Runtime error encountered:', err);
console.error(err.stack);
process.exit(1);
}

function handleError(err) {
if (err.code === 'ECONNREFUSED') {
showConnectionError();
} else if (err.message.toLowerCase().includes('multiple tabs')) {
console.error(err.message);
} else {
showRuntimeError(err);
}
}

function run() {
if (cli.skipAutolaunch) {
lighthouseRun(urls).catch(handleError);
} else {
// because you can't cancel a promise yet
const SIGINT = Symbol('SIGINT');
const isSigint = new Promise((resolve, reject) => {
process.on('SIGINT', () => reject(SIGINT));
});

Promise
.race([launchChromeAndRun(urls), isSigint])
.catch(maybeSigint => {
if (maybeSigint === SIGINT) {
return cleanup
.doCleanup()
.then(() => process.exit(130))
.catch(err => {
console.error(err);
console.error(err.stack);
process.exit(130);
});
}
return handleError(maybeSigint);
});
}
}

// kick off a lighthouse run
run();
require('./bin.js').run();
46 changes: 46 additions & 0 deletions lighthouse-core/gather/drivers/cri.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,52 @@ class CriConnection extends Connection {
});
}

/**
* @return {!Promise<string>}
*/
_runJsonCommand(command) {
return new Promise((resolve, reject) => {
http.get({
hostname: hostname,
port: port,
path: '/json/' + command
}, response => {
var data = '';
response.on('data', chunk => {
data += chunk;
});
response.on('end', _ => {
if (response.statusCode === 200) {
resolve(JSON.parse(data));
return;
}
reject('Unable to fetch webSocketDebuggerUrl, status: ' + response.statusCode);
});
});
});
}

/**
* @override
*/
disconnect() {
if (!this._ws) {
return Promise.reject('connect() must be called before attempting to disconnect.');
}
this._ws.removeAllListeners();
this._ws.close();
this._ws = null;
return Promise.resolve();
}

/**
* @override
* @param {string} message
*/
sendRawMessage(message) {
this._ws.send(message);
}

getCurrentTabId() {
return Promise.resolve(this._tab.id);
}
Expand Down
13 changes: 4 additions & 9 deletions lighthouse-core/gather/gather-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,10 @@ class GatherRunner {
log.log('status', 'Initializing…');
// Enable emulation if required.
return Promise.resolve(options.flags.mobile && driver.beginEmulation())
.then(_ => {
return driver.cleanAndDisableBrowserCaches();
}).then(_ => {
// Check if multiple tabs of origin are open
return driver.checkForMultipleTabsAttached(options.url);
}).then(_ => {
// Clears storage for origin.
return driver.clearDataForOrigin(options.url);
});
.then(_ => driver.enableRuntimeEvents())
.then(_ => driver.cleanAndDisableBrowserCaches())
.then(_ => driver.checkForMultipleTabsAttached(options.url))
.then(_ => driver.clearDataForOrigin(options.url));
}

static disposeDriver(driver) {
Expand Down
7 changes: 3 additions & 4 deletions lighthouse-core/test/gather/fake-driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,15 @@ module.exports = {
beginEmulation() {
return Promise.resolve();
},

checkForMultipleTabsAttached() {
return Promise.resolve();
},

cleanAndDisableBrowserCaches() {},
clearDataForOrigin() {},
reloadForCleanStateIfNeeded() {
return Promise.resolve();
},
enableRuntimeEvents() {
return Promise.resolve();
},
cleanAndDisableBrowserCaches() {},
clearDataForOrigin() {},
beginTrace() {
Expand Down
26 changes: 20 additions & 6 deletions lighthouse-core/test/gather/gather-runner-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,16 @@ describe('GatherRunner', function() {
calledEmulation = true;
return Promise.resolve();
},
cleanAndDisableBrowserCaches() {},
clearDataForOrigin() {},
checkForMultipleTabsAttached() {}
enableRuntimeEvents() {
return Promise.resolve();
},
checkForMultipleTabsAttached() {},
cleanAndDisableBrowserCaches() {
return Promise.resolve();
},
clearDataForOrigin() {
return Promise.resolve();
}
};

return GatherRunner.setupDriver(driver, {
Expand All @@ -105,9 +112,16 @@ describe('GatherRunner', function() {
calledEmulation = true;
return Promise.resolve();
},
cleanAndDisableBrowserCaches() {},
clearDataForOrigin() {},
checkForMultipleTabsAttached() {}
enableRuntimeEvents() {
return Promise.resolve();
},
checkForMultipleTabsAttached() {},
cleanAndDisableBrowserCaches() {
return Promise.resolve();
},
clearDataForOrigin() {
return Promise.resolve();
}
};

return GatherRunner.setupDriver(driver, {
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/test/lib/drivers/driver-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function createActiveWorker(id, url, controlledClients) {
};
}

driverStub.sendCommand = function(command, params) {
connection.sendCommand = function(command, params) {
switch (command) {
case 'DOM.getDocument':
return Promise.resolve({root: {nodeId: 249}});
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.