From 9f3eca4367b2d6eab43fb62261bc619a0ad0b2c5 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Mon, 11 Mar 2024 15:00:18 +0530 Subject: [PATCH 1/6] [bidi][java] Add Browser module --- .../src/org/openqa/selenium/bidi/Browser.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 java/src/org/openqa/selenium/bidi/Browser.java diff --git a/java/src/org/openqa/selenium/bidi/Browser.java b/java/src/org/openqa/selenium/bidi/Browser.java new file mode 100644 index 0000000000000..996c82076c4c8 --- /dev/null +++ b/java/src/org/openqa/selenium/bidi/Browser.java @@ -0,0 +1,71 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi; + +import java.io.StringReader; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.json.Json; +import org.openqa.selenium.json.JsonInput; +import org.openqa.selenium.json.TypeToken; + +public class Browser { + private final BiDi bidi; + + private static final Json JSON = new Json(); + + private final Function userContextInfoMapper = + jsonInput -> { + Map response = jsonInput.read(Map.class); + try (StringReader reader = new StringReader(JSON.toJson(response.get("userContext"))); + JsonInput input = JSON.newInput(reader)) { + return input.read(String.class); + } + }; + + private final Function> userContextsInfoMapper = + jsonInput -> { + Map response = jsonInput.read(Map.class); + try (StringReader reader = new StringReader(JSON.toJson(response.get("userContexts"))); + JsonInput input = JSON.newInput(reader)) { + return input.read(new TypeToken>() {}.getType()); + } + }; + + public Browser(WebDriver driver) { + this.bidi = ((HasBiDi) driver).getBiDi(); + } + + public String createUserContext() { + return bidi.send(new Command<>("browser.createUserContext", Map.of(), userContextInfoMapper)); + } + + public List getUserContexts() { + return bidi.send(new Command<>("browser.getUserContexts", Map.of(), userContextsInfoMapper)); + } + + public String removeUserContext(String userContext) { + return bidi.send( + new Command<>( + "browser.removeUserContext", + Map.of("userContext", userContext), + userContextInfoMapper)); + } +} From 0513dd6ec6cc0109ad0acbb58127095f63c5175c Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Mon, 11 Mar 2024 18:07:50 +0530 Subject: [PATCH 2/6] [bidi][java] Add browser module --- .../src/org/openqa/selenium/bidi/Browser.java | 26 +++--- .../openqa/selenium/bidi/browser/BUILD.bazel | 28 ++++++ .../bidi/browser/BrowserCommandsTest.java | 89 +++++++++++++++++++ 3 files changed, 130 insertions(+), 13 deletions(-) create mode 100644 java/test/org/openqa/selenium/bidi/browser/BUILD.bazel create mode 100644 java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java diff --git a/java/src/org/openqa/selenium/bidi/Browser.java b/java/src/org/openqa/selenium/bidi/Browser.java index 996c82076c4c8..f9b819534f050 100644 --- a/java/src/org/openqa/selenium/bidi/Browser.java +++ b/java/src/org/openqa/selenium/bidi/Browser.java @@ -17,36 +17,36 @@ package org.openqa.selenium.bidi; -import java.io.StringReader; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Function; import org.openqa.selenium.WebDriver; -import org.openqa.selenium.json.Json; import org.openqa.selenium.json.JsonInput; -import org.openqa.selenium.json.TypeToken; public class Browser { private final BiDi bidi; - private static final Json JSON = new Json(); - private final Function userContextInfoMapper = jsonInput -> { Map response = jsonInput.read(Map.class); - try (StringReader reader = new StringReader(JSON.toJson(response.get("userContext"))); - JsonInput input = JSON.newInput(reader)) { - return input.read(String.class); - } + return (String) response.get("userContext"); }; private final Function> userContextsInfoMapper = jsonInput -> { Map response = jsonInput.read(Map.class); - try (StringReader reader = new StringReader(JSON.toJson(response.get("userContexts"))); - JsonInput input = JSON.newInput(reader)) { - return input.read(new TypeToken>() {}.getType()); - } + List> userContextsResponse = + (List>) response.get("userContexts"); + + List userContexts = new ArrayList<>(); + userContextsResponse.forEach( + map -> { + String userContext = map.get("userContext"); + userContexts.add(userContext); + }); + + return userContexts; }; public Browser(WebDriver driver) { diff --git a/java/test/org/openqa/selenium/bidi/browser/BUILD.bazel b/java/test/org/openqa/selenium/bidi/browser/BUILD.bazel new file mode 100644 index 0000000000000..fcfc9fb62c973 --- /dev/null +++ b/java/test/org/openqa/selenium/bidi/browser/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//java:defs.bzl", "JUNIT5_DEPS", "java_selenium_test_suite") + +java_selenium_test_suite( + name = "large-tests", + size = "large", + srcs = glob(["*Test.java"]), + browsers = [ + "firefox", + ], + tags = [ + "selenium-remote", + ], + deps = [ + "//java/src/org/openqa/selenium/bidi", + "//java/src/org/openqa/selenium/firefox", + "//java/src/org/openqa/selenium/json", + "//java/src/org/openqa/selenium/remote", + "//java/src/org/openqa/selenium/support", + "//java/test/org/openqa/selenium/environment", + "//java/test/org/openqa/selenium/testing:annotations", + "//java/test/org/openqa/selenium/testing:test-base", + "//java/test/org/openqa/selenium/testing/drivers", + artifact("com.google.guava:guava"), + artifact("org.junit.jupiter:junit-jupiter-api"), + artifact("org.assertj:assertj-core"), + ] + JUNIT5_DEPS, +) diff --git a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java new file mode 100644 index 0000000000000..2392e3dc3c580 --- /dev/null +++ b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java @@ -0,0 +1,89 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.bidi.browser; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.openqa.selenium.testing.Safely.safelyCall; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.bidi.Browser; +import org.openqa.selenium.environment.webserver.AppServer; +import org.openqa.selenium.environment.webserver.NettyAppServer; +import org.openqa.selenium.testing.JupiterTestBase; + +class BrowserCommandsTest extends JupiterTestBase { + + private AppServer server; + private Browser browser; + + @BeforeEach + public void setUp() { + server = new NettyAppServer(); + server.start(); + browser = new Browser(driver); + } + + @Test + void canCreateAUserContext() { + String userContext = browser.createUserContext(); + + assertThat(userContext).isNotNull(); + + browser.removeUserContext(userContext); + } + + @Test + void canGetUserContexts() { + String userContext1 = browser.createUserContext(); + String userContext2 = browser.createUserContext(); + + List userContexts = browser.getUserContexts(); + assertThat(userContexts.size()).isGreaterThanOrEqualTo(2); + + browser.removeUserContext(userContext1); + browser.removeUserContext(userContext2); + } + + @Test + void canRemoveUserContext() { + String userContext1 = browser.createUserContext(); + String userContext2 = browser.createUserContext(); + + List userContexts = browser.getUserContexts(); + assertThat(userContexts.size()).isGreaterThanOrEqualTo(2); + + browser.removeUserContext(userContext2); + + List updatedUserContexts = browser.getUserContexts(); + assertThat(userContext1).isIn(updatedUserContexts); + assertThat(userContext2).isNotIn(updatedUserContexts); + + browser.removeUserContext(userContext1); + } + + @AfterEach + public void quitDriver() { + if (driver != null) { + driver.quit(); + } + safelyCall(server::stop); + } +} From 36be14e13ccc85ae1313343af9434fcb46070088 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Mon, 11 Mar 2024 18:29:35 +0530 Subject: [PATCH 3/6] [java] Ignore tests that are not implemented --- .../bidi/browser/BrowserCommandsTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java index 2392e3dc3c580..70bf0a3bf13e4 100644 --- a/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java +++ b/java/test/org/openqa/selenium/bidi/browser/BrowserCommandsTest.java @@ -19,6 +19,10 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.openqa.selenium.testing.Safely.safelyCall; +import static org.openqa.selenium.testing.drivers.Browser.EDGE; +import static org.openqa.selenium.testing.drivers.Browser.FIREFOX; +import static org.openqa.selenium.testing.drivers.Browser.IE; +import static org.openqa.selenium.testing.drivers.Browser.SAFARI; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -28,6 +32,7 @@ import org.openqa.selenium.environment.webserver.AppServer; import org.openqa.selenium.environment.webserver.NettyAppServer; import org.openqa.selenium.testing.JupiterTestBase; +import org.openqa.selenium.testing.NotYetImplemented; class BrowserCommandsTest extends JupiterTestBase { @@ -42,6 +47,10 @@ public void setUp() { } @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) void canCreateAUserContext() { String userContext = browser.createUserContext(); @@ -51,6 +60,10 @@ void canCreateAUserContext() { } @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) void canGetUserContexts() { String userContext1 = browser.createUserContext(); String userContext2 = browser.createUserContext(); @@ -63,6 +76,10 @@ void canGetUserContexts() { } @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) void canRemoveUserContext() { String userContext1 = browser.createUserContext(); String userContext2 = browser.createUserContext(); From 796304649a28af07d4291f223963b27f815c16fc Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 12 Mar 2024 10:15:20 +0530 Subject: [PATCH 4/6] [java] Remove user context does not return anything --- java/src/org/openqa/selenium/bidi/Browser.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/java/src/org/openqa/selenium/bidi/Browser.java b/java/src/org/openqa/selenium/bidi/Browser.java index f9b819534f050..6cbd326fc5155 100644 --- a/java/src/org/openqa/selenium/bidi/Browser.java +++ b/java/src/org/openqa/selenium/bidi/Browser.java @@ -61,11 +61,7 @@ public List getUserContexts() { return bidi.send(new Command<>("browser.getUserContexts", Map.of(), userContextsInfoMapper)); } - public String removeUserContext(String userContext) { - return bidi.send( - new Command<>( - "browser.removeUserContext", - Map.of("userContext", userContext), - userContextInfoMapper)); + public void removeUserContext(String userContext) { + bidi.send(new Command<>("browser.removeUserContext", Map.of("userContext", userContext))); } } From 5e6d9358dae499e45d55e3a39899972b08000a38 Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 12 Mar 2024 10:48:50 +0530 Subject: [PATCH 5/6] [bidi][js] Add Browser module --- .../node/selenium-webdriver/bidi/browser.js | 80 +++++++++++++++++ .../test/bidi/browser_test.js | 86 +++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 javascript/node/selenium-webdriver/bidi/browser.js create mode 100644 javascript/node/selenium-webdriver/test/bidi/browser_test.js diff --git a/javascript/node/selenium-webdriver/bidi/browser.js b/javascript/node/selenium-webdriver/bidi/browser.js new file mode 100644 index 0000000000000..3ea5920b2b8e6 --- /dev/null +++ b/javascript/node/selenium-webdriver/bidi/browser.js @@ -0,0 +1,80 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +const {WebElement} = require('../lib/webdriver') + +class Browser { + constructor(driver) { + this._driver = driver + } + + async init() { + if (!(await this._driver.getCapabilities()).get('webSocketUrl')) { + throw Error('WebDriver instance must support BiDi protocol') + } + + this.bidi = await this._driver.getBidi() + } + + async createUserContext() { + const command = { + method: 'browser.createUserContext', + params: {}, + } + + let response = await this.bidi.send(command) + + return response.result.userContext + } + + async getUserContexts() { + const command = { + method: 'browser.getUserContexts', + params: {}, + } + + let response = await this.bidi.send(command) + + let userContexts = [] + + let userContextsArray = response.result.userContexts + + for (let userContextJson of userContextsArray) { + userContexts.push(userContextJson.userContext) + } + + return userContexts + } + + async removeUserContext(userContext) { + const command = { + method: 'browser.removeUserContext', + params: { userContext: userContext }, + } + + await this.bidi.send(command) + } + +} + +async function getBrowserInstance(driver) { + let instance = new Browser(driver) + await instance.init() + return instance +} + +module.exports = getBrowserInstance diff --git a/javascript/node/selenium-webdriver/test/bidi/browser_test.js b/javascript/node/selenium-webdriver/test/bidi/browser_test.js new file mode 100644 index 0000000000000..aef5d11309a15 --- /dev/null +++ b/javascript/node/selenium-webdriver/test/bidi/browser_test.js @@ -0,0 +1,86 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +'use strict' + +const assert = require('assert') +const fileServer = require('../../lib/test/fileserver') +const firefox = require('../../firefox') +const {ignore, Pages, suite} = require('../../lib/test') +const {Browser, By, until} = require('../..') +const BrowserBiDi = require('../../bidi/browser') + +suite( + function (env) { + describe('BiDi Browser', function () { + let driver + + beforeEach(async function () { + driver = await env.builder().setFirefoxOptions(new firefox.Options().enableBidi()).build() + }) + + afterEach(function () { + return driver.quit() + }) + + xit('can create a user context', async function () { + const browser = await BrowserBiDi(driver) + + const userContext = await browser.createUserContext() + + assert.notEqual(userContext, null) + + await browser.removeUserContext(userContext) + }) + + xit('can get user contexts', async function () { + const browser = await BrowserBiDi(driver) + + const userContext1 = await browser.createUserContext() + const userContext2 = await browser.createUserContext() + + const userContexts = await browser.getUserContexts() + + assert.strictEqual(userContexts.length >= 2, true) + + await browser.removeUserContext(userContext1) + await browser.removeUserContext(userContext2) + }) + + xit('can remove user context', async function () { + const browser = await BrowserBiDi(driver) + + const userContext1 = await browser.createUserContext() + const userContext2 = await browser.createUserContext() + + const userContexts = await browser.getUserContexts() + + assert.strictEqual(userContexts.length >= 2, true) + + await browser.removeUserContext(userContext2) + + const updatedUserContexts = await browser.getUserContexts() + + assert.strictEqual(updatedUserContexts.includes(userContext1), true) + assert.strictEqual(updatedUserContexts.includes(userContext2), false) + + await browser.removeUserContext(userContext1) + }) + }) + }, + {browsers: [Browser.FIREFOX]}, +) From 1b40d184c6980531a45c45550d32a7b99e870caa Mon Sep 17 00:00:00 2001 From: Puja Jagani Date: Tue, 12 Mar 2024 10:49:35 +0530 Subject: [PATCH 6/6] Remove unused import --- javascript/node/selenium-webdriver/bidi/browser.js | 2 -- javascript/node/selenium-webdriver/test/bidi/browser_test.js | 1 - 2 files changed, 3 deletions(-) diff --git a/javascript/node/selenium-webdriver/bidi/browser.js b/javascript/node/selenium-webdriver/bidi/browser.js index 3ea5920b2b8e6..35a1b8adef4c2 100644 --- a/javascript/node/selenium-webdriver/bidi/browser.js +++ b/javascript/node/selenium-webdriver/bidi/browser.js @@ -15,8 +15,6 @@ // specific language governing permissions and limitations // under the License. -const {WebElement} = require('../lib/webdriver') - class Browser { constructor(driver) { this._driver = driver diff --git a/javascript/node/selenium-webdriver/test/bidi/browser_test.js b/javascript/node/selenium-webdriver/test/bidi/browser_test.js index aef5d11309a15..885433550d820 100644 --- a/javascript/node/selenium-webdriver/test/bidi/browser_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/browser_test.js @@ -18,7 +18,6 @@ 'use strict' const assert = require('assert') -const fileServer = require('../../lib/test/fileserver') const firefox = require('../../firefox') const {ignore, Pages, suite} = require('../../lib/test') const {Browser, By, until} = require('../..')