Skip to content

Commit 66ba89a

Browse files
committed
Make SafariOptions extend MutableCapabilities
This means that the `MutableCapabilities` need some smarts to handle the common pattern of attempting to do something like: ``` DesiredCapabilities caps = new DesiredCapabilities(); caps.setCapability(SafariOptions.CAPABILITY, new SafariOptiosn()); ```
1 parent c2ece25 commit 66ba89a

File tree

5 files changed

+83
-61
lines changed

5 files changed

+83
-61
lines changed

java/client/src/org/openqa/selenium/MutableCapabilities.java

+18
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,23 @@
2121
import java.io.Serializable;
2222
import java.util.Collections;
2323
import java.util.HashMap;
24+
import java.util.HashSet;
2425
import java.util.Map;
26+
import java.util.Set;
2527

2628
public class MutableCapabilities implements Capabilities, Serializable {
2729

2830
private static final long serialVersionUID = -112816287184979465L;
31+
private static final Set<String> OPTION_KEYS;
32+
static {
33+
HashSet<String> keys = new HashSet<>();
34+
keys.add("safari.options");
35+
OPTION_KEYS = Collections.unmodifiableSet(keys);
36+
}
2937

3038
private final Map<String, Object> caps = new HashMap<>();
3139

40+
3241
public MutableCapabilities() {
3342
// no-arg constructor
3443
}
@@ -106,6 +115,15 @@ public void setCapability(String capabilityName, Platform value) {
106115
}
107116

108117
public void setCapability(String key, Object value) {
118+
// We have to special-case some keys and values because of the popular idiom of calling
119+
// something like "capabilities.setCapability(SafariOptions.CAPABILITY, new SafariOptions());
120+
// and this is no longer needed as options are capabilities. There will be a large amount of
121+
// legacy code that will always try and follow this pattern, however.
122+
if (OPTION_KEYS.contains(key) && value instanceof Capabilities) {
123+
merge((Capabilities) value);
124+
return;
125+
}
126+
109127
caps.put(key, value);
110128
}
111129

java/client/src/org/openqa/selenium/safari/SafariDriver.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public SafariDriver() {
4646
* @see SafariOptions#fromCapabilities(org.openqa.selenium.Capabilities)
4747
*
4848
* @param desiredCapabilities capabilities requested of the driver
49+
* @deprecated Use {@link SafariDriver(SafariOptions)} instead.
4950
*/
51+
@Deprecated
5052
public SafariDriver(Capabilities desiredCapabilities) {
5153
this(SafariOptions.fromCapabilities(desiredCapabilities));
5254
}
@@ -57,7 +59,7 @@ public SafariDriver(Capabilities desiredCapabilities) {
5759
* @param safariOptions safari specific options / capabilities for the driver
5860
*/
5961
public SafariDriver(SafariOptions safariOptions) {
60-
super(getExecutor(safariOptions), safariOptions.toCapabilities());
62+
super(getExecutor(safariOptions), safariOptions);
6163
}
6264

6365
private static CommandExecutor getExecutor(SafariOptions options) {

java/client/src/org/openqa/selenium/safari/SafariOptions.java

+25-60
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
import com.google.gson.JsonObject;
2222

2323
import org.openqa.selenium.Capabilities;
24+
import org.openqa.selenium.MutableCapabilities;
25+
import org.openqa.selenium.Platform;
2426
import org.openqa.selenium.WebDriverException;
27+
import org.openqa.selenium.remote.CapabilityType;
2528
import org.openqa.selenium.remote.DesiredCapabilities;
2629

2730
import java.io.IOException;
2831
import java.util.Map;
32+
import java.util.TreeMap;
2933

3034
/**
3135
* Class to manage options specific to {@link SafariDriver}.
@@ -39,13 +43,12 @@
3943
* SafariDriver driver = new SafariDriver(options);
4044
*
4145
* // For use with RemoteWebDriver:
42-
* DesiredCapabilities capabilities = DesiredCapabilities.safari();
43-
* capabilities.setCapability(SafariOptions.CAPABILITY, options);
4446
* RemoteWebDriver driver = new RemoteWebDriver(
45-
* new URL("http://localhost:4444/wd/hub"), capabilities);
47+
* new URL("http://localhost:4444/wd/hub"),
48+
* options);
4649
* </code></pre>
4750
*/
48-
public class SafariOptions {
51+
public class SafariOptions extends MutableCapabilities {
4952

5053
/**
5154
* Key used to store SafariOptions in a {@link DesiredCapabilities} object.
@@ -60,20 +63,16 @@ private Option() {} // Utility class.
6063
private static final String PORT = "port";
6164
}
6265

63-
/**
64-
* @see #setPort(int)
65-
*/
66-
private int port = 0;
66+
private Map<String, Object> options = new TreeMap<>();
6767

68-
/**
69-
* @see #setUseCleanSession(boolean)
70-
*/
71-
private boolean useCleanSession = false;
68+
public SafariOptions() {
69+
setCapability(Option.PORT, 0);
70+
setCapability(Option.CLEAN_SESSION, false);
71+
setCapability(Option.TECHNOLOGY_PREVIEW, false);
7272

73-
/**
74-
* @see #setUseTechnologyPreview(boolean)
75-
*/
76-
private boolean useTechnologyPreview = false;
73+
setCapability(CapabilityType.BROWSER_NAME, "safari");
74+
setCapability(CapabilityType.PLATFORM, Platform.MAC);
75+
}
7776

7877
/**
7978
* Construct a {@link SafariOptions} instance from given capabilites.
@@ -109,7 +108,7 @@ public static SafariOptions fromCapabilities(Capabilities capabilities)
109108
* or 0 if the server should select a free port.
110109
*/
111110
SafariOptions setPort(int port) {
112-
this.port = port;
111+
options.put(Option.PORT, port);
113112
return this;
114113
}
115114

@@ -124,7 +123,7 @@ SafariOptions setPort(int port) {
124123
* @param useCleanSession If true, the SafariDriver will erase all existing session data.
125124
*/
126125
public SafariOptions setUseCleanSession(boolean useCleanSession) {
127-
this.useCleanSession = useCleanSession;
126+
options.put(Option.CLEAN_SESSION, useCleanSession);
128127
return this;
129128
}
130129

@@ -136,7 +135,7 @@ public SafariOptions setUseCleanSession(boolean useCleanSession) {
136135
* otherwise will use the release version of Safari.
137136
*/
138137
public SafariOptions setUseTechnologyPreview(boolean useTechnologyPreview) {
139-
this.useTechnologyPreview = useTechnologyPreview;
138+
options.put(Option.TECHNOLOGY_PREVIEW, useTechnologyPreview);
140139
return this;
141140
}
142141

@@ -148,45 +147,27 @@ public SafariOptions setUseTechnologyPreview(boolean useTechnologyPreview) {
148147
* @see #setPort(int)
149148
*/
150149
public int getPort() {
151-
return port;
150+
return (int) options.getOrDefault(Option.PORT, 0);
152151
}
153152

154153
/**
155154
* @return Whether the SafariDriver should erase all session data before launching Safari.
156155
* @see #setUseCleanSession(boolean)
157156
*/
158157
public boolean getUseCleanSession() {
159-
return useCleanSession;
158+
return (boolean) options.getOrDefault(Option.CLEAN_SESSION, false);
160159
}
161160

162161
public boolean getUseTechnologyPreview() {
163-
return useTechnologyPreview;
162+
return (boolean) options.getOrDefault(Option.TECHNOLOGY_PREVIEW, false);
164163
}
165164

166165
// (De)serialization of the options
167166

168-
/**
169-
* Converts this instance to its JSON representation.
170-
*
171-
* @return The JSON representation of the options.
172-
* @throws IOException If an error occurred while reading the Safari extension files.
173-
*/
174-
public JsonObject toJson() throws IOException {
175-
JsonObject options = new JsonObject();
176-
options.addProperty(Option.PORT, port);
177-
options.addProperty(Option.CLEAN_SESSION, useCleanSession);
178-
options.addProperty(Option.TECHNOLOGY_PREVIEW, useTechnologyPreview);
179-
return options;
180-
}
181-
182167
/**
183168
* Parse a Map and reconstruct the {@link SafariOptions}.
184-
* A temporary directory is created to hold all Safari extension files.
185169
*
186-
* @param options A Map derived from the output of {@link #toJson()}.
187170
* @return A {@link SafariOptions} instance associated with these extensions.
188-
* @throws IOException If an error occurred while writing the safari extensions to a
189-
* temporary directory.
190171
*/
191172
private static SafariOptions fromJsonMap(Map<?, ?> options) throws IOException {
192173
SafariOptions safariOptions = new SafariOptions();
@@ -215,26 +196,10 @@ private static SafariOptions fromJsonMap(Map<?, ?> options) throws IOException {
215196
* reflected in the returned capabilities.
216197
*
217198
* @return DesiredCapabilities for Safari with these extensions.
199+
* @deprecated {@code SafariOptions} are already {@link MutableCapabilities}.
218200
*/
219-
DesiredCapabilities toCapabilities() {
220-
DesiredCapabilities capabilities = DesiredCapabilities.safari();
221-
capabilities.setCapability(CAPABILITY, this);
222-
return capabilities;
223-
}
224-
225-
@Override
226-
public boolean equals(Object other) {
227-
if (!(other instanceof SafariOptions)) {
228-
return false;
229-
}
230-
SafariOptions that = (SafariOptions) other;
231-
return this.port == that.port
232-
&& this.useCleanSession == that.useCleanSession
233-
&& this.useTechnologyPreview == that.useTechnologyPreview;
234-
}
235-
236-
@Override
237-
public int hashCode() {
238-
return Objects.hashCode(this.port, this.useCleanSession, this.useTechnologyPreview);
201+
@Deprecated
202+
MutableCapabilities toCapabilities() {
203+
return this;
239204
}
240205
}

java/client/test/org/openqa/selenium/safari/SafariDriverTests.java

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
AlertsTest.class,
3333
CleanSessionTest.class,
3434
CrossDomainTest.class,
35+
SafariOptionsTest.class,
3536
TechnologyPreviewTest.class,
3637
})
3738
public class SafariDriverTests {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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.safari;
19+
20+
import static org.junit.Assert.assertEquals;
21+
22+
import org.junit.Test;
23+
import org.openqa.selenium.remote.DesiredCapabilities;
24+
25+
public class SafariOptionsTest {
26+
27+
@Test
28+
public void commonUsagePatternWorks() {
29+
SafariOptions options = new SafariOptions().setPort(99);
30+
DesiredCapabilities caps = new DesiredCapabilities();
31+
caps.setCapability(SafariOptions.CAPABILITY, options);
32+
33+
assertEquals(options.asMap(), caps.asMap());
34+
}
35+
36+
}

0 commit comments

Comments
 (0)