mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-11-04 15:00:11 +00:00
fix: round lighthouse category scores and show unscored categories as n/a (#2924)
The `lighthouse_audit` text summary formatted each category score as `(score ?? 0) * 100`. That had two problems: - A `null` category score, which Lighthouse uses for "not scored", was printed as `0`, so it looked the same as a real score of 0 (#2915). - Fractional scores showed floating-point noise, e.g. `0.57` printed as `56.99999999999999` (#2916). The summary now prints `Math.round(score * 100)`, which matches how the Lighthouse report renders category scores, and prints `n/a` for a `null` score. Structured content (`structuredContent.lighthouseResult`) is unchanged and still carries the raw scores, including `null`. The text summary is the only place these scores are formatted. Testing: - Added a `McpResponse` unit test and snapshot covering `0.57` → `57`, a real `0` → `0`, and `null` → `n/a`, plus a check that the structured content keeps the raw `0.57`/`0`/`null`. The new test fails on the old code. - `tests/McpResponse.test.ts` and `tests/tools/lighthouse.test.ts` pass locally. - `npm run check-format` passes, and `npm run gen` leaves no diff. Fixes #2915 Fixes #2916
This commit is contained in:
1 parent
93e06ab21f
commit
70076808cd
3 files changed
+111
-3
No files matched your search
+5
-3
@@ -1174,9 +1174,11 @@ Call ${handleDialog(this.#args).name} to handle it before continuing.`);
|
||||
response.push(`URL: ${summary.url}`);
|
||||
response.push('### Category Scores');
|
||||
for (const score of summary.scores) {
|
||||
response.push(
|
||||
`- ${score.title}: ${(score.score ?? 0) * 100} (${score.id})`,
|
||||
);
|
||||
// Lighthouse uses a null score for categories that could not be
|
||||
// scored and renders scores as Math.round(score * 100).
|
||||
const formattedScore =
|
||||
score.score === null ? 'n/a' : Math.round(score.score * 100);
|
||||
response.push(`- ${score.title}: ${formattedScore} (${score.id})`);
|
||||
}
|
||||
response.push('### Audit Summary');
|
||||
response.push(`Passed: ${summary.audits.passed}`);
|
||||
|
||||
@@ -1367,6 +1367,64 @@ exports[`lighthouse > includes lighthouse report paths 2`] = `
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`lighthouse > rounds category scores and shows unscored categories as n/a 1`] = `
|
||||
## Lighthouse Audit Results
|
||||
Mode: navigation
|
||||
Device: desktop
|
||||
URL: https://example.com
|
||||
### Category Scores
|
||||
- Accessibility: 57 (accessibility)
|
||||
- SEO: 0 (seo)
|
||||
- Agentic Browsing: n/a (agentic-browsing)
|
||||
### Audit Summary
|
||||
Passed: 10
|
||||
Failed: 1
|
||||
Total Timing: 1000ms
|
||||
### Reports
|
||||
- /tmp/report.json
|
||||
- /tmp/report.html
|
||||
`;
|
||||
|
||||
exports[`lighthouse > rounds category scores and shows unscored categories as n/a 2`] = `
|
||||
{
|
||||
"lighthouseResult": {
|
||||
"summary": {
|
||||
"mode": "navigation",
|
||||
"device": "desktop",
|
||||
"url": "https://example.com",
|
||||
"scores": [
|
||||
{
|
||||
"id": "accessibility",
|
||||
"title": "Accessibility",
|
||||
"score": 0.57
|
||||
},
|
||||
{
|
||||
"id": "seo",
|
||||
"title": "SEO",
|
||||
"score": 0
|
||||
},
|
||||
{
|
||||
"id": "agentic-browsing",
|
||||
"title": "Agentic Browsing",
|
||||
"score": null
|
||||
}
|
||||
],
|
||||
"audits": {
|
||||
"failed": 1,
|
||||
"passed": 10
|
||||
},
|
||||
"timing": {
|
||||
"total": 1000
|
||||
}
|
||||
},
|
||||
"reports": [
|
||||
"/tmp/report.json",
|
||||
"/tmp/report.html"
|
||||
]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`third-party developer tools > lists third-party developer tools 1`] = `
|
||||
## Third-party developer tools
|
||||
My Tool Group: A group of tools
|
||||
|
||||
@@ -930,6 +930,54 @@ describe('lighthouse', () => {
|
||||
t.assert.snapshot(stabilizeStructuredContent(structuredContent));
|
||||
});
|
||||
});
|
||||
|
||||
it('rounds category scores and shows unscored categories as n/a', async t => {
|
||||
await withMcpContext(async (response, context) => {
|
||||
const lighthouseResult = {
|
||||
summary: {
|
||||
mode: 'navigation',
|
||||
device: 'desktop',
|
||||
url: 'https://example.com',
|
||||
scores: [
|
||||
{
|
||||
id: 'accessibility',
|
||||
title: 'Accessibility',
|
||||
score: 0.57,
|
||||
},
|
||||
{
|
||||
id: 'seo',
|
||||
title: 'SEO',
|
||||
score: 0,
|
||||
},
|
||||
{
|
||||
id: 'agentic-browsing',
|
||||
title: 'Agentic Browsing',
|
||||
score: null,
|
||||
},
|
||||
],
|
||||
audits: {
|
||||
failed: 1,
|
||||
passed: 10,
|
||||
},
|
||||
timing: {
|
||||
total: 1000,
|
||||
},
|
||||
},
|
||||
reports: ['/tmp/report.json', '/tmp/report.html'],
|
||||
};
|
||||
|
||||
response.attachLighthouseResult(lighthouseResult);
|
||||
const {content, structuredContent} = await response.handle(context);
|
||||
|
||||
const text = getTextContent(content[0]);
|
||||
assert.ok(text.includes('- Accessibility: 57 (accessibility)'));
|
||||
assert.ok(text.includes('- SEO: 0 (seo)'));
|
||||
assert.ok(text.includes('- Agentic Browsing: n/a (agentic-browsing)'));
|
||||
|
||||
t.assert.snapshot(text);
|
||||
t.assert.snapshot(stabilizeStructuredContent(structuredContent));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('third-party developer tools', () => {
|
||||
|
||||
Reference in new issue
Block a user