Skip to content

Commit 77521cc

Browse files
authored
[bidi] [java] [js] Add browser module (#13677)
1 parent ad17dd2 commit 77521cc

File tree

5 files changed

+364
-0
lines changed

5 files changed

+364
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.bidi;
19+
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.function.Function;
24+
import org.openqa.selenium.WebDriver;
25+
import org.openqa.selenium.json.JsonInput;
26+
27+
public class Browser {
28+
private final BiDi bidi;
29+
30+
private final Function<JsonInput, String> userContextInfoMapper =
31+
jsonInput -> {
32+
Map<String, Object> response = jsonInput.read(Map.class);
33+
return (String) response.get("userContext");
34+
};
35+
36+
private final Function<JsonInput, List<String>> userContextsInfoMapper =
37+
jsonInput -> {
38+
Map<String, Object> response = jsonInput.read(Map.class);
39+
List<Map<String, String>> userContextsResponse =
40+
(List<Map<String, String>>) response.get("userContexts");
41+
42+
List<String> userContexts = new ArrayList<>();
43+
userContextsResponse.forEach(
44+
map -> {
45+
String userContext = map.get("userContext");
46+
userContexts.add(userContext);
47+
});
48+
49+
return userContexts;
50+
};
51+
52+
public Browser(WebDriver driver) {
53+
this.bidi = ((HasBiDi) driver).getBiDi();
54+
}
55+
56+
public String createUserContext() {
57+
return bidi.send(new Command<>("browser.createUserContext", Map.of(), userContextInfoMapper));
58+
}
59+
60+
public List<String> getUserContexts() {
61+
return bidi.send(new Command<>("browser.getUserContexts", Map.of(), userContextsInfoMapper));
62+
}
63+
64+
public void removeUserContext(String userContext) {
65+
bidi.send(new Command<>("browser.removeUserContext", Map.of("userContext", userContext)));
66+
}
67+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
load("@rules_jvm_external//:defs.bzl", "artifact")
2+
load("//java:defs.bzl", "JUNIT5_DEPS", "java_selenium_test_suite")
3+
4+
java_selenium_test_suite(
5+
name = "large-tests",
6+
size = "large",
7+
srcs = glob(["*Test.java"]),
8+
browsers = [
9+
"firefox",
10+
],
11+
tags = [
12+
"selenium-remote",
13+
],
14+
deps = [
15+
"//java/src/org/openqa/selenium/bidi",
16+
"//java/src/org/openqa/selenium/firefox",
17+
"//java/src/org/openqa/selenium/json",
18+
"//java/src/org/openqa/selenium/remote",
19+
"//java/src/org/openqa/selenium/support",
20+
"//java/test/org/openqa/selenium/environment",
21+
"//java/test/org/openqa/selenium/testing:annotations",
22+
"//java/test/org/openqa/selenium/testing:test-base",
23+
"//java/test/org/openqa/selenium/testing/drivers",
24+
artifact("com.google.guava:guava"),
25+
artifact("org.junit.jupiter:junit-jupiter-api"),
26+
artifact("org.assertj:assertj-core"),
27+
] + JUNIT5_DEPS,
28+
)
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.bidi.browser;
19+
20+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
21+
import static org.openqa.selenium.testing.Safely.safelyCall;
22+
import static org.openqa.selenium.testing.drivers.Browser.EDGE;
23+
import static org.openqa.selenium.testing.drivers.Browser.FIREFOX;
24+
import static org.openqa.selenium.testing.drivers.Browser.IE;
25+
import static org.openqa.selenium.testing.drivers.Browser.SAFARI;
26+
27+
import java.util.List;
28+
import org.junit.jupiter.api.AfterEach;
29+
import org.junit.jupiter.api.BeforeEach;
30+
import org.junit.jupiter.api.Test;
31+
import org.openqa.selenium.bidi.Browser;
32+
import org.openqa.selenium.environment.webserver.AppServer;
33+
import org.openqa.selenium.environment.webserver.NettyAppServer;
34+
import org.openqa.selenium.testing.JupiterTestBase;
35+
import org.openqa.selenium.testing.NotYetImplemented;
36+
37+
class BrowserCommandsTest extends JupiterTestBase {
38+
39+
private AppServer server;
40+
private Browser browser;
41+
42+
@BeforeEach
43+
public void setUp() {
44+
server = new NettyAppServer();
45+
server.start();
46+
browser = new Browser(driver);
47+
}
48+
49+
@Test
50+
@NotYetImplemented(SAFARI)
51+
@NotYetImplemented(IE)
52+
@NotYetImplemented(EDGE)
53+
@NotYetImplemented(FIREFOX)
54+
void canCreateAUserContext() {
55+
String userContext = browser.createUserContext();
56+
57+
assertThat(userContext).isNotNull();
58+
59+
browser.removeUserContext(userContext);
60+
}
61+
62+
@Test
63+
@NotYetImplemented(SAFARI)
64+
@NotYetImplemented(IE)
65+
@NotYetImplemented(EDGE)
66+
@NotYetImplemented(FIREFOX)
67+
void canGetUserContexts() {
68+
String userContext1 = browser.createUserContext();
69+
String userContext2 = browser.createUserContext();
70+
71+
List<String> userContexts = browser.getUserContexts();
72+
assertThat(userContexts.size()).isGreaterThanOrEqualTo(2);
73+
74+
browser.removeUserContext(userContext1);
75+
browser.removeUserContext(userContext2);
76+
}
77+
78+
@Test
79+
@NotYetImplemented(SAFARI)
80+
@NotYetImplemented(IE)
81+
@NotYetImplemented(EDGE)
82+
@NotYetImplemented(FIREFOX)
83+
void canRemoveUserContext() {
84+
String userContext1 = browser.createUserContext();
85+
String userContext2 = browser.createUserContext();
86+
87+
List<String> userContexts = browser.getUserContexts();
88+
assertThat(userContexts.size()).isGreaterThanOrEqualTo(2);
89+
90+
browser.removeUserContext(userContext2);
91+
92+
List<String> updatedUserContexts = browser.getUserContexts();
93+
assertThat(userContext1).isIn(updatedUserContexts);
94+
assertThat(userContext2).isNotIn(updatedUserContexts);
95+
96+
browser.removeUserContext(userContext1);
97+
}
98+
99+
@AfterEach
100+
public void quitDriver() {
101+
if (driver != null) {
102+
driver.quit();
103+
}
104+
safelyCall(server::stop);
105+
}
106+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
class Browser {
19+
constructor(driver) {
20+
this._driver = driver
21+
}
22+
23+
async init() {
24+
if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
25+
throw Error('WebDriver instance must support BiDi protocol')
26+
}
27+
28+
this.bidi = await this._driver.getBidi()
29+
}
30+
31+
async createUserContext() {
32+
const command = {
33+
method: 'browser.createUserContext',
34+
params: {},
35+
}
36+
37+
let response = await this.bidi.send(command)
38+
39+
return response.result.userContext
40+
}
41+
42+
async getUserContexts() {
43+
const command = {
44+
method: 'browser.getUserContexts',
45+
params: {},
46+
}
47+
48+
let response = await this.bidi.send(command)
49+
50+
let userContexts = []
51+
52+
let userContextsArray = response.result.userContexts
53+
54+
for (let userContextJson of userContextsArray) {
55+
userContexts.push(userContextJson.userContext)
56+
}
57+
58+
return userContexts
59+
}
60+
61+
async removeUserContext(userContext) {
62+
const command = {
63+
method: 'browser.removeUserContext',
64+
params: { userContext: userContext },
65+
}
66+
67+
await this.bidi.send(command)
68+
}
69+
70+
}
71+
72+
async function getBrowserInstance(driver) {
73+
let instance = new Browser(driver)
74+
await instance.init()
75+
return instance
76+
}
77+
78+
module.exports = getBrowserInstance
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
'use strict'
19+
20+
const assert = require('assert')
21+
const firefox = require('../../firefox')
22+
const {ignore, Pages, suite} = require('../../lib/test')
23+
const {Browser, By, until} = require('../..')
24+
const BrowserBiDi = require('../../bidi/browser')
25+
26+
suite(
27+
function (env) {
28+
describe('BiDi Browser', function () {
29+
let driver
30+
31+
beforeEach(async function () {
32+
driver = await env.builder().setFirefoxOptions(new firefox.Options().enableBidi()).build()
33+
})
34+
35+
afterEach(function () {
36+
return driver.quit()
37+
})
38+
39+
xit('can create a user context', async function () {
40+
const browser = await BrowserBiDi(driver)
41+
42+
const userContext = await browser.createUserContext()
43+
44+
assert.notEqual(userContext, null)
45+
46+
await browser.removeUserContext(userContext)
47+
})
48+
49+
xit('can get user contexts', async function () {
50+
const browser = await BrowserBiDi(driver)
51+
52+
const userContext1 = await browser.createUserContext()
53+
const userContext2 = await browser.createUserContext()
54+
55+
const userContexts = await browser.getUserContexts()
56+
57+
assert.strictEqual(userContexts.length >= 2, true)
58+
59+
await browser.removeUserContext(userContext1)
60+
await browser.removeUserContext(userContext2)
61+
})
62+
63+
xit('can remove user context', async function () {
64+
const browser = await BrowserBiDi(driver)
65+
66+
const userContext1 = await browser.createUserContext()
67+
const userContext2 = await browser.createUserContext()
68+
69+
const userContexts = await browser.getUserContexts()
70+
71+
assert.strictEqual(userContexts.length >= 2, true)
72+
73+
await browser.removeUserContext(userContext2)
74+
75+
const updatedUserContexts = await browser.getUserContexts()
76+
77+
assert.strictEqual(updatedUserContexts.includes(userContext1), true)
78+
assert.strictEqual(updatedUserContexts.includes(userContext2), false)
79+
80+
await browser.removeUserContext(userContext1)
81+
})
82+
})
83+
},
84+
{browsers: [Browser.FIREFOX]},
85+
)

0 commit comments

Comments
 (0)