lighthouse 10.0.0-dev.20230213 → 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/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 +1 -1
- 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-template.html +0 -177
- package/report/test-assets/faux-psi.d.ts +0 -34
- package/report/test-assets/faux-psi.js +0 -168
- package/report/test-assets/lhr-3.0.0.json +0 -2332
- package/report/test-assets/lhr-4.3.0.json +0 -4754
- package/report/test-assets/lhr-5.0.0.json +0 -5994
- package/report/test-assets/lhr-6.0.0.json +0 -7222
- package/report/test-assets/lhr-8.5.0.json +0 -8679
- 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
|
@@ -2,9 +2,10 @@ export default Doctype;
|
|
|
2
2
|
declare class Doctype extends Audit {
|
|
3
3
|
/**
|
|
4
4
|
* @param {LH.Artifacts} artifacts
|
|
5
|
-
* @
|
|
5
|
+
* @param {LH.Audit.Context} context
|
|
6
|
+
* @return {Promise<LH.Audit.Product>}
|
|
6
7
|
*/
|
|
7
|
-
static audit(artifacts: LH.Artifacts): LH.Audit.Product
|
|
8
|
+
static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
|
|
8
9
|
}
|
|
9
10
|
export namespace UIStrings {
|
|
10
11
|
const title: string;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {Audit} from '../audit.js';
|
|
8
8
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
9
|
+
import {ProcessedTrace} from '../../computed/processed-trace.js';
|
|
9
10
|
|
|
10
11
|
const UIStrings = {
|
|
11
12
|
/** Title of a Lighthouse audit that provides detail on the doctype of a page. This descriptive title is shown to users when the pages's doctype is set to HTML. */
|
|
@@ -43,15 +44,16 @@ class Doctype extends Audit {
|
|
|
43
44
|
failureTitle: str_(UIStrings.failureTitle),
|
|
44
45
|
description: str_(UIStrings.description),
|
|
45
46
|
requiredArtifacts: ['Doctype'],
|
|
46
|
-
__internalOptionalArtifacts: ['InspectorIssues'],
|
|
47
|
+
__internalOptionalArtifacts: ['InspectorIssues', 'traces'],
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* @param {LH.Artifacts} artifacts
|
|
52
|
-
* @
|
|
53
|
+
* @param {LH.Audit.Context} context
|
|
54
|
+
* @return {Promise<LH.Audit.Product>}
|
|
53
55
|
*/
|
|
54
|
-
static audit(artifacts) {
|
|
56
|
+
static async audit(artifacts, context) {
|
|
55
57
|
if (!artifacts.Doctype) {
|
|
56
58
|
return {
|
|
57
59
|
score: 0,
|
|
@@ -64,7 +66,16 @@ class Doctype extends Audit {
|
|
|
64
66
|
const doctypePublicId = artifacts.Doctype.publicId;
|
|
65
67
|
const doctypeSystemId = artifacts.Doctype.systemId;
|
|
66
68
|
const compatMode = artifacts.Doctype.documentCompatMode;
|
|
67
|
-
|
|
69
|
+
|
|
70
|
+
/** @type {LH.Crdp.Audits.QuirksModeIssueDetails[]} */
|
|
71
|
+
let quirksModeIssues = [];
|
|
72
|
+
if (artifacts.traces && artifacts.InspectorIssues) {
|
|
73
|
+
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
74
|
+
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
75
|
+
const mainFrameId = processedTrace.mainFrameInfo.frameId;
|
|
76
|
+
quirksModeIssues =
|
|
77
|
+
artifacts.InspectorIssues.quirksModeIssue.filter(issue => issue.frameId === mainFrameId);
|
|
78
|
+
}
|
|
68
79
|
|
|
69
80
|
// Can only determine limited quirks mode with some helps from the protocol via
|
|
70
81
|
// inspector issues. But cannot get inspector issues in snapshot mode, so in that
|
|
@@ -13,8 +13,8 @@ const UIStrings = {
|
|
|
13
13
|
/** Title of a Lighthouse audit that provides detail on the ability to paste into input fields. This descriptive title is shown to users when the page does not allow pasting of content into input fields. */
|
|
14
14
|
failureTitle: 'Prevents users from pasting into input fields',
|
|
15
15
|
/** Description of a Lighthouse audit that tells the user why they should allow pasting of content into input fields. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
|
|
16
|
-
description: 'Preventing input pasting is a UX
|
|
17
|
-
'and
|
|
16
|
+
description: 'Preventing input pasting is a bad practice for the UX, ' +
|
|
17
|
+
'and weakens security by blocking password managers.' +
|
|
18
18
|
'[Learn more about user-friendly input fields](https://developer.chrome.com/docs/lighthouse/best-practices/paste-preventing-inputs/).',
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -95,9 +95,7 @@ class NetworkMonitor extends NetworkMonitorEventEmitter {
|
|
|
95
95
|
const frameNavigations = this._frameNavigations;
|
|
96
96
|
if (!frameNavigations.length) return {};
|
|
97
97
|
|
|
98
|
-
const
|
|
99
|
-
const mainFrameId = frameTreeResponse.frameTree.frame.id;
|
|
100
|
-
const mainFrameNavigations = frameNavigations.filter(frame => frame.id === mainFrameId);
|
|
98
|
+
const mainFrameNavigations = frameNavigations.filter(frame => !frame.parentId);
|
|
101
99
|
if (!mainFrameNavigations.length) log.warn('NetworkMonitor', 'No detected navigations');
|
|
102
100
|
|
|
103
101
|
// The requested URL is the initiator request for the first frame navigation.
|
|
@@ -8,7 +8,7 @@ import FRGatherer from '../base-gatherer.js';
|
|
|
8
8
|
import {waitForFrameNavigated, waitForLoadEvent} from '../driver/wait-for-condition.js';
|
|
9
9
|
import DevtoolsLog from './devtools-log.js';
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const AFTER_RETURN_TIMEOUT = 100;
|
|
12
12
|
const TEMP_PAGE_PAUSE_TIMEOUT = 100;
|
|
13
13
|
|
|
14
14
|
class BFCacheFailures extends FRGatherer {
|
|
@@ -122,14 +122,13 @@ class BFCacheFailures extends FRGatherer {
|
|
|
122
122
|
|
|
123
123
|
// The bfcache failure event is not necessarily emitted by this point.
|
|
124
124
|
// If we are expecting a bfcache failure event but haven't seen one, we should wait for it.
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
// This timeout also allows the environment to "settle" before gathering enters it's cleanup phase.
|
|
126
|
+
await new Promise(resolve => setTimeout(resolve, AFTER_RETURN_TIMEOUT));
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
128
|
+
// If we still can't get the failure reasons after the timeout we should fail loudly,
|
|
129
|
+
// otherwise this gatherer will return no failures when there should be failures.
|
|
130
|
+
if (frameNavigatedEvent.type !== 'BackForwardCacheRestore' && !bfCacheEvent) {
|
|
131
|
+
throw new Error('bfcache failed but the failure reasons were not emitted in time');
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
session.off('Page.backForwardCacheNotUsed', onBfCacheNotUsed);
|
package/package.json
CHANGED
|
@@ -765,7 +765,7 @@
|
|
|
765
765
|
"message": "Avoids requesting the notification permission on page load"
|
|
766
766
|
},
|
|
767
767
|
"core/audits/dobetterweb/paste-preventing-inputs.js | description": {
|
|
768
|
-
"message": "Preventing input pasting is a UX
|
|
768
|
+
"message": "Preventing input pasting is a bad practice for the UX, and weakens security by blocking password managers.[Learn more about user-friendly input fields](https://developer.chrome.com/docs/lighthouse/best-practices/paste-preventing-inputs/)."
|
|
769
769
|
},
|
|
770
770
|
"core/audits/dobetterweb/paste-preventing-inputs.js | failureTitle": {
|
|
771
771
|
"message": "Prevents users from pasting into input fields"
|
|
@@ -765,7 +765,7 @@
|
|
|
765
765
|
"message": "Âv́ôíd̂ś r̂éq̂úêśt̂ín̂ǵ t̂h́ê ńôt́îf́îćât́îón̂ ṕêŕm̂íŝśîón̂ ón̂ ṕâǵê ĺôád̂"
|
|
766
766
|
},
|
|
767
767
|
"core/audits/dobetterweb/paste-preventing-inputs.js | description": {
|
|
768
|
-
"message": "P̂ŕêv́êńt̂ín̂ǵ îńp̂út̂ ṕâśt̂ín̂ǵ îś â
|
|
768
|
+
"message": "P̂ŕêv́êńt̂ín̂ǵ îńp̂út̂ ṕâśt̂ín̂ǵ îś â b́âd́ p̂ŕâćt̂íĉé f̂ór̂ t́ĥé ÛX́, âńd̂ ẃêák̂én̂ś ŝéĉúr̂ít̂ý b̂ý b̂ĺôćk̂ín̂ǵ p̂áŝśŵór̂d́ m̂án̂áĝér̂ś.[L̂éâŕn̂ ḿôŕê áb̂óût́ ûśêŕ-f̂ŕîén̂d́l̂ý îńp̂út̂ f́îél̂d́ŝ](https://developer.chrome.com/docs/lighthouse/best-practices/paste-preventing-inputs/)."
|
|
769
769
|
},
|
|
770
770
|
"core/audits/dobetterweb/paste-preventing-inputs.js | failureTitle": {
|
|
771
771
|
"message": "P̂ŕêv́êńt̂ś ûśêŕŝ f́r̂óm̂ ṕâśt̂ín̂ǵ îńt̂ó îńp̂út̂ f́îél̂d́ŝ"
|
package/.codecov.yml
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# validate this file:
|
|
2
|
-
# curl --data-binary @.codecov.yml https://codecov.io/validate
|
|
3
|
-
|
|
4
|
-
comment: off
|
|
5
|
-
|
|
6
|
-
# partial line support
|
|
7
|
-
parsers:
|
|
8
|
-
javascript:
|
|
9
|
-
enable_partials: yes
|
|
10
|
-
|
|
11
|
-
# docs:
|
|
12
|
-
# https://codecov.readme.io/v4.3.6/docs/commit-status
|
|
13
|
-
# https://gist.github.com/stevepeak/53bee7b2c326b24a9b4a
|
|
14
|
-
coverage:
|
|
15
|
-
status:
|
|
16
|
-
project:
|
|
17
|
-
default:
|
|
18
|
-
threshold: 1%
|
|
19
|
-
if_not_found: success # no commit found? still set a success
|
|
20
|
-
patch:
|
|
21
|
-
default:
|
|
22
|
-
if_not_found: success
|
package/.cz-config.js
DELETED
|
@@ -1,24 +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
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
module.exports = {
|
|
9
|
-
allowBreakingChanges: ['core'],
|
|
10
|
-
allowCustomScopes: true,
|
|
11
|
-
scopes: [],
|
|
12
|
-
types: [
|
|
13
|
-
{value: 'new_audit', name: 'new_audit: A new audit'},
|
|
14
|
-
{value: 'core', name: 'core: Driver, gather, (non-new) audits, LHR JSON, etc'},
|
|
15
|
-
{value: 'tests', name: 'tests: Tests, smokehouse, etc'},
|
|
16
|
-
{value: 'i18n', name: 'i18n: Internationalization'},
|
|
17
|
-
{value: 'docs', name: 'docs: Documentation'},
|
|
18
|
-
{value: 'deps', name: 'deps: Dependency bumps only'},
|
|
19
|
-
{value: 'report', name: 'report: Report, UI, renderers'},
|
|
20
|
-
{value: 'cli', name: 'cli: CLI stuff'},
|
|
21
|
-
{value: 'clients', name: 'clients: Extension, DevTools, or LR stuff'},
|
|
22
|
-
{value: 'misc', name: 'misc: Something else entirely'}
|
|
23
|
-
]
|
|
24
|
-
};
|
package/.gitattributes
DELETED
package/.mailmap
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
Brendan Kenny <bckenny@gmail.com> Brendan Kenny <bckenny@google.com>
|
|
2
|
-
Connor Clark <cjamcl@gmail.com> cjamcl <cjamcl@google.com>
|
|
3
|
-
Connor Clark <cjamcl@gmail.com> Connor Clark <cjamcl@google.com>
|
|
4
|
-
Patrick Hulce <patrick.hulce@gmail.com> Patrick Hulce <phulce@google.com>
|
|
5
|
-
Paul Irish <paul.irish@gmail.com> Paul Irish <paulirish@google.com>
|
|
6
|
-
Paul Lewis <github@aerotwist.com> Paul Lewis <gravatar@aerotwist.com>
|
package/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
|
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of
|
|
9
|
-
experience, education, socio-economic status, nationality, personal appearance,
|
|
10
|
-
race, religion, or sexual identity and orientation.
|
|
11
|
-
|
|
12
|
-
## Our Standards
|
|
13
|
-
|
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
|
15
|
-
include:
|
|
16
|
-
|
|
17
|
-
* Using welcoming and inclusive language
|
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
|
19
|
-
* Gracefully accepting constructive criticism
|
|
20
|
-
* Focusing on what is best for the community
|
|
21
|
-
* Showing empathy towards other community members
|
|
22
|
-
|
|
23
|
-
Examples of unacceptable behavior by participants include:
|
|
24
|
-
|
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
26
|
-
advances
|
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
28
|
-
* Public or private harassment
|
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
|
30
|
-
address, without explicit permission
|
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
-
professional setting
|
|
33
|
-
|
|
34
|
-
## Our Responsibilities
|
|
35
|
-
|
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
|
38
|
-
response to any instances of unacceptable behavior.
|
|
39
|
-
|
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or reject
|
|
41
|
-
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
42
|
-
not aligned to this Code of Conduct, or to ban temporarily or permanently any
|
|
43
|
-
contributor for other behaviors that they deem inappropriate, threatening,
|
|
44
|
-
offensive, or harmful.
|
|
45
|
-
|
|
46
|
-
## Scope
|
|
47
|
-
|
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
|
49
|
-
when an individual is representing the project or its community. Examples of
|
|
50
|
-
representing a project or community include using an official project e-mail
|
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
|
53
|
-
further defined and clarified by project maintainers.
|
|
54
|
-
|
|
55
|
-
This Code of Conduct also applies outside the project spaces when the Project
|
|
56
|
-
Steward has a reasonable belief that an individual's behavior may have a
|
|
57
|
-
negative impact on the project or its community.
|
|
58
|
-
|
|
59
|
-
## Conflict Resolution
|
|
60
|
-
|
|
61
|
-
We do not believe that all conflict is bad; healthy debate and disagreement
|
|
62
|
-
often yield positive results. However, it is never okay to be disrespectful or
|
|
63
|
-
to engage in behavior that violates the project’s code of conduct.
|
|
64
|
-
|
|
65
|
-
If you see someone violating the code of conduct, you are encouraged to address
|
|
66
|
-
the behavior directly with those involved. Many issues can be resolved quickly
|
|
67
|
-
and easily, and this gives people more control over the outcome of their
|
|
68
|
-
dispute. If you are unable to resolve the matter for any reason, or if the
|
|
69
|
-
behavior is threatening or harassing, report it. We are dedicated to providing
|
|
70
|
-
an environment where participants feel welcome and safe.
|
|
71
|
-
|
|
72
|
-
Reports should be directed to *Brendan Kenny (bckenny@google.com)*, the
|
|
73
|
-
Project Steward(s) for *Lighthouse*. It is the Project Steward’s duty to
|
|
74
|
-
receive and address reported violations of the code of conduct. They will then
|
|
75
|
-
work with a committee consisting of representatives from the Open Source
|
|
76
|
-
Programs Office and the Google Open Source Strategy team. If for any reason you
|
|
77
|
-
are uncomfortable reaching out to the Project Steward, please email
|
|
78
|
-
opensource@google.com.
|
|
79
|
-
|
|
80
|
-
We will investigate every complaint, but you may not receive a direct response.
|
|
81
|
-
We will use our discretion in determining when and how to follow up on reported
|
|
82
|
-
incidents, which may range from not taking action to permanent expulsion from
|
|
83
|
-
the project and project-sponsored spaces. We will notify the accused of the
|
|
84
|
-
report and provide them an opportunity to discuss it before any action is taken.
|
|
85
|
-
The identity of the reporter will be omitted from the details of the report
|
|
86
|
-
supplied to the accused. In potentially harmful situations, such as ongoing
|
|
87
|
-
harassment or threats to anyone's safety, we may take action without notice.
|
|
88
|
-
|
|
89
|
-
## Attribution
|
|
90
|
-
|
|
91
|
-
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
|
|
92
|
-
available at
|
|
93
|
-
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
package/eslint-local-rules.cjs
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright 2019 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
|
-
/**
|
|
9
|
-
* @fileoverview A collection of eslint rules written specifically for
|
|
10
|
-
* Lighthouse. These are included by the eslint-plugin-local-rules plugin.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
/** @typedef {import('eslint').Rule.RuleModule} RuleModule */
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Use `require.resolve()` to resolve the location of `path` from a location of
|
|
19
|
-
* `baseDir` and return it. Returns null if unable to resolve a path.
|
|
20
|
-
* @param {string} path
|
|
21
|
-
* @param {string} baseDir
|
|
22
|
-
* @return {string|null}
|
|
23
|
-
*/
|
|
24
|
-
function requireResolveOrNull(path, baseDir) {
|
|
25
|
-
try {
|
|
26
|
-
return require.resolve(path, {
|
|
27
|
-
paths: [baseDir],
|
|
28
|
-
});
|
|
29
|
-
} catch (err) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* An eslint rule ensuring that any require() of a local path (aka not a core
|
|
36
|
-
* module or a module dependency) includes a file extension (.js' or '.json').
|
|
37
|
-
* @type {RuleModule}
|
|
38
|
-
*/
|
|
39
|
-
const requireFileExtension = {
|
|
40
|
-
meta: {
|
|
41
|
-
docs: {
|
|
42
|
-
description: 'disallow require() without a file extension',
|
|
43
|
-
category: 'Best Practices',
|
|
44
|
-
recommended: false,
|
|
45
|
-
},
|
|
46
|
-
schema: [],
|
|
47
|
-
fixable: 'code',
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
create(context) {
|
|
51
|
-
return {
|
|
52
|
-
CallExpression(node) {
|
|
53
|
-
// Only look at instances of `require(moduleName: string)`.
|
|
54
|
-
if (node.type !== 'CallExpression') return;
|
|
55
|
-
if (node.callee.type !== 'Identifier' || node.callee.name !== 'require') return;
|
|
56
|
-
if (!node.arguments.length) return;
|
|
57
|
-
const arg0 = node.arguments[0];
|
|
58
|
-
if (arg0.type !== 'Literal' || typeof arg0.value !== 'string') return;
|
|
59
|
-
|
|
60
|
-
const requiredPath = arg0.value;
|
|
61
|
-
|
|
62
|
-
// If it's not a local file, we don't care.
|
|
63
|
-
if (!requiredPath.startsWith('.')) return;
|
|
64
|
-
|
|
65
|
-
// Check that `requiredPath` is resolvable from the source file.
|
|
66
|
-
const contextDirname = path.dirname(context.getFilename());
|
|
67
|
-
const resolvedRequiredPath = requireResolveOrNull(requiredPath, contextDirname);
|
|
68
|
-
if (!resolvedRequiredPath) {
|
|
69
|
-
return context.report({
|
|
70
|
-
node: node,
|
|
71
|
-
message: `Cannot resolve module '${requiredPath}'.`,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// If it has a file extension, it's good to go.
|
|
76
|
-
if (requiredPath.endsWith('.js')) return;
|
|
77
|
-
if (requiredPath.endsWith('.json')) return;
|
|
78
|
-
|
|
79
|
-
context.report({
|
|
80
|
-
node: node,
|
|
81
|
-
message: 'Local require path must have a file extension.',
|
|
82
|
-
fix(fixer) {
|
|
83
|
-
// Find the correct file extension/filename ending of the requiredPath.
|
|
84
|
-
let fixedPath = path.relative(contextDirname, resolvedRequiredPath);
|
|
85
|
-
if (!fixedPath.startsWith('.')) fixedPath = `./${fixedPath}`;
|
|
86
|
-
|
|
87
|
-
// Usually `fixedPath.startsWith(requiredPath)` and this will just add
|
|
88
|
-
// a suffix to the existing path, but sometimes humans write confusing
|
|
89
|
-
// paths, e.g. './core/lib/../lib/lh-error.js'. To cover both
|
|
90
|
-
// cases, double check that the paths resolve to the same file.
|
|
91
|
-
const resolvedFixedPath = requireResolveOrNull(fixedPath, contextDirname);
|
|
92
|
-
|
|
93
|
-
// If somehow they don't point to the same file, don't try to fix.
|
|
94
|
-
if (resolvedFixedPath !== resolvedRequiredPath) return null;
|
|
95
|
-
|
|
96
|
-
return fixer.replaceText(arg0, `'${fixedPath}'`);
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
module.exports = {
|
|
105
|
-
'require-file-extension': requireFileExtension,
|
|
106
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
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
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=app-test.d.ts.map
|
|
@@ -1,52 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
import {act, render} from '@testing-library/preact';
|
|
8
|
-
|
|
9
|
-
import {App} from '../src/app';
|
|
10
|
-
import {flowResult} from './sample-flow';
|
|
11
|
-
|
|
12
|
-
it('renders a standalone report with summary', async () => {
|
|
13
|
-
const root = render(<App flowResult={flowResult}/>);
|
|
14
|
-
|
|
15
|
-
expect(root.getByTestId('Summary')).toBeTruthy();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('renders the navigation step', async () => {
|
|
19
|
-
global.location.hash = '#index=0';
|
|
20
|
-
const root = render(<App flowResult={flowResult}/>);
|
|
21
|
-
|
|
22
|
-
expect(root.getByTestId('Report')).toBeTruthy();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('renders the timespan step', async () => {
|
|
26
|
-
global.location.hash = '#index=1';
|
|
27
|
-
const root = render(<App flowResult={flowResult}/>);
|
|
28
|
-
|
|
29
|
-
expect(root.getByTestId('Report')).toBeTruthy();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('renders the snapshot step', async () => {
|
|
33
|
-
global.location.hash = '#index=2';
|
|
34
|
-
const root = render(<App flowResult={flowResult}/>);
|
|
35
|
-
|
|
36
|
-
expect(root.getByTestId('Report')).toBeTruthy();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('toggles collapsed mode when hamburger button clicked', async () => {
|
|
40
|
-
const root = render(<App flowResult={flowResult}/>);
|
|
41
|
-
|
|
42
|
-
const app = root.getByTestId('App');
|
|
43
|
-
const hamburgerButton = root.getByLabelText('Button that opens and closes the sidebar');
|
|
44
|
-
|
|
45
|
-
expect(app.classList).not.toContain('App--collapsed');
|
|
46
|
-
|
|
47
|
-
await act(() => {
|
|
48
|
-
hamburgerButton.click();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
expect(app.classList).toContain('App--collapsed');
|
|
52
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
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
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=common-test.d.ts.map
|
|
@@ -1,103 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
import jestMock from 'jest-mock';
|
|
8
|
-
import {act, render} from '@testing-library/preact';
|
|
9
|
-
|
|
10
|
-
import {timers} from '../../core/test/test-env/fake-timers.js';
|
|
11
|
-
import {FlowStepThumbnail} from '../src/common';
|
|
12
|
-
|
|
13
|
-
let lhr: LH.Result;
|
|
14
|
-
|
|
15
|
-
describe('FlowStepThumbnail', () => {
|
|
16
|
-
before(() => timers.useFakeTimers());
|
|
17
|
-
after(() => timers.dispose());
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
global.console.warn = jestMock.fn();
|
|
21
|
-
|
|
22
|
-
lhr = {
|
|
23
|
-
gatherMode: 'navigation',
|
|
24
|
-
configSettings: {screenEmulation: {width: 400, height: 600}},
|
|
25
|
-
audits: {
|
|
26
|
-
'screenshot-thumbnails': {
|
|
27
|
-
details: {
|
|
28
|
-
type: 'filmstrip',
|
|
29
|
-
items: [
|
|
30
|
-
{data: 'frame1'},
|
|
31
|
-
{data: 'frame2'},
|
|
32
|
-
],
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
fullPageScreenshot: {
|
|
37
|
-
screenshot: {data: 'FPS', width: 400, height: 600},
|
|
38
|
-
nodes: {},
|
|
39
|
-
},
|
|
40
|
-
} as any;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('renders a thumbnail', () => {
|
|
44
|
-
const root = render(<FlowStepThumbnail lhr={lhr} width={200} height={200} />);
|
|
45
|
-
|
|
46
|
-
const thumbnail = root.getByAltText(/Screenshot/);
|
|
47
|
-
expect(thumbnail.style.width).toEqual('200px');
|
|
48
|
-
expect(thumbnail.style.height).toEqual('200px');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('renders nothing without dimensions', () => {
|
|
52
|
-
const root = render(<FlowStepThumbnail lhr={lhr} />);
|
|
53
|
-
|
|
54
|
-
expect(() => root.getByAltText(/Screenshot/)).toThrow();
|
|
55
|
-
expect(global.console.warn).toHaveBeenCalled();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('interpolates height', () => {
|
|
59
|
-
const root = render(<FlowStepThumbnail lhr={lhr} width={200} />);
|
|
60
|
-
|
|
61
|
-
const thumbnail = root.getByAltText(/Screenshot/);
|
|
62
|
-
expect(thumbnail.style.width).toEqual('200px');
|
|
63
|
-
expect(thumbnail.style.height).toEqual('300px');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('interpolates width', () => {
|
|
67
|
-
const root = render(<FlowStepThumbnail lhr={lhr} height={150} />);
|
|
68
|
-
|
|
69
|
-
const thumbnail = root.getByAltText(/Screenshot/);
|
|
70
|
-
expect(thumbnail.style.width).toEqual('100px');
|
|
71
|
-
expect(thumbnail.style.height).toEqual('150px');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('uses last filmstrip thumbnail', () => {
|
|
75
|
-
const root = render(<FlowStepThumbnail lhr={lhr} height={150} />);
|
|
76
|
-
|
|
77
|
-
const thumbnail = root.getByAltText(/Screenshot/) as HTMLImageElement;
|
|
78
|
-
expect(thumbnail.src).toContain('frame2');
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('uses full page screenshot if filmstrip unavailable', () => {
|
|
82
|
-
delete lhr.audits['screenshot-thumbnails'];
|
|
83
|
-
const root = render(<FlowStepThumbnail lhr={lhr} height={150} />);
|
|
84
|
-
|
|
85
|
-
const thumbnail = root.getByAltText(/Screenshot/) as HTMLImageElement;
|
|
86
|
-
expect(thumbnail.src).toContain('FPS');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('renders animated thumbnail for timespan', async () => {
|
|
90
|
-
lhr.gatherMode = 'timespan';
|
|
91
|
-
const root = render(<FlowStepThumbnail lhr={lhr} height={150} />);
|
|
92
|
-
|
|
93
|
-
const thumbnail = root.getByAltText(/Animated/) as HTMLImageElement;
|
|
94
|
-
expect(thumbnail.style.width).toEqual('100px');
|
|
95
|
-
expect(thumbnail.style.height).toEqual('150px');
|
|
96
|
-
|
|
97
|
-
expect(thumbnail.src).toContain('frame1');
|
|
98
|
-
await act(() => {
|
|
99
|
-
timers.advanceTimersByTime(501);
|
|
100
|
-
});
|
|
101
|
-
expect(thumbnail.src).toContain('frame2');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
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
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=flow-report-pptr-test.d.ts.map
|
|
@@ -1,59 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
import puppeteer, {Browser, Page} from 'puppeteer';
|
|
8
|
-
|
|
9
|
-
import {ReportGenerator} from '../../report/generator/report-generator.js';
|
|
10
|
-
import {swapFlowLocale} from '../../shared/localization/swap-flow-locale.js';
|
|
11
|
-
import {flowResult} from './sample-flow';
|
|
12
|
-
|
|
13
|
-
describe('Lighthouse Flow Report', () => {
|
|
14
|
-
console.log('\n✨ Be sure to have recently run this: yarn build-report');
|
|
15
|
-
|
|
16
|
-
let browser: Browser;
|
|
17
|
-
let page: Page;
|
|
18
|
-
const pageErrors: Error[] = [];
|
|
19
|
-
|
|
20
|
-
before(async () => {
|
|
21
|
-
browser = await puppeteer.launch({
|
|
22
|
-
headless: true,
|
|
23
|
-
});
|
|
24
|
-
page = await browser.newPage();
|
|
25
|
-
page.on('pageerror', pageError => pageErrors.push(pageError));
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
after(async () => {
|
|
29
|
-
if (pageErrors.length > 0) console.error(pageErrors);
|
|
30
|
-
|
|
31
|
-
await browser.close();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('Renders the flow report', () => {
|
|
35
|
-
before(async () => {
|
|
36
|
-
const html = ReportGenerator.generateFlowReportHtml(flowResult);
|
|
37
|
-
await page.setContent(html);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should load with no errors', async () => {
|
|
41
|
-
expect(pageErrors).toHaveLength(0);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('Renders the flow report (i18n)', () => {
|
|
46
|
-
before(async () => {
|
|
47
|
-
const html = ReportGenerator.generateFlowReportHtml(swapFlowLocale(flowResult, 'es'));
|
|
48
|
-
await page.setContent(html);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should load with no errors', async () => {
|
|
52
|
-
expect(pageErrors).toHaveLength(0);
|
|
53
|
-
const el = await page.$('.SummarySectionHeader__content');
|
|
54
|
-
if (!el) throw new Error();
|
|
55
|
-
const text = await el.evaluate(el => el.textContent);
|
|
56
|
-
expect(text).toEqual('Todos los informes');
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
}).timeout(35_000);
|