lighthouse-reporting 1.3.1 → 1.4.0
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/README.md +16 -43
- package/dist/index.cjs +2 -0
- package/dist/index.js +4 -2
- package/dist/lighthouse-reporting.umd.cjs +46 -7
- package/dist/lighthouseReports.cjs +40 -2
- package/dist/lighthouseReports.d.ts +43 -1
- package/dist/lighthouseReports.js +41 -3
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -92,10 +92,12 @@ import {
|
|
|
92
92
|
LighthouseResult,
|
|
93
93
|
StorybookIndexStory,
|
|
94
94
|
storybookPlaywright,
|
|
95
|
+
writeScoresToJson
|
|
95
96
|
} from 'lighthouse-reporting'
|
|
96
97
|
|
|
97
98
|
playwrightLighthouseTest.setTimeout(60000)
|
|
98
|
-
const
|
|
99
|
+
const lhScoresDir = path.join(process.cwd(), process.env.LH_SCORES_DIR || 'lh-scores')
|
|
100
|
+
const reportDir = path.join(process.cwd(), process.env.LH_REPORT_DIR || 'lighthouse')
|
|
99
101
|
const htmlFilePath = path.join(reportDir, 'index.html')
|
|
100
102
|
|
|
101
103
|
const stories = storybookPlaywright.getStories('./storybook-static/index.json', (story) => {
|
|
@@ -147,6 +149,8 @@ const runLighthouse = async (story: StorybookIndexStory, context: BrowserContext
|
|
|
147
149
|
const scores = getScores(result)
|
|
148
150
|
await writeCsvResult(reportDir, name, scores, thresholds)
|
|
149
151
|
await writeHtmlListEntryWithRetry(htmlFilePath, name, scores, thresholds, result.comparisonError)
|
|
152
|
+
// write score results in JSON, allows generating the Average csv report
|
|
153
|
+
await writeScoresToJson(lhScoresDir, name, scores, result)
|
|
150
154
|
}
|
|
151
155
|
```
|
|
152
156
|
|
|
@@ -162,6 +166,8 @@ import { PlaywrightTestConfig } from '@playwright/test'
|
|
|
162
166
|
|
|
163
167
|
const baseURL = 'http://127.0.0.1:6009'
|
|
164
168
|
// process.env.LH_REPORT_DIR = 'lighthouse-storybook' // adjust lighthouse output folder if required
|
|
169
|
+
// process.env.LH_SCORES_DIR = 'lh-scores' // to write and store scores in json format or write average report
|
|
170
|
+
|
|
165
171
|
|
|
166
172
|
const config: PlaywrightTestConfig = {
|
|
167
173
|
use: {
|
|
@@ -209,49 +215,13 @@ export default config
|
|
|
209
215
|
<summary>global-setup.ts</summary>
|
|
210
216
|
|
|
211
217
|
```ts
|
|
212
|
-
import {
|
|
213
|
-
|
|
214
|
-
const baseURL = 'http://127.0.0.1:6009'
|
|
215
|
-
// process.env.LH_REPORT_DIR = 'lighthouse-storybook' // adjust lighthouse output folder if required
|
|
218
|
+
import { lighthouseSetup } from 'lighthouse-reporting'
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
viewport: { width: 1280, height: 820 },
|
|
220
|
-
ignoreHTTPSErrors: true,
|
|
221
|
-
acceptDownloads: false,
|
|
222
|
-
trace: 'off',
|
|
223
|
-
baseURL,
|
|
224
|
-
screenshot: { mode: 'off' },
|
|
225
|
-
},
|
|
226
|
-
projects: [
|
|
227
|
-
{
|
|
228
|
-
name: 'chromium',
|
|
229
|
-
use: {
|
|
230
|
-
browserName: 'chromium',
|
|
231
|
-
launchOptions: { args: ['--disable-gpu'] },
|
|
232
|
-
},
|
|
233
|
-
retries: 0,
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
expect: { toMatchSnapshot: { threshold: 0.2 } },
|
|
237
|
-
reporter: 'line',
|
|
238
|
-
testDir: 'test/storybook',
|
|
239
|
-
testMatch: '*.spec.ts',
|
|
240
|
-
fullyParallel: true,
|
|
241
|
-
globalSetup: './src/global-setup.ts',
|
|
242
|
-
globalTeardown: './src/global-teardown.ts',
|
|
243
|
-
forbidOnly: true,
|
|
244
|
-
webServer: [
|
|
245
|
-
{
|
|
246
|
-
command: 'npx http-server ./storybook-static --port 6009 --silent',
|
|
247
|
-
url: `${baseURL}/index.json`,
|
|
248
|
-
timeout: 15 * 1000,
|
|
249
|
-
reuseExistingServer: false,
|
|
250
|
-
ignoreHTTPSErrors: true,
|
|
251
|
-
},
|
|
252
|
-
],
|
|
220
|
+
async function globalSetup() {
|
|
221
|
+
await lighthouseSetup()
|
|
253
222
|
}
|
|
254
|
-
|
|
223
|
+
|
|
224
|
+
export default globalSetup
|
|
255
225
|
```
|
|
256
226
|
|
|
257
227
|
</details>
|
|
@@ -260,10 +230,13 @@ export default config
|
|
|
260
230
|
<summary>global-teardown.ts</summary>
|
|
261
231
|
|
|
262
232
|
```ts
|
|
263
|
-
import { lighthousePlaywrightTeardown } from 'lighthouse-reporting'
|
|
233
|
+
import { lighthousePlaywrightTeardown, buildAverageCsv } from 'lighthouse-reporting'
|
|
234
|
+
|
|
235
|
+
const lhScoresDir = path.join(process.cwd(), process.env.LH_SCORES_DIR || 'lh-scores')
|
|
264
236
|
|
|
265
237
|
async function globalTeardown() {
|
|
266
238
|
await lighthousePlaywrightTeardown()
|
|
239
|
+
await buildAverageCsv(lhScoresDir)
|
|
267
240
|
}
|
|
268
241
|
|
|
269
242
|
export default globalTeardown
|
package/dist/index.cjs
CHANGED
|
@@ -13,8 +13,10 @@ require("get-port");
|
|
|
13
13
|
require("@playwright/test");
|
|
14
14
|
exports.lighthousePlaywrightTeardown = hooks.lighthousePlaywrightTeardown;
|
|
15
15
|
exports.lighthouseSetup = hooks.lighthouseSetup;
|
|
16
|
+
exports.buildAverageCsv = lighthouseReports.buildAverageCsv;
|
|
16
17
|
exports.getScores = lighthouseReports.getScores;
|
|
17
18
|
exports.writeCsvResult = lighthouseReports.writeCsvResult;
|
|
18
19
|
exports.writeHtmlListEntryWithRetry = lighthouseReports.writeHtmlListEntryWithRetry;
|
|
20
|
+
exports.writeScoresToJson = lighthouseReports.writeScoresToJson;
|
|
19
21
|
exports.playwrightLighthouseTest = playwrightLighthouseTest.playwrightLighthouseTest;
|
|
20
22
|
exports.storybookPlaywright = storybookPlaywright.storybookPlaywright;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lighthousePlaywrightTeardown, lighthouseSetup } from "./hooks.js";
|
|
2
|
-
import { getScores, writeCsvResult, writeHtmlListEntryWithRetry } from "./lighthouseReports.js";
|
|
2
|
+
import { buildAverageCsv, getScores, writeCsvResult, writeHtmlListEntryWithRetry, writeScoresToJson } from "./lighthouseReports.js";
|
|
3
3
|
import { playwrightLighthouseTest } from "./playwrightLighthouseTest.js";
|
|
4
4
|
import { storybookPlaywright } from "./storybookPlaywright.js";
|
|
5
5
|
import "os";
|
|
@@ -10,11 +10,13 @@ import "./constants-226e9774.js";
|
|
|
10
10
|
import "get-port";
|
|
11
11
|
import "@playwright/test";
|
|
12
12
|
export {
|
|
13
|
+
buildAverageCsv,
|
|
13
14
|
getScores,
|
|
14
15
|
lighthousePlaywrightTeardown,
|
|
15
16
|
lighthouseSetup,
|
|
16
17
|
playwrightLighthouseTest,
|
|
17
18
|
storybookPlaywright,
|
|
18
19
|
writeCsvResult,
|
|
19
|
-
writeHtmlListEntryWithRetry
|
|
20
|
+
writeHtmlListEntryWithRetry,
|
|
21
|
+
writeScoresToJson
|
|
20
22
|
};
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
async function lighthousePlaywrightTeardown() {
|
|
22
22
|
await fse.remove(path.join(os.tmpdir(), PW_TMP_DIR));
|
|
23
23
|
}
|
|
24
|
-
const writeCsvResult = async (reportDir2, name, scores, thresholds, swimlanes = []) => {
|
|
24
|
+
const writeCsvResult = async (reportDir2, name, scores, thresholds = {}, swimlanes = []) => {
|
|
25
25
|
let csvData = Object.keys(scores).join(",");
|
|
26
26
|
if (swimlanes.length > 0) {
|
|
27
27
|
csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
|
|
28
28
|
}
|
|
29
29
|
csvData += "\n";
|
|
30
30
|
csvData += Object.values(scores).join(",");
|
|
31
|
-
if (swimlanes.length > 0) {
|
|
31
|
+
if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
|
|
32
32
|
csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
|
|
33
33
|
}
|
|
34
34
|
await fse.writeFile(path.join(reportDir2, `${name}.csv`), csvData);
|
|
@@ -61,6 +61,42 @@
|
|
|
61
61
|
prev[key] = Math.floor(c.score * 100);
|
|
62
62
|
return prev;
|
|
63
63
|
}, {});
|
|
64
|
+
const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
|
|
65
|
+
const json = Object.entries(scores).reduce((prev, [k, score]) => {
|
|
66
|
+
prev[k] = { score };
|
|
67
|
+
return prev;
|
|
68
|
+
}, {});
|
|
69
|
+
const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
|
|
70
|
+
return {
|
|
71
|
+
title: result.lhr.audits[v.id].title,
|
|
72
|
+
nodes: v.nodes.length
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
if (accessibilityViolations.length > 0) {
|
|
76
|
+
json.accessibility.issues = accessibilityViolations;
|
|
77
|
+
}
|
|
78
|
+
await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
|
|
79
|
+
};
|
|
80
|
+
const buildAverageCsv = async (lhScoresDir) => {
|
|
81
|
+
const files = await fse.readdir(lhScoresDir);
|
|
82
|
+
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
83
|
+
const scores = {};
|
|
84
|
+
for (const fileName of jsonFiles) {
|
|
85
|
+
const score = await fse.readJson(
|
|
86
|
+
path.join(lhScoresDir, fileName)
|
|
87
|
+
);
|
|
88
|
+
Object.entries(score).forEach(([k, v]) => {
|
|
89
|
+
if (!scores[k]) {
|
|
90
|
+
scores[k] = 0;
|
|
91
|
+
}
|
|
92
|
+
scores[k] += v.score;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
Object.entries(scores).forEach(([k, v]) => {
|
|
96
|
+
scores[k] = v / jsonFiles.length;
|
|
97
|
+
});
|
|
98
|
+
await writeCsvResult(lhScoresDir, "_AVERAGE_", scores);
|
|
99
|
+
};
|
|
64
100
|
class Locked extends Error {
|
|
65
101
|
constructor(port) {
|
|
66
102
|
super(`${port} is locked`);
|
|
@@ -71,7 +107,7 @@
|
|
|
71
107
|
young: /* @__PURE__ */ new Set()
|
|
72
108
|
};
|
|
73
109
|
const releaseOldLockedPortsIntervalMs = 1e3 * 15;
|
|
74
|
-
let
|
|
110
|
+
let timeout;
|
|
75
111
|
const getLocalHosts = () => {
|
|
76
112
|
const interfaces = os.networkInterfaces();
|
|
77
113
|
const results = /* @__PURE__ */ new Set([void 0, "0.0.0.0"]);
|
|
@@ -137,13 +173,14 @@
|
|
|
137
173
|
exclude = new Set(excludeIterable);
|
|
138
174
|
}
|
|
139
175
|
}
|
|
140
|
-
if (
|
|
141
|
-
|
|
176
|
+
if (timeout === void 0) {
|
|
177
|
+
timeout = setTimeout(() => {
|
|
178
|
+
timeout = void 0;
|
|
142
179
|
lockedPorts.old = lockedPorts.young;
|
|
143
180
|
lockedPorts.young = /* @__PURE__ */ new Set();
|
|
144
181
|
}, releaseOldLockedPortsIntervalMs);
|
|
145
|
-
if (
|
|
146
|
-
|
|
182
|
+
if (timeout.unref) {
|
|
183
|
+
timeout.unref();
|
|
147
184
|
}
|
|
148
185
|
}
|
|
149
186
|
const hosts = getLocalHosts();
|
|
@@ -214,6 +251,7 @@
|
|
|
214
251
|
await test.expect(page).toHaveScreenshot(`${story.id}.png`, screenshotOptions);
|
|
215
252
|
}
|
|
216
253
|
};
|
|
254
|
+
exports2.buildAverageCsv = buildAverageCsv;
|
|
217
255
|
exports2.getScores = getScores;
|
|
218
256
|
exports2.lighthousePlaywrightTeardown = lighthousePlaywrightTeardown;
|
|
219
257
|
exports2.lighthouseSetup = lighthouseSetup;
|
|
@@ -221,5 +259,6 @@
|
|
|
221
259
|
exports2.storybookPlaywright = storybookPlaywright;
|
|
222
260
|
exports2.writeCsvResult = writeCsvResult;
|
|
223
261
|
exports2.writeHtmlListEntryWithRetry = writeHtmlListEntryWithRetry;
|
|
262
|
+
exports2.writeScoresToJson = writeScoresToJson;
|
|
224
263
|
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
225
264
|
});
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const fse = require("fs-extra");
|
|
5
|
-
const writeCsvResult = async (reportDir, name, scores, thresholds, swimlanes = []) => {
|
|
5
|
+
const writeCsvResult = async (reportDir, name, scores, thresholds = {}, swimlanes = []) => {
|
|
6
6
|
let csvData = Object.keys(scores).join(",");
|
|
7
7
|
if (swimlanes.length > 0) {
|
|
8
8
|
csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
|
|
9
9
|
}
|
|
10
10
|
csvData += "\n";
|
|
11
11
|
csvData += Object.values(scores).join(",");
|
|
12
|
-
if (swimlanes.length > 0) {
|
|
12
|
+
if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
|
|
13
13
|
csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
|
|
14
14
|
}
|
|
15
15
|
await fse.writeFile(path.join(reportDir, `${name}.csv`), csvData);
|
|
@@ -42,6 +42,44 @@ const getScores = (result) => Object.entries(result.lhr.categories).reduce((prev
|
|
|
42
42
|
prev[key] = Math.floor(c.score * 100);
|
|
43
43
|
return prev;
|
|
44
44
|
}, {});
|
|
45
|
+
const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
|
|
46
|
+
const json = Object.entries(scores).reduce((prev, [k, score]) => {
|
|
47
|
+
prev[k] = { score };
|
|
48
|
+
return prev;
|
|
49
|
+
}, {});
|
|
50
|
+
const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
|
|
51
|
+
return {
|
|
52
|
+
title: result.lhr.audits[v.id].title,
|
|
53
|
+
nodes: v.nodes.length
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
if (accessibilityViolations.length > 0) {
|
|
57
|
+
json.accessibility.issues = accessibilityViolations;
|
|
58
|
+
}
|
|
59
|
+
await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
|
|
60
|
+
};
|
|
61
|
+
const buildAverageCsv = async (lhScoresDir) => {
|
|
62
|
+
const files = await fse.readdir(lhScoresDir);
|
|
63
|
+
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
64
|
+
const scores = {};
|
|
65
|
+
for (const fileName of jsonFiles) {
|
|
66
|
+
const score = await fse.readJson(
|
|
67
|
+
path.join(lhScoresDir, fileName)
|
|
68
|
+
);
|
|
69
|
+
Object.entries(score).forEach(([k, v]) => {
|
|
70
|
+
if (!scores[k]) {
|
|
71
|
+
scores[k] = 0;
|
|
72
|
+
}
|
|
73
|
+
scores[k] += v.score;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
Object.entries(scores).forEach(([k, v]) => {
|
|
77
|
+
scores[k] = v / jsonFiles.length;
|
|
78
|
+
});
|
|
79
|
+
await writeCsvResult(lhScoresDir, "_AVERAGE_", scores);
|
|
80
|
+
};
|
|
81
|
+
exports.buildAverageCsv = buildAverageCsv;
|
|
45
82
|
exports.getScores = getScores;
|
|
46
83
|
exports.writeCsvResult = writeCsvResult;
|
|
47
84
|
exports.writeHtmlListEntryWithRetry = writeHtmlListEntryWithRetry;
|
|
85
|
+
exports.writeScoresToJson = writeScoresToJson;
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
interface NodeDetails {
|
|
2
|
+
lhId: string;
|
|
3
|
+
devtoolsNodePath: string;
|
|
4
|
+
selector: string;
|
|
5
|
+
boudingRect: {
|
|
6
|
+
[k: string]: number;
|
|
7
|
+
};
|
|
8
|
+
snippet: string;
|
|
9
|
+
nodeLabel: string;
|
|
10
|
+
}
|
|
11
|
+
interface RuleExecutionError {
|
|
12
|
+
name: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
interface AxeRuleResult {
|
|
16
|
+
id: string;
|
|
17
|
+
impact?: string;
|
|
18
|
+
tags: Array<string>;
|
|
19
|
+
nodes: Array<{
|
|
20
|
+
target: Array<string>;
|
|
21
|
+
failureSummary?: string;
|
|
22
|
+
node: NodeDetails;
|
|
23
|
+
relatedNodes: NodeDetails[];
|
|
24
|
+
}>;
|
|
25
|
+
error?: RuleExecutionError;
|
|
26
|
+
}
|
|
1
27
|
export interface LighthouseResult {
|
|
2
28
|
lhr: {
|
|
3
29
|
categories: {
|
|
@@ -5,12 +31,28 @@ export interface LighthouseResult {
|
|
|
5
31
|
score: number;
|
|
6
32
|
};
|
|
7
33
|
};
|
|
34
|
+
audits: {
|
|
35
|
+
[k: string]: {
|
|
36
|
+
title: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
artifacts: {
|
|
41
|
+
Accessibility: {
|
|
42
|
+
violations: Array<AxeRuleResult>;
|
|
43
|
+
};
|
|
8
44
|
};
|
|
9
45
|
comparisonError?: string;
|
|
10
46
|
}
|
|
11
|
-
export declare const writeCsvResult: (reportDir: string, name: string, scores: Record<string, number>, thresholds
|
|
47
|
+
export declare const writeCsvResult: (reportDir: string, name: string, scores: Record<string, number>, thresholds?: Record<string, number>, swimlanes?: Array<string>) => Promise<void>;
|
|
12
48
|
/**
|
|
13
49
|
* workaround conflicts when multiple threads write the same file
|
|
14
50
|
*/
|
|
15
51
|
export declare const writeHtmlListEntryWithRetry: (htmlFilePath: string, name: string, scores: Record<string, number>, thresholds: Record<string, number>, comparisonError?: string, addReportLink?: boolean) => Promise<void>;
|
|
16
52
|
export declare const getScores: (result: LighthouseResult) => Record<string, number>;
|
|
53
|
+
export declare const writeScoresToJson: (lhScoresDir: string, name: string, scores: Record<string, number>, result: LighthouseResult) => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Generate average csv file. Make sure to use writeScoresToJson in your test!
|
|
56
|
+
*/
|
|
57
|
+
export declare const buildAverageCsv: (lhScoresDir: string) => Promise<void>;
|
|
58
|
+
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fse from "fs-extra";
|
|
3
|
-
const writeCsvResult = async (reportDir, name, scores, thresholds, swimlanes = []) => {
|
|
3
|
+
const writeCsvResult = async (reportDir, name, scores, thresholds = {}, swimlanes = []) => {
|
|
4
4
|
let csvData = Object.keys(scores).join(",");
|
|
5
5
|
if (swimlanes.length > 0) {
|
|
6
6
|
csvData += "," + swimlanes.map((swimlane) => `${swimlane}_threshold`);
|
|
7
7
|
}
|
|
8
8
|
csvData += "\n";
|
|
9
9
|
csvData += Object.values(scores).join(",");
|
|
10
|
-
if (swimlanes.length > 0) {
|
|
10
|
+
if (swimlanes.length > 0 && Object.keys(thresholds).length > 0) {
|
|
11
11
|
csvData += "," + swimlanes.map((swimlane) => thresholds[swimlane]);
|
|
12
12
|
}
|
|
13
13
|
await fse.writeFile(path.join(reportDir, `${name}.csv`), csvData);
|
|
@@ -40,8 +40,46 @@ const getScores = (result) => Object.entries(result.lhr.categories).reduce((prev
|
|
|
40
40
|
prev[key] = Math.floor(c.score * 100);
|
|
41
41
|
return prev;
|
|
42
42
|
}, {});
|
|
43
|
+
const writeScoresToJson = async (lhScoresDir, name, scores, result) => {
|
|
44
|
+
const json = Object.entries(scores).reduce((prev, [k, score]) => {
|
|
45
|
+
prev[k] = { score };
|
|
46
|
+
return prev;
|
|
47
|
+
}, {});
|
|
48
|
+
const accessibilityViolations = result.artifacts.Accessibility.violations.map((v) => {
|
|
49
|
+
return {
|
|
50
|
+
title: result.lhr.audits[v.id].title,
|
|
51
|
+
nodes: v.nodes.length
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
if (accessibilityViolations.length > 0) {
|
|
55
|
+
json.accessibility.issues = accessibilityViolations;
|
|
56
|
+
}
|
|
57
|
+
await fse.writeFile(path.join(lhScoresDir, `${name}.json`), JSON.stringify(json, null, 2));
|
|
58
|
+
};
|
|
59
|
+
const buildAverageCsv = async (lhScoresDir) => {
|
|
60
|
+
const files = await fse.readdir(lhScoresDir);
|
|
61
|
+
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
62
|
+
const scores = {};
|
|
63
|
+
for (const fileName of jsonFiles) {
|
|
64
|
+
const score = await fse.readJson(
|
|
65
|
+
path.join(lhScoresDir, fileName)
|
|
66
|
+
);
|
|
67
|
+
Object.entries(score).forEach(([k, v]) => {
|
|
68
|
+
if (!scores[k]) {
|
|
69
|
+
scores[k] = 0;
|
|
70
|
+
}
|
|
71
|
+
scores[k] += v.score;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
Object.entries(scores).forEach(([k, v]) => {
|
|
75
|
+
scores[k] = v / jsonFiles.length;
|
|
76
|
+
});
|
|
77
|
+
await writeCsvResult(lhScoresDir, "_AVERAGE_", scores);
|
|
78
|
+
};
|
|
43
79
|
export {
|
|
80
|
+
buildAverageCsv,
|
|
44
81
|
getScores,
|
|
45
82
|
writeCsvResult,
|
|
46
|
-
writeHtmlListEntryWithRetry
|
|
83
|
+
writeHtmlListEntryWithRetry,
|
|
84
|
+
writeScoresToJson
|
|
47
85
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse-reporting",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build && vite build -c vite.umd.config.ts && tsc -p ./tsconfig.build.json",
|
|
@@ -24,25 +24,25 @@
|
|
|
24
24
|
},
|
|
25
25
|
"optionalDependencies": {
|
|
26
26
|
"@playwright/test": "^1",
|
|
27
|
-
"get-port": "
|
|
27
|
+
"get-port": ">=7"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@playwright/test": "^1.34.3",
|
|
31
31
|
"@types/fs-extra": "^11.0.1",
|
|
32
|
-
"@types/node": "^20.
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
34
|
-
"@typescript-eslint/parser": "^5.
|
|
35
|
-
"eslint": "^8.
|
|
32
|
+
"@types/node": "^20.3.1",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^5.60.0",
|
|
34
|
+
"@typescript-eslint/parser": "^5.60.0",
|
|
35
|
+
"eslint": "^8.43.0",
|
|
36
36
|
"eslint-config-prettier": "^8.8.0",
|
|
37
37
|
"eslint-plugin-prettier": "^4.2.1",
|
|
38
|
-
"get-port": "^
|
|
38
|
+
"get-port": "^7.0.0",
|
|
39
39
|
"husky": "^8.0.3",
|
|
40
40
|
"npm-run-all": "^4.1.5",
|
|
41
41
|
"prettier": "^2.8.8",
|
|
42
|
-
"semantic-release": "^21.0.
|
|
43
|
-
"typescript": "^5.
|
|
42
|
+
"semantic-release": "^21.0.5",
|
|
43
|
+
"typescript": "^5.1.3",
|
|
44
44
|
"vite": "^4.3.9",
|
|
45
|
-
"vite-plugin-static-copy": "^0.
|
|
45
|
+
"vite-plugin-static-copy": "^0.16.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"fs-extra": "^11.1.1"
|