Skip to content

Commit 03173c2

Browse files
committed
[java][BiDi] implement emulation.setTimezoneOverride
1 parent 7df7a1c commit 03173c2

File tree

8 files changed

+249
-32
lines changed

8 files changed

+249
-32
lines changed

java/src/org/openqa/selenium/bidi/Command.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public Command(
4848
Function<JsonInput, X> mapper,
4949
boolean sendsResponse) {
5050
this.method = Require.nonNull("Method name", method);
51-
this.params = Map.copyOf(Require.nonNull("Command parameters", params));
51+
this.params = Require.nonNull("Command parameters", params);
5252
this.mapper = Require.nonNull("Mapper for result", mapper);
5353
this.sendsResponse = sendsResponse;
5454
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.emulation;
19+
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
public abstract class AbstractOverrideParameters implements OverrideParameters {
25+
protected final Map<String, Object> map = new HashMap<>();
26+
27+
@Override
28+
public OverrideParameters contexts(List<String> contexts) {
29+
if (contexts == null || contexts.isEmpty()) {
30+
throw new IllegalArgumentException("Contexts cannot be null or empty");
31+
}
32+
if (map.containsKey("userContexts")) {
33+
throw new IllegalArgumentException("Cannot specify both contexts and userContexts");
34+
}
35+
map.put("contexts", contexts);
36+
return this;
37+
}
38+
39+
@Override
40+
public OverrideParameters userContexts(List<String> userContexts) {
41+
if (userContexts == null || userContexts.isEmpty()) {
42+
throw new IllegalArgumentException("User contexts cannot be null or empty");
43+
}
44+
if (map.containsKey("contexts")) {
45+
throw new IllegalArgumentException("Cannot specify both contexts and userContexts");
46+
}
47+
map.put("userContexts", userContexts);
48+
return this;
49+
}
50+
51+
@Override
52+
public Map<String, Object> toMap() {
53+
// Validate that either contexts or userContexts is set
54+
if (!map.containsKey("contexts") && !map.containsKey("userContexts")) {
55+
throw new IllegalStateException("Must specify either contexts or userContexts");
56+
}
57+
return map;
58+
}
59+
}

java/src/org/openqa/selenium/bidi/emulation/Emulation.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,10 @@ public Map<String, Object> setGeolocationOverride(SetGeolocationOverrideParamete
4343
return bidi.send(
4444
new Command<>("emulation.setGeolocationOverride", parameters.toMap(), Map.class));
4545
}
46+
47+
public Map<String, Object> setTimezoneOverride(SetTimezoneOverrideParameters parameters) {
48+
Require.nonNull("SetTimezoneOverride parameters", parameters);
49+
50+
return bidi.send(new Command<>("emulation.setTimezoneOverride", parameters.toMap(), Map.class));
51+
}
4652
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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.emulation;
19+
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
public interface OverrideParameters {
24+
OverrideParameters contexts(List<String> contexts);
25+
26+
OverrideParameters userContexts(List<String> userContexts);
27+
28+
Map<String, Object> toMap();
29+
}

java/src/org/openqa/selenium/bidi/emulation/SetGeolocationOverrideParameters.java

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@
1717

1818
package org.openqa.selenium.bidi.emulation;
1919

20-
import java.util.HashMap;
21-
import java.util.List;
22-
import java.util.Map;
23-
24-
public class SetGeolocationOverrideParameters {
25-
private final Map<String, Object> map = new HashMap<>();
20+
public class SetGeolocationOverrideParameters extends AbstractOverrideParameters {
2621

2722
// Constructor for coordinates - must specify either contexts or userContexts later
2823
public SetGeolocationOverrideParameters(GeolocationCoordinates coordinates) {
@@ -40,33 +35,15 @@ public SetGeolocationOverrideParameters(GeolocationPositionError error) {
4035
map.put("error", error.toMap());
4136
}
4237

43-
public SetGeolocationOverrideParameters contexts(List<String> contexts) {
44-
if (contexts == null || contexts.isEmpty()) {
45-
throw new IllegalArgumentException("Contexts cannot be null or empty");
46-
}
47-
if (map.containsKey("userContexts")) {
48-
throw new IllegalArgumentException("Cannot specify both contexts and userContexts");
49-
}
50-
map.put("contexts", contexts);
38+
@Override
39+
public SetGeolocationOverrideParameters contexts(java.util.List<String> contexts) {
40+
super.contexts(contexts);
5141
return this;
5242
}
5343

54-
public SetGeolocationOverrideParameters userContexts(List<String> userContexts) {
55-
if (userContexts == null || userContexts.isEmpty()) {
56-
throw new IllegalArgumentException("User contexts cannot be null or empty");
57-
}
58-
if (map.containsKey("contexts")) {
59-
throw new IllegalArgumentException("Cannot specify both contexts and userContexts");
60-
}
61-
map.put("userContexts", userContexts);
44+
@Override
45+
public SetGeolocationOverrideParameters userContexts(java.util.List<String> userContexts) {
46+
super.userContexts(userContexts);
6247
return this;
6348
}
64-
65-
public Map<String, Object> toMap() {
66-
// Validate that either contexts or userContexts is set
67-
if (!map.containsKey("contexts") && !map.containsKey("userContexts")) {
68-
throw new IllegalStateException("Must specify either contexts or userContexts");
69-
}
70-
return Map.copyOf(map);
71-
}
7249
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.openqa.selenium.bidi.emulation;
2+
3+
public class SetTimezoneOverrideParameters extends AbstractOverrideParameters {
4+
5+
public SetTimezoneOverrideParameters(String timezone) {
6+
map.put("timezone", timezone);
7+
}
8+
9+
@Override
10+
public SetTimezoneOverrideParameters contexts(java.util.List<String> contexts) {
11+
super.contexts(contexts);
12+
return this;
13+
}
14+
15+
@Override
16+
public SetTimezoneOverrideParameters userContexts(java.util.List<String> userContexts) {
17+
super.userContexts(userContexts);
18+
return this;
19+
}
20+
}

java/test/org/openqa/selenium/bidi/emulation/EmulationTest.java renamed to java/test/org/openqa/selenium/bidi/emulation/SetGeolocationOverrideTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import org.openqa.selenium.testing.NeedsSecureServer;
3939

4040
@NeedsSecureServer
41-
class EmulationTest extends JupiterTestBase {
41+
class SetGeolocationOverrideTest extends JupiterTestBase {
4242
Object getBrowserGeolocation(WebDriver driver, String userContext, String origin) {
4343
JavascriptExecutor executor = (JavascriptExecutor) driver;
4444
Permission permission = new Permission(driver);
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package org.openqa.selenium.bidi.emulation;
2+
3+
import static org.openqa.selenium.testing.drivers.Browser.FIREFOX;
4+
5+
import java.util.List;
6+
import org.junit.jupiter.api.Test;
7+
import org.openqa.selenium.JavascriptExecutor;
8+
import org.openqa.selenium.WebDriver;
9+
import org.openqa.selenium.WindowType;
10+
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
11+
import org.openqa.selenium.bidi.browsingcontext.CreateContextParameters;
12+
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
13+
import org.openqa.selenium.bidi.module.Browser;
14+
import org.openqa.selenium.testing.Ignore;
15+
import org.openqa.selenium.testing.JupiterTestBase;
16+
import org.openqa.selenium.testing.NeedsFreshDriver;
17+
import org.openqa.selenium.testing.NeedsSecureServer;
18+
19+
@NeedsSecureServer
20+
public class SetTimezoneOverrideTest extends JupiterTestBase {
21+
String getTimezoneString(WebDriver driver, String context) {
22+
JavascriptExecutor executor = (JavascriptExecutor) driver;
23+
24+
driver.switchTo().window(context);
25+
return (String)
26+
executor.executeScript("return Intl.DateTimeFormat().resolvedOptions().timeZone;");
27+
}
28+
29+
Number getTimezoneOffset(WebDriver driver, String context) {
30+
JavascriptExecutor executor = (JavascriptExecutor) driver;
31+
32+
driver.switchTo().window(context);
33+
return (Number) executor.executeScript("return new Date().getTimezoneOffset()");
34+
}
35+
36+
@Test
37+
@NeedsFreshDriver
38+
void canSetTimezoneOverrideInContext() {
39+
BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
40+
String contextId = context.getId();
41+
42+
String url = appServer.whereIsSecure("blank.html");
43+
context.navigate(url, ReadinessState.COMPLETE);
44+
45+
Emulation emul = new Emulation(driver);
46+
String timezone = "America/Los_Angeles";
47+
String tzOrg = getTimezoneString(driver, contextId);
48+
emul.setTimezoneOverride(
49+
new SetTimezoneOverrideParameters(timezone).contexts(List.of(contextId)));
50+
51+
String tzString = getTimezoneString(driver, contextId);
52+
Number tzOffset = getTimezoneOffset(driver, contextId);
53+
54+
assert tzString.equals(timezone)
55+
: "Timezone string mismatch: expected " + timezone + ", got " + tzString;
56+
assert tzOffset.intValue() == 420 : "Timezone offset mismatch: expected 420, got " + tzOffset;
57+
58+
emul.setTimezoneOverride(new SetTimezoneOverrideParameters(null).contexts(List.of(contextId)));
59+
String TzNew = getTimezoneString(driver, contextId);
60+
assert TzNew.equals(tzOrg) : "Timezone reset failed: expected " + tzOrg + ", got " + TzNew;
61+
}
62+
63+
@Test
64+
@NeedsFreshDriver
65+
void canSetTimeZoneOverrideInUserContext() {
66+
Browser browser = new Browser(driver);
67+
String userContext = browser.createUserContext();
68+
69+
BrowsingContext context =
70+
new BrowsingContext(
71+
driver, new CreateContextParameters(WindowType.TAB).userContext(userContext));
72+
String contextId = context.getId();
73+
74+
String url = appServer.whereIsSecure("blank.html");
75+
context.navigate(url, ReadinessState.COMPLETE);
76+
77+
Emulation emul = new Emulation(driver);
78+
String timezone = "Europe/London";
79+
String tzOrg = getTimezoneString(driver, contextId);
80+
emul.setTimezoneOverride(
81+
new SetTimezoneOverrideParameters(timezone).userContexts(List.of(userContext)));
82+
83+
String tzString = getTimezoneString(driver, contextId);
84+
Number tzOffset = getTimezoneOffset(driver, contextId);
85+
86+
assert tzString.equals(timezone)
87+
: "Timezone string mismatch: expected " + timezone + ", got " + tzString;
88+
assert tzOffset.intValue() == 0 : "Timezone offset mismatch: expected 0, got " + tzOffset;
89+
90+
emul.setTimezoneOverride(
91+
new SetTimezoneOverrideParameters(null).userContexts(List.of(userContext)));
92+
String TzNew = getTimezoneString(driver, contextId);
93+
assert TzNew.equals(tzOrg) : "Timezone reset failed: expected " + tzOrg + ", got " + TzNew;
94+
95+
context.close();
96+
browser.removeUserContext(userContext);
97+
}
98+
99+
@Test
100+
@NeedsFreshDriver
101+
@Ignore(FIREFOX)
102+
void canSetTimezoneOverrideUsingOffset() {
103+
BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
104+
String contextId = context.getId();
105+
106+
String url = appServer.whereIsSecure("blank.html");
107+
context.navigate(url, ReadinessState.COMPLETE);
108+
109+
Emulation emul = new Emulation(driver);
110+
String timezone = "+05:30";
111+
String tzOrg = getTimezoneString(driver, contextId);
112+
113+
emul.setTimezoneOverride(
114+
new SetTimezoneOverrideParameters(timezone).contexts(List.of(contextId)));
115+
116+
String tzString = getTimezoneString(driver, contextId);
117+
Number tzOffset = getTimezoneOffset(driver, contextId);
118+
119+
assert tzOffset.intValue() == -330 : "Expected timezone offset -330, got " + tzOffset;
120+
assert tzString.equals("+05:30") : "Expected timezone '+05:30', got " + tzString;
121+
122+
emul.setTimezoneOverride(new SetTimezoneOverrideParameters(null).contexts(List.of(contextId)));
123+
String tzNew = getTimezoneString(driver, contextId);
124+
assert tzNew.equals(tzOrg) : "Timezone reset failed: expected " + tzOrg + ", got " + tzNew;
125+
}
126+
}

0 commit comments

Comments
 (0)