Skip to content

Commit 0dd4c1e

Browse files
authored
Merge branch 'trunk' into performance-improvements
2 parents 27ca016 + 8960ff0 commit 0dd4c1e

File tree

7 files changed

+188
-12
lines changed

7 files changed

+188
-12
lines changed

.github/workflows/ci-javascript.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ jobs:
3131
bazel test
3232
--flaky_test_attempts 3
3333
--test_tag_filters ${{ matrix.browser }}
34+
--local_test_jobs 1
3435
//javascript/node/...

common/repositories.bzl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ js_library(
199199

200200
http_archive(
201201
name = "linux_chrome",
202-
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.61/linux64/chrome-linux64.zip",
203-
sha256 = "14492d3cfe33cb11d4cc310321182ebf839d33687494c0bb528b05225b9b5f0c",
202+
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.62/linux64/chrome-linux64.zip",
203+
sha256 = "6f42045c9134bdd3cfcea03fb54876ad061da998cabd624c92a25ac6811cd737",
204204
build_file_content = """
205205
load("@aspect_rules_js//js:defs.bzl", "js_library")
206206
package(default_visibility = ["//visibility:public"])
@@ -221,8 +221,8 @@ js_library(
221221

222222
http_archive(
223223
name = "mac_chrome",
224-
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.61/mac-x64/chrome-mac-x64.zip",
225-
sha256 = "5b7753cc0102151c8e162c4ed66df8303e390d90ae193a290db1c406cf0fa644",
224+
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.62/mac-x64/chrome-mac-x64.zip",
225+
sha256 = "be21f6b9387c6e52c318b60379291959693889e27c3e64111e95135ecffa82ad",
226226
strip_prefix = "chrome-mac-x64",
227227
patch_cmds = [
228228
"mv 'Google Chrome for Testing.app' Chrome.app",
@@ -243,8 +243,8 @@ js_library(
243243

244244
http_archive(
245245
name = "linux_chromedriver",
246-
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.61/linux64/chromedriver-linux64.zip",
247-
sha256 = "eef5a27798bd6cecae18bdaff64773bf6c96d99a9634d6434127120eb89ac713",
246+
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.62/linux64/chromedriver-linux64.zip",
247+
sha256 = "a304e692480c726bae846bf6dee36316305d0b8f4826dfafeab8d6bbbc6e7214",
248248
strip_prefix = "chromedriver-linux64",
249249
build_file_content = """
250250
load("@aspect_rules_js//js:defs.bzl", "js_library")
@@ -261,8 +261,8 @@ js_library(
261261

262262
http_archive(
263263
name = "mac_chromedriver",
264-
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.61/mac-x64/chromedriver-mac-x64.zip",
265-
sha256 = "3af4643bf9815ce93722a66dbe32b33ac04f05a673abe60e6fffd2b17b6007d9",
264+
url = "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.62/mac-x64/chromedriver-mac-x64.zip",
265+
sha256 = "05665a6b5fb71141b5d519998e36f01b650f661942a56dd7f6b929896ae38333",
266266
strip_prefix = "chromedriver-mac-x64",
267267
build_file_content = """
268268
load("@aspect_rules_js//js:defs.bzl", "js_library")

java/src/org/openqa/selenium/grid/node/docker/DockerSessionFactory.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,16 @@ private Map<String, String> getVideoContainerEnvVars(
373373
// Capabilities set to env vars with higher precedence
374374
setCapsToEnvVars(sessionRequestCapabilities, envVars);
375375
envVars.put("DISPLAY_CONTAINER_NAME", containerIp);
376-
Optional<String> testName = ofNullable(getTestName(sessionRequestCapabilities));
377-
testName.ifPresent(name -> envVars.put("SE_VIDEO_FILE_NAME", String.format("%s.mp4", name)));
376+
Optional<String> videoName =
377+
ofNullable(getVideoFileName(sessionRequestCapabilities, "se:videoName"))
378+
.or(() -> ofNullable(getVideoFileName(sessionRequestCapabilities, "se:name")));
379+
videoName.ifPresent(name -> envVars.put("SE_VIDEO_FILE_NAME", String.format("%s.mp4", name)));
378380
return envVars;
379381
}
380382

381-
private String getTestName(Capabilities sessionRequestCapabilities) {
382-
Optional<Object> testName = ofNullable(sessionRequestCapabilities.getCapability("se:name"));
383+
private String getVideoFileName(Capabilities sessionRequestCapabilities, String capabilityName) {
384+
Optional<Object> testName =
385+
ofNullable(sessionRequestCapabilities.getCapability(capabilityName));
383386
if (testName.isPresent()) {
384387
String name = testName.get().toString();
385388
if (!name.isEmpty()) {

javascript/node/selenium-webdriver/bidi/logInspector.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,17 @@ class LogInspector {
6666
}
6767

6868
removeCallback(id) {
69+
let hasId = false
6970
for (const [, callbacks] of this.listener) {
7071
if (callbacks.has(id)) {
7172
callbacks.delete(id)
73+
hasId = true
7274
}
7375
}
76+
77+
if (!hasId) {
78+
throw Error(`Callback with id ${id} not found`)
79+
}
7480
}
7581

7682
invokeCallbacks(eventType, data) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
const logInspector = require('../bidi/logInspector')
19+
20+
class Script {
21+
#driver
22+
#logInspector
23+
24+
constructor(driver) {
25+
this.#driver = driver
26+
}
27+
28+
// This should be done in the constructor.
29+
// But since it needs to call async methods we cannot do that in the constructor.
30+
// We can have a separate async method that initialises the Script instance.
31+
// However, that pattern does not allow chaining the methods as we would like the user to use it.
32+
// Since it involves awaiting to get the instance and then another await to call the method.
33+
// Using this allows the user to do this "await driver.script().addJavaScriptErrorHandler(callback)"
34+
async #init() {
35+
if (this.#logInspector !== undefined) {
36+
return
37+
}
38+
this.#logInspector = await logInspector(this.#driver)
39+
}
40+
41+
async addJavaScriptErrorHandler(callback) {
42+
await this.#init()
43+
return await this.#logInspector.onJavascriptException(callback)
44+
}
45+
46+
async removeJavaScriptErrorHandler(id) {
47+
await this.#init()
48+
await this.#logInspector.removeCallback(id)
49+
}
50+
51+
async addConsoleMessageHandler(callback) {
52+
await this.#init()
53+
return this.#logInspector.onConsoleEntry(callback)
54+
}
55+
56+
async removeConsoleMessageHandler(id) {
57+
await this.#init()
58+
59+
await this.#logInspector.removeCallback(id)
60+
}
61+
}
62+
63+
module.exports = Script

javascript/node/selenium-webdriver/lib/webdriver.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const { isObject } = require('./util')
4343
const BIDI = require('../bidi')
4444
const { PinnedScript } = require('./pinnedScript')
4545
const JSZip = require('jszip')
46+
const Script = require('./script')
4647

4748
// Capability names that are defined in the W3C spec.
4849
const W3C_CAPABILITY_NAMES = new Set([
@@ -654,6 +655,7 @@ function filterNonW3CCaps(capabilities) {
654655
* @implements {IWebDriver}
655656
*/
656657
class WebDriver {
658+
#script = undefined
657659
/**
658660
* @param {!(./session.Session|IThenable<!./session.Session>)} session Either
659661
* a known session or a promise that will be resolved to a session.
@@ -1104,6 +1106,16 @@ class WebDriver {
11041106
return new TargetLocator(this)
11051107
}
11061108

1109+
script() {
1110+
// The Script calls the LogInspector which maintains state of the callbacks.
1111+
// Returning a new instance of the same driver will not work while removing callbacks.
1112+
if (this.#script === undefined) {
1113+
this.#script = new Script(this)
1114+
}
1115+
1116+
return this.#script
1117+
}
1118+
11071119
validatePrintPageParams(keys, object) {
11081120
let page = {}
11091121
let margin = {}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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('node:assert')
21+
const { Browser } = require('../../')
22+
const { Pages, suite } = require('../../lib/test')
23+
const { until } = require('../../index')
24+
25+
suite(
26+
function (env) {
27+
let driver
28+
29+
beforeEach(async function () {
30+
driver = await env.builder().build()
31+
})
32+
33+
afterEach(async function () {
34+
await driver.quit()
35+
})
36+
37+
function delay(ms) {
38+
return new Promise((resolve) => setTimeout(resolve, ms))
39+
}
40+
41+
describe('script()', function () {
42+
it('can listen to console log', async function () {
43+
let log = null
44+
const handler = await driver.script().addConsoleMessageHandler((logEntry) => {
45+
log = logEntry
46+
})
47+
48+
await driver.get(Pages.logEntryAdded)
49+
await driver.findElement({ id: 'consoleLog' }).click()
50+
51+
await delay(3000)
52+
53+
assert.equal(log.text, 'Hello, world!')
54+
assert.equal(log.realm, null)
55+
assert.equal(log.type, 'console')
56+
assert.equal(log.level, 'info')
57+
assert.equal(log.method, 'log')
58+
assert.equal(log.args.length, 1)
59+
await driver.script().removeConsoleMessageHandler(handler)
60+
})
61+
62+
it('can listen to javascript error', async function () {
63+
let log = null
64+
const handler = await driver.script().addJavaScriptErrorHandler((logEntry) => {
65+
log = logEntry
66+
})
67+
68+
await driver.get(Pages.logEntryAdded)
69+
await driver.findElement({ id: 'jsException' }).click()
70+
71+
await delay(3000)
72+
73+
assert.equal(log.text, 'Error: Not working')
74+
assert.equal(log.type, 'javascript')
75+
assert.equal(log.level, 'error')
76+
77+
await driver.script().removeJavaScriptErrorHandler(handler)
78+
})
79+
80+
it('throws an error while removing a handler that does not exist', async function () {
81+
try {
82+
await driver.script().removeJavaScriptErrorHandler(10)
83+
assert.fail('Expected error not thrown. Non-existent handler cannot be removed')
84+
} catch (e) {
85+
assert.strictEqual(e.message, 'Callback with id 10 not found')
86+
}
87+
})
88+
})
89+
},
90+
{ browsers: [Browser.FIREFOX, Browser.CHROME, Browser.EDGE] },
91+
)

0 commit comments

Comments
 (0)