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

core(lhr): support printf displayValues #5099

Merged
merged 10 commits into from
May 4, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions lighthouse-core/audits/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ class Audit {
result.rawValue = true;
}

const displayValue = result.displayValue ? `${result.displayValue}` : '';

let auditDescription = audit.meta.description;
if (audit.meta.failureDescription) {
if (score < Util.PASS_THRESHOLD) {
Expand All @@ -177,7 +175,7 @@ class Audit {

return {
score,
displayValue,
displayValue: result.displayValue || '',
rawValue: result.rawValue,
error: result.error,
debugString: result.debugString,
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/bootup-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class BootupTime extends Audit {
return {
score,
rawValue: totalBootupTime,
displayValue: Util.formatMilliseconds(totalBootupTime),
displayValue: [Util.MS_DISPLAY_VALUE, totalBootupTime],
details,
extendedInfo: {
value: extendedInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ class UnusedBytes extends Audit {
const wastedKb = Math.round(wastedBytes / KB_IN_BYTES);
const wastedMs = this.computeWasteWithTTIGraph(results, graph, simulator);

/** @type {LH.Audit.DisplayValue} */
let displayValue = result.displayValue || '';
if (typeof result.displayValue === 'undefined' && wastedBytes) {
displayValue = `Potential savings of ${wastedBytes} bytes`;
displayValue = ['Potential savings of %d\xa0KB', wastedKb];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: switch conditional above to testing wastedKb

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

const summary = {
Expand Down
6 changes: 4 additions & 2 deletions lighthouse-core/audits/byte-efficiency/total-byte-weight.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
'use strict';

const ByteEfficiencyAudit = require('./byte-efficiency-audit');
const Util = require('../../report/html/renderer/util');

class TotalByteWeight extends ByteEfficiencyAudit {
/**
Expand Down Expand Up @@ -92,7 +91,10 @@ class TotalByteWeight extends ByteEfficiencyAudit {
return {
score,
rawValue: totalBytes,
displayValue: `Total size was ${Util.formatBytesToKB(totalBytes, 1)}`,
displayValue: [
'Total size was %d\xa0KB',
totalBytes / 1024,
],
extendedInfo: {
value: {
results,
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/dobetterweb/dom-size.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class DOMSize extends Audit {
return {
score,
rawValue: stats.totalDOMNodes,
displayValue: `${Util.formatNumber(stats.totalDOMNodes)} nodes`,
displayValue: ['%d nodes', stats.totalDOMNodes],
extendedInfo: {
value: items,
},
Expand Down
3 changes: 1 addition & 2 deletions lighthouse-core/audits/estimated-input-latency.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
'use strict';

const Audit = require('./audit');
const Util = require('../report/html/renderer/util');

class EstimatedInputLatency extends Audit {
/**
Expand Down Expand Up @@ -57,7 +56,7 @@ class EstimatedInputLatency extends Audit {
context.options.scoreMedian
),
rawValue: metricResult.timing,
displayValue: Util.formatMilliseconds(metricResult.timing, 1),
displayValue: ['%d\xa0ms', metricResult.timing],
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/first-contentful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class FirstContentfulPaint extends Audit {
context.options.scoreMedian
),
rawValue: metricResult.timing,
displayValue: Util.formatMilliseconds(metricResult.timing),
displayValue: [Util.MS_DISPLAY_VALUE, metricResult.timing],
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/first-cpu-idle.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class FirstCPUIdle extends Audit {
context.options.scoreMedian
),
rawValue: metricResult.timing,
displayValue: Util.formatMilliseconds(metricResult.timing),
displayValue: [Util.MS_DISPLAY_VALUE, metricResult.timing],
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/first-meaningful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class FirstMeaningfulPaint extends Audit {
context.options.scoreMedian
),
rawValue: metricResult.timing,
displayValue: Util.formatMilliseconds(metricResult.timing),
displayValue: [Util.MS_DISPLAY_VALUE, metricResult.timing],
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class InteractiveMetric extends Audit {
context.options.scoreMedian
),
rawValue: timeInMs,
displayValue: Util.formatMilliseconds(timeInMs),
displayValue: [Util.MS_DISPLAY_VALUE, timeInMs],
extendedInfo: {
value: extendedInfo,
},
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/mainthread-work-breakdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class MainThreadWorkBreakdown extends Audit {
return {
score,
rawValue: totalExecutionTime,
displayValue: Util.formatMilliseconds(totalExecutionTime),
displayValue: ['%d\xa0ms', totalExecutionTime],
details: tableDetails,
extendedInfo: {
value: extendedInfo,
Expand Down
3 changes: 1 addition & 2 deletions lighthouse-core/audits/redirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
'use strict';

const Audit = require('./audit');
const Util = require('../report/html/renderer/util');
const UnusedBytes = require('./byte-efficiency/byte-efficiency-audit');

class Redirects extends Audit {
Expand Down Expand Up @@ -97,7 +96,7 @@ class Redirects extends Audit {
// We award a passing grade if you only have 1 redirect
score: redirectRequests.length <= 2 ? 1 : UnusedBytes.scoreForWastedMs(totalWastedMs),
rawValue: totalWastedMs,
displayValue: Util.formatMilliseconds(totalWastedMs, 1),
displayValue: ['%d\xa0ms', totalWastedMs],
extendedInfo: {
value: {
wastedMs: totalWastedMs,
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/audits/speed-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class SpeedIndex extends Audit {
context.options.scoreMedian
),
rawValue: metricResult.timing,
displayValue: Util.formatMilliseconds(metricResult.timing),
displayValue: [Util.MS_DISPLAY_VALUE, metricResult.timing],
};
}
}
Expand Down
3 changes: 1 addition & 2 deletions lighthouse-core/audits/uses-rel-preconnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
'use strict';

const Audit = require('./audit');
const Util = require('../report/html/renderer/util');
const UnusedBytes = require('./byte-efficiency/byte-efficiency-audit');
// Preconnect establishes a "clean" socket. Chrome's socket manager will keep an unused socket
// around for 10s. Meaning, the time delta between processing preconnect a request should be <10s,
Expand Down Expand Up @@ -158,7 +157,7 @@ class UsesRelPreconnectAudit extends Audit {
return {
score: UnusedBytes.scoreForWastedMs(maxWasted),
rawValue: maxWasted,
displayValue: Util.formatMilliseconds(maxWasted),
displayValue: ['Potential savings of %10d\xa0ms', maxWasted],
extendedInfo: {
value: results,
},
Expand Down
3 changes: 1 addition & 2 deletions lighthouse-core/audits/uses-rel-preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
'use strict';

const Audit = require('./audit');
const Util = require('../report/html/renderer/util');
const UnusedBytes = require('./byte-efficiency/byte-efficiency-audit');
const THRESHOLD_IN_MS = 100;

Expand Down Expand Up @@ -183,7 +182,7 @@ class UsesRelPreloadAudit extends Audit {
return {
score: UnusedBytes.scoreForWastedMs(wastedMs),
rawValue: wastedMs,
displayValue: Util.formatMilliseconds(wastedMs),
displayValue: ['Potential savings of %10d\xa0ms', wastedMs],
extendedInfo: {
value: results,
},
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/report/html/renderer/category-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CategoryRenderer {
let title = audit.result.description;

if (audit.result.displayValue) {
title += `: ${audit.result.displayValue}`;
title += `: ${Util.formatDisplayValue(audit.result.displayValue)}`;
}

if (audit.result.debugString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
titleEl.textContent = audit.result.description;

const valueEl = this.dom.find('.lh-perf-metric__value span', tmpl);
valueEl.textContent = audit.result.displayValue;
valueEl.textContent = Util.formatDisplayValue(audit.result.displayValue);

const descriptionEl = this.dom.find('.lh-perf-metric__description', tmpl);
descriptionEl.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.helpText));
Expand All @@ -42,7 +42,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
* @return {!Element}
*/
_renderPerfHintAudit(audit, scale) {
const tooltipAttrs = {title: audit.result.displayValue};
const tooltipAttrs = {title: Util.formatDisplayValue(audit.result.displayValue)};

const element = this.dom.createElement('details', [
'lh-perf-hint',
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/report/html/renderer/report-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ if (typeof module !== 'undefined' && module.exports) {
* manual: (boolean|undefined),
* notApplicable: (boolean|undefined),
* debugString: (string|undefined),
* displayValue: string,
* displayValue: (string|Array<string|number>),
* helpText: string,
* scoreDisplayMode: string,
* extendedInfo: Object,
Expand Down
34 changes: 34 additions & 0 deletions lighthouse-core/report/html/renderer/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,40 @@ class Util {
return PASS_THRESHOLD;
}

static get MS_DISPLAY_VALUE() {
return `%10d${NBSP}ms`;
}

/**
* @param {string|Array<string|number>=} displayValue
* @return {string}
*/
static formatDisplayValue(displayValue) {
if (typeof displayValue === 'string' || typeof displayValue === 'undefined') {
return displayValue || '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd prefer being super clear

    if (typeof displayValue === 'string') return displayValue;
    if (typeof displayValue === 'undefined') return '';

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

const template = /** @type {string} */ displayValue.shift();
if (typeof template !== 'string') {
// First value should always be the format string, but we don't want to fail to build
// a report, return a placeholder.
return 'UNKNOWN';
}

let output = template;
while (displayValue.length) {
const replacement = /** @type {number|string} */ (displayValue.shift());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    assert.equal(format(['%s']), '%s', 'not enough replacements');
    assert.equal(format(['%s', 'a', 'a']), 'a', 'extra replacements');

i think we may want to console.warn() in these cases. Allow them, but raise a warning flag.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just switch to regular indexing and avoid these shift assertions? Or could be a reduce

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

output = output.replace(/%([0-9.]+)?(d|s)/, match => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this allows more than one decimal point? and no support for granularity when it's a string?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct if you mess up your format string it'll put NaN
correct %s is just straight up replacement

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant should it be more like /%([0-9]*(?:\.[0-9]*))?d|s/ or whatever (you covered the no granularity + string case now)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, tweaked it a bit

const granularity = Number(match.match(/[0-9.]+/)) || 1;
return match === '%s' ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert.equal(format(['%10s', 123.456]), '120');

currently this does pass, fwiw. shoudl we also throw a warning if you are matching 's' and have a granularity?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified regex to not match this 👍

replacement.toLocaleString() :
(Math.round(Number(replacement) / granularity) * granularity).toLocaleString();
});
}

return output;
}

/**
* Convert a score to a rating label.
* @param {number} score
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ describe('Byte efficiency base audit', () => {
],
}, graph, simulator);

assert.ok(result.displayValue.includes('2048 bytes'), 'contains correct bytes');
assert.ok(result.displayValue.includes(2), 'contains correct KB');
});

it('should work on real graphs', async () => {
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/test/audits/dobetterweb/dom-size-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('Num DOM nodes audit', () => {
const auditResult = DOMSize.audit(artifact, {options});
assert.equal(auditResult.score, 0.43);
assert.equal(auditResult.rawValue, numNodes);
assert.equal(auditResult.displayValue, `${numNodes.toLocaleString()} nodes`);
assert.deepEqual(auditResult.displayValue, ['%d nodes', numNodes]);
assert.equal(auditResult.details.items[0].totalNodes, numNodes.toLocaleString());
assert.equal(auditResult.details.items[0].depth, '1');
assert.equal(auditResult.details.items[0].width, '2');
Expand Down
3 changes: 2 additions & 1 deletion lighthouse-core/test/audits/estimated-input-latency-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

const Audit = require('../../audits/estimated-input-latency');
const Runner = require('../../runner');
const Util = require('../../report/html/renderer/util');
const assert = require('assert');
const options = Audit.defaultOptions;

Expand All @@ -29,7 +30,7 @@ describe('Performance: estimated-input-latency audit', () => {
return Audit.audit(artifacts, {options, settings}).then(output => {
assert.equal(output.debugString, undefined);
assert.equal(Math.round(output.rawValue * 10) / 10, 17.1);
assert.equal(output.displayValue, '17\xa0ms');
assert.equal(Util.formatDisplayValue(output.displayValue), '17\xa0ms');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test the real object here like dom-size-test.js above?

assert.equal(output.score, 1);
});
});
Expand Down
5 changes: 3 additions & 2 deletions lighthouse-core/test/audits/first-meaningful-paint-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

const FMPAudit = require('../../audits/first-meaningful-paint.js');
const Audit = require('../../audits/audit.js');
const Util = require('../../report/html/renderer/util');
const assert = require('assert');
const options = FMPAudit.defaultOptions;
const trace = require('../fixtures/traces/progressive-app-m60.json');
Expand All @@ -26,7 +27,7 @@ describe('Performance: first-meaningful-paint audit', () => {
const fmpResult = await FMPAudit.audit(artifacts, context);

assert.equal(fmpResult.score, 1);
assert.equal(fmpResult.displayValue, '780\xa0ms');
assert.equal(Util.formatDisplayValue(fmpResult.displayValue), '780\xa0ms');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with these

assert.equal(fmpResult.rawValue, 783.328);
});

Expand All @@ -39,7 +40,7 @@ describe('Performance: first-meaningful-paint audit', () => {
const fmpResult = await FMPAudit.audit(artifacts, context);

assert.equal(fmpResult.score, 0.79);
assert.equal(fmpResult.displayValue, '2,850\xa0ms');
assert.equal(Util.formatDisplayValue(fmpResult.displayValue), '2,850\xa0ms');
assert.equal(Math.round(fmpResult.rawValue), 2851);
});
});
5 changes: 3 additions & 2 deletions lighthouse-core/test/audits/interactive-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

const Interactive = require('../../audits/interactive.js');
const Runner = require('../../runner.js');
const Util = require('../../report/html/renderer/util');
const assert = require('assert');
const options = Interactive.defaultOptions;

Expand All @@ -33,7 +34,7 @@ describe('Performance: interactive audit', () => {
return Interactive.audit(artifacts, {options, settings}).then(output => {
assert.equal(output.score, 1);
assert.equal(Math.round(output.rawValue), 1582);
assert.equal(output.displayValue, '1,580\xa0ms');
assert.equal(Util.formatDisplayValue(output.displayValue), '1,580\xa0ms');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and these :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

});
});

Expand All @@ -51,7 +52,7 @@ describe('Performance: interactive audit', () => {
return Interactive.audit(artifacts, {options, settings}).then(output => {
assert.equal(output.score, 0.97);
assert.equal(Math.round(output.rawValue), 2712);
assert.equal(output.displayValue, '2,710\xa0ms');
assert.equal(Util.formatDisplayValue(output.displayValue), '2,710\xa0ms');
});
});
});
12 changes: 12 additions & 0 deletions lighthouse-core/test/report/html/renderer/util-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,16 @@ describe('util helpers', () => {
assert.equal(Util.calculateRating(0.80), 'pass');
assert.equal(Util.calculateRating(1.00), 'pass');
});

it('formats display values', () => {
const format = (...args) => Util.formatDisplayValue(...args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need to rest and then spread since they're all arrays below?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

assert.equal(format(undefined), '');
assert.equal(format([1]), 'UNKNOWN');
assert.equal(format(['%s %s', 'Hello', 'Paul']), 'Hello Paul');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello formatDisplayValue

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

assert.equal(format(['%s%', 99.9]), '99.9%');
assert.equal(format(['%d%', 99.9]), '100%');
assert.equal(format(['%s ms', 12345.678]), '12,345.678 ms');
assert.equal(format(['%10d ms', 12345.678]), '12,350 ms');
assert.equal(format(['%.01d ms', 12345.678]), '12,345.68 ms');
});
});
Loading