Skip to content

Commit

Permalink
terminology fixes and docs added to extension
Browse files Browse the repository at this point in the history
  • Loading branch information
brendankenny committed Aug 27, 2016
1 parent ca444bf commit 8dbd6fa
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 70 deletions.
97 changes: 66 additions & 31 deletions lighthouse-extension/app/src/lighthouse-background.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const ExtensionProtocol = require('../../../lighthouse-core/gather/drivers/extension');
const Runner = require('../../../lighthouse-core/runner');
const Config = require('../../../lighthouse-core/config/config');
const configJSON = require('../../../lighthouse-core/config/default.json');
const defaultConfig = require('../../../lighthouse-core/config/default.json');
const log = require('../../../lighthouse-core/lib/log');

const STORAGE_KEY = 'lighthouse_audits';
const _flatten = arr => [].concat.apply([], arr);

Expand All @@ -39,27 +39,45 @@ window.createPageAndPopulate = function(results) {
});
};

window.runAudits = function(options, audits) {
/**
* @param {!Object} options Lighthouse options.
* @param {!Array<string>} requestedAudits Names of audits to run.
* @return {!Promise}
*/
window.runLighthouse = function(options, requestedAudits) {
// Default to 'info' logging level.
log.setLevel('info');
const driver = new ExtensionProtocol();

return driver.getCurrentTabURL()
.then(url => {
// Setup the run config, audits are calculated by selected options
const config = new Config(configJSON, new Set(audits));

// Add in the URL to the options.
return Runner.run(driver, Object.assign({}, options, {url, config}));
}).catch(e => {
console.error(e);
throw e;
});
.then(url => {
// Always start with a freshly parsed default config.
const runConfig = JSON.parse(JSON.stringify(defaultConfig));

// Filter out audits not requested.
requestedAudits = new Set(requestedAudits);
runConfig.audits = runConfig.audits.filter(audit => requestedAudits.has(audit));
const config = new Config(runConfig);

// Add url and config to fresh options object.
const runOptions = Object.assign({}, options, {url, config});

// Run Lighthouse.
return Runner.run(driver, runOptions);
}).catch(e => {
console.error(e);
throw e;
});
};

window.getListOfAudits = function() {
/**
* Returns list of aggregation categories (each with a list of its constituent
* audits) from the default config.
* @return {!Array<{name: string, audits: !Array<string>}>}
*/
window.getDefaultAggregations = function() {
return _flatten(
configJSON.aggregations.map(aggregation => {
defaultConfig.aggregations.map(aggregation => {
if (aggregation.items.length === 1) {
return {
name: aggregation.name,
Expand All @@ -69,34 +87,51 @@ window.getListOfAudits = function() {

return aggregation.items;
})
);
).map(aggregation => {
return {
name: aggregation.name,
audits: Object.keys(aggregation.criteria)
};
});
};

window.saveAudits = function(audits) {
let storage = {};
storage[STORAGE_KEY] = {};

window.getListOfAudits().forEach(audit => {
storage[STORAGE_KEY][audit.name] = audits.indexOf(audit.name) > -1;
/**
* Save currently selected set of aggregation categories to local storage.
* @param {!Array<{name: string, audits: !Array<string>}>} selectedAggregations
*/
window.saveSelectedAggregations = function(selectedAggregations) {
const storage = {
[STORAGE_KEY]: {}
};

window.getDefaultAggregations().forEach(audit => {
const selected = selectedAggregations.indexOf(audit.name) > -1;
storage[STORAGE_KEY][audit.name] = selected;
});

chrome.storage.local.set(storage);
};

window.fetchAudits = function() {
/**
* Load selected aggregation categories from local storage.
* @return {!Promise<!Object<boolean>>}
*/
window.loadSelectedAggregations = function() {
return new Promise(resolve => {
chrome.storage.local.get(STORAGE_KEY, result => {
const audits = result[STORAGE_KEY];

// create list of default audits
let defaultAudits = {};
window.getListOfAudits().forEach(audit => {
defaultAudits[audit.name] = true;
// Start with list of all default aggregations set to true so list is
// always up to date.
const defaultAggregations = {};
window.getDefaultAggregations().forEach(aggregation => {
defaultAggregations[aggregation.name] = true;
});

// merge default and saved audits together so we always have the latest list of audits
// Load saved aggregation selections.
const savedSelections = result[STORAGE_KEY];

// Overwrite defaults with any saved aggregation selections.
resolve(
Object.assign({}, defaultAudits, audits)
Object.assign(defaultAggregations, savedSelections)
);
});
});
Expand Down
96 changes: 57 additions & 39 deletions lighthouse-extension/app/src/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';

const _flatten = arr => [].concat.apply([], arr);

document.addEventListener('DOMContentLoaded', _ => {
const background = chrome.extension.getBackgroundPage();
const aggregations = background.getListOfAudits();
const defaultAggregations = background.getDefaultAggregations();

const siteNameEl = window.document.querySelector('header h2');
const generateReportEl = document.getElementById('generate-report');
Expand All @@ -38,7 +39,7 @@ document.addEventListener('DOMContentLoaded', _ => {

let spinnerAnimation;

const startSpinner = _ => {
function startSpinner() {
statusEl.classList.add(subpageVisibleClass);
spinnerAnimation = spinnerEl.animate([
{transform: 'rotate(0deg)'},
Expand All @@ -47,72 +48,88 @@ document.addEventListener('DOMContentLoaded', _ => {
duration: 1000,
iterations: Infinity
});
};
}

const stopSpinner = _ => {
function stopSpinner() {
spinnerAnimation.cancel();
statusEl.classList.remove(subpageVisibleClass);
};
}

const logstatus = ([, message, details]) => {
function logstatus([, message, details]) {
statusMessageEl.textContent = message;
statusDetailsMessageEl.textContent = details;
};
}

const createOptionItem = (text, isChecked) => {
function createOptionItem(text, isChecked) {
const input = document.createElement('input');
const attributes = [['type', 'checkbox'], ['value', text]];
input.setAttribute('type', 'checkbox');
input.setAttribute('value', text);
if (isChecked) {
attributes.push(['checked', 'checked']);
input.setAttribute('checked', 'checked');
}

attributes.forEach(attr => input.setAttribute.apply(input, attr));

const label = document.createElement('label');
label.appendChild(input);
label.appendChild(document.createTextNode(text));
const listItem = document.createElement('li');
listItem.appendChild(label);

return listItem;
};

const generateOptionsList = (list, selectedAudits) => {
}

/**
* Generates a document fragment containing a list of checkboxes and labels
* for the aggregation categories.
* @param {!Object<boolean>} selectedAggregations
* @return {!DocumentFragment}
*/
function generateOptionsList(list, selectedAggregations) {
const frag = document.createDocumentFragment();

aggregations.forEach(aggregation => {
frag.appendChild(createOptionItem(aggregation.name, selectedAudits[aggregation.name]));
defaultAggregations.forEach(aggregation => {
const isChecked = selectedAggregations[aggregation.name];
frag.appendChild(createOptionItem(aggregation.name, isChecked));
});

list.appendChild(frag);
};
return frag;
}

/**
* Returns an array of names of audits from the selected aggregation
* categories.
* @param {!Object<boolean>} selectedAggregations
* @return {!Array<string>}
*/
function getAuditsFromSelected(selectedAggregations) {
const auditLists = defaultAggregations.filter(aggregation => {
return selectedAggregations[aggregation.name];
}).map(selectedAggregation => {
return selectedAggregation.audits;
});

const getAuditsFromCategory = audits => _flatten(
Object.keys(audits).filter(audit => audits[audit]).map(audit => {
const auditsInCategory = aggregations
.find(aggregation => aggregation.name === audit).criteria;

return Object.keys(auditsInCategory);
})
);
return _flatten(auditLists);
}

background.listenForStatus(logstatus);
background.fetchAudits().then(audits => {
generateOptionsList(optionsList, audits);
background.loadSelectedAggregations().then(aggregations => {
const frag = generateOptionsList(optionsList, aggregations);
optionsList.appendChild(frag);
});

generateReportEl.addEventListener('click', () => {
startSpinner();
feedbackEl.textContent = '';

background.fetchAudits()
.then(getAuditsFromCategory)
.then(audits => background.runAudits({
flags: {
mobile: true,
loadPage: true
}
}, audits))
background.loadSelectedAggregations()
.then(getAuditsFromSelected)
.then(selectedAudits => {
return background.runLighthouse({
flags: {
mobile: true,
loadPage: true
}
}, selectedAudits);
})
.then(results => {
background.createPageAndPopulate(results);
})
Expand All @@ -133,9 +150,10 @@ document.addEventListener('DOMContentLoaded', _ => {
});

okButton.addEventListener('click', () => {
const checkedAudits = Array.from(optionsEl.querySelectorAll(':checked'))
// Save selected aggregation categories on options page close.
const checkedAggregations = Array.from(optionsEl.querySelectorAll(':checked'))
.map(input => input.value);
background.saveAudits(checkedAudits);
background.saveSelectedAggregations(checkedAggregations);

optionsEl.classList.remove(subpageVisibleClass);
});
Expand Down

0 comments on commit 8dbd6fa

Please sign in to comment.