mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-28 11:22:57 +08:00
fix: set emulatedUserAgent and use finalDisplayedUrl in lighthouse_audit (#2795)
`lighthouse_audit` never set `emulatedUserAgent`, so desktop audits ran with Lighthouse's default mobile UA. It now mirrors the UA constants Lighthouse's own presets use. It also reported `URL: undefined` in snapshot mode, because `mainDocumentUrl` is only populated for navigations; it now uses `finalDisplayedUrl`.
This commit is contained in:
+15
-1
@@ -21,6 +21,16 @@ import {ToolCategory} from './categories.js';
|
||||
import {startTrace} from './performance.js';
|
||||
import {definePageTool} from './ToolDefinition.js';
|
||||
|
||||
// Kept in sync with `constants.userAgents` in Lighthouse's
|
||||
// core/config/constants.js, which `lighthouse:default` and the `desktop`
|
||||
// preset use. The bundle in src/third_party only re-exports the runner
|
||||
// entrypoints, so these cannot be imported and are mirrored here alongside the
|
||||
// screen emulation metrics below. Refresh via scripts/update-lighthouse.ts.
|
||||
const MOBILE_USER_AGENT =
|
||||
'Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Mobile Safari/537.36';
|
||||
const DESKTOP_USER_AGENT =
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36';
|
||||
|
||||
export const lighthouseAudit = definePageTool((args: ParsedArguments) => ({
|
||||
name: 'lighthouse_audit',
|
||||
description: `Get Lighthouse score and reports for accessibility, SEO, best practices, and agentic browsing. This excludes performance. For performance audits, run ${startTrace(args).name}`,
|
||||
@@ -79,6 +89,7 @@ export const lighthouseAudit = definePageTool((args: ParsedArguments) => ({
|
||||
deviceScaleFactor: 1,
|
||||
disabled: false,
|
||||
};
|
||||
flags.emulatedUserAgent = DESKTOP_USER_AGENT;
|
||||
} else {
|
||||
flags.formFactor = 'mobile';
|
||||
flags.screenEmulation = {
|
||||
@@ -88,6 +99,7 @@ export const lighthouseAudit = definePageTool((args: ParsedArguments) => ({
|
||||
deviceScaleFactor: 1.75,
|
||||
disabled: false,
|
||||
};
|
||||
flags.emulatedUserAgent = MOBILE_USER_AGENT;
|
||||
}
|
||||
|
||||
let result: RunnerResult | undefined;
|
||||
@@ -162,7 +174,9 @@ export const lighthouseAudit = definePageTool((args: ParsedArguments) => ({
|
||||
summary: {
|
||||
mode,
|
||||
device,
|
||||
url: lhr.mainDocumentUrl,
|
||||
// `mainDocumentUrl` is only set for navigations, whereas
|
||||
// `finalDisplayedUrl` is populated for every gather mode.
|
||||
url: lhr.finalDisplayedUrl,
|
||||
scores: categoryScores,
|
||||
audits: {
|
||||
failed: failedAudits,
|
||||
|
||||
+5
-1
@@ -201,12 +201,16 @@ export function createHandlerMocks(options: Partial<ParsedArguments> = {}): {
|
||||
return {page, context, response, args};
|
||||
}
|
||||
|
||||
export function createMockRunnerResult(): RunnerResult {
|
||||
export function createMockRunnerResult(
|
||||
lhrOverrides: Partial<Result> = {},
|
||||
): RunnerResult {
|
||||
const lhr = {
|
||||
finalDisplayedUrl: 'http://localhost',
|
||||
mainDocumentUrl: 'http://localhost',
|
||||
categories: {},
|
||||
audits: {},
|
||||
timing: {total: 0},
|
||||
...lhrOverrides,
|
||||
};
|
||||
return {
|
||||
lhr: lhr as unknown as Result,
|
||||
|
||||
@@ -108,6 +108,84 @@ describe('lighthouse', () => {
|
||||
sinon.assert.calledOnceWithExactly(page.restoreEmulation);
|
||||
});
|
||||
|
||||
it('emulates a desktop user agent for desktop audits', async () => {
|
||||
const {page, context, response, args} = createHandlerMocks();
|
||||
context.saveTemporaryFile.resolves({filepath: 'report.json'});
|
||||
const navigation = sinon
|
||||
.stub(lighthouseRunner, 'navigation')
|
||||
.resolves(createMockRunnerResult());
|
||||
|
||||
await lighthouseAudit(args).handler(
|
||||
{
|
||||
params: {
|
||||
mode: 'navigation',
|
||||
device: 'desktop',
|
||||
},
|
||||
page,
|
||||
},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
const {flags} = navigation.firstCall.args[2];
|
||||
assert.equal(flags?.formFactor, 'desktop');
|
||||
assert.match(String(flags?.emulatedUserAgent), /Macintosh/);
|
||||
assert.doesNotMatch(String(flags?.emulatedUserAgent), /Mobile/);
|
||||
});
|
||||
|
||||
it('emulates a mobile user agent for mobile audits', async () => {
|
||||
const {page, context, response, args} = createHandlerMocks();
|
||||
context.saveTemporaryFile.resolves({filepath: 'report.json'});
|
||||
const snapshot = sinon
|
||||
.stub(lighthouseRunner, 'snapshot')
|
||||
.resolves(createMockRunnerResult());
|
||||
|
||||
await lighthouseAudit(args).handler(
|
||||
{
|
||||
params: {
|
||||
mode: 'snapshot',
|
||||
device: 'mobile',
|
||||
},
|
||||
page,
|
||||
},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
const {flags} = snapshot.firstCall.args[1];
|
||||
assert.equal(flags?.formFactor, 'mobile');
|
||||
assert.match(String(flags?.emulatedUserAgent), /Mobile Safari/);
|
||||
});
|
||||
|
||||
it('reports the URL in snapshot mode, where mainDocumentUrl is unset', async () => {
|
||||
const {page, context, response, args} = createHandlerMocks();
|
||||
context.saveTemporaryFile.resolves({filepath: 'report.json'});
|
||||
sinon.stub(lighthouseRunner, 'snapshot').resolves(
|
||||
createMockRunnerResult({
|
||||
mainDocumentUrl: undefined,
|
||||
finalDisplayedUrl: 'https://example.com/page',
|
||||
}),
|
||||
);
|
||||
|
||||
await lighthouseAudit(args).handler(
|
||||
{
|
||||
params: {
|
||||
mode: 'snapshot',
|
||||
device: 'mobile',
|
||||
},
|
||||
page,
|
||||
},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
sinon.assert.calledOnce(response.attachLighthouseResult);
|
||||
assert.equal(
|
||||
response.attachLighthouseResult.firstCall.args[0].summary.url,
|
||||
'https://example.com/page',
|
||||
);
|
||||
});
|
||||
|
||||
it('runs Lighthouse in snapshot mode with mobile device', async () => {
|
||||
server.addHtmlRoute('/test-mobile', html`<div>Test Mobile</div>`);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user