forked from checkinholiday/lighthouse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherrors-in-console.js
120 lines (102 loc) · 4.5 KB
/
errors-in-console.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Audits a page to determine whether it contains console errors.
* This is done by collecting Chrome console log messages and filtering out the non-error ones.
*/
import log from 'lighthouse-logger';
import {Audit} from './audit.js';
import {JSBundles} from '../computed/js-bundles.js';
import * as i18n from '../lib/i18n/i18n.js';
const UIStrings = {
/** Title of a Lighthouse audit that provides detail on browser errors. This descriptive title is shown to users when no browser errors were logged into the devtools console. */
title: 'No browser errors logged to the console',
/** Title of a Lighthouse audit that provides detail on browser errors. This descriptive title is shown to users when browser errors occurred and were logged into the devtools console. */
failureTitle: 'Browser errors were logged to the console',
/** Description of a Lighthouse audit that tells the user why errors being logged to the devtools console are a cause for concern and so should be fixed. This is displayed after a user expands the section to see more. No character length limits. */
description: 'Errors logged to the console indicate unresolved problems. ' +
'They can come from network request failures and other browser concerns. ' +
'[Learn more about this errors in console diagnostic audit](https://developer.chrome.com/docs/lighthouse/best-practices/errors-in-console/)',
};
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
/** @typedef {{ignoredPatterns?: Array<RegExp|string>}} AuditOptions */
class ErrorLogs extends Audit {
/**
* @return {LH.Audit.Meta}
*/
static get meta() {
return {
id: 'errors-in-console',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['ConsoleMessages', 'SourceMaps', 'Scripts'],
};
}
/** @return {AuditOptions} */
static get defaultOptions() {
// Any failed network requests with error messsage aren't actionable
return {ignoredPatterns: ['ERR_BLOCKED_BY_CLIENT.Inspector']};
}
/**
* @template {{description: string | undefined}} T
* @param {Array<T>} items
* @param {AuditOptions} options
* @return {Array<T>}
*/
static filterAccordingToOptions(items, options) {
const {ignoredPatterns, ...restOfOptions} = options;
const otherOptionKeys = Object.keys(restOfOptions);
if (otherOptionKeys.length) log.warn(this.meta.id, 'Unrecognized options', otherOptionKeys);
if (!ignoredPatterns) return items;
return items.filter(({description}) => {
if (!description) return true;
for (const pattern of ignoredPatterns) {
if (pattern instanceof RegExp && pattern.test(description)) return false;
if (typeof pattern === 'string' && description.includes(pattern)) return false;
}
return true;
});
}
/**
* @param {LH.Artifacts} artifacts
* @param {LH.Audit.Context} context
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
/** @type {AuditOptions} */
const auditOptions = context.options;
const bundles = await JSBundles.request(artifacts, context);
/** @type {Array<{source: string, description: string|undefined, sourceLocation: LH.Audit.Details.SourceLocationValue|undefined}>} */
const consoleRows = artifacts.ConsoleMessages
.filter(item => item.level === 'error')
.map(item => {
const bundle = bundles.find(bundle => bundle.script.scriptId === item.scriptId);
return {
source: item.source,
description: item.text,
sourceLocation: Audit.makeSourceLocationFromConsoleMessage(item, bundle),
};
});
const tableRows = ErrorLogs.filterAccordingToOptions(consoleRows, auditOptions)
.sort((a, b) => (a.description || '').localeCompare(b.description || ''));
/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
/* eslint-disable max-len */
{key: 'sourceLocation', valueType: 'source-location', label: str_(i18n.UIStrings.columnSource)},
{key: 'description', valueType: 'code', label: str_(i18n.UIStrings.columnDescription)},
/* eslint-enable max-len */
];
const details = Audit.makeTableDetails(headings, tableRows);
const numErrors = tableRows.length;
return {
score: Number(numErrors === 0),
details,
};
}
}
export default ErrorLogs;
export {UIStrings};