Skip to content

Commit b0ed73a

Browse files
authoredAug 14, 2024··
refactor(plugin-lighthouse): format audit value (#794)
1 parent da41f18 commit b0ed73a

File tree

3 files changed

+131
-32
lines changed

3 files changed

+131
-32
lines changed
 

‎packages/plugin-lighthouse/src/lib/runner/utils.ts

+52-31
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { bold } from 'ansis';
2-
import type { Config } from 'lighthouse';
2+
import type { Config, FormattedIcu } from 'lighthouse';
33
import log from 'lighthouse-logger';
44
import desktopConfig from 'lighthouse/core/config/desktop-config.js';
55
import experimentalConfig from 'lighthouse/core/config/experimental-config.js';
66
import perfConfig from 'lighthouse/core/config/perf-config.js';
7+
import Details from 'lighthouse/types/lhr/audit-details';
78
import { Result } from 'lighthouse/types/lhr/audit-result';
89
import { AuditOutput, AuditOutputs } from '@code-pushup/models';
9-
import { importModule, readJsonFile, ui } from '@code-pushup/utils';
10+
import {
11+
formatReportScore,
12+
importModule,
13+
readJsonFile,
14+
ui,
15+
} from '@code-pushup/utils';
1016
import type { LighthouseOptions } from '../types';
1117
import { logUnsupportedDetails, toAuditDetails } from './details/details';
1218
import { LighthouseCliFlags } from './types';
@@ -38,43 +44,58 @@ export class LighthouseAuditParsingError extends Error {
3844
}
3945
}
4046

47+
function formatBaseAuditOutput(lhrAudit: Result): AuditOutput {
48+
const {
49+
id: slug,
50+
score,
51+
numericValue,
52+
displayValue,
53+
scoreDisplayMode,
54+
} = lhrAudit;
55+
return {
56+
slug,
57+
score: score ?? 1,
58+
value: numericValue ?? score ?? 0,
59+
displayValue:
60+
displayValue ??
61+
(scoreDisplayMode === 'binary'
62+
? score === 1
63+
? 'passed'
64+
: 'failed'
65+
: score
66+
? `${formatReportScore(score)}%`
67+
: undefined),
68+
};
69+
}
70+
71+
function processAuditDetails(
72+
auditOutput: AuditOutput,
73+
details: FormattedIcu<Details>,
74+
): AuditOutput {
75+
try {
76+
const parsedDetails = toAuditDetails(details);
77+
return Object.keys(parsedDetails).length > 0
78+
? { ...auditOutput, details: parsedDetails }
79+
: auditOutput;
80+
} catch (error) {
81+
throw new LighthouseAuditParsingError(auditOutput.slug, error as Error);
82+
}
83+
}
84+
4185
export function toAuditOutputs(
4286
lhrAudits: Result[],
4387
{ verbose = false }: { verbose?: boolean } = {},
4488
): AuditOutputs {
4589
if (verbose) {
4690
logUnsupportedDetails(lhrAudits);
4791
}
92+
return lhrAudits.map(audit => {
93+
const auditOutput = formatBaseAuditOutput(audit);
4894

49-
return lhrAudits.map(
50-
({
51-
id: slug,
52-
score,
53-
numericValue: value = 0, // not every audit has a numericValue
54-
details,
55-
displayValue,
56-
}: Result) => {
57-
const auditOutput: AuditOutput = {
58-
slug,
59-
score: score ?? 1, // score can be null
60-
value,
61-
displayValue,
62-
};
63-
64-
if (details != null) {
65-
try {
66-
const parsedDetails = toAuditDetails(details);
67-
return Object.keys(parsedDetails).length > 0
68-
? { ...auditOutput, details: parsedDetails }
69-
: auditOutput;
70-
} catch (error) {
71-
throw new LighthouseAuditParsingError(slug, error as Error);
72-
}
73-
}
74-
75-
return auditOutput;
76-
},
77-
);
95+
return audit.details == null
96+
? auditOutput
97+
: processAuditDetails(auditOutput, audit.details);
98+
});
7899
}
79100

80101
export type LighthouseLogLevel =

‎packages/plugin-lighthouse/src/lib/runner/utils.unit.test.ts

+74
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,80 @@ describe('toAuditOutputs', () => {
128128
);
129129
});
130130

131+
it('should set displayValue to "passed" when binary score equals 1', () => {
132+
expect(
133+
toAuditOutputs([
134+
{
135+
id: 'image-aspect-ratio',
136+
title: 'Displays images with correct aspect ratio',
137+
description:
138+
'Image display dimensions should match natural aspect ratio. [Learn more about image aspect ratio](https://developer.chrome.com/docs/lighthouse/best-practices/image-aspect-ratio/).',
139+
score: 1,
140+
scoreDisplayMode: 'binary',
141+
},
142+
]),
143+
).toStrictEqual(
144+
expect.arrayContaining([
145+
expect.objectContaining({ displayValue: 'passed' }),
146+
]),
147+
);
148+
});
149+
150+
it('should set displayValue to "failed" when binary score equals 0', () => {
151+
expect(
152+
toAuditOutputs([
153+
{
154+
id: 'image-aspect-ratio',
155+
title: 'Displays images with correct aspect ratio',
156+
description:
157+
'Image display dimensions should match natural aspect ratio. [Learn more about image aspect ratio](https://developer.chrome.com/docs/lighthouse/best-practices/image-aspect-ratio/).',
158+
score: 0,
159+
scoreDisplayMode: 'binary',
160+
},
161+
]),
162+
).toStrictEqual(
163+
expect.arrayContaining([
164+
expect.objectContaining({ displayValue: 'failed' }),
165+
]),
166+
);
167+
});
168+
169+
it('should set audit value to its score when numericValue is missing', () => {
170+
expect(
171+
toAuditOutputs([
172+
{
173+
id: 'image-aspect-ratio',
174+
title: 'Displays images with correct aspect ratio',
175+
description:
176+
'Image display dimensions should match natural aspect ratio. [Learn more about image aspect ratio](https://developer.chrome.com/docs/lighthouse/best-practices/image-aspect-ratio/).',
177+
score: 1,
178+
scoreDisplayMode: 'binary',
179+
},
180+
]),
181+
).toStrictEqual(
182+
expect.arrayContaining([expect.objectContaining({ value: 1 })]),
183+
);
184+
});
185+
186+
it('should set audit displayValue to formatted score when displayValue is missing and scoreDisplayMode is not binary', () => {
187+
expect(
188+
toAuditOutputs([
189+
{
190+
id: 'unsized-images',
191+
title: 'Image elements do not have explicit `width` and `height`',
192+
description:
193+
'Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/articles/optimize-cls#images_without_dimensions)',
194+
score: 0.5,
195+
scoreDisplayMode: 'metricSavings',
196+
},
197+
]),
198+
).toStrictEqual(
199+
expect.arrayContaining([
200+
expect.objectContaining({ displayValue: '50%' }),
201+
]),
202+
);
203+
});
204+
131205
it('should not parse given audit details', () => {
132206
expect(
133207
toAuditOutputs(

‎packages/utils/src/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ export {
8181
ScoredGroup,
8282
ScoredReport,
8383
} from './lib/reports/types';
84-
export { calcDuration, compareIssueSeverity } from './lib/reports/utils';
84+
export {
85+
calcDuration,
86+
compareIssueSeverity,
87+
formatReportScore,
88+
} from './lib/reports/utils';
8589
export { isSemver, normalizeSemver, sortSemvers } from './lib/semver';
8690
export * from './lib/text-formats';
8791
export {

0 commit comments

Comments
 (0)
Please sign in to comment.