lighthouse 10.0.0 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog-pre10.md +6085 -0
- package/core/audits/dobetterweb/doctype.d.ts +3 -2
- package/core/audits/dobetterweb/doctype.js +15 -4
- package/core/audits/dobetterweb/paste-preventing-inputs.js +2 -2
- package/core/gather/driver/network-monitor.js +1 -3
- package/core/gather/gatherers/bf-cache-failures.js +7 -8
- package/package.json +2 -2
- package/shared/localization/locales/en-US.json +1 -1
- package/shared/localization/locales/en-XL.json +1 -1
- package/.codecov.yml +0 -22
- package/.cz-config.js +0 -24
- package/.gitattributes +0 -5
- package/.mailmap +0 -6
- package/CODE_OF_CONDUCT.md +0 -93
- package/eslint-local-rules.cjs +0 -106
- package/flow-report/test/app-test.d.ts +0 -7
- package/flow-report/test/app-test.tsx +0 -52
- package/flow-report/test/common-test.d.ts +0 -7
- package/flow-report/test/common-test.tsx +0 -103
- package/flow-report/test/flow-report-pptr-test.d.ts +0 -7
- package/flow-report/test/flow-report-pptr-test.ts +0 -59
- package/flow-report/test/header-test.d.ts +0 -7
- package/flow-report/test/header-test.tsx +0 -55
- package/flow-report/test/run-flow-report-tests.sh +0 -20
- package/flow-report/test/sample-flow.d.ts +0 -7
- package/flow-report/test/sample-flow.ts +0 -17
- package/flow-report/test/setup/env-setup.d.ts +0 -11
- package/flow-report/test/setup/env-setup.ts +0 -55
- package/flow-report/test/sidebar/flow-test.d.ts +0 -7
- package/flow-report/test/sidebar/flow-test.tsx +0 -65
- package/flow-report/test/sidebar/sidebar-test.d.ts +0 -7
- package/flow-report/test/sidebar/sidebar-test.tsx +0 -116
- package/flow-report/test/summary/category-test.d.ts +0 -7
- package/flow-report/test/summary/category-test.tsx +0 -206
- package/flow-report/test/summary/summary-test.d.ts +0 -7
- package/flow-report/test/summary/summary-test.tsx +0 -124
- package/flow-report/test/topbar-test.d.ts +0 -7
- package/flow-report/test/topbar-test.tsx +0 -84
- package/flow-report/test/util-test.d.ts +0 -7
- package/flow-report/test/util-test.tsx +0 -133
- package/flow-report/test/wrappers/category-score-test.d.ts +0 -7
- package/flow-report/test/wrappers/category-score-test.tsx +0 -84
- package/flow-report/test/wrappers/markdown-test.d.ts +0 -7
- package/flow-report/test/wrappers/markdown-test.tsx +0 -17
- package/report/test/clients/bundle-test.js +0 -65
- package/report/test/generator/file-namer-test.js +0 -27
- package/report/test/generator/report-generator-test.js +0 -160
- package/report/test/renderer/__snapshots__/report-renderer-axe-test.js.snap +0 -15
- package/report/test/renderer/category-renderer-test.js +0 -575
- package/report/test/renderer/components-test.js +0 -124
- package/report/test/renderer/crc-details-renderer-test.js +0 -116
- package/report/test/renderer/details-renderer-test.js +0 -882
- package/report/test/renderer/dom-test.js +0 -257
- package/report/test/renderer/element-screenshot-renderer-test.js +0 -183
- package/report/test/renderer/i18n-formatter-test.js +0 -179
- package/report/test/renderer/performance-category-renderer-test.js +0 -417
- package/report/test/renderer/pwa-category-renderer-test.js +0 -301
- package/report/test/renderer/report-renderer-axe-test.js +0 -85
- package/report/test/renderer/report-renderer-test.js +0 -268
- package/report/test/renderer/report-ui-features-test.js +0 -773
- package/report/test/renderer/report-utils-test.js +0 -219
- package/report/test/renderer/snippet-renderer-test.js +0 -291
- package/report/test/renderer/text-encoding-test.js +0 -43
- package/report/test-assets/faux-psi.d.ts +0 -34
- package/shared/test/localization/format-test.js +0 -430
- package/shared/test/localization/locales-test.js +0 -45
- package/shared/test/localization/swap-locale-test.js +0 -127
- package/shared/test/util-test.js +0 -214
- package/vercel.json +0 -6
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright 2017 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
-
* 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
|
|
4
|
-
* 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.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import assert from 'assert/strict';
|
|
8
|
-
|
|
9
|
-
import jsdom from 'jsdom';
|
|
10
|
-
|
|
11
|
-
import {ReportUtils} from '../../renderer/report-utils.js';
|
|
12
|
-
import {I18nFormatter} from '../../renderer/i18n-formatter.js';
|
|
13
|
-
import {DOM} from '../../renderer/dom.js';
|
|
14
|
-
import {DetailsRenderer} from '../../renderer/details-renderer.js';
|
|
15
|
-
import {PerformanceCategoryRenderer} from '../../renderer/performance-category-renderer.js';
|
|
16
|
-
import {readJson} from '../../../core/test/test-utils.js';
|
|
17
|
-
import {Globals} from '../../renderer/report-globals.js';
|
|
18
|
-
|
|
19
|
-
const sampleResultsOrig = readJson('../../../core/test/results/sample_v2.json', import.meta);
|
|
20
|
-
|
|
21
|
-
describe('PerfCategoryRenderer', () => {
|
|
22
|
-
let category;
|
|
23
|
-
let renderer;
|
|
24
|
-
let sampleResults;
|
|
25
|
-
|
|
26
|
-
before(() => {
|
|
27
|
-
Globals.apply({
|
|
28
|
-
providedStrings: {},
|
|
29
|
-
i18n: new I18nFormatter('en'),
|
|
30
|
-
reportJson: null,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const {document} = new jsdom.JSDOM().window;
|
|
34
|
-
const dom = new DOM(document);
|
|
35
|
-
const detailsRenderer = new DetailsRenderer(dom);
|
|
36
|
-
renderer = new PerformanceCategoryRenderer(dom, detailsRenderer);
|
|
37
|
-
|
|
38
|
-
// TODO: don't call a LH.ReportResult `sampleResults`, which is typically always LH.Result
|
|
39
|
-
sampleResults = ReportUtils.prepareReportResult(sampleResultsOrig);
|
|
40
|
-
category = sampleResults.categories.performance;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
after(() => {
|
|
44
|
-
Globals.i18n = undefined;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('renders the category header', () => {
|
|
48
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
49
|
-
const score = categoryDOM.querySelector('.lh-category-header');
|
|
50
|
-
const value = categoryDOM.querySelector('.lh-category-header .lh-gauge__percentage');
|
|
51
|
-
const title = score.querySelector('.lh-gauge__label');
|
|
52
|
-
|
|
53
|
-
assert.deepEqual(score, score.firstElementChild, 'first child is a score');
|
|
54
|
-
const scoreInDom = Number(value.textContent);
|
|
55
|
-
assert.ok(Number.isInteger(scoreInDom) && scoreInDom > 10, 'category score is rounded');
|
|
56
|
-
assert.equal(title.textContent, category.title, 'title is set');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('renders the sections', () => {
|
|
60
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
61
|
-
const sections = categoryDOM.querySelectorAll('.lh-category > .lh-audit-group');
|
|
62
|
-
assert.equal(sections.length, 5);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('renders the metrics', () => {
|
|
66
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
67
|
-
const metricsSection = categoryDOM.querySelectorAll('.lh-category > .lh-audit-group')[0];
|
|
68
|
-
|
|
69
|
-
const metricAudits = category.auditRefs.filter(audit => audit.group === 'metrics');
|
|
70
|
-
const timelineElements = metricsSection.querySelectorAll('.lh-metric');
|
|
71
|
-
const nontimelineElements = metricsSection.querySelectorAll('.lh-audit');
|
|
72
|
-
assert.equal(timelineElements.length + nontimelineElements.length, metricAudits.length);
|
|
73
|
-
assert.deepStrictEqual(
|
|
74
|
-
Array.from(timelineElements).map(el => el.id),
|
|
75
|
-
[
|
|
76
|
-
'first-contentful-paint',
|
|
77
|
-
'largest-contentful-paint',
|
|
78
|
-
'total-blocking-time',
|
|
79
|
-
'cumulative-layout-shift',
|
|
80
|
-
'speed-index',
|
|
81
|
-
]
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('renders notApplicable metrics with n/a text', () => {
|
|
86
|
-
const perfWithNaMetric = JSON.parse(JSON.stringify(category));
|
|
87
|
-
const tbt = perfWithNaMetric.auditRefs.find(audit => audit.id === 'total-blocking-time');
|
|
88
|
-
assert(tbt);
|
|
89
|
-
const {id, title, description} = tbt.result;
|
|
90
|
-
tbt.result = {
|
|
91
|
-
id,
|
|
92
|
-
title,
|
|
93
|
-
description,
|
|
94
|
-
scoreDisplayMode: 'notApplicable',
|
|
95
|
-
score: null,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const perfDom = renderer.render(perfWithNaMetric, sampleResults.categoryGroups);
|
|
99
|
-
const tbtElement = perfDom.querySelector('.lh-metric#total-blocking-time');
|
|
100
|
-
assert(tbtElement);
|
|
101
|
-
assert.equal(tbtElement.querySelector('.lh-metric__title').textContent, 'Total Blocking Time');
|
|
102
|
-
assert.equal(tbtElement.querySelector('.lh-metric__value').textContent, '--');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('does not render metrics section if no metric group audits', () => {
|
|
106
|
-
// Remove metrics from category
|
|
107
|
-
const newCategory = JSON.parse(JSON.stringify(category));
|
|
108
|
-
newCategory.auditRefs = category.auditRefs.filter(audit => audit.group !== 'metrics');
|
|
109
|
-
|
|
110
|
-
const categoryDOM = renderer.render(newCategory, sampleResults.categoryGroups);
|
|
111
|
-
const sections = categoryDOM.querySelectorAll('.lh-category > .lh-audit-group');
|
|
112
|
-
const metricSection = categoryDOM.querySelector('.lh-audit-group--metrics');
|
|
113
|
-
assert.ok(!metricSection);
|
|
114
|
-
assert.equal(sections.length, 4);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('renders the metrics variance disclaimer as markdown', () => {
|
|
118
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
119
|
-
const disclaimerEl =
|
|
120
|
-
categoryDOM.querySelector('.lh-category-header__description > .lh-metrics__disclaimer');
|
|
121
|
-
|
|
122
|
-
assert.ok(disclaimerEl.textContent.includes('Values are estimated'));
|
|
123
|
-
const disclamerLink = disclaimerEl.querySelector('a');
|
|
124
|
-
assert.ok(disclamerLink, 'disclaimer contains coverted markdown link');
|
|
125
|
-
const disclamerUrl = new URL(disclamerLink.href);
|
|
126
|
-
assert.strictEqual(disclamerUrl.hostname, 'developer.chrome.com');
|
|
127
|
-
const calcLink = disclaimerEl.querySelector('a.lh-calclink');
|
|
128
|
-
assert.ok(calcLink, 'disclaimer contains scorecalc link');
|
|
129
|
-
assert.strictEqual(new URL(calcLink.href).hostname, 'googlechrome.github.io');
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('does not render disclaimer if there is no category gauge', () => {
|
|
133
|
-
// Timespan mode uses a category fraction instead of a gauge.
|
|
134
|
-
const categoryDOM = renderer.render(
|
|
135
|
-
category,
|
|
136
|
-
sampleResults.categoryGroups,
|
|
137
|
-
{gatherMode: 'timespan'}
|
|
138
|
-
);
|
|
139
|
-
const disclaimerEl = categoryDOM.querySelector('.lh-metrics__disclaimer');
|
|
140
|
-
assert.ok(!disclaimerEl);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('ignores hidden audits', () => {
|
|
144
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
145
|
-
|
|
146
|
-
const hiddenAudits = category.auditRefs.filter(audit => audit.group === 'hidden');
|
|
147
|
-
const auditElements = [...categoryDOM.querySelectorAll('.lh-audit')];
|
|
148
|
-
const matchingElements = auditElements
|
|
149
|
-
.filter(el => hiddenAudits.some(audit => audit.id === el.id));
|
|
150
|
-
expect(matchingElements).toHaveLength(0);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('renders the failing performance opportunities', () => {
|
|
154
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
155
|
-
|
|
156
|
-
const oppAudits = category.auditRefs.filter(audit =>
|
|
157
|
-
audit.result.details &&
|
|
158
|
-
audit.result.details.type === 'opportunity' &&
|
|
159
|
-
!ReportUtils.showAsPassed(audit.result));
|
|
160
|
-
const oppElements = [...categoryDOM.querySelectorAll('.lh-audit--load-opportunity')];
|
|
161
|
-
expect(oppElements.map(e => e.id).sort()).toEqual(oppAudits.map(a => a.id).sort());
|
|
162
|
-
expect(oppElements.length).toBeGreaterThan(0);
|
|
163
|
-
expect(oppElements.length).toMatchInlineSnapshot('6');
|
|
164
|
-
|
|
165
|
-
const oppElement = oppElements[0];
|
|
166
|
-
const oppSparklineBarElement = oppElement.querySelector('.lh-sparkline__bar');
|
|
167
|
-
const oppSparklineElement = oppElement.querySelector('.lh-load-opportunity__sparkline');
|
|
168
|
-
const oppTitleElement = oppElement.querySelector('.lh-audit__title');
|
|
169
|
-
const oppWastedElement = oppElement.querySelector('.lh-audit__display-text');
|
|
170
|
-
assert.ok(oppTitleElement.textContent, 'did not render title');
|
|
171
|
-
assert.ok(oppSparklineBarElement.style.width, 'did not set sparkline width');
|
|
172
|
-
assert.ok(oppWastedElement.textContent, 'did not render stats');
|
|
173
|
-
assert.ok(oppSparklineElement.title, 'did not set tooltip on sparkline');
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('renders performance opportunities with an errorMessage', () => {
|
|
177
|
-
const auditWithError = {
|
|
178
|
-
score: 0,
|
|
179
|
-
result: {
|
|
180
|
-
score: null, scoreDisplayMode: 'error', errorMessage: 'Yikes!!', title: 'Bug #2',
|
|
181
|
-
description: '',
|
|
182
|
-
details: {
|
|
183
|
-
overallSavingsMs: 0,
|
|
184
|
-
items: [],
|
|
185
|
-
type: 'opportunity',
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const fakeCategory = Object.assign({}, category, {auditRefs: [auditWithError]});
|
|
191
|
-
const categoryDOM = renderer.render(fakeCategory, sampleResults.categoryGroups);
|
|
192
|
-
const tooltipEl = categoryDOM.querySelector('.lh-audit--load-opportunity .lh-tooltip--error');
|
|
193
|
-
assert.ok(tooltipEl, 'did not render error message');
|
|
194
|
-
assert.ok(/Yikes!!/.test(tooltipEl.textContent));
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('renders performance opportunities\' explanation', () => {
|
|
198
|
-
const auditWithExplanation = {
|
|
199
|
-
score: 0,
|
|
200
|
-
result: {
|
|
201
|
-
score: 0, scoreDisplayMode: 'numeric',
|
|
202
|
-
numericValue: 100, explanation: 'Yikes!!', title: 'Bug #2', description: '',
|
|
203
|
-
details: {
|
|
204
|
-
overallSavingsMs: 0,
|
|
205
|
-
items: [],
|
|
206
|
-
type: 'opportunity',
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const fakeCategory = Object.assign({}, category, {auditRefs: [auditWithExplanation]});
|
|
212
|
-
const categoryDOM = renderer.render(fakeCategory, sampleResults.categoryGroups);
|
|
213
|
-
|
|
214
|
-
const selector = '.lh-audit--load-opportunity .lh-audit-explanation';
|
|
215
|
-
const tooltipEl = categoryDOM.querySelector(selector);
|
|
216
|
-
assert.ok(tooltipEl, 'did not render explanation text');
|
|
217
|
-
assert.ok(/Yikes!!/.test(tooltipEl.textContent));
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('renders the failing diagnostics', () => {
|
|
221
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
222
|
-
const diagnosticSection = categoryDOM.querySelector(
|
|
223
|
-
'.lh-category > .lh-audit-group.lh-audit-group--diagnostics');
|
|
224
|
-
|
|
225
|
-
const diagnosticAuditIds = category.auditRefs.filter(audit => {
|
|
226
|
-
return !audit.group &&
|
|
227
|
-
!(audit.result.details && audit.result.details.type === 'opportunity') &&
|
|
228
|
-
!ReportUtils.showAsPassed(audit.result);
|
|
229
|
-
}).map(audit => audit.id).sort();
|
|
230
|
-
assert.ok(diagnosticAuditIds.length > 0);
|
|
231
|
-
|
|
232
|
-
const diagnosticElementIds = [...diagnosticSection.querySelectorAll('.lh-audit')]
|
|
233
|
-
.map(el => el.id).sort();
|
|
234
|
-
assert.deepStrictEqual(diagnosticElementIds, diagnosticAuditIds);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('renders the passed audits', () => {
|
|
238
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
239
|
-
const passedSection = categoryDOM.querySelector('.lh-clump--passed');
|
|
240
|
-
|
|
241
|
-
const passedAudits = category.auditRefs.filter(audit =>
|
|
242
|
-
!audit.group &&
|
|
243
|
-
ReportUtils.showAsPassed(audit.result));
|
|
244
|
-
const passedElements = passedSection.querySelectorAll('.lh-audit');
|
|
245
|
-
assert.equal(passedElements.length, passedAudits.length);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Unsupported by perf cat renderer right now.
|
|
249
|
-
it.skip('renders any manual audits', () => {
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
describe('getWastedMs', () => {
|
|
253
|
-
it('handles erroring opportunities', () => {
|
|
254
|
-
const auditWithDebug = {
|
|
255
|
-
score: 0,
|
|
256
|
-
result: {
|
|
257
|
-
error: true, score: 0,
|
|
258
|
-
numericValue: 100, explanation: 'Yikes!!', title: 'Bug #2',
|
|
259
|
-
details: {
|
|
260
|
-
overallSavingsMs: 0,
|
|
261
|
-
items: [],
|
|
262
|
-
type: 'opportunity',
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
};
|
|
266
|
-
const wastedMs = renderer._getWastedMs(auditWithDebug);
|
|
267
|
-
assert.ok(Number.isFinite(wastedMs), 'Finite number not returned by wastedMs');
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
describe('budgets', () => {
|
|
272
|
-
it('renders the group and header', () => {
|
|
273
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
274
|
-
|
|
275
|
-
const budgetsGroup = categoryDOM.querySelector('.lh-audit-group.lh-audit-group--budgets');
|
|
276
|
-
assert.ok(budgetsGroup);
|
|
277
|
-
|
|
278
|
-
const header = budgetsGroup.querySelector('.lh-audit-group__header');
|
|
279
|
-
assert.ok(header);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('renders the performance budget table', () => {
|
|
283
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
284
|
-
const budgetTable = categoryDOM.querySelector('#performance-budget.lh-table');
|
|
285
|
-
assert.ok(budgetTable);
|
|
286
|
-
|
|
287
|
-
const lhrBudgetEntries = sampleResults.audits['performance-budget'].details.items;
|
|
288
|
-
const tableRows = budgetTable.querySelectorAll('tbody > tr');
|
|
289
|
-
assert.strictEqual(tableRows.length, lhrBudgetEntries.length);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('renders the timing budget table', () => {
|
|
293
|
-
const categoryDOM = renderer.render(category, sampleResults.categoryGroups);
|
|
294
|
-
const budgetTable = categoryDOM.querySelector('#timing-budget.lh-table');
|
|
295
|
-
assert.ok(budgetTable);
|
|
296
|
-
|
|
297
|
-
const lhrBudgetEntries = sampleResults.audits['timing-budget'].details.items;
|
|
298
|
-
const tableRows = budgetTable.querySelectorAll('tbody > tr');
|
|
299
|
-
assert.strictEqual(tableRows.length, lhrBudgetEntries.length);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('does not render the budgets section when all budget audits are notApplicable', () => {
|
|
303
|
-
const budgetlessCategory = JSON.parse(JSON.stringify(category));
|
|
304
|
-
['performance-budget', 'timing-budget'].forEach((id) => {
|
|
305
|
-
const budgetRef = budgetlessCategory.auditRefs.find(a => a.id === id);
|
|
306
|
-
budgetRef.result.scoreDisplayMode = 'notApplicable';
|
|
307
|
-
delete budgetRef.result.details;
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
const categoryDOM = renderer.render(budgetlessCategory, sampleResults.categoryGroups);
|
|
311
|
-
const budgetsGroup = categoryDOM.querySelector('.lh-audit-group.lh-audit-group--budgets');
|
|
312
|
-
assert.strictEqual(budgetsGroup, null);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
describe('_getScoringCalculatorHref', () => {
|
|
317
|
-
it('creates a working link given some auditRefs', () => {
|
|
318
|
-
const categoryClone = JSON.parse(JSON.stringify(category));
|
|
319
|
-
|
|
320
|
-
// CLS of 0 is both valid and falsy. Make sure it doesn't become 'null'
|
|
321
|
-
const cls = categoryClone.auditRefs.find(audit => audit.id === 'cumulative-layout-shift');
|
|
322
|
-
cls.result.numericValue = 0;
|
|
323
|
-
|
|
324
|
-
const href = renderer._getScoringCalculatorHref(categoryClone.auditRefs);
|
|
325
|
-
const url = new URL(href);
|
|
326
|
-
expect(url.hash.split('&')).toMatchInlineSnapshot(`
|
|
327
|
-
Array [
|
|
328
|
-
"#FCP=6844",
|
|
329
|
-
"LCP=9320",
|
|
330
|
-
"TBT=1221",
|
|
331
|
-
"CLS=0",
|
|
332
|
-
"SI=8114",
|
|
333
|
-
"TTI=8191",
|
|
334
|
-
"FMP=6844",
|
|
335
|
-
]
|
|
336
|
-
`);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it('also appends device and version number', () => {
|
|
340
|
-
Globals.reportJson = {
|
|
341
|
-
configSettings: {formFactor: 'mobile'},
|
|
342
|
-
lighthouseVersion: '6.0.0',
|
|
343
|
-
};
|
|
344
|
-
const href = renderer._getScoringCalculatorHref(category.auditRefs);
|
|
345
|
-
const url = new URL(href);
|
|
346
|
-
try {
|
|
347
|
-
expect(url.hash.split('&')).toMatchInlineSnapshot(`
|
|
348
|
-
Array [
|
|
349
|
-
"#FCP=6844",
|
|
350
|
-
"LCP=9320",
|
|
351
|
-
"TBT=1221",
|
|
352
|
-
"CLS=0.14",
|
|
353
|
-
"SI=8114",
|
|
354
|
-
"TTI=8191",
|
|
355
|
-
"FMP=6844",
|
|
356
|
-
"device=mobile",
|
|
357
|
-
"version=6.0.0",
|
|
358
|
-
]
|
|
359
|
-
`);
|
|
360
|
-
} finally {
|
|
361
|
-
Globals.reportJson = null;
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it('uses null if the metric\'s value is undefined', () => {
|
|
366
|
-
const categoryClone = JSON.parse(JSON.stringify(category));
|
|
367
|
-
const lcp = categoryClone.auditRefs.find(audit => audit.id === 'largest-contentful-paint');
|
|
368
|
-
lcp.result.numericValue = undefined;
|
|
369
|
-
lcp.result.score = null;
|
|
370
|
-
const href = renderer._getScoringCalculatorHref(categoryClone.auditRefs);
|
|
371
|
-
expect(href).toContain('LCP=null');
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('uses null if the metric\'s value is null (LR)', () => {
|
|
375
|
-
const categoryClone = JSON.parse(JSON.stringify(category));
|
|
376
|
-
const lcp = categoryClone.auditRefs.find(audit => audit.id === 'largest-contentful-paint');
|
|
377
|
-
// In LR, we think there might be some case where undefined becomes null, but we can't prove it.
|
|
378
|
-
lcp.result.numericValue = null;
|
|
379
|
-
lcp.result.score = null;
|
|
380
|
-
const href = renderer._getScoringCalculatorHref(categoryClone.auditRefs);
|
|
381
|
-
expect(href).toContain('LCP=null');
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// This is done all in CSS, but tested here.
|
|
386
|
-
describe('metric description toggles', () => {
|
|
387
|
-
let container;
|
|
388
|
-
let toggle;
|
|
389
|
-
const metricsSelector = '.lh-audit-group--metrics';
|
|
390
|
-
const toggleSelector = '.lh-metrics-toggle__input';
|
|
391
|
-
const magicSelector =
|
|
392
|
-
'.lh-metrics-toggle__input:checked ~ .lh-metrics-container .lh-metric__description';
|
|
393
|
-
let getDescriptionsAfterCheckedToggle;
|
|
394
|
-
|
|
395
|
-
describe('works if there is a performance category', () => {
|
|
396
|
-
before(() => {
|
|
397
|
-
container = renderer.render(category, sampleResults.categoryGroups);
|
|
398
|
-
const metricsAuditGroup = container.querySelector(metricsSelector);
|
|
399
|
-
toggle = metricsAuditGroup.querySelector(toggleSelector);
|
|
400
|
-
// In the CSS, our magicSelector will flip display from `none` to `block`
|
|
401
|
-
getDescriptionsAfterCheckedToggle = _ => metricsAuditGroup.querySelectorAll(magicSelector);
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
it('descriptions hidden by default', () => {
|
|
405
|
-
assert.ok(getDescriptionsAfterCheckedToggle().length === 0);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
it('can toggle description visibility', () => {
|
|
409
|
-
assert.ok(getDescriptionsAfterCheckedToggle().length === 0);
|
|
410
|
-
toggle.click();
|
|
411
|
-
assert.ok(getDescriptionsAfterCheckedToggle().length > 2);
|
|
412
|
-
toggle.click();
|
|
413
|
-
assert.ok(getDescriptionsAfterCheckedToggle().length === 0);
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
});
|