This commit is contained in:
Brendan Kenny 2017-03-08 14:42:22 -08:00 коммит произвёл Brendan Kenny
Родитель e54fc41d7f
Коммит b5afd60e3b
68 изменённых файлов: 184 добавлений и 574 удалений

Просмотреть файл

@ -20,4 +20,4 @@ lighthouse-cli/types/*.js
# Handlebar-templates
lighthouse-core/report/templates/report-templates.js
lighthouse-core/formatters/partials/templates/report-partials.js
lighthouse-core/report/partials/templates/report-partials.js

2
.gitignore поставляемый
Просмотреть файл

@ -38,5 +38,5 @@ lighthouse-cli/types/*.map
/chrome-win32/
/chrome.zip
lighthouse-core/formatters/partials/templates/
lighthouse-core/report/partials/templates/
lighthouse-core/report/templates/*.js

Просмотреть файл

@ -18,7 +18,7 @@
module.exports = {
report: 'lighthouse-core/**/templates/*.html',
reportDist: 'lighthouse-core/report/templates/',
partials: 'lighthouse-core/formatters/partials/*.html',
partialsDist: 'lighthouse-core/formatters/partials/templates/',
partials: 'lighthouse-core/report/partials/*.html',
partialsDist: 'lighthouse-core/report/partials/templates/',
dist: 'dist'
};

Просмотреть файл

@ -32,8 +32,8 @@ class PerfXReportGenerator extends ReportGenerator {
return scriptArr;
}
_registerFormatters(audits) {
super._registerFormatters(audits);
_registerPartials(audits) {
super._registerPartials(audits);
const configPanelTemplate = Handlebars.compile(configPanelPartial);
const criticalRequestChains = audits['critical-request-chains'].extendedInfo.value;
Handlebars.registerPartial('config-panel', configPanelTemplate(criticalRequestChains));

Просмотреть файл

@ -29,7 +29,6 @@ import {Results, AuditResult} from './types/types';
const fs = require('fs');
const ReportGenerator = require('../lighthouse-core/report/report-generator');
const Formatter = require('../lighthouse-core/formatters/formatter');
const log = require('../lighthouse-core/lib/log');

Просмотреть файл

@ -23,7 +23,7 @@
*/
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class AxeAudit extends Audit {
/**

Просмотреть файл

@ -17,7 +17,7 @@
'use strict';
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
const KB_IN_BYTES = 1024;
const WASTEFUL_THRESHOLD_IN_BYTES = 20 * KB_IN_BYTES;

Просмотреть файл

@ -20,7 +20,7 @@
'use strict';
const Audit = require('./byte-efficiency-audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
const TracingProcessor = require('../../lib/traces/tracing-processor');
const URL = require('../../lib/url-shim');

Просмотреть файл

@ -18,7 +18,7 @@
'use strict';
const Audit = require('./audit');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
class CriticalRequestChains extends Audit {
/**

Просмотреть файл

@ -23,7 +23,7 @@
*/
const Audit = require('./audit');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
class Deprecations extends Audit {
/**

Просмотреть файл

@ -25,7 +25,7 @@
const Audit = require('../audit');
const TracingProcessor = require('../../lib/traces/tracing-processor');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
const MAX_DOM_NODES = 1500;
const MAX_DOM_TREE_WIDTH = 60;

Просмотреть файл

@ -19,7 +19,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class ExternalAnchorsUseRelNoopenerAudit extends Audit {
/**

Просмотреть файл

@ -23,7 +23,7 @@
'use strict';
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class GeolocationOnStart extends Audit {
/**

Просмотреть файл

@ -23,7 +23,7 @@
const Audit = require('../audit');
const URL = require('../../lib/url-shim');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class LinkBlockingFirstPaintAudit extends Audit {

Просмотреть файл

@ -23,7 +23,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NoConsoleTimeAudit extends Audit {

Просмотреть файл

@ -24,7 +24,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NoDateNowAudit extends Audit {

Просмотреть файл

@ -22,7 +22,7 @@
'use strict';
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NoDocWriteAudit extends Audit {

Просмотреть файл

@ -25,7 +25,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const EventHelpers = require('../../lib/event-helpers');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NoMutationEventsAudit extends Audit {

Просмотреть файл

@ -25,7 +25,7 @@
const Audit = require('../audit');
const URL = require('../../lib/url-shim');
const StyleHelpers = require('../../lib/styles-helpers');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NoOldFlexboxAudit extends Audit {

Просмотреть файл

@ -23,7 +23,7 @@
'use strict';
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class NotificationOnStart extends Audit {
/**

Просмотреть файл

@ -24,7 +24,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class UsesHTTP2Audit extends Audit {

Просмотреть файл

@ -25,7 +25,7 @@
const URL = require('../../lib/url-shim');
const Audit = require('../audit');
const EventHelpers = require('../../lib/event-helpers');
const Formatter = require('../../formatters/formatter');
const Formatter = require('../../report/formatter');
class PassiveEventsAudit extends Audit {

Просмотреть файл

@ -18,7 +18,7 @@
const Audit = require('./audit');
const TracingProcessor = require('../lib/traces/tracing-processor');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
// Parameters (in ms) for log-normal CDF scoring. To see the curve:
// https://www.desmos.com/calculator/srv0hqhf7d

Просмотреть файл

@ -19,7 +19,7 @@
const Audit = require('./audit');
const TracingProcessor = require('../lib/traces/tracing-processor');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
// Parameters (in ms) for log-normal CDF scoring. To see the curve:
// https://www.desmos.com/calculator/joz3pqttdq

Просмотреть файл

@ -18,7 +18,7 @@
'use strict';
const Audit = require('./audit');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
class ManifestBackgroundColor extends Audit {
/**

Просмотреть файл

@ -18,7 +18,7 @@
'use strict';
const Audit = require('./audit');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
class Screenshots extends Audit {
/**

Просмотреть файл

@ -19,7 +19,7 @@
const Audit = require('./audit');
const TracingProcessor = require('../lib/traces/tracing-processor');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
// Parameters (in ms) for log-normal CDF scoring. To see the curve:
// https://www.desmos.com/calculator/mdgjzchijg

Просмотреть файл

@ -11,7 +11,7 @@
const Audit = require('./audit');
const TracingProcessor = require('../lib/traces/tracing-processor');
const FMPMetric = require('./first-meaningful-paint');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
// Parameters (in ms) for log-normal CDF scoring. To see the curve:
// https://www.desmos.com/calculator/jlrx14q4w8

Просмотреть файл

@ -18,7 +18,7 @@
'use strict';
const Audit = require('./audit');
const Formatter = require('../formatters/formatter');
const Formatter = require('../report/formatter');
class UserTimings extends Audit {
/**

Просмотреть файл

@ -41,7 +41,7 @@ gulp.task('js-compile', function() {
.pipe(replace('require(\'../lib/traces/devtools-timeline-model\');',
'DevtoolsTimelineModel'))
.pipe(replace('require(\'speedline\');', 'function(arg) {};'))
.pipe(replace(/require\('(\.\.\/)*formatters\/formatter'\);/g, '{};'))
.pipe(replace(/require\('(\.\.\/)*report\/formatter'\);/g, '{};'))
// Replace any non-local import (e.g. not starting with .) with a dummy type. These are likely
// the built-in Node modules. But not always, so TODO(samthor): Fix this.

Просмотреть файл

@ -1,38 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const path = require('path');
const fs = require('fs');
const Formatter = require('./formatter');
const html = fs.readFileSync(path.join(__dirname, 'partials/accessibility.html'), 'utf8');
class Accessibilty extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = Accessibilty;

Просмотреть файл

@ -1,38 +0,0 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
const path = require('path');
const fs = require('fs');
const html = fs.readFileSync(path.join(__dirname, 'partials/cards.html'), 'utf8');
class Card extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = Card;

Просмотреть файл

@ -1,42 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const path = require('path');
const fs = require('fs');
const Formatter = require('./formatter');
const html = fs.readFileSync(path.join(__dirname, 'partials/critical-request-chains.html'), 'utf8');
class CriticalRequestChains extends Formatter {
/**
* gets the formatter for the CLI Printer and the HTML report.
*/
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = CriticalRequestChains;

Просмотреть файл

@ -1,81 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
class Formatter {
static get CAPITAL_LETTERS() {
return /([A-Z])/g;
}
static get SUPPORTED_FORMATS() {
// Get the available formatters if they don't already exist.
if (!this._formatters) {
this._getFormatters();
}
// From the formatters we can establish a master list of supported format names.
if (!this._supportedFormatsNames) {
this._generateSupportedFormats();
}
return this._supportedFormatsNames;
}
static _getFormatters() {
this._formatters = {
accessibility: require('./accessibility'),
cards: require('./cards'),
criticalRequestChains: require('./critical-request-chains'),
urlList: require('./url-list'),
null: require('./null-formatter'),
speedline: require('./speedline-formatter'),
table: require('./table'),
userTimings: require('./user-timings')
};
}
static _generateSupportedFormats() {
const formatNames = Object.keys(this._formatters);
this._supportedFormatsNames = formatNames.reduce((prev, format) => {
// Reformulates names like criticalNetworkChains to CRITICAL_NETWORK_CHAINS so they appear
// like a bunch of constants.
const formatName = format.replace(Formatter.CAPITAL_LETTERS, '_$1').toUpperCase();
prev[formatName] = format;
return prev;
}, {});
}
static getByName(name) {
if (!this._formatters) {
this._getFormatters();
}
if (!this._formatters[name]) {
throw new Error(`Unknown formatter: ${name}`);
}
return this._formatters[name];
}
static getFormatter() {
throw new Error('Formatter must implement getFormatter()');
}
}
module.exports = Formatter;

Просмотреть файл

@ -1,34 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
class NullFormatter extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
return '';
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = NullFormatter;

Просмотреть файл

@ -1,37 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
const path = require('path');
const fs = require('fs');
const html = fs.readFileSync(path.join(__dirname, 'partials/speedline.html'), 'utf8');
class SpeedlineFormatter extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = SpeedlineFormatter;

Просмотреть файл

@ -1,38 +0,0 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
const path = require('path');
const fs = require('fs');
const html = fs.readFileSync(path.join(__dirname, 'partials/table.html'), 'utf8');
class Table extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = Table;

Просмотреть файл

@ -1,38 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
const path = require('path');
const fs = require('fs');
const html = fs.readFileSync(path.join(__dirname, 'partials/url-list.html'), 'utf8');
class UrlList extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = UrlList;

Просмотреть файл

@ -1,38 +0,0 @@
/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const Formatter = require('./formatter');
const path = require('path');
const fs = require('fs');
const html = fs.readFileSync(path.join(__dirname, 'partials/user-timings.html'), 'utf8');
class UserTimings extends Formatter {
static getFormatter(type) {
switch (type) {
case 'html':
// Returns a handlebars string to be used by the Report.
return html;
default:
throw new Error('Unknown formatter type');
}
}
}
module.exports = UserTimings;

Просмотреть файл

@ -0,0 +1,45 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const fs = require('fs');
// Auto convert partial filenames to lookup for audits to use.
const formatters = {};
fs.readdirSync(__dirname + '/partials')
.filter(filename => filename.endsWith('.html'))
.forEach(filename => {
const baseName = filename.replace(/\.html$/, '');
const capsName = baseName.replace(/-/g, '_').toUpperCase();
formatters[capsName] = baseName;
});
class Formatter {
/**
* Getter that returns a list of supported formatters, mapping an all-caps
* name to the basename of the available formatter partials
* (e.g. `CRITICAL_REQUEST_CHAINS` to `critical-request-chains).
* @return {!Object<string, string>}
*/
static get SUPPORTED_FORMATS() {
return formatters;
}
}
module.exports = Formatter;

Просмотреть файл

@ -21,14 +21,10 @@
const Handlebars = require('handlebars/runtime');
const handlebarHelpers = require('./handlebar-helpers');
const reportTemplate = require('./templates/report-templates');
const reportPartials = require('../formatters/partials/templates/report-partials');
const reportPartials = require('../report/partials/templates/report-partials');
const fs = require('fs');
const path = require('path');
function toKebabCase(string) {
return string && string.replace(/([A-Z])/g, '-$1').toLowerCase();
}
class ReportGenerator {
constructor() {
@ -52,11 +48,11 @@ class ReportGenerator {
// Cannot DRY this up and dynamically create paths because fs.readdirSync
// doesn't browserify well with a variable path. See https://github.com/substack/brfs/issues/36.
const partialStyles = [
fs.readFileSync(__dirname + '/../formatters/partials/cards.css', 'utf8'),
fs.readFileSync(__dirname + '/../formatters/partials/critical-request-chains.css', 'utf8'),
fs.readFileSync(__dirname + '/../formatters/partials/table.css', 'utf8'),
fs.readFileSync(__dirname + '/../formatters/partials/url-list.css', 'utf8'),
fs.readFileSync(__dirname + '/../formatters/partials/user-timings.css', 'utf8')
fs.readFileSync(__dirname + '/../report/partials/cards.css', 'utf8'),
fs.readFileSync(__dirname + '/../report/partials/critical-request-chains.css', 'utf8'),
fs.readFileSync(__dirname + '/../report/partials/table.css', 'utf8'),
fs.readFileSync(__dirname + '/../report/partials/url-list.css', 'utf8'),
fs.readFileSync(__dirname + '/../report/partials/user-timings.css', 'utf8')
];
return [
@ -131,25 +127,23 @@ class ReportGenerator {
}
/**
* Register the formatter for each extendedInfo.
* Register the partial used for each extendedInfo under the audit's name.
* @param {!Object} audits Lighthouse results.audits.
*/
_registerFormatters(audits) {
Object.keys(audits).forEach(audit => {
// Use value rather than key for audit.
audit = audits[audit];
_registerPartials(audits) {
Object.keys(audits).forEach(auditName => {
const audit = audits[auditName];
if (!audit.extendedInfo) {
return;
}
if (!audit.extendedInfo.formatter) {
// HTML formatter not provided for this subItem
return;
const partialName = audit.extendedInfo.formatter;
const partial = reportPartials.report.partials[partialName];
if (!partial) {
throw new Error(`${auditName} requested unknown partial for formatting`);
}
const partials = reportPartials.report.partials;
const partialName = toKebabCase(audit.extendedInfo.formatter);
const partial = partials[partialName] || partials['null-formatter'];
Handlebars.registerPartial(audit.name, Handlebars.template(partial));
});
}
@ -162,7 +156,7 @@ class ReportGenerator {
* @return {string} HTML of the report page.
*/
generateHTML(results, reportContext = 'extension', reportsCatalog) {
this._registerFormatters(results.audits);
this._registerPartials(results.audits);
results.aggregations.forEach(aggregation => {
aggregation.score.forEach(score => {

Просмотреть файл

@ -146,7 +146,7 @@
"displayValue": "0",
"rawValue": true,
"extendedInfo": {
"formatter": "userTimings",
"formatter": "user-timings",
"value": []
},
"name": "user-timings",
@ -185,7 +185,7 @@
"rawValue": false,
"optimalValue": 0,
"extendedInfo": {
"formatter": "criticalRequestChains",
"formatter": "critical-request-chains",
"value": {
"chains": {
"32513.1": {

Просмотреть файл

@ -1,68 +0,0 @@
/**
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
/* eslint max-nested-callbacks: ["error", 5] */
/* eslint-env mocha */
const assert = require('assert');
const walk = require('walk');
const path = require('path');
const Handlebars = require('handlebars');
const handlebarHelpers = require('../../report/handlebar-helpers');
const walkTree = new Promise((resolve, reject) => {
const fullFilePath = path.join(__dirname, '../../formatters/');
const walker = walk.walk(fullFilePath, {
filters: ['partials']
});
const formatters = [];
walker.on('file', (root, fileStats, next) => {
if (fileStats.name === 'formatter.js' || !fileStats.name.endsWith('.js')) {
return next();
}
formatters.push(require(root + '/' + fileStats.name));
next();
});
walker.on('end', () => {
resolve(formatters);
});
});
describe('Formatters', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
it('has no formatters failing when getFormatter("html") is called', () => {
return walkTree.then(formatters => {
formatters.forEach(formatter => {
assert.doesNotThrow(_ => formatter.getFormatter('html'), 'bad: ' + formatter.name);
});
});
});
it('has no formatters succeeding when getFormatter("invalid-formatter") is called', () => {
return walkTree.then(formatters => {
formatters.forEach(formatter => {
assert.throws(_ => formatter.getFormatter('invalid-formatter'));
});
});
});
});

Просмотреть файл

@ -16,29 +16,23 @@
'use strict';
const Formatter = require('../../formatters/formatter.js');
const Formatter = require('../../report/formatter.js');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
/* eslint-env mocha */
describe('Formatter', () => {
it('returns supported formats', () => {
// Force the internal _formatters to not exist
Formatter._formatters = null;
assert.notEqual(Formatter.SUPPORTED_FORMATS, undefined);
assert.ok(Formatter.SUPPORTED_FORMATS);
});
it('returns supported formats when called by name', () => {
// Force the internal _formatters to not exist
Formatter._formatters = null;
assert.notEqual(Formatter.getByName('accessibility'), undefined);
});
it('throws when invalid format is provided', () => {
assert.throws(_ => Formatter.getByName('invalid-format'), Error);
});
it('throws when getFormatter is called directly', () => {
assert.throws(_ => Formatter.getFormatter(), Error);
it('maps supported format constants to partial filenames', () => {
Object.keys(Formatter.SUPPORTED_FORMATS).forEach(capsName => {
const baseName = Formatter.SUPPORTED_FORMATS[capsName];
const filePath = path.normalize(`${__dirname}/../../report/partials/${baseName}.html`);
assert.doesNotThrow(_ => fs.accessSync(filePath), `partial at '${filePath}' not found`);
});
});
});

Просмотреть файл

@ -18,12 +18,14 @@
/* eslint-env mocha */
const AccessibilityFormatter = require('../../formatters/accessibility.js');
const Handlebars = require('handlebars');
const assert = require('assert');
const handlebarHelpers = require('../../report/handlebar-helpers');
const handlebarHelpers = require('../../../report/handlebar-helpers');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname +
'/../../../report/partials/accessibility.html', 'utf8');
describe('Formatter', () => {
describe('Accessibility partial generation', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
@ -31,8 +33,7 @@ describe('Formatter', () => {
it('generates valid html output', () => {
Handlebars.registerHelper(handlebarHelpers);
const formatter = AccessibilityFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
let output = template({nodes: [{target: 'some-id'}]});
assert.ok(output.match(/1 element failed this test/g), 'msg for one input');

Просмотреть файл

@ -17,11 +17,12 @@
/* eslint-env mocha */
const CardsFormatter = require('../../formatters/cards.js');
const Handlebars = require('handlebars');
const assert = require('assert');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname + '/../../../report/partials/cards.html', 'utf8');
describe('CardsFormatter', () => {
describe('Cards partial generation', () => {
const extendedInfo = {
value: [
{title: 'Total DOM Nodes', value: 3500, target: '1,500 nodes'},
@ -31,8 +32,7 @@ describe('CardsFormatter', () => {
};
it('generates valid html output', () => {
const formatter = CardsFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
const output = template(extendedInfo.value).split('\n').join('');
assert.ok(output.match('title="snippet"'), 'adds title attribute for snippet');
assert.ok(output.match('class="cards__container"'), 'adds wrapper class');

Просмотреть файл

@ -18,11 +18,13 @@
/* eslint-env mocha */
const criticalRequestChainFormatter = require('../../formatters/critical-request-chains.js');
const assert = require('assert');
const Handlebars = require('handlebars');
const URL = require('../../lib/url-shim');
const handlebarHelpers = require('../../report/handlebar-helpers');
const URL = require('../../../lib/url-shim');
const handlebarHelpers = require('../../../report/handlebar-helpers');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname +
'/../../../report/partials/critical-request-chains.html', 'utf8');
const superLongName =
'https://example.com/thisIsASuperLongURLThatWillTriggerFilenameTruncationWhichWeWantToTest.js';
@ -77,15 +79,14 @@ const extendedInfo = {
}
};
describe('CRC Formatter', () => {
describe('CRC partial generation', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
it('generates valid HTML output', () => {
Handlebars.registerHelper(handlebarHelpers);
const formatter = criticalRequestChainFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
const output = template(extendedInfo).split('\n').join('');
const filename = URL.getDisplayName(superLongName);
const filenameRegExp = new RegExp(filename, 'im');

Просмотреть файл

@ -17,10 +17,12 @@
/* eslint-env mocha */
const SpeedlineFormatter = require('../../formatters/speedline-formatter.js');
const Handlebars = require('handlebars');
const assert = require('assert');
const handlebarHelpers = require('../../report/handlebar-helpers');
const handlebarHelpers = require('../../../report/handlebar-helpers');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname +
'/../../../report/partials/speedline.html', 'utf8');
const mockExtendedInfo = {
timings: {
@ -38,7 +40,7 @@ const mockExtendedInfo = {
frames: []
};
describe('Formatter', () => {
describe('Speedline partial generation', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
@ -46,8 +48,7 @@ describe('Formatter', () => {
it('generates valid html output', () => {
Handlebars.registerHelper(handlebarHelpers);
const formatter = SpeedlineFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
const formatted = template(mockExtendedInfo).split('\n').join('');
assert.equal(typeof formatted, 'string');

Просмотреть файл

@ -17,12 +17,14 @@
/* eslint-env mocha */
const TableFormatter = require('../../formatters/table.js');
const Handlebars = require('handlebars');
const handlebarHelpers = require('../../report/handlebar-helpers.js');
const assert = require('assert');
const handlebarHelpers = require('../../../report/handlebar-helpers');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname +
'/../../../report/partials/table.html', 'utf8');
describe('TableFormatter', () => {
describe('Table partial generation', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
@ -45,8 +47,7 @@ describe('TableFormatter', () => {
it('generates valid html output', () => {
Handlebars.registerHelper(handlebarHelpers);
const formatter = TableFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
const output = template(extendedInfo).split('\n').join('');
assert.ok(output.match('<table class="table_list'), 'creates a table');
assert.ok(output.match('multicolumn'), 'adds multicolumn class for large tables');

Просмотреть файл

@ -18,12 +18,14 @@
/* eslint-env mocha */
const UserTimingsFormatter = require('../../formatters/user-timings.js');
const assert = require('assert');
const Handlebars = require('handlebars');
const handlebarHelpers = require('../../report/handlebar-helpers');
const handlebarHelpers = require('../../../report/handlebar-helpers');
const fs = require('fs');
const partialHtml = fs.readFileSync(__dirname +
'/../../../report/partials/user-timings.html', 'utf8');
describe('User Timings Formatter', () => {
describe('User Timings partial generation', () => {
after(() => {
Object.keys(handlebarHelpers).forEach(Handlebars.unregisterHelper, Handlebars);
});
@ -45,8 +47,7 @@ describe('User Timings Formatter', () => {
Handlebars.registerHelper(handlebarHelpers);
const formatter = UserTimingsFormatter.getFormatter('html');
const template = Handlebars.compile(formatter);
const template = Handlebars.compile(partialHtml);
const output = template(extendedInfo).split('\n').join('');
assert.ok(/Mark: 10/.test(output));

Просмотреть файл

@ -18,6 +18,8 @@
const ReportGenerator = require('../../report/report-generator.js');
const sampleResults = require('../results/sample.json');
const assert = require('assert');
const Formatter = require('../../report/formatter');
const Handlebars = require('handlebars/runtime');
/* eslint-env mocha */
@ -153,4 +155,38 @@ describe('Report', () => {
assert.ok(!html.includes(
'<img src="test.gif" onerror="alert(10)">'), 'non-recognized HTML is sanitized');
});
describe('Partials', () => {
it('registers known partials', () => {
const reportGenerator = new ReportGenerator();
const audits = {
fakeAudit: {
name: 'fake-audit',
extendedInfo: {
formatter: Formatter.SUPPORTED_FORMATS.CRITICAL_REQUEST_CHAINS
}
}
};
reportGenerator._registerPartials(audits);
assert.ok(Handlebars.partials['fake-audit']);
Handlebars.unregisterPartial('fake-audit');
});
it('throws on requesting an unknown partial', () => {
const reportGenerator = new ReportGenerator();
const audits = {
fakeAudit: {
name: 'bad-audit',
extendedInfo: {
formatter: Formatter.SUPPORTED_FORMATS.NOT_A_REAL_THING
}
}
};
assert.throws(_ => reportGenerator._registerPartials(audits));
});
});
});

Просмотреть файл

@ -206,7 +206,7 @@
"displayValue": "0",
"rawValue": true,
"extendedInfo": {
"formatter": "userTimings",
"formatter": "user-timings",
"value": []
},
"name": "user-timings",
@ -241,7 +241,7 @@
"rawValue": false,
"optimalValue": 0,
"extendedInfo": {
"formatter": "criticalRequestChains",
"formatter": "critical-request-chains",
"value": {
"chains": {
"62339.1": {
@ -481,7 +481,7 @@
"displayValue": "4 warnings found",
"rawValue": false,
"extendedInfo": {
"formatter": "urlList",
"formatter": "url-list",
"value": [
{
"label": "line: 45",
@ -949,7 +949,7 @@
"displayValue": "",
"rawValue": false,
"extendedInfo": {
"formatter": "urlList",
"formatter": "url-list",
"value": [
{
"url": "<a href=\"https://www.google.com/\" target=\"_blank\">"
@ -969,7 +969,7 @@
"displayValue": "",
"rawValue": false,
"extendedInfo": {
"formatter": "urlList",
"formatter": "url-list",
"value": [
{
"label": "line: 252, col: 25",
@ -1163,7 +1163,7 @@
"displayValue": "",
"rawValue": false,
"extendedInfo": {
"formatter": "urlList",
"formatter": "url-list",
"value": [
{
"label": "line: 153, col: 12",
@ -1354,7 +1354,7 @@
"displayValue": "",
"rawValue": false,
"extendedInfo": {
"formatter": "urlList",
"formatter": "url-list",
"value": [
{
"label": "line: 262, col: 16",

Просмотреть файл

@ -58,7 +58,7 @@ gulp.task('images', () => {
gulp.task('concat-css', () => {
return gulp.src([
'../lighthouse-core/report/styles/report.css',
'../lighthouse-core/formatters/partials/*.css',
'../lighthouse-core/report/partials/*.css',
'app/styles/viewer.css',
])
.pipe($.concat('viewer.css'))
@ -132,7 +132,7 @@ gulp.task('watch', [
gulp.watch([
'app/styles/**/*.css',
'../lighthouse-core/report/styles/**/*.css',
'../lighthouse-core/formatters/partials/*.css'
'../lighthouse-core/report/partials/*.css'
]).on('change', () => {
runSequence('concat-css');
});

Просмотреть файл

@ -54,7 +54,6 @@
"istanbul": "^0.4.3",
"jsdom": "^9.0.0",
"mocha": "^3.2.0",
"walk": "^2.3.9",
"zone.js": "^0.7.3"
},
"dependencies": {

Просмотреть файл

@ -931,10 +931,6 @@ for-own@^0.1.3:
dependencies:
for-in "^0.1.5"
foreachasync@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@ -2769,12 +2765,6 @@ vinyl@^1.2.0:
clone-stats "^0.0.1"
replace-ext "0.0.1"
walk@^2.3.9:
version "2.3.9"
resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.9.tgz#31b4db6678f2ae01c39ea9fb8725a9031e558a7b"
dependencies:
foreachasync "^3.0.0"
webidl-conversions@^3.0.0, webidl-conversions@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"