From a9e6b5110885f85d34bb4af041a9f23a8d428369 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 6 Jan 2025 16:37:11 -0800 Subject: [PATCH] chore(bidi): implement query selector all ($$) method (#34226) --- .../src/server/bidi/bidiExecutionContext.ts | 20 ++++++++++++- .../bidi/expectations/bidi-chromium-page.txt | 20 ++++++------- .../bidi-firefox-nightly-page.txt | 30 +++++++++---------- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts index f53b160ccf..de1b50bd1a 100644 --- a/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts +++ b/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts @@ -103,7 +103,25 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate { } async getProperties(context: js.ExecutionContext, objectId: js.ObjectId): Promise> { - throw new Error('Method not implemented.'); + const handle = this.createHandle(context, { objectId }); + try { + const names = await handle.evaluate(object => { + const names = []; + const descriptors = Object.getOwnPropertyDescriptors(object); + for (const name in descriptors) { + if (descriptors[name]?.enumerable) + names.push(name); + } + return names; + }); + const values = await Promise.all(names.map(name => handle.evaluateHandle((object, name) => object[name], name))); + const map = new Map(); + for (let i = 0; i < names.length; i++) + map.set(names[i], values[i]); + return map; + } finally { + handle.dispose(); + } } createHandle(context: js.ExecutionContext, jsRemoteObject: js.RemoteObject): js.JSHandle { diff --git a/tests/bidi/expectations/bidi-chromium-page.txt b/tests/bidi/expectations/bidi-chromium-page.txt index da2bee1fef..0664b52591 100644 --- a/tests/bidi/expectations/bidi-chromium-page.txt +++ b/tests/bidi/expectations/bidi-chromium-page.txt @@ -64,12 +64,12 @@ page/elementhandle-press.spec.ts › should reset selection when not focused [pa page/elementhandle-press.spec.ts › should work [pass] page/elementhandle-press.spec.ts › should work with number input [pass] page/elementhandle-query-selector.spec.ts › should query existing element [pass] -page/elementhandle-query-selector.spec.ts › should query existing elements [fail] -page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] +page/elementhandle-query-selector.spec.ts › should query existing elements [pass] +page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [pass] page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] page/elementhandle-query-selector.spec.ts › should work for adopted elements [fail] -page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] -page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] +page/elementhandle-query-selector.spec.ts › xpath should query existing element [pass] +page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [pass] page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [fail] page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] @@ -1690,7 +1690,7 @@ page/page-wait-for-url.spec.ts › should work with commit and about:blank [time page/page-wait-for-url.spec.ts › should work with history.pushState() [pass] page/page-wait-for-url.spec.ts › should work with history.replaceState() [pass] page/page-wait-for-url.spec.ts › should work with url match for same document navigations [pass] -page/queryselector.spec.ts › $$ should work with bogus Array.from [fail] +page/queryselector.spec.ts › $$ should work with bogus Array.from [pass] page/queryselector.spec.ts › should auto-detect css selector [pass] page/queryselector.spec.ts › should auto-detect text selector [pass] page/queryselector.spec.ts › should auto-detect xpath selector [pass] @@ -1699,14 +1699,14 @@ page/queryselector.spec.ts › should auto-detect xpath selector with starting p page/queryselector.spec.ts › should query existing element with css selector @smoke [pass] page/queryselector.spec.ts › should query existing element with text selector [pass] page/queryselector.spec.ts › should query existing element with xpath selector [pass] -page/queryselector.spec.ts › should query existing elements [fail] -page/queryselector.spec.ts › should return empty array if nothing is found [fail] +page/queryselector.spec.ts › should query existing elements [pass] +page/queryselector.spec.ts › should return empty array if nothing is found [pass] page/queryselector.spec.ts › should return null for non-existing element [pass] page/queryselector.spec.ts › should support >> syntax [pass] page/queryselector.spec.ts › should throw for non-string selector [pass] -page/queryselector.spec.ts › xpath should query existing element [fail] -page/queryselector.spec.ts › xpath should return empty array for non-existing element [fail] -page/queryselector.spec.ts › xpath should return multiple elements [fail] +page/queryselector.spec.ts › xpath should query existing element [pass] +page/queryselector.spec.ts › xpath should return empty array for non-existing element [pass] +page/queryselector.spec.ts › xpath should return multiple elements [pass] page/retarget.spec.ts › check retargeting [pass] page/retarget.spec.ts › direct actions retargeting [pass] page/retarget.spec.ts › editable retargeting [pass] diff --git a/tests/bidi/expectations/bidi-firefox-nightly-page.txt b/tests/bidi/expectations/bidi-firefox-nightly-page.txt index f7e4292227..e9edb983e3 100644 --- a/tests/bidi/expectations/bidi-firefox-nightly-page.txt +++ b/tests/bidi/expectations/bidi-firefox-nightly-page.txt @@ -64,11 +64,11 @@ page/elementhandle-press.spec.ts › should reset selection when not focused [pa page/elementhandle-press.spec.ts › should work [pass] page/elementhandle-press.spec.ts › should work with number input [pass] page/elementhandle-query-selector.spec.ts › should query existing element [pass] -page/elementhandle-query-selector.spec.ts › should query existing elements [fail] -page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] +page/elementhandle-query-selector.spec.ts › should query existing elements [pass] +page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [pass] page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] -page/elementhandle-query-selector.spec.ts › should work for adopted elements [timeout] -page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] +page/elementhandle-query-selector.spec.ts › should work for adopted elements [pass] +page/elementhandle-query-selector.spec.ts › xpath should query existing element [pass] page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] @@ -1702,23 +1702,23 @@ page/page-wait-for-url.spec.ts › should work with commit and about:blank [pass page/page-wait-for-url.spec.ts › should work with history.pushState() [fail] page/page-wait-for-url.spec.ts › should work with history.replaceState() [fail] page/page-wait-for-url.spec.ts › should work with url match for same document navigations [timeout] -page/queryselector.spec.ts › $$ should work with bogus Array.from [fail] -page/queryselector.spec.ts › should auto-detect css selector [fail] +page/queryselector.spec.ts › $$ should work with bogus Array.from [pass] +page/queryselector.spec.ts › should auto-detect css selector [pass] page/queryselector.spec.ts › should auto-detect text selector [pass] page/queryselector.spec.ts › should auto-detect xpath selector [pass] page/queryselector.spec.ts › should auto-detect xpath selector starting with .. [pass] page/queryselector.spec.ts › should auto-detect xpath selector with starting parenthesis [pass] -page/queryselector.spec.ts › should query existing element with css selector @smoke [fail] +page/queryselector.spec.ts › should query existing element with css selector @smoke [pass] page/queryselector.spec.ts › should query existing element with text selector [pass] page/queryselector.spec.ts › should query existing element with xpath selector [pass] -page/queryselector.spec.ts › should query existing elements [fail] -page/queryselector.spec.ts › should return empty array if nothing is found [fail] +page/queryselector.spec.ts › should query existing elements [pass] +page/queryselector.spec.ts › should return empty array if nothing is found [pass] page/queryselector.spec.ts › should return null for non-existing element [pass] page/queryselector.spec.ts › should support >> syntax [pass] page/queryselector.spec.ts › should throw for non-string selector [pass] -page/queryselector.spec.ts › xpath should query existing element [fail] -page/queryselector.spec.ts › xpath should return empty array for non-existing element [fail] -page/queryselector.spec.ts › xpath should return multiple elements [fail] +page/queryselector.spec.ts › xpath should query existing element [pass] +page/queryselector.spec.ts › xpath should return empty array for non-existing element [pass] +page/queryselector.spec.ts › xpath should return multiple elements [pass] page/retarget.spec.ts › check retargeting [fail] page/retarget.spec.ts › direct actions retargeting [pass] page/retarget.spec.ts › editable retargeting [pass] @@ -1769,13 +1769,13 @@ page/selectors-frame.spec.ts › click should survive iframe navigation [pass] page/selectors-frame.spec.ts › click should survive navigation [pass] page/selectors-frame.spec.ts › should capture after the enter-frame [pass] page/selectors-frame.spec.ts › should click in lazy iframe [pass] -page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [fail] +page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [pass] page/selectors-frame.spec.ts › should non work for non-frame [pass] page/selectors-frame.spec.ts › should not allow capturing before enter-frame [pass] page/selectors-frame.spec.ts › should not allow dangling enter-frame [pass] page/selectors-frame.spec.ts › should not allow leading enter-frame [pass] -page/selectors-frame.spec.ts › should work for $ and $$ [fail] -page/selectors-frame.spec.ts › should work for $ and $$ (handle) [fail] +page/selectors-frame.spec.ts › should work for $ and $$ [pass] +page/selectors-frame.spec.ts › should work for $ and $$ (handle) [pass] page/selectors-frame.spec.ts › should work for $$eval [pass] page/selectors-frame.spec.ts › should work for $$eval (handle) [pass] page/selectors-frame.spec.ts › should work for $eval [pass]