From 5db74edbaf4ea34d3906543c71119b3b031f5457 Mon Sep 17 00:00:00 2001 From: Natallia Harshunova Date: Tue, 25 Nov 2025 18:36:49 +0000 Subject: [PATCH 1/8] add elementsID into console data message --- src/McpResponse.ts | 11 ++-- src/formatters/consoleFormatter.ts | 54 +++++++++++++++++-- tests/McpResponse.test.ts | 11 ++-- .../consoleFormatter.test.js.snapshot | 2 + tests/formatters/consoleFormatter.test.ts | 16 ++++-- tests/tools/console.test.js.snapshot | 13 +++++ tests/tools/console.test.ts | 21 +++----- tests/utils.ts | 11 ++++ 8 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 tests/tools/console.test.js.snapshot diff --git a/src/McpResponse.ts b/src/McpResponse.ts index b7de0440..af7c8b51 100644 --- a/src/McpResponse.ts +++ b/src/McpResponse.ts @@ -255,7 +255,7 @@ export class McpResponse implements Response { const mappedIssueMessage = mapIssueToMessageObject(message); if (!mappedIssueMessage) throw new Error( - "Can't prpovide detals for the msgid " + consoleMessageStableId, + "Can't provide detals for the msgid " + consoleMessageStableId, ); consoleData = { consoleMessageStableId, @@ -402,7 +402,7 @@ Call ${handleDialog.name} to handle it before continuing.`); } response.push(...this.#formatNetworkRequestData(context, data.bodies)); - response.push(...this.#formatConsoleData(data.consoleData)); + response.push(...this.#formatConsoleData(context, data.consoleData)); if (this.#networkRequestsOptions?.include) { let requests = context.getNetworkRequests( @@ -500,13 +500,16 @@ Call ${handleDialog.name} to handle it before continuing.`); }; } - #formatConsoleData(data: ConsoleMessageData | undefined): string[] { + #formatConsoleData( + context: McpContext, + data: ConsoleMessageData | undefined, + ): string[] { const response: string[] = []; if (!data) { return response; } - response.push(formatConsoleEventVerbose(data)); + response.push(formatConsoleEventVerbose(data, context)); return response; } diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index 0e4672aa..84cb680a 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -5,6 +5,7 @@ */ import type {AggregatedIssue} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; +import type {McpContext} from '../McpContext.js'; export interface ConsoleMessageData { consoleMessageStableId: number; @@ -36,11 +37,14 @@ function getArgs(msg: ConsoleMessageData) { } // The verbose format for a console message, including all details. -export function formatConsoleEventVerbose(msg: ConsoleMessageData): string { +export function formatConsoleEventVerbose( + msg: ConsoleMessageData, + context?: McpContext, +): string { const aggregatedIssue = msg.item; const result = [ `ID: ${msg.consoleMessageStableId}`, - `Message: ${msg.type}> ${aggregatedIssue ? formatIssue(aggregatedIssue, msg.description) : msg.message}`, + `Message: ${msg.type}> ${aggregatedIssue ? formatIssue(aggregatedIssue, msg.description, context) : msg.message}`, aggregatedIssue ? undefined : formatArgs(msg), ].filter(line => !!line); return result.join('\n'); @@ -65,10 +69,15 @@ function formatArgs(consoleData: ConsoleMessageData): string { return result.join('\n'); } - +interface IssueDetailsWithResources { + violatingNodeId?: number; + nodeId?: number; + documentNodeId?: number; +} export function formatIssue( issue: AggregatedIssue, description?: string, + context?: McpContext, ): string { const result: string[] = []; @@ -87,6 +96,45 @@ export function formatIssue( } } + const issues: Array<{details?: () => IssueDetailsWithResources}> = [ + ...issue.getGenericIssues(), + ...issue.getLowContrastIssues(), + ...issue.getElementAccessibilityIssues(), + ...issue.getQuirksModeIssues(), + // ...issue.getAttributionReportingIssues(), // Uncomment when AttributionReportingIssue has details() + ]; + const affectedElement: Array<{uid?: string; data?: object}> = []; + for (const singleIssue of issues) { + if (!singleIssue.details) break; + + const details = + singleIssue.details() as unknown as IssueDetailsWithResources; + let uid; + if (details.violatingNodeId && context) { + uid = context.resolveCdpElementId(details.violatingNodeId); + } + if (details.nodeId && context) { + uid = context.resolveCdpElementId(details.nodeId); + } + if (details.documentNodeId && context) { + uid = context.resolveCdpElementId(details.documentNodeId); + } + + // eslint-disable-next-line + const data = structuredClone(details) as any; + delete data.violatingNodeId; + delete data.errorType; + delete data.frameId; + affectedElement.push({uid, data: data}); + } + if (affectedElement.length) { + result.push('### Affected resources'); + } + result.push( + ...affectedElement.map(item => { + return `uid=${item.uid} data=${JSON.stringify(item.data)}`; + }), + ); if (result.length === 0) return 'No details provided for the issue ' + issue.code(); return result.join('\n'); diff --git a/tests/McpResponse.test.ts b/tests/McpResponse.test.ts index b045454d..9031f6dd 100644 --- a/tests/McpResponse.test.ts +++ b/tests/McpResponse.test.ts @@ -10,11 +10,8 @@ import {tmpdir} from 'node:os'; import {join} from 'node:path'; import {describe, it} from 'node:test'; -import sinon from 'sinon'; - -import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - import { + getMockAggregatedIssue, getMockRequest, getMockResponse, html, @@ -302,7 +299,7 @@ describe('McpResponse', () => { it("doesn't list the issue message if mapping returns null", async () => { await withBrowser(async (response, context) => { - const mockAggregatedIssue = sinon.createStubInstance(AggregatedIssue); + const mockAggregatedIssue = getMockAggregatedIssue(); const mockDescription = { file: 'not-existing-description-file.md', links: [], @@ -321,7 +318,7 @@ describe('McpResponse', () => { it('throws error if mapping returns null on get issue details', async () => { await withBrowser(async (response, context) => { - const mockAggregatedIssue = sinon.createStubInstance(AggregatedIssue); + const mockAggregatedIssue = getMockAggregatedIssue(); const mockDescription = { file: 'not-existing-description-file.md', links: [], @@ -335,7 +332,7 @@ describe('McpResponse', () => { try { await response.handle('test', context); } catch (e) { - assert.ok(e.message.includes("Can't prpovide detals for the msgid 1")); + assert.ok(e.message.includes("Can't provide detals for the msgid 1")); } }); }); diff --git a/tests/formatters/consoleFormatter.test.js.snapshot b/tests/formatters/consoleFormatter.test.js.snapshot index d6803572..9f6bfaf4 100644 --- a/tests/formatters/consoleFormatter.test.js.snapshot +++ b/tests/formatters/consoleFormatter.test.js.snapshot @@ -43,4 +43,6 @@ This is a mock issue description Learn more: [Learn more](http://example.com/learnmore) [Learn more 2](http://example.com/another-learnmore) +### Affected resources +uid=undefined data={"violatingNodeAttribute":"test"} `; diff --git a/tests/formatters/consoleFormatter.test.ts b/tests/formatters/consoleFormatter.test.ts index eabe2a44..8734a91f 100644 --- a/tests/formatters/consoleFormatter.test.ts +++ b/tests/formatters/consoleFormatter.test.ts @@ -6,14 +6,12 @@ import {describe, it} from 'node:test'; -import sinon from 'sinon'; - -import {AggregatedIssue} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import type {ConsoleMessageData} from '../../src/formatters/consoleFormatter.js'; import { formatConsoleEventShort, formatConsoleEventVerbose, } from '../../src/formatters/consoleFormatter.js'; +import {getMockAggregatedIssue} from '../utils.js'; describe('consoleFormatter', () => { describe('formatConsoleEventShort', () => { @@ -97,7 +95,15 @@ describe('consoleFormatter', () => { }); it('formats a console.log message with issue type', t => { - const mockAggregatedIssue = sinon.createStubInstance(AggregatedIssue); + const testGenericIssue = { + details: () => { + return { + violatingNodeId: 2, + violatingNodeAttribute: 'test', + }; + }, + }; + const mockAggregatedIssue = getMockAggregatedIssue(); const mockDescription = { file: 'mock.md', links: [ @@ -109,6 +115,8 @@ describe('consoleFormatter', () => { ], }; mockAggregatedIssue.getDescription.returns(mockDescription); + // @ts-expect-error generic issue stub bypass + mockAggregatedIssue.getGenericIssues.returns(new Set([testGenericIssue])); const mockDescriptionFileContent = '# Mock Issue Title\n\nThis is a mock issue description'; diff --git a/tests/tools/console.test.js.snapshot b/tests/tools/console.test.js.snapshot new file mode 100644 index 00000000..8abb44b3 --- /dev/null +++ b/tests/tools/console.test.js.snapshot @@ -0,0 +1,13 @@ +exports[`console > get_console_message > issues type > gets issue details 1`] = ` +# test response +ID: 1 +Message: issue> An element doesn't have an autocomplete attribute + +A form field has an \`id\` or \`name\` attribute that the browser's autofill recognizes. However, it doesn't have an \`autocomplete\` attribute assigned. This might prevent the browser from correctly autofilling the form. + +To fix this issue, provide an \`autocomplete\` attribute. +Learn more: +[HTML attribute: autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values) +### Affected resources +uid=1_1 data={"violatingNodeAttribute":"name"} +`; diff --git a/tests/tools/console.test.ts b/tests/tools/console.test.ts index 0724a503..92bc1fe5 100644 --- a/tests/tools/console.test.ts +++ b/tests/tools/console.test.ts @@ -17,11 +17,10 @@ import { import {withBrowser} from '../utils.js'; describe('console', () => { + before(async () => { + await loadIssueDescriptions(); + }); describe('list_console_messages', () => { - before(async () => { - await loadIssueDescriptions(); - }); - it('list messages', async () => { await withBrowser(async (response, context) => { await listConsoleMessages.handler({params: {}}, response, context); @@ -160,7 +159,7 @@ describe('console', () => { setIssuesEnabled(false); }); - it('gets issue details', async () => { + it('gets issue details', async t => { await withBrowser(async (response, context) => { const page = await context.newPage(); const issuePromise = new Promise(resolve => { @@ -169,6 +168,7 @@ describe('console', () => { }); }); await page.setContent(''); + await context.createTextSnapshot(); await issuePromise; await listConsoleMessages.handler({params: {}}, response, context); const response2 = new McpResponse(); @@ -178,16 +178,7 @@ describe('console', () => { context, ); const formattedResponse = await response2.handle('test', context); - const textContent = formattedResponse[0] as {text: string}; - const learnMoreLinks = - '[HTML attribute: autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values)'; - const detailsDescription = - "A form field has an `id` or `name` attribute that the browser's autofill recognizes. However, it doesn't have an `autocomplete` attribute assigned. This might prevent the browser from correctly autofilling the form.\n\nTo fix this issue, provide an `autocomplete` attribute."; - const title = - "Message: issue> An element doesn't have an autocomplete attribute"; - assert.ok(textContent.text.includes(title)); - assert.ok(textContent.text.includes(detailsDescription)); - assert.ok(textContent.text.includes(learnMoreLinks)); + t.assert.snapshot?.(formattedResponse[0].text); }); }); }); diff --git a/tests/utils.ts b/tests/utils.ts index 3a717381..45a4bea2 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -13,7 +13,9 @@ import type { HTTPResponse, LaunchOptions, } from 'puppeteer-core'; +import sinon from 'sinon'; +import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import {McpContext} from '../src/McpContext.js'; import {McpResponse} from '../src/McpResponse.js'; import {stableIdSymbol} from '../src/PageCollector.js'; @@ -180,3 +182,12 @@ export function stabilizeResponseOutput(text: unknown) { output = output.replaceAll(savedSnapshot, 'Saved snapshot to '); return output; } + +export function getMockAggregatedIssue(): sinon.SinonStubbedInstance { + const mockAggregatedIssue = sinon.createStubInstance(AggregatedIssue); + mockAggregatedIssue.getGenericIssues.returns(new Set()); + mockAggregatedIssue.getLowContrastIssues.returns(new Set()); + mockAggregatedIssue.getElementAccessibilityIssues.returns(new Set()); + mockAggregatedIssue.getQuirksModeIssues.returns(new Set()); + return mockAggregatedIssue; +} From d1af7f02bcdb850a3c90327534634f45d8686483 Mon Sep 17 00:00:00 2001 From: Natallia Harshunova Date: Wed, 26 Nov 2025 10:03:43 +0000 Subject: [PATCH 2/8] Add request parsing from issue details --- src/formatters/consoleFormatter.ts | 58 +++++++++++++++---- .../consoleFormatter.test.js.snapshot | 2 +- tests/tools/console.test.js.snapshot | 18 +++++- tests/tools/console.test.ts | 34 ++++++++++- tests/utils.ts | 2 + 5 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index 84cb680a..75fa7677 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -73,6 +73,10 @@ interface IssueDetailsWithResources { violatingNodeId?: number; nodeId?: number; documentNodeId?: number; + request?: { + requestId?: string; + url: string; + }; } export function formatIssue( issue: AggregatedIssue, @@ -96,20 +100,29 @@ export function formatIssue( } } - const issues: Array<{details?: () => IssueDetailsWithResources}> = [ + const issues: Array<{details?: () => IssueDetailsWithResources, getDetails?: () => IssueDetailsWithResources}> = [ + ...issue.getCorsIssues(), + ...issue.getMixedContentIssues(), ...issue.getGenericIssues(), ...issue.getLowContrastIssues(), ...issue.getElementAccessibilityIssues(), ...issue.getQuirksModeIssues(), - // ...issue.getAttributionReportingIssues(), // Uncomment when AttributionReportingIssue has details() ]; - const affectedElement: Array<{uid?: string; data?: object}> = []; + const affectedResources: Array<{ + uid?: string; + data?: object; + request?: string|number; + }> = []; for (const singleIssue of issues) { - if (!singleIssue.details) break; + if (!singleIssue.details && !singleIssue.getDetails) continue; + + let details = + singleIssue.details?.() as unknown as IssueDetailsWithResources; + if (!details) details = singleIssue.getDetails?.() as unknown as IssueDetailsWithResources; + if (!details) continue; - const details = - singleIssue.details() as unknown as IssueDetailsWithResources; let uid; + let request: number | string | undefined; if (details.violatingNodeId && context) { uid = context.resolveCdpElementId(details.violatingNodeId); } @@ -120,22 +133,45 @@ export function formatIssue( uid = context.resolveCdpElementId(details.documentNodeId); } + if (details.request) { + request = details.request.url; + if (details.request.requestId && context) { + const resolvedId = context.resolveCdpRequestId( + details.request.requestId, + ); + if (resolvedId) { + request = resolvedId; + } + } + } + // eslint-disable-next-line const data = structuredClone(details) as any; delete data.violatingNodeId; + delete data.nodeId; + delete data.documentNodeId; delete data.errorType; delete data.frameId; - affectedElement.push({uid, data: data}); + delete data.request; + affectedResources.push({ + uid, + data: data, + request + }); } - if (affectedElement.length) { + if (affectedResources.length) { result.push('### Affected resources'); } result.push( - ...affectedElement.map(item => { - return `uid=${item.uid} data=${JSON.stringify(item.data)}`; + ...affectedResources.map(item => { + const details = []; + if(item.uid) details.push(`uid=${item.uid}`); + if(item.data) details.push(`data=${JSON.stringify(item.data)}`); + if(item.request) details.push((typeof item.request === 'number' ? `reqid=` : 'url=') + item.request); + return details.join(' '); }), ); if (result.length === 0) return 'No details provided for the issue ' + issue.code(); return result.join('\n'); -} +} \ No newline at end of file diff --git a/tests/formatters/consoleFormatter.test.js.snapshot b/tests/formatters/consoleFormatter.test.js.snapshot index 9f6bfaf4..2052e435 100644 --- a/tests/formatters/consoleFormatter.test.js.snapshot +++ b/tests/formatters/consoleFormatter.test.js.snapshot @@ -44,5 +44,5 @@ Learn more: [Learn more](http://example.com/learnmore) [Learn more 2](http://example.com/another-learnmore) ### Affected resources -uid=undefined data={"violatingNodeAttribute":"test"} +data={"violatingNodeAttribute":"test"} `; diff --git a/tests/tools/console.test.js.snapshot b/tests/tools/console.test.js.snapshot index 8abb44b3..28de4a89 100644 --- a/tests/tools/console.test.js.snapshot +++ b/tests/tools/console.test.js.snapshot @@ -1,4 +1,4 @@ -exports[`console > get_console_message > issues type > gets issue details 1`] = ` +exports[`console > get_console_message > issues type > gets issue details with node id parsing 1`] = ` # test response ID: 1 Message: issue> An element doesn't have an autocomplete attribute @@ -11,3 +11,19 @@ Learn more: ### Affected resources uid=1_1 data={"violatingNodeAttribute":"name"} `; + +exports[`console > get_console_message > issues type > gets issue details with request id parsing 1`] = ` +# test response +ID: 1 +Message: issue> Ensure CORS response header values are valid + +A cross-origin resource sharing (CORS) request was blocked because of invalid or missing response headers of the request or the associated [preflight request](issueCorsPreflightRequest). + +To fix this issue, ensure the response to the CORS request and/or the associated [preflight request](issueCorsPreflightRequest) are not missing headers and use valid header values. + +Note that if an opaque response is sufficient, the request's mode can be set to \`no-cors\` to fetch the resource with CORS disabled; that way CORS headers are not required but the response content is inaccessible (opaque). +Learn more: +[Cross-Origin Resource Sharing (\`CORS\`)](https://web.dev/cross-origin-resource-sharing) +### Affected resources +reqid=1 data={"corsErrorStatus":{"corsError":"PreflightMissingAllowOriginHeader","failedParameter":""},"isWarning":false,"initiatorOrigin":"","clientSecurityState":{"initiatorIsSecureContext":false,"initiatorIPAddressSpace":"Loopback","privateNetworkRequestPolicy":"BlockFromInsecureToMorePrivate"}} +`; diff --git a/tests/tools/console.test.ts b/tests/tools/console.test.ts index 92bc1fe5..57c0a682 100644 --- a/tests/tools/console.test.ts +++ b/tests/tools/console.test.ts @@ -159,7 +159,7 @@ describe('console', () => { setIssuesEnabled(false); }); - it('gets issue details', async t => { + it('gets issue details with node id parsing', async t => { await withBrowser(async (response, context) => { const page = await context.newPage(); const issuePromise = new Promise(resolve => { @@ -181,6 +181,38 @@ describe('console', () => { t.assert.snapshot?.(formattedResponse[0].text); }); }); + it('gets issue details with request id parsing', async t => { + await withBrowser(async (response, context) => { + const page = await context.newPage(); + const issuePromise = new Promise(resolve => { + page.once('issue', () => { + resolve(); + }); + }); + await page.setContent(` + + `); + await context.createTextSnapshot(); + await issuePromise; + await listConsoleMessages.handler({params: {}}, response, context); + const response2 = new McpResponse(); + await getConsoleMessage.handler( + {params: {msgid: 1}}, + response2, + context, + ); + const formattedResponse = await response2.handle('test', context); + t.assert.snapshot?.(formattedResponse[0].text); + }); + }); }); }); }); diff --git a/tests/utils.ts b/tests/utils.ts index 45a4bea2..8cd5d03e 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -189,5 +189,7 @@ export function getMockAggregatedIssue(): sinon.SinonStubbedInstance Date: Wed, 26 Nov 2025 10:07:15 +0000 Subject: [PATCH 3/8] formatting --- src/formatters/consoleFormatter.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index 75fa7677..46976d7f 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -100,7 +100,10 @@ export function formatIssue( } } - const issues: Array<{details?: () => IssueDetailsWithResources, getDetails?: () => IssueDetailsWithResources}> = [ + const issues: Array<{ + details?: () => IssueDetailsWithResources; + getDetails?: () => IssueDetailsWithResources; + }> = [ ...issue.getCorsIssues(), ...issue.getMixedContentIssues(), ...issue.getGenericIssues(), @@ -111,14 +114,16 @@ export function formatIssue( const affectedResources: Array<{ uid?: string; data?: object; - request?: string|number; + request?: string | number; }> = []; for (const singleIssue of issues) { if (!singleIssue.details && !singleIssue.getDetails) continue; let details = singleIssue.details?.() as unknown as IssueDetailsWithResources; - if (!details) details = singleIssue.getDetails?.() as unknown as IssueDetailsWithResources; + if (!details) + details = + singleIssue.getDetails?.() as unknown as IssueDetailsWithResources; if (!details) continue; let uid; @@ -156,8 +161,8 @@ export function formatIssue( affectedResources.push({ uid, data: data, - request - }); + request, + }); } if (affectedResources.length) { result.push('### Affected resources'); @@ -165,13 +170,16 @@ export function formatIssue( result.push( ...affectedResources.map(item => { const details = []; - if(item.uid) details.push(`uid=${item.uid}`); - if(item.data) details.push(`data=${JSON.stringify(item.data)}`); - if(item.request) details.push((typeof item.request === 'number' ? `reqid=` : 'url=') + item.request); + if (item.uid) details.push(`uid=${item.uid}`); + if (item.data) details.push(`data=${JSON.stringify(item.data)}`); + if (item.request) + details.push( + (typeof item.request === 'number' ? `reqid=` : 'url=') + item.request, + ); return details.join(' '); }), ); if (result.length === 0) return 'No details provided for the issue ' + issue.code(); return result.join('\n'); -} \ No newline at end of file +} From 6345245981e51949fd7926da3c2a149e15f35aec Mon Sep 17 00:00:00 2001 From: Natallia Harshunova Date: Wed, 26 Nov 2025 11:00:49 +0000 Subject: [PATCH 4/8] Fix order of details --- src/formatters/consoleFormatter.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index 46976d7f..7c56d490 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -171,11 +171,12 @@ export function formatIssue( ...affectedResources.map(item => { const details = []; if (item.uid) details.push(`uid=${item.uid}`); - if (item.data) details.push(`data=${JSON.stringify(item.data)}`); - if (item.request) + if (item.request) { details.push( (typeof item.request === 'number' ? `reqid=` : 'url=') + item.request, ); + } + if (item.data) details.push(`data=${JSON.stringify(item.data)}`); return details.join(' '); }), ); From 478b74c8cee6da61b667cae14e8c2e222bfc4766 Mon Sep 17 00:00:00 2001 From: Natallia Harshunova Date: Wed, 26 Nov 2025 12:08:06 +0000 Subject: [PATCH 5/8] Attempt to fix flaky test --- tests/tools/console.test.js.snapshot | 2 +- tests/tools/console.test.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/tools/console.test.js.snapshot b/tests/tools/console.test.js.snapshot index 28de4a89..51c3e09d 100644 --- a/tests/tools/console.test.js.snapshot +++ b/tests/tools/console.test.js.snapshot @@ -25,5 +25,5 @@ Note that if an opaque response is sufficient, the request's mode can be set to Learn more: [Cross-Origin Resource Sharing (\`CORS\`)](https://web.dev/cross-origin-resource-sharing) ### Affected resources -reqid=1 data={"corsErrorStatus":{"corsError":"PreflightMissingAllowOriginHeader","failedParameter":""},"isWarning":false,"initiatorOrigin":"","clientSecurityState":{"initiatorIsSecureContext":false,"initiatorIPAddressSpace":"Loopback","privateNetworkRequestPolicy":"BlockFromInsecureToMorePrivate"}} +url=https://example.com/data.json data={"corsErrorStatus":{"corsError":"PreflightMissingAllowOriginHeader","failedParameter":""},"isWarning":false,"initiatorOrigin":"","clientSecurityState":{"initiatorIsSecureContext":false,"initiatorIPAddressSpace":"Loopback","privateNetworkRequestPolicy":"BlockFromInsecureToMorePrivate"}} `; diff --git a/tests/tools/console.test.ts b/tests/tools/console.test.ts index 57c0a682..11b10090 100644 --- a/tests/tools/console.test.ts +++ b/tests/tools/console.test.ts @@ -189,6 +189,20 @@ describe('console', () => { resolve(); }); }); + await page.setRequestInterception(true); + page.on('request', request => { + if (request.url().includes('example.com')) { + void request.respond({ + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({}), + }); + } else { + void request.continue(); + } + }); await page.setContent(`