lighthouse 8.5.1-dev.20210928 → 8.5.1-dev.20211002
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/flow-report/.eslintrc.cjs +49 -0
- package/flow-report/assets/styles.css +1 -0
- package/flow-report/jest.config.js +1 -1
- package/flow-report/package.json +4 -0
- package/flow-report/src/app.tsx +8 -5
- package/flow-report/src/header.tsx +5 -1
- package/flow-report/src/i18n/i18n.tsx +44 -0
- package/flow-report/src/i18n/localized-strings.js +11 -0
- package/flow-report/src/i18n/ui-strings.js +40 -0
- package/flow-report/src/sidebar/sidebar.tsx +10 -15
- package/flow-report/src/summary/category.tsx +21 -13
- package/flow-report/src/summary/summary.tsx +24 -10
- package/flow-report/src/topbar.tsx +4 -1
- package/flow-report/src/util.ts +7 -7
- package/flow-report/test/app-test.tsx +1 -12
- package/flow-report/test/header-test.tsx +7 -13
- package/flow-report/test/sample-flow.ts +17 -0
- package/flow-report/test/sidebar/flow-test.tsx +6 -12
- package/flow-report/test/sidebar/sidebar-test.tsx +7 -13
- package/flow-report/test/summary/category-test.tsx +22 -14
- package/flow-report/test/summary/summary-test.tsx +5 -13
- package/flow-report/test/util-test.tsx +1 -12
- package/flow-report/tsconfig.json +1 -0
- package/jest.config.js +0 -15
- package/lighthouse-core/fraggle-rock/api.js +10 -0
- package/lighthouse-core/fraggle-rock/user-flow.js +27 -3
- package/lighthouse-core/lib/i18n/i18n.js +13 -1
- package/lighthouse-core/lib/i18n/locales/en-US.json +45 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +45 -0
- package/lighthouse-core/lib/i18n/swap-flow-locale.js +20 -0
- package/lighthouse-core/lib/stack-packs.js +1 -13
- package/package.json +11 -9
- package/readme.md +1 -1
- package/report/clients/psi.js +1 -0
- package/report/test/clients/psi-test.js +2 -3
- package/report/test/renderer/report-renderer-axe-test.js +86 -0
- package/report/test/renderer/report-renderer-test.js +0 -55
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +5 -3
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -1
|
@@ -4,22 +4,26 @@
|
|
|
4
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
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import {dirname} from 'path';
|
|
9
|
-
import {fileURLToPath} from 'url';
|
|
10
|
-
|
|
7
|
+
import {FunctionComponent} from 'preact';
|
|
11
8
|
import {render} from '@testing-library/preact';
|
|
12
9
|
|
|
13
10
|
import {SummaryTooltip} from '../../src/summary/category';
|
|
14
11
|
import {Util} from '../../../report/renderer/util';
|
|
12
|
+
import {flowResult} from '../sample-flow';
|
|
13
|
+
import {I18nProvider} from '../../src/i18n/i18n';
|
|
14
|
+
import {FlowResultContext} from '../../src/util';
|
|
15
|
+
|
|
16
|
+
let wrapper: FunctionComponent;
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
wrapper = ({children}) => (
|
|
20
|
+
<FlowResultContext.Provider value={flowResult}>
|
|
21
|
+
<I18nProvider>
|
|
22
|
+
{children}
|
|
23
|
+
</I18nProvider>
|
|
24
|
+
</FlowResultContext.Provider>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
23
27
|
|
|
24
28
|
describe('SummaryTooltip', () => {
|
|
25
29
|
it('renders tooltip with rating', async () => {
|
|
@@ -28,7 +32,8 @@ describe('SummaryTooltip', () => {
|
|
|
28
32
|
const category = reportResult.categories['seo'];
|
|
29
33
|
|
|
30
34
|
const root = render(
|
|
31
|
-
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}
|
|
35
|
+
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>,
|
|
36
|
+
{wrapper}
|
|
32
37
|
);
|
|
33
38
|
|
|
34
39
|
const rating = root.getByTestId('SummaryTooltip__rating');
|
|
@@ -43,7 +48,8 @@ describe('SummaryTooltip', () => {
|
|
|
43
48
|
const category = reportResult.categories['performance'];
|
|
44
49
|
|
|
45
50
|
const root = render(
|
|
46
|
-
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}
|
|
51
|
+
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>,
|
|
52
|
+
{wrapper}
|
|
47
53
|
);
|
|
48
54
|
|
|
49
55
|
expect(() => root.getByTestId('SummaryTooltip__rating')).toThrow();
|
|
@@ -56,7 +62,9 @@ describe('SummaryTooltip', () => {
|
|
|
56
62
|
const category = reportResult.categories['performance'];
|
|
57
63
|
|
|
58
64
|
const root = render(
|
|
59
|
-
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}
|
|
65
|
+
<SummaryTooltip category={category} gatherMode={reportResult.gatherMode}/>,
|
|
66
|
+
{wrapper}
|
|
67
|
+
|
|
60
68
|
);
|
|
61
69
|
|
|
62
70
|
const rating = root.getByTestId('SummaryTooltip__rating');
|
|
@@ -4,24 +4,14 @@
|
|
|
4
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
5
|
*/
|
|
6
6
|
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import {dirname} from 'path';
|
|
9
|
-
import {fileURLToPath} from 'url';
|
|
10
|
-
|
|
11
7
|
import {render} from '@testing-library/preact';
|
|
12
8
|
import {FunctionComponent} from 'preact';
|
|
13
9
|
|
|
10
|
+
import {I18nProvider} from '../../src/i18n/i18n';
|
|
14
11
|
import {SummaryHeader, SummaryFlowStep} from '../../src/summary/summary';
|
|
15
12
|
import {FlowResultContext} from '../../src/util';
|
|
16
13
|
import {ReportRendererProvider} from '../../src/wrappers/report-renderer';
|
|
17
|
-
|
|
18
|
-
const flowResult: LH.FlowResult = JSON.parse(
|
|
19
|
-
fs.readFileSync(
|
|
20
|
-
// eslint-disable-next-line max-len
|
|
21
|
-
`${dirname(fileURLToPath(import.meta.url))}/../../../lighthouse-core/test/fixtures/fraggle-rock/reports/sample-lhrs.json`,
|
|
22
|
-
'utf-8'
|
|
23
|
-
)
|
|
24
|
-
);
|
|
14
|
+
import {flowResult} from '../sample-flow';
|
|
25
15
|
|
|
26
16
|
let wrapper: FunctionComponent;
|
|
27
17
|
|
|
@@ -29,7 +19,9 @@ beforeEach(() => {
|
|
|
29
19
|
wrapper = ({children}) => (
|
|
30
20
|
<FlowResultContext.Provider value={flowResult}>
|
|
31
21
|
<ReportRendererProvider>
|
|
32
|
-
|
|
22
|
+
<I18nProvider>
|
|
23
|
+
{children}
|
|
24
|
+
</I18nProvider>
|
|
33
25
|
</ReportRendererProvider>
|
|
34
26
|
</FlowResultContext.Provider>
|
|
35
27
|
);
|
|
@@ -4,24 +4,13 @@
|
|
|
4
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
5
|
*/
|
|
6
6
|
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import {dirname} from 'path';
|
|
9
|
-
import {fileURLToPath} from 'url';
|
|
10
|
-
|
|
11
7
|
import {jest} from '@jest/globals';
|
|
12
8
|
import {renderHook} from '@testing-library/preact-hooks';
|
|
13
9
|
import {FunctionComponent} from 'preact';
|
|
14
10
|
import {act} from 'preact/test-utils';
|
|
15
11
|
|
|
16
12
|
import {FlowResultContext, useCurrentLhr} from '../src/util';
|
|
17
|
-
|
|
18
|
-
const flowResult: LH.FlowResult = JSON.parse(
|
|
19
|
-
fs.readFileSync(
|
|
20
|
-
// eslint-disable-next-line max-len
|
|
21
|
-
`${dirname(fileURLToPath(import.meta.url))}/../../lighthouse-core/test/fixtures/fraggle-rock/reports/sample-lhrs.json`,
|
|
22
|
-
'utf-8'
|
|
23
|
-
)
|
|
24
|
-
);
|
|
13
|
+
import {flowResult} from './sample-flow';
|
|
25
14
|
|
|
26
15
|
let wrapper: FunctionComponent;
|
|
27
16
|
|
package/jest.config.js
CHANGED
|
@@ -6,18 +6,6 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
module.exports = {
|
|
9
|
-
collectCoverage: false,
|
|
10
|
-
coverageReporters: ['none'],
|
|
11
|
-
collectCoverageFrom: [
|
|
12
|
-
'**/lighthouse-core/**/*.js',
|
|
13
|
-
'**/lighthouse-cli/**/*.js',
|
|
14
|
-
'**/report/**/*.js',
|
|
15
|
-
'**/lighthouse-viewer/**/*.js',
|
|
16
|
-
],
|
|
17
|
-
coveragePathIgnorePatterns: [
|
|
18
|
-
'/test/',
|
|
19
|
-
'/scripts/',
|
|
20
|
-
],
|
|
21
9
|
setupFilesAfterEnv: ['./lighthouse-core/test/test-utils.js'],
|
|
22
10
|
testEnvironment: 'node',
|
|
23
11
|
testMatch: [
|
|
@@ -26,12 +14,9 @@ module.exports = {
|
|
|
26
14
|
'**/report/**/*-test.js',
|
|
27
15
|
'**/lighthouse-core/test/fraggle-rock/**/*-test-pptr.js',
|
|
28
16
|
'**/lighthouse-treemap/**/*-test.js',
|
|
29
|
-
'**/lighthouse-treemap/**/*-test-pptr.js',
|
|
30
17
|
'**/lighthouse-viewer/**/*-test.js',
|
|
31
|
-
'**/lighthouse-viewer/**/*-test-pptr.js',
|
|
32
18
|
'**/third-party/**/*-test.js',
|
|
33
19
|
'**/clients/test/**/*-test.js',
|
|
34
|
-
'**/docs/**/*.test.js',
|
|
35
20
|
],
|
|
36
21
|
transform: {},
|
|
37
22
|
prettierPath: null,
|
|
@@ -8,9 +8,19 @@
|
|
|
8
8
|
const {snapshot} = require('./gather/snapshot-runner.js');
|
|
9
9
|
const {startTimespan} = require('./gather/timespan-runner.js');
|
|
10
10
|
const {navigation} = require('./gather/navigation-runner.js');
|
|
11
|
+
const UserFlow = require('./user-flow.js');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {import('puppeteer').Page} page
|
|
15
|
+
* @param {UserFlow.UserFlowOptions} [options]
|
|
16
|
+
*/
|
|
17
|
+
async function startFlow(page, options) {
|
|
18
|
+
return new UserFlow(page, options);
|
|
19
|
+
}
|
|
11
20
|
|
|
12
21
|
module.exports = {
|
|
13
22
|
snapshot,
|
|
14
23
|
startTimespan,
|
|
15
24
|
navigation,
|
|
25
|
+
startFlow,
|
|
16
26
|
};
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const {generateFlowReportHtml} = require('../../report/generator/report-generator.js');
|
|
9
|
-
const {
|
|
9
|
+
const {snapshot} = require('./gather/snapshot-runner.js');
|
|
10
|
+
const {startTimespan} = require('./gather/timespan-runner.js');
|
|
11
|
+
const {navigation} = require('./gather/navigation-runner.js');
|
|
10
12
|
|
|
11
13
|
/** @typedef {Parameters<snapshot>[0]} FrOptions */
|
|
12
14
|
/** @typedef {Omit<FrOptions, 'page'>} UserFlowOptions */
|
|
@@ -49,6 +51,29 @@ class UserFlow {
|
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} url
|
|
56
|
+
* @param {StepOptions=} stepOptions
|
|
57
|
+
*/
|
|
58
|
+
_getNextNavigationOptions(url, stepOptions) {
|
|
59
|
+
const options = {url, ...this.options, ...stepOptions};
|
|
60
|
+
|
|
61
|
+
// On repeat navigations, we want to disable storage reset by default (i.e. it's not a cold load).
|
|
62
|
+
const isSubsequentNavigation = this.steps.some(step => step.lhr.gatherMode === 'navigation');
|
|
63
|
+
if (isSubsequentNavigation) {
|
|
64
|
+
const configContext = {...options.configContext};
|
|
65
|
+
const settingsOverrides = {...configContext.settingsOverrides};
|
|
66
|
+
if (settingsOverrides.disableStorageReset === undefined) {
|
|
67
|
+
settingsOverrides.disableStorageReset = true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
configContext.settingsOverrides = settingsOverrides;
|
|
71
|
+
options.configContext = configContext;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return options;
|
|
75
|
+
}
|
|
76
|
+
|
|
52
77
|
/**
|
|
53
78
|
* @param {string} url
|
|
54
79
|
* @param {StepOptions=} stepOptions
|
|
@@ -56,8 +81,7 @@ class UserFlow {
|
|
|
56
81
|
async navigate(url, stepOptions) {
|
|
57
82
|
if (this.currentTimespan) throw Error('Timespan already in progress');
|
|
58
83
|
|
|
59
|
-
const
|
|
60
|
-
const result = await navigation(options);
|
|
84
|
+
const result = await navigation(this._getNextNavigationOptions(url, stepOptions));
|
|
61
85
|
if (!result) throw Error('Navigation returned undefined');
|
|
62
86
|
|
|
63
87
|
const providedName = stepOptions && stepOptions.stepName;
|
|
@@ -350,7 +350,7 @@ function getRendererFormattedStrings(locale) {
|
|
|
350
350
|
/** @type {Record<string, string>} */
|
|
351
351
|
const strings = {};
|
|
352
352
|
for (const icuMessageId of icuMessageIds) {
|
|
353
|
-
const
|
|
353
|
+
const {filename, key} = getIcuMessageIdParts(icuMessageId);
|
|
354
354
|
if (!filename.endsWith('util.js')) throw new Error(`Unexpected message: ${icuMessageId}`);
|
|
355
355
|
|
|
356
356
|
strings[key] = localeMessages[icuMessageId].message;
|
|
@@ -524,6 +524,17 @@ function isStringOrIcuMessage(value) {
|
|
|
524
524
|
return typeof value === 'string' || isIcuMessage(value);
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
+
/**
|
|
528
|
+
* @param {string} i18nMessageId
|
|
529
|
+
*/
|
|
530
|
+
function getIcuMessageIdParts(i18nMessageId) {
|
|
531
|
+
if (!MESSAGE_I18N_ID_REGEX.test(i18nMessageId)) {
|
|
532
|
+
throw Error(`"${i18nMessageId}" does not appear to be a valid ICU message id`);
|
|
533
|
+
}
|
|
534
|
+
const [filename, key] = i18nMessageId.split(' | ');
|
|
535
|
+
return {filename, key};
|
|
536
|
+
}
|
|
537
|
+
|
|
527
538
|
module.exports = {
|
|
528
539
|
_formatPathAsString,
|
|
529
540
|
UIStrings,
|
|
@@ -538,4 +549,5 @@ module.exports = {
|
|
|
538
549
|
isStringOrIcuMessage,
|
|
539
550
|
// TODO: exported for backwards compatibility. Consider removing on future breaking change.
|
|
540
551
|
createMessageInstanceIdFn: createIcuMessageFn,
|
|
552
|
+
getIcuMessageIdParts,
|
|
541
553
|
};
|
|
@@ -1,4 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
+
"flow-report/src/i18n/ui-strings.js | allReports": {
|
|
3
|
+
"message": "All Reports"
|
|
4
|
+
},
|
|
5
|
+
"flow-report/src/i18n/ui-strings.js | desktop": {
|
|
6
|
+
"message": "Desktop"
|
|
7
|
+
},
|
|
8
|
+
"flow-report/src/i18n/ui-strings.js | mobile": {
|
|
9
|
+
"message": "Mobile"
|
|
10
|
+
},
|
|
11
|
+
"flow-report/src/i18n/ui-strings.js | navigationDescription": {
|
|
12
|
+
"message": "Page load"
|
|
13
|
+
},
|
|
14
|
+
"flow-report/src/i18n/ui-strings.js | navigationReport": {
|
|
15
|
+
"message": "Navigation report"
|
|
16
|
+
},
|
|
17
|
+
"flow-report/src/i18n/ui-strings.js | ratingAverage": {
|
|
18
|
+
"message": "Average"
|
|
19
|
+
},
|
|
20
|
+
"flow-report/src/i18n/ui-strings.js | ratingError": {
|
|
21
|
+
"message": "Error"
|
|
22
|
+
},
|
|
23
|
+
"flow-report/src/i18n/ui-strings.js | ratingFail": {
|
|
24
|
+
"message": "Poor"
|
|
25
|
+
},
|
|
26
|
+
"flow-report/src/i18n/ui-strings.js | ratingPass": {
|
|
27
|
+
"message": "Good"
|
|
28
|
+
},
|
|
29
|
+
"flow-report/src/i18n/ui-strings.js | snapshotDescription": {
|
|
30
|
+
"message": "Captured state of page"
|
|
31
|
+
},
|
|
32
|
+
"flow-report/src/i18n/ui-strings.js | snapshotReport": {
|
|
33
|
+
"message": "Snapshot report"
|
|
34
|
+
},
|
|
35
|
+
"flow-report/src/i18n/ui-strings.js | summary": {
|
|
36
|
+
"message": "Summary"
|
|
37
|
+
},
|
|
38
|
+
"flow-report/src/i18n/ui-strings.js | timespanDescription": {
|
|
39
|
+
"message": "User interactions"
|
|
40
|
+
},
|
|
41
|
+
"flow-report/src/i18n/ui-strings.js | timespanReport": {
|
|
42
|
+
"message": "Timespan report"
|
|
43
|
+
},
|
|
44
|
+
"flow-report/src/i18n/ui-strings.js | title": {
|
|
45
|
+
"message": "Lighthouse User Flow Report"
|
|
46
|
+
},
|
|
2
47
|
"lighthouse-core/audits/accessibility/accesskeys.js | description": {
|
|
3
48
|
"message": "Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://web.dev/accesskeys/)."
|
|
4
49
|
},
|
|
@@ -1,4 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
+
"flow-report/src/i18n/ui-strings.js | allReports": {
|
|
3
|
+
"message": "Âĺl̂ Ŕêṕôŕt̂ś"
|
|
4
|
+
},
|
|
5
|
+
"flow-report/src/i18n/ui-strings.js | desktop": {
|
|
6
|
+
"message": "D̂éŝḱt̂óp̂"
|
|
7
|
+
},
|
|
8
|
+
"flow-report/src/i18n/ui-strings.js | mobile": {
|
|
9
|
+
"message": "M̂ób̂íl̂é"
|
|
10
|
+
},
|
|
11
|
+
"flow-report/src/i18n/ui-strings.js | navigationDescription": {
|
|
12
|
+
"message": "P̂áĝé l̂óâd́"
|
|
13
|
+
},
|
|
14
|
+
"flow-report/src/i18n/ui-strings.js | navigationReport": {
|
|
15
|
+
"message": "N̂áv̂íĝát̂íôń r̂ép̂ór̂t́"
|
|
16
|
+
},
|
|
17
|
+
"flow-report/src/i18n/ui-strings.js | ratingAverage": {
|
|
18
|
+
"message": "Âv́êŕâǵê"
|
|
19
|
+
},
|
|
20
|
+
"flow-report/src/i18n/ui-strings.js | ratingError": {
|
|
21
|
+
"message": "Êŕr̂ór̂"
|
|
22
|
+
},
|
|
23
|
+
"flow-report/src/i18n/ui-strings.js | ratingFail": {
|
|
24
|
+
"message": "P̂óôŕ"
|
|
25
|
+
},
|
|
26
|
+
"flow-report/src/i18n/ui-strings.js | ratingPass": {
|
|
27
|
+
"message": "Ĝóôd́"
|
|
28
|
+
},
|
|
29
|
+
"flow-report/src/i18n/ui-strings.js | snapshotDescription": {
|
|
30
|
+
"message": "Ĉáp̂t́ûŕêd́ ŝt́ât́ê óf̂ ṕâǵê"
|
|
31
|
+
},
|
|
32
|
+
"flow-report/src/i18n/ui-strings.js | snapshotReport": {
|
|
33
|
+
"message": "Ŝńâṕŝh́ôt́ r̂ép̂ór̂t́"
|
|
34
|
+
},
|
|
35
|
+
"flow-report/src/i18n/ui-strings.js | summary": {
|
|
36
|
+
"message": "Ŝúm̂ḿâŕŷ"
|
|
37
|
+
},
|
|
38
|
+
"flow-report/src/i18n/ui-strings.js | timespanDescription": {
|
|
39
|
+
"message": "Ûśêŕ îńt̂ér̂áĉt́îón̂ś"
|
|
40
|
+
},
|
|
41
|
+
"flow-report/src/i18n/ui-strings.js | timespanReport": {
|
|
42
|
+
"message": "T̂ím̂éŝṕâń r̂ép̂ór̂t́"
|
|
43
|
+
},
|
|
44
|
+
"flow-report/src/i18n/ui-strings.js | title": {
|
|
45
|
+
"message": "L̂íĝh́t̂h́ôúŝé Ûśêŕ F̂ĺôẃ R̂ép̂ór̂t́"
|
|
46
|
+
},
|
|
2
47
|
"lighthouse-core/audits/accessibility/accesskeys.js | description": {
|
|
3
48
|
"message": "Âćĉéŝś k̂éŷś l̂ét̂ úŝér̂ś q̂úîćk̂ĺŷ f́ôćûś â ṕâŕt̂ óf̂ t́ĥé p̂áĝé. F̂ór̂ ṕr̂óp̂ér̂ ńâv́îǵât́îón̂, éâćĥ áĉćêśŝ ḱêý m̂úŝt́ b̂é ûńîq́ûé. [L̂éâŕn̂ ḿôŕê](https://web.dev/accesskeys/)."
|
|
4
49
|
},
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2021 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
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const swapLocale = require('./swap-locale.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {LH.FlowResult} flowResult
|
|
12
|
+
* @param {LH.Locale} locale
|
|
13
|
+
*/
|
|
14
|
+
module.exports = function swapFlowLocale(flowResult, locale) {
|
|
15
|
+
const localizedFlowResult = JSON.parse(JSON.stringify(flowResult));
|
|
16
|
+
localizedFlowResult.steps = flowResult.steps.map(step => {
|
|
17
|
+
return {...step, lhr: swapLocale(step.lhr, locale).lhr};
|
|
18
|
+
});
|
|
19
|
+
return localizedFlowResult;
|
|
20
|
+
};
|
|
@@ -9,18 +9,6 @@ const log = require('lighthouse-logger');
|
|
|
9
9
|
const stackPacks = require('lighthouse-stack-packs');
|
|
10
10
|
const i18n = require('./i18n/i18n.js');
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Resolve a module on web and node
|
|
14
|
-
* @param {string} module
|
|
15
|
-
*/
|
|
16
|
-
function resolve(module) {
|
|
17
|
-
if (!require.resolve) {
|
|
18
|
-
return `node_modules/${module}`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return require.resolve(module);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
12
|
/**
|
|
25
13
|
* Pairs consisting of a stack pack's ID and the set of stacks needed to be
|
|
26
14
|
* detected in a page to display that pack's advice.
|
|
@@ -87,7 +75,7 @@ function getStackPacks(pageStacks) {
|
|
|
87
75
|
|
|
88
76
|
// Create i18n handler to get translated strings.
|
|
89
77
|
const str_ = i18n.createMessageInstanceIdFn(
|
|
90
|
-
|
|
78
|
+
`node_modules/lighthouse-stack-packs/packs/${matchedPack.id}.js`,
|
|
91
79
|
matchedPack.UIStrings
|
|
92
80
|
);
|
|
93
81
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
|
-
"version": "8.5.1-dev.
|
|
3
|
+
"version": "8.5.1-dev.20211002",
|
|
4
4
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
5
5
|
"main": "./lighthouse-core/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"smokehouse": "./lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js"
|
|
10
10
|
},
|
|
11
11
|
"engines": {
|
|
12
|
-
"node": ">=12.
|
|
12
|
+
"node": ">=12.20.0 && 12.* || >=14.13 && 14.* || >=15"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build-all": "npm-run-posix-or-windows build-all:task",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"jest": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
|
|
38
38
|
"test": "yarn diff:sample-json && yarn lint --quiet && yarn unit && yarn type-check",
|
|
39
39
|
"test-bundle": "yarn smoke --runner bundle -j=1 --retries=2 --invert-match forms",
|
|
40
|
-
"test-clients": "yarn jest \"$PWD/clients/\"",
|
|
41
|
-
"test-viewer": "yarn unit-viewer && yarn jest lighthouse-viewer
|
|
42
|
-
"test-treemap": "yarn unit-treemap && yarn jest lighthouse-treemap
|
|
40
|
+
"test-clients": "yarn jest \"$PWD/clients/\" && yarn jest --testMatch=\"**/clients/test/**/*-test-pptr.js\"",
|
|
41
|
+
"test-viewer": "yarn unit-viewer && yarn jest --testMatch=\"**/lighthouse-viewer/**/*-test-pptr.js\"",
|
|
42
|
+
"test-treemap": "yarn unit-treemap && yarn jest --testMatch=\"**/lighthouse-treemap/**/*-test-pptr.js\"",
|
|
43
43
|
"test-lantern": "bash lighthouse-core/scripts/test-lantern.sh",
|
|
44
44
|
"test-legacy-javascript": "bash lighthouse-core/scripts/test-legacy-javascript.sh",
|
|
45
|
-
"test-docs": "yarn --cwd docs/recipes/
|
|
45
|
+
"test-docs": "yarn --cwd docs/recipes/ test",
|
|
46
46
|
"test-proto": "yarn compile-proto && yarn build-proto-roundtrip",
|
|
47
47
|
"unit-core": "yarn jest \"lighthouse-core\"",
|
|
48
48
|
"unit-cli": "yarn jest \"lighthouse-cli/\"",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"unit-treemap": "yarn jest \"lighthouse-treemap/.*-test.js\"",
|
|
51
51
|
"unit-viewer": "yarn jest \"lighthouse-viewer/.*-test.js\"",
|
|
52
52
|
"unit-flow": "yarn jest \"flow-report/.*-test.[tj]s[x]?\"",
|
|
53
|
-
"unit": "yarn
|
|
54
|
-
"unit:ci": "NODE_OPTIONS=--max-old-space-size=8192 npm run
|
|
53
|
+
"unit": "yarn jest",
|
|
54
|
+
"unit:ci": "NODE_OPTIONS=--max-old-space-size=8192 npm run jest -- --ci",
|
|
55
55
|
"core-unit": "yarn unit-core",
|
|
56
56
|
"cli-unit": "yarn unit-cli",
|
|
57
57
|
"viewer-unit": "yarn unit-viewer",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"update:lantern-baseline": "node lighthouse-core/scripts/lantern/update-baseline-lantern-values.js",
|
|
75
75
|
"update:sample-artifacts": "node lighthouse-core/scripts/update-report-fixtures.js",
|
|
76
76
|
"update:sample-json": "yarn i18n:collect-strings && node ./lighthouse-cli -A=./lighthouse-core/test/results/artifacts --config-path=./lighthouse-core/test/results/sample-config.js --output=json --output-path=./lighthouse-core/test/results/sample_v2.json && node lighthouse-core/scripts/cleanup-LHR-for-diff.js ./lighthouse-core/test/results/sample_v2.json --only-remove-timing",
|
|
77
|
+
"update:flow-sample-json": "node ./lighthouse-core/scripts/update-flow-fixtures.js",
|
|
77
78
|
"update:test-devtools": "bash lighthouse-core/test/chromium-web-tests/test-locally.sh --reset-results",
|
|
78
79
|
"test-devtools": "bash lighthouse-core/test/chromium-web-tests/test-locally.sh",
|
|
79
80
|
"open-devtools": "bash lighthouse-core/scripts/open-devtools.sh",
|
|
@@ -88,7 +89,8 @@
|
|
|
88
89
|
"serve-dist": "cd dist && python -m SimpleHTTPServer",
|
|
89
90
|
"serve-gh-pages": "cd dist/gh-pages && python -m SimpleHTTPServer",
|
|
90
91
|
"serve-treemap": "yarn serve-gh-pages",
|
|
91
|
-
"serve-viewer": "yarn serve-gh-pages"
|
|
92
|
+
"serve-viewer": "yarn serve-gh-pages",
|
|
93
|
+
"flow-report": "yarn build-report --flow && node ./lighthouse-core/scripts/build-test-flow-report.js"
|
|
92
94
|
},
|
|
93
95
|
"devDependencies": {
|
|
94
96
|
"@build-tracker/cli": "^1.0.0-beta.15",
|
package/readme.md
CHANGED
|
@@ -52,7 +52,7 @@ The Chrome extension was available prior to Lighthouse being available in Chrome
|
|
|
52
52
|
|
|
53
53
|
The Node CLI provides the most flexibility in how Lighthouse runs can be configured and reported. Users who want more advanced usage, or want to run Lighthouse in an automated fashion should use the Node CLI.
|
|
54
54
|
|
|
55
|
-
_Lighthouse requires Node 12 LTS (12.
|
|
55
|
+
_Lighthouse requires Node 12 LTS (12.20) or later._
|
|
56
56
|
|
|
57
57
|
**Installation**:
|
|
58
58
|
|
package/report/clients/psi.js
CHANGED
|
@@ -77,6 +77,7 @@ export function prepareLabData(LHResult, document) {
|
|
|
77
77
|
reportLHR.categoryGroups,
|
|
78
78
|
{environment: 'PSI', gatherMode: lhResult.gatherMode}
|
|
79
79
|
);
|
|
80
|
+
perfCategoryEl.append(dom.createComponent('styles'));
|
|
80
81
|
|
|
81
82
|
const scoreGaugeEl = dom.find('.lh-score__gauge', perfCategoryEl);
|
|
82
83
|
scoreGaugeEl.remove();
|
|
@@ -67,8 +67,6 @@ describe('PSI', () => {
|
|
|
67
67
|
// Check that the report exists and has some content.
|
|
68
68
|
assert.ok(result.perfCategoryEl instanceof document.defaultView.Element);
|
|
69
69
|
assert.ok(result.perfCategoryEl.outerHTML.length > 50000, 'perfCategory HTML is populated');
|
|
70
|
-
assert.ok(!result.perfCategoryEl.outerHTML.includes('lh-permalink'),
|
|
71
|
-
'PSI\'s perfCategory HTML doesn\'t include a lh-permalink element');
|
|
72
70
|
// Assume using default locale.
|
|
73
71
|
const title = result.perfCategoryEl.querySelector('.lh-audit-group--metrics')
|
|
74
72
|
.querySelector('.lh-audit-group__title').textContent;
|
|
@@ -83,7 +81,8 @@ describe('PSI', () => {
|
|
|
83
81
|
|
|
84
82
|
assert.ok(result.perfCategoryEl instanceof document.defaultView.Element);
|
|
85
83
|
assert.ok(result.perfCategoryEl.outerHTML.length > 50000, 'perfCategory HTML is populated');
|
|
86
|
-
|
|
84
|
+
// styles for .lh-permalink are ok, but not the HTML
|
|
85
|
+
assert.ok(!result.perfCategoryEl.outerHTML.includes('class="lh-permalink'),
|
|
87
86
|
'PSI\'s perfCategory HTML doesn\'t include a lh-permalink element');
|
|
88
87
|
|
|
89
88
|
assert.equal(typeof result.finalScreenshotDataUri, 'string');
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2021 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
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/* eslint-env jest */
|
|
9
|
+
|
|
10
|
+
import jsdom from 'jsdom';
|
|
11
|
+
|
|
12
|
+
import {Util} from '../../renderer/util.js';
|
|
13
|
+
import {DOM} from '../../renderer/dom.js';
|
|
14
|
+
import {DetailsRenderer} from '../../renderer/details-renderer.js';
|
|
15
|
+
import {CategoryRenderer} from '../../renderer/category-renderer.js';
|
|
16
|
+
import {ReportRenderer} from '../../renderer/report-renderer.js';
|
|
17
|
+
import sampleResultsOrig from '../../../lighthouse-core/test/results/sample_v2.json';
|
|
18
|
+
|
|
19
|
+
describe('ReportRendererAxe', () => {
|
|
20
|
+
describe('with aXe', () => {
|
|
21
|
+
let axe;
|
|
22
|
+
let renderer;
|
|
23
|
+
let sampleResults;
|
|
24
|
+
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
const {window} = new jsdom.JSDOM();
|
|
27
|
+
const dom = new DOM(window.document);
|
|
28
|
+
const detailsRenderer = new DetailsRenderer(dom);
|
|
29
|
+
const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
|
|
30
|
+
renderer = new ReportRenderer(dom, categoryRenderer);
|
|
31
|
+
sampleResults = Util.prepareReportResult(sampleResultsOrig);
|
|
32
|
+
|
|
33
|
+
// Needed by axe-core
|
|
34
|
+
// https://github.com/dequelabs/axe-core/blob/581c441c/doc/examples/jsdom/test/a11y.js#L24
|
|
35
|
+
global.window = global.self = window;
|
|
36
|
+
global.Node = global.self.Node;
|
|
37
|
+
global.Element = global.self.Element;
|
|
38
|
+
|
|
39
|
+
// axe-core must be imported after the global polyfills
|
|
40
|
+
axe = (await import('axe-core')).default;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterAll(() => {
|
|
44
|
+
global.window = undefined;
|
|
45
|
+
global.Node = undefined;
|
|
46
|
+
global.Element = undefined;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('renders without axe violations', () => {
|
|
50
|
+
const container = renderer._dom._document.createElement('main');
|
|
51
|
+
const output = renderer.renderReport(sampleResults, container);
|
|
52
|
+
|
|
53
|
+
renderer._dom._document.body.appendChild(container);
|
|
54
|
+
|
|
55
|
+
const config = {
|
|
56
|
+
rules: {
|
|
57
|
+
// Reports may have duplicate ids
|
|
58
|
+
// https://github.com/GoogleChrome/lighthouse/issues/9432
|
|
59
|
+
'duplicate-id': {enabled: false},
|
|
60
|
+
'duplicate-id-aria': {enabled: false},
|
|
61
|
+
'landmark-no-duplicate-contentinfo': {enabled: false},
|
|
62
|
+
// The following rules are disable for axe-core + jsdom compatibility
|
|
63
|
+
// https://github.com/dequelabs/axe-core/tree/b573b1c1/doc/examples/jest_react#to-run-the-example
|
|
64
|
+
'color-contrast': {enabled: false},
|
|
65
|
+
'link-in-text-block': {enabled: false},
|
|
66
|
+
// Report has empty links prior to i18n-ing.
|
|
67
|
+
'link-name': {enabled: false},
|
|
68
|
+
// May not be a real issue. https://github.com/dequelabs/axe-core/issues/2958
|
|
69
|
+
'nested-interactive': {enabled: false},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return new Promise(resolve => {
|
|
74
|
+
axe.run(output, config, (error, {violations}) => {
|
|
75
|
+
expect(error).toBeNull();
|
|
76
|
+
expect(violations).toEqual([]);
|
|
77
|
+
resolve();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
// This test takes 40s on fast hardware, and 50-60s on GHA.
|
|
81
|
+
// https://github.com/dequelabs/axe-core/tree/b573b1c1/doc/examples/jest_react#timeout-issues
|
|
82
|
+
},
|
|
83
|
+
/* timeout= */ 100 * 1000
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
});
|