Skip to content

Commit 2b74370

Browse files
Merge branch 'trunk' into remote-session-settings-json
2 parents 5e06f1e + 62aa0e5 commit 2b74370

File tree

39 files changed

+727
-168
lines changed

39 files changed

+727
-168
lines changed

.github/workflows/bazel.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ on:
7070
jobs:
7171
bazel:
7272
name: ${{ inputs.name }}
73-
runs-on: ${{ inputs.os == 'macos' && 'macos-13' || format('{0}-latest', inputs.os) }}
73+
runs-on: ${{ format('{0}-latest', inputs.os) }}
7474
env:
7575
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7676
SEL_M2_USER: ${{ secrets.SEL_M2_USER }}

.github/workflows/ci-python.yml

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
docs:
1717
name: Documentation
1818
needs: build
19-
runs-on: ubuntu-20.04
19+
runs-on: ubuntu-latest
2020
steps:
2121
- name: Checkout source tree
2222
uses: actions/checkout@v4
@@ -36,7 +36,7 @@ jobs:
3636
lint:
3737
name: Lint
3838
needs: build
39-
runs-on: ubuntu-20.04
39+
runs-on: ubuntu-latest
4040
steps:
4141
- name: Checkout source tree
4242
uses: actions/checkout@v4
@@ -58,7 +58,7 @@ jobs:
5858
mypy:
5959
name: Mypy
6060
needs: build
61-
runs-on: ubuntu-20.04
61+
runs-on: ubuntu-latest
6262
steps:
6363
- name: Checkout source tree
6464
uses: actions/checkout@v4
@@ -81,19 +81,32 @@ jobs:
8181
name: Remote Tests
8282
needs: build
8383
uses: ./.github/workflows/bazel.yml
84+
strategy:
85+
fail-fast: false
86+
matrix:
87+
include:
88+
- browser: firefox
8489
with:
85-
name: Integration Tests (remote)
86-
browser: firefox
87-
cache-key: py-remote
90+
name: Integration Tests (remote, ${{ matrix.browser }})
91+
browser: ${{ matrix.browser }}
92+
cache-key: py-remote-${{ matrix.browser }}
8893
run: bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:test-remote
8994

90-
safari-tests:
91-
name: Safari Tests
95+
browser-tests:
96+
name: Browser Tests
9297
needs: build
9398
uses: ./.github/workflows/bazel.yml
99+
strategy:
100+
fail-fast: false
101+
matrix:
102+
include:
103+
- browser: safari
104+
os: macos
105+
- browser: chrome
106+
os: macos
94107
with:
95-
name: Integration Tests (safari)
96-
browser: safari
97-
os: macos
98-
cache-key: py-safari
99-
run: bazel test --local_test_jobs 1 --flaky_test_attempts 3 //py:test-safari
108+
name: Integration Tests (${{ matrix.browser }}, ${{ matrix.os }})
109+
browser: ${{ matrix.browser }}
110+
os: ${{ matrix.os }}
111+
cache-key: py-browser-${{ matrix.browser }}
112+
run: bazel test --flaky_test_attempts 3 //py:test-${{ matrix.browser }}

.github/workflows/label-commenter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ permissions:
1212
jobs:
1313
comment:
1414
if: github.repository_owner == 'seleniumhq'
15-
runs-on: ubuntu-20.04
15+
runs-on: ubuntu-latest
1616
steps:
1717
- uses: actions/checkout@v4
1818
- name: Label Commenter

common/src/web/formPage.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@
8080
<option value="oranges">Oranges</option>
8181
</select>
8282

83+
<select id="invisible_multi_select" multiple>
84+
<option selected="selected" value="apples" style="opacity: 0;">Apples</option>
85+
<option value="oranges">Oranges</option>
86+
<option selected="selected" value="lemons">Lemons</option>
87+
</select>
88+
8389
<select name="select-default">
8490
<option>One</option>
8591
<option>Two</option>

dotnet/src/webdriver/Command.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Collections.Generic;
2222
using System.Text.Json;
2323
using System.Text.Json.Serialization;
24+
using System.Text.Json.Serialization.Metadata;
2425

2526
namespace OpenQA.Selenium
2627
{
@@ -35,7 +36,7 @@ public class Command
3536

3637
private readonly static JsonSerializerOptions s_jsonSerializerOptions = new()
3738
{
38-
TypeInfoResolver = CommandJsonSerializerContext.Default,
39+
TypeInfoResolver = JsonTypeInfoResolver.Combine(CommandJsonSerializerContext.Default, new DefaultJsonTypeInfoResolver()),
3940
Converters = { new ResponseValueJsonConverter() }
4041
};
4142

dotnet/src/webdriver/SeleniumManager.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ public static class SeleniumManager
4040
{
4141
private static readonly ILogger _logger = Log.GetLogger(typeof(SeleniumManager));
4242

43-
private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNameCaseInsensitive = true, TypeInfoResolver = SeleniumManagerSerializerContext.Default };
44-
4543
private static readonly Lazy<string> _lazyBinaryFullPath = new(() =>
4644
{
4745
string? binaryFullPath = Environment.GetEnvironmentVariable("SE_MANAGER_PATH");
@@ -187,7 +185,7 @@ private static ResultResponse RunCommand(string fileName, string arguments)
187185

188186
try
189187
{
190-
jsonResponse = JsonSerializer.Deserialize<SeleniumManagerResponse>(output, _serializerOptions)!;
188+
jsonResponse = JsonSerializer.Deserialize(output, SeleniumManagerSerializerContext.Default.SeleniumManagerResponse)!;
191189
}
192190
catch (Exception ex)
193191
{
@@ -210,11 +208,11 @@ private static ResultResponse RunCommand(string fileName, string arguments)
210208
}
211209
}
212210

213-
internal record SeleniumManagerResponse(IReadOnlyList<LogEntryResponse> Logs, ResultResponse Result)
211+
internal sealed record SeleniumManagerResponse(IReadOnlyList<LogEntryResponse> Logs, ResultResponse Result)
214212
{
215-
public record LogEntryResponse(string Level, string Message);
213+
public sealed record LogEntryResponse(string Level, string Message);
216214

217-
public record ResultResponse
215+
public sealed record ResultResponse
218216
(
219217
[property: JsonPropertyName("driver_path")]
220218
string DriverPath,
@@ -224,5 +222,6 @@ string BrowserPath
224222
}
225223

226224
[JsonSerializable(typeof(SeleniumManagerResponse))]
227-
internal partial class SeleniumManagerSerializerContext : JsonSerializerContext;
225+
[JsonSourceGenerationOptions(PropertyNameCaseInsensitive = true)]
226+
internal sealed partial class SeleniumManagerSerializerContext : JsonSerializerContext;
228227
}

dotnet/test/common/CommandTests.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// <copyright file="CommandTests.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using NUnit.Framework;
21+
using System.Collections.Generic;
22+
23+
namespace OpenQA.Selenium
24+
{
25+
[TestFixture]
26+
public class CommandTests
27+
{
28+
[Test]
29+
public void CommandSerializesAnonymousType()
30+
{
31+
var parameters = new Dictionary<string, object>
32+
{
33+
["arg"] = new { param1 = true, param2 = false },
34+
};
35+
36+
var command = new Command(new SessionId("session"), "test command", parameters);
37+
38+
Assert.That(command.ParametersAsJsonString, Is.EqualTo("""{"arg":{"param1":true,"param2":false}}"""));
39+
}
40+
}
41+
}

java/src/org/openqa/selenium/manager/SeleniumManager.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,11 @@ private synchronized Path getBinary() {
194194
} else if (current.is(MAC)) {
195195
folder = "macos";
196196
} else if (current.is(LINUX)) {
197-
folder = "linux";
197+
if (System.getProperty("os.arch").contains("arm")) {
198+
throw new WebDriverException("Linux ARM is not supported by Selenium Manager");
199+
} else {
200+
folder = "linux";
201+
}
198202
} else if (current.is(UNIX)) {
199203
LOG.warning(
200204
String.format(

java/src/org/openqa/selenium/netty/server/NettyServer.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.netty.handler.ssl.SslContext;
2828
import io.netty.handler.ssl.SslContextBuilder;
2929
import io.netty.handler.ssl.util.SelfSignedCertificate;
30+
import io.netty.util.concurrent.Future;
3031
import io.netty.util.internal.logging.InternalLoggerFactory;
3132
import io.netty.util.internal.logging.JdkLoggerFactory;
3233
import java.io.IOException;
@@ -127,8 +128,11 @@ public URL getUrl() {
127128
@Override
128129
public void stop() {
129130
try {
130-
bossGroup.shutdownGracefully().sync();
131-
workerGroup.shutdownGracefully().sync();
131+
Future<?> bossShutdown = bossGroup.shutdownGracefully();
132+
Future<?> workerShutdown = workerGroup.shutdownGracefully();
133+
134+
bossShutdown.sync();
135+
workerShutdown.sync();
132136

133137
channel.closeFuture().sync();
134138
} catch (InterruptedException e) {

java/src/org/openqa/selenium/remote/http/HttpMessage.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@
2929
import java.util.HashMap;
3030
import java.util.List;
3131
import java.util.Map;
32-
import java.util.Objects;
3332
import java.util.Set;
3433
import java.util.function.BiConsumer;
3534
import java.util.function.Supplier;
36-
import java.util.stream.Collectors;
3735
import org.openqa.selenium.internal.Require;
3836

3937
abstract class HttpMessage<M extends HttpMessage<M>> {
@@ -92,11 +90,8 @@ public Iterable<String> getHeaderNames() {
9290
* @return an iterable view of the values
9391
*/
9492
public Iterable<String> getHeaders(String name) {
95-
return headers.entrySet().stream()
96-
.filter(e -> Objects.nonNull(e.getKey()))
97-
.filter(e -> e.getKey().equalsIgnoreCase(name.toLowerCase()))
98-
.flatMap((e) -> e.getValue().stream())
99-
.collect(Collectors.toList());
93+
return Collections.unmodifiableCollection(
94+
headers.getOrDefault(name.toLowerCase(), Collections.emptyList()));
10095
}
10196

10297
/**
@@ -106,12 +101,8 @@ public Iterable<String> getHeaders(String name) {
106101
* @return the value
107102
*/
108103
public String getHeader(String name) {
109-
return headers.entrySet().stream()
110-
.filter(e -> Objects.nonNull(e.getKey()))
111-
.filter(e -> e.getKey().equalsIgnoreCase(name.toLowerCase()))
112-
.flatMap((e) -> e.getValue().stream())
113-
.findFirst()
114-
.orElse(null);
104+
List<String> values = headers.getOrDefault(name.toLowerCase(), Collections.emptyList());
105+
return !values.isEmpty() ? values.get(0) : null;
115106
}
116107

117108
/**
@@ -123,7 +114,7 @@ public String getHeader(String name) {
123114
* @return self
124115
*/
125116
public M setHeader(String name, String value) {
126-
return removeHeader(name).addHeader(name, value);
117+
return removeHeader(name.toLowerCase()).addHeader(name.toLowerCase(), value);
127118
}
128119

129120
/**
@@ -135,7 +126,7 @@ public M setHeader(String name, String value) {
135126
* @return self
136127
*/
137128
public M addHeader(String name, String value) {
138-
headers.computeIfAbsent(name, (n) -> new ArrayList<>()).add(value);
129+
headers.computeIfAbsent(name.toLowerCase(), (n) -> new ArrayList<>()).add(value);
139130
return self();
140131
}
141132

@@ -146,7 +137,7 @@ public M addHeader(String name, String value) {
146137
* @return self
147138
*/
148139
public M removeHeader(String name) {
149-
headers.keySet().removeIf(header -> header.equalsIgnoreCase(name));
140+
headers.remove(name.toLowerCase());
150141
return self();
151142
}
152143

0 commit comments

Comments
 (0)