From bd93b1441e239800dd60ef7fcd7cb588a13c63d1 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 6 Jul 2026 13:31:13 +0100 Subject: [PATCH 1/4] chore: make InjectedScript know the frameSeq (#41635) --- packages/injected/src/injectedScript.ts | 4 ++++ packages/playwright-core/src/server/dom.ts | 1 + packages/playwright-core/src/server/page.ts | 1 - packages/trace-viewer/src/ui/snapshotTab.tsx | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/injected/src/injectedScript.ts b/packages/injected/src/injectedScript.ts index bb72c31e4afed..0ce7c80dd9c28 100644 --- a/packages/injected/src/injectedScript.ts +++ b/packages/injected/src/injectedScript.ts @@ -78,6 +78,7 @@ interface WebKitLegacyDeviceMotionEvent extends DeviceMotionEvent { export type InjectedScriptOptions = { isUnderTest: boolean; sdkLanguage: Language; + frameSeq: number; // For strict error and codegen testIdAttributeName: string; stableRafCount: number; @@ -99,6 +100,7 @@ export class InjectedScript { private _highlight: Highlight | undefined; readonly isUnderTest: boolean; private _sdkLanguage: Language; + private _frameSeq: number; private _testIdAttributeNameForStrictErrorAndConsoleCodegen: string = 'data-testid'; readonly window: Window & typeof globalThis; readonly document: Document; @@ -141,6 +143,7 @@ export class InjectedScript { // inside a trace viewer snapshot, where "window" differs from "globalThis". this.utils.builtins = new UtilityScript(window, options.isUnderTest).builtins; this._sdkLanguage = options.sdkLanguage; + this._frameSeq = options.frameSeq; this._testIdAttributeNameForStrictErrorAndConsoleCodegen = options.testIdAttributeName; this._evaluator = new SelectorEvaluatorImpl(); this.consoleApi = new ConsoleAPI(this); @@ -318,6 +321,7 @@ export class InjectedScript { ariaSnapshotWithRefs(node: Node, options: AriaTreeOptions & { depth?: number }): { text: string, iframeRefs: string[], iframeDepths: Record } { if (node.nodeType !== Node.ELEMENT_NODE) throw this.createStacklessError('Can only capture aria snapshot of Element nodes.'); + options = { ...options, refPrefix: this._frameSeq && options.mode === 'ai' ? 'f' + this._frameSeq : '' }; const ariaSnapshot = generateAriaTree(node as Element, options); const rendered = renderAriaTree(ariaSnapshot, options); this._lastAriaSnapshotForQuery = ariaSnapshot; diff --git a/packages/playwright-core/src/server/dom.ts b/packages/playwright-core/src/server/dom.ts index c58c9029146ad..c46aa5ebedc7e 100644 --- a/packages/playwright-core/src/server/dom.ts +++ b/packages/playwright-core/src/server/dom.ts @@ -91,6 +91,7 @@ export class FrameExecutionContext extends js.ExecutionContext { const options: InjectedScriptOptions = { isUnderTest: isUnderTest(), sdkLanguage, + frameSeq: this.frame.seq, testIdAttributeName: selectorsRegistry.testIdAttributeName(), stableRafCount: this.frame._page.delegate.rafCountForStablePosition(), browserName: this.frame._page.browserContext._browser.options.name, diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 39537e0598e37..1a576e209dd40 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -1121,7 +1121,6 @@ export async function ariaSnapshotForFrame(progress: Progress, frame: frames.Fra return injected.ariaSnapshotWithRefs(element, options); }, { mode: options.mode ?? 'default', - refPrefix: resolvedFrame.seq ? 'f' + resolvedFrame.seq : '', doNotRenderActive: options.doNotRenderActive, info: resolved.info, depth: options.depth, diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 6045b89935313..dd24dd8c048d3 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -86,7 +86,7 @@ export const SnapshotTabsView: React.FunctionComponent<{ { const win = window.open(snapshotUrls?.popoutUrl || '', '_blank'); win?.addEventListener('DOMContentLoaded', () => { - const injectedScript = new InjectedScript(win as any, { isUnderTest, sdkLanguage, testIdAttributeName, stableRafCount: 1, browserName: 'chromium', customEngines: [] }); + const injectedScript = new InjectedScript(win as any, { isUnderTest, frameSeq: 0, sdkLanguage, testIdAttributeName, stableRafCount: 1, browserName: 'chromium', customEngines: [] }); injectedScript.consoleApi.install(); }); }} /> @@ -311,7 +311,7 @@ function createRecorders(recorders: { recorder: Recorder, frameSelector: string return; const win = frameWindow as any; if (!win._recorder && force) { - const injectedScript = new InjectedScript(frameWindow as any, { isUnderTest, sdkLanguage, testIdAttributeName, stableRafCount: 1, browserName: 'chromium', customEngines: [] }); + const injectedScript = new InjectedScript(frameWindow as any, { isUnderTest, frameSeq: 0, sdkLanguage, testIdAttributeName, stableRafCount: 1, browserName: 'chromium', customEngines: [] }); const recorder = new Recorder(injectedScript); win._injectedScript = injectedScript; win._recorder = { recorder, frameSelector: parentFrameSelector }; From 05281620d9b5b606b566375523abfb8fa491d700 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:43:28 +0200 Subject: [PATCH 2/4] chore(deps): remove unused @octokit/graphql-schema from root devDependencies (#41639) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Skn0tt <14912729+Skn0tt@users.noreply.github.com> --- package-lock.json | 42 ++---------------------------------------- package.json | 1 - 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index 971041d56b81c..b08b5f6ade1cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,6 @@ "@eslint/js": "9.39.4", "@jest/expect-utils": "30.4.1", "@modelcontextprotocol/sdk": "1.29.0", - "@octokit/graphql-schema": "15.26.1", "@stylistic/eslint-plugin": "5.10.0", "@types/babel__code-frame": "7.27.0", "@types/babel__core": "7.20.5", @@ -2100,17 +2099,6 @@ "node": ">= 20" } }, - "node_modules/@octokit/graphql-schema": { - "version": "15.26.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql-schema/-/graphql-schema-15.26.1.tgz", - "integrity": "sha512-RFDC2MpRBd4AxSRvUeBIVeBU7ojN/SxDfALUd7iVYOSeEK3gZaqR2MGOysj4Zh2xj2RY5fQAUT+Oqq7hWTraMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graphql": "^16.0.0", - "graphql-tag": "^2.10.3" - } - }, "node_modules/@octokit/openapi-types": { "version": "27.0.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", @@ -5900,32 +5888,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphql": { - "version": "16.14.2", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.2.tgz", - "integrity": "sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.7.tgz", - "integrity": "sha512-xnE/NFzy+0eIesvAsREJZ284zTl/wYuBAvpsFSDhRGRdRHdnE90M21Q3xAWyYInb0J756c6x0pIQ62+vtvOs1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -8973,8 +8935,8 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "devOptional": true, - "license": "0BSD" + "license": "0BSD", + "optional": true }, "node_modules/tunnel": { "version": "0.0.6", diff --git a/package.json b/package.json index e7310d0ffd40c..78f7b8b6af487 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ "@eslint/js": "9.39.4", "@jest/expect-utils": "30.4.1", "@modelcontextprotocol/sdk": "1.29.0", - "@octokit/graphql-schema": "15.26.1", "@stylistic/eslint-plugin": "5.10.0", "@types/babel__code-frame": "7.27.0", "@types/babel__core": "7.20.5", From 434bb845de747a9ebacb4f87724de52f92af89ef Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 6 Jul 2026 17:25:51 +0200 Subject: [PATCH 3/4] test(network): skip response.body() navigation race test under tracing (#41644) --- tests/page/page-network-response.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/page/page-network-response.spec.ts b/tests/page/page-network-response.spec.ts index 53f0ac96c1b80..a0282b9840a90 100644 --- a/tests/page/page-network-response.spec.ts +++ b/tests/page/page-network-response.spec.ts @@ -451,8 +451,9 @@ it('Response.formData() should parse multipart/form-data in page context', async expect(result.fileContent).toBe('hello'); }); -it('should give a readable error when response.body() races with navigation', async ({ page, server, browserName }) => { +it('should give a readable error when response.body() races with navigation', async ({ page, server, browserName, trace }) => { it.skip(browserName === 'firefox', 'Firefox keeps the response body available after navigating away, so it never throws'); + it.skip(trace === 'on', 'Tracing fetches response bodies eagerly, so the body is already cached before navigation'); it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41512' }); const [response] = await Promise.all([ page.waitForResponse(server.PREFIX + '/title.html'), From 4f86fd5c9a53275aa54234a12b82b00c1a1eea46 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 6 Jul 2026 17:51:31 +0100 Subject: [PATCH 4/4] test: update expectations for page-evaluate.spec.ts:374 (#41645) --- tests/page/page-evaluate.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/page/page-evaluate.spec.ts b/tests/page/page-evaluate.spec.ts index d01b19cef008d..19166207a4da1 100644 --- a/tests/page/page-evaluate.spec.ts +++ b/tests/page/page-evaluate.spec.ts @@ -377,12 +377,12 @@ it('should properly serialize PerformanceMeasure object', async ({ page }) => { window.builtins.performance.mark('end'); window.builtins.performance.measure('my-measure', 'start', 'end'); return window.builtins.performance.getEntriesByType('measure'); - })).toEqual([{ + })).toEqual([expect.objectContaining({ duration: expect.any(Number), entryType: 'measure', name: 'my-measure', startTime: expect.any(Number), - }]); + })]); }); it('should properly serialize window.performance object', async ({ page }) => {