Skip to content

Commit 5d9746e

Browse files
committed
[java] better support users creating sauce sessions from existing Selenium Options
1 parent 748ab19 commit 5d9746e

File tree

4 files changed

+158
-19
lines changed

4 files changed

+158
-19
lines changed

java/main/src/main/java/com/saucelabs/saucebindings/SauceSession.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.openqa.selenium.edge.EdgeOptions;
1515
import org.openqa.selenium.firefox.FirefoxOptions;
1616
import org.openqa.selenium.ie.InternetExplorerOptions;
17+
import org.openqa.selenium.remote.DesiredCapabilities;
1718
import org.openqa.selenium.remote.RemoteWebDriver;
1819
import org.openqa.selenium.safari.SafariOptions;
1920

@@ -29,7 +30,10 @@ public class SauceSession {
2930
@Getter private String result;
3031

3132
private static SauceOptions castMutableCapabilities(MutableCapabilities capabilities) {
32-
if (ChromeOptions.class.equals(capabilities.getClass())) {
33+
if (DesiredCapabilities.class.equals(capabilities.getClass())) {
34+
String msg = "DesiredCapabilities class does not create valid w3c compliant capabilities and are deprecated; Please update";
35+
throw new InvalidSauceOptionsArgumentException(msg);
36+
} else if (ChromeOptions.class.equals(capabilities.getClass())) {
3337
return SauceOptions.chrome((ChromeOptions) capabilities).build();
3438
} else if (EdgeOptions.class.equals(capabilities.getClass())) {
3539
return SauceOptions.edge((EdgeOptions) capabilities).build();
@@ -39,8 +43,11 @@ private static SauceOptions castMutableCapabilities(MutableCapabilities capabili
3943
return SauceOptions.safari((SafariOptions) capabilities).build();
4044
} else if (InternetExplorerOptions.class.equals(capabilities.getClass())) {
4145
return SauceOptions.ie((InternetExplorerOptions) capabilities).build();
46+
} else if (MutableCapabilities.class.equals(capabilities.getClass())) {
47+
return new SauceOptions(capabilities.asMap());
48+
} else {
49+
throw new InvalidSauceOptionsArgumentException("Browser Options class not recognized: " + capabilities.getClass());
4250
}
43-
throw new InvalidSauceOptionsArgumentException("invalid browser option class: " + capabilities.getClass());
4451
}
4552

4653
public SauceSession() {
@@ -134,7 +141,7 @@ public Results getAccessibilityResults(boolean frames) {
134141
* @return an object with the accessibility analysis
135142
*/
136143
public Results getAccessibilityResults(AxeBuilder builder) {
137-
validateSessionStarted("getAccessibilityResults()");
144+
validateSessionStarted("getAccessibilityResults");
138145
return builder.analyze(driver);
139146
}
140147

@@ -160,7 +167,7 @@ public void stop(Boolean passed) {
160167
* Providing Context for Selenium Commands</a>
161168
*/
162169
public void annotate(String comment) {
163-
validateSessionStarted("annotate()");
170+
validateSessionStarted("annotate");
164171
driver.executeScript("sauce:context=" + comment);
165172
}
166173

@@ -172,7 +179,7 @@ public void annotate(String comment) {
172179
* Test Annotation Methods</a>
173180
*/
174181
public void pause() {
175-
validateSessionStarted("pause()");
182+
validateSessionStarted("pause");
176183
String sauceTestLink = String.format("https://app.saucelabs.com/tests/%s",
177184
this.driver.getSessionId());
178185
driver.executeScript("sauce: break");
@@ -191,7 +198,7 @@ public void pause() {
191198
* Test Annotation Methods</a>
192199
*/
193200
public void disableLogging() {
194-
validateSessionStarted("disableLogging()");
201+
validateSessionStarted("disableLogging");
195202
driver.executeScript("sauce: disable log");
196203
}
197204

@@ -203,7 +210,7 @@ public void disableLogging() {
203210
* Test Annotation Methods</a>
204211
*/
205212
public void enableLogging() {
206-
validateSessionStarted("enableLogging()");
213+
validateSessionStarted("enableLogging");
207214
driver.executeScript("sauce: enable log");
208215
}
209216

@@ -215,7 +222,7 @@ public void enableLogging() {
215222
* Test Annotation Methods</a>
216223
*/
217224
public void stopNetwork() {
218-
validateSessionStarted("stopNetwork()");
225+
validateSessionStarted("stopNetwork");
219226
validateMac("Can only stop network for a Mac Platform;");
220227

221228
driver.executeScript("sauce: stop network");
@@ -229,7 +236,7 @@ public void stopNetwork() {
229236
* Test Annotation Methods</a>
230237
*/
231238
public void startNetwork() {
232-
validateSessionStarted("startNetwork()");
239+
validateSessionStarted("startNetwork");
233240
validateMac("Can only start network for a Mac Platform;");
234241

235242
driver.executeScript("sauce: start network");
@@ -245,7 +252,7 @@ public void startNetwork() {
245252
* @see BaseConfigurations#setName(String)
246253
*/
247254
public void changeTestName(String name) {
248-
validateSessionStarted("changeName()");
255+
validateSessionStarted("changeName");
249256
driver.executeScript("sauce:job-name=" + name);
250257
}
251258

@@ -259,7 +266,7 @@ public void changeTestName(String name) {
259266
* @see BaseConfigurations#setTags(List)
260267
*/
261268
public void addTags(List<String> tags) {
262-
validateSessionStarted("setTags()");
269+
validateSessionStarted("setTags");
263270
String tagString = String.join(",", tags);
264271
driver.executeScript("sauce:job-tags=" + tagString);
265272
}
@@ -301,7 +308,7 @@ private void updateResult(String result) {
301308

302309
private void validateSessionStarted(String method) {
303310
if (driver == null) {
304-
throw new SauceSessionNotStartedException(method);
311+
throw new SauceSessionNotStartedException(method + "()");
305312
}
306313
}
307314

java/main/src/main/java/com/saucelabs/saucebindings/options/SauceOptions.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,15 @@ private static Map<String, Object> loadJSON(Path path) throws IOException {
118118
}
119119

120120
/**
121-
* This is intended to facilitate using a JSON file or a YAML to create a SauceOptions instance
122-
* It is currently private, but might be made public in the future
123-
* Raise an issue on GitHub if you have a use case for it
121+
* Public so SauceSession can support MutableCapabilities without making MutableCapabilities constructor public
122+
* This is primarily intended to facilitate using a JSON file or a YAML to create a SauceOptions instance
124123
*
124+
* @deprecated This is intended for private access, do not use directly
125125
* @see SauceOptions(Path)
126-
* @param map Capabilities to use to create a SauceSession
126+
* @param map key value pairs to set on a SauceOptions instance
127127
*/
128-
private SauceOptions(Map<String, Object> map) {
128+
@Deprecated
129+
public SauceOptions(Map<String, Object> map) {
129130
this(new MutableCapabilities(map));
130131
}
131132

java/main/src/test/java/com/saucelabs/saucebindings/SauceSessionTest.java

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.saucelabs.saucebindings.options.SauceOptions;
77
import org.junit.Assert;
88
import org.junit.Before;
9+
import org.junit.Ignore;
910
import org.junit.Rule;
1011
import org.junit.Test;
1112
import org.mockito.Matchers;
@@ -25,6 +26,7 @@
2526
public class SauceSessionTest {
2627
private SauceOptions sauceOptions = Mockito.spy(SauceOptions.chrome().build());
2728
private SauceSession sauceSession = Mockito.spy(new SauceSession());
29+
private MutableCapabilities mutableCapabilities = new MutableCapabilities();
2830
private final SauceSession sauceOptsSession = Mockito.spy(new SauceSession(sauceOptions));
2931
private final RemoteWebDriver dummyRemoteDriver = Mockito.mock(RemoteWebDriver.class);
3032
private final MutableCapabilities dummyMutableCapabilities = Mockito.mock(MutableCapabilities.class);
@@ -60,6 +62,22 @@ public void usesProvidedSauceOptions() {
6062
Mockito.verify(sauceOptions).toCapabilities();
6163
}
6264

65+
@Test(expected = InvalidSauceOptionsArgumentException.class)
66+
public void errorsOnDesiredCaps() {
67+
DesiredCapabilities caps = new DesiredCapabilities();
68+
caps.setBrowserName("chrome");
69+
sauceSession = new SauceSession(caps);
70+
}
71+
72+
@Test
73+
public void usesProvidedValidMutableCaps() {
74+
MutableCapabilities caps = new MutableCapabilities();
75+
caps.setCapability("browserName", "chrome");
76+
77+
sauceSession = new SauceSession(caps);
78+
Assert.assertEquals(Browser.CHROME, sauceSession.getSauceOptions().getBrowserName());
79+
}
80+
6381
@Test
6482
public void usesProvidedSeleniumOptions() {
6583
FirefoxOptions seOpts = new FirefoxOptions();
@@ -92,9 +110,57 @@ public void usesProvidedSeleniumOptions() {
92110

93111
@Test(expected = InvalidSauceOptionsArgumentException.class)
94112
public void doesNotUseDesiredCapabilities() {
95-
DesiredCapabilities caps = new DesiredCapabilities();
113+
sauceSession = new SauceSession(new DesiredCapabilities());
114+
}
96115

97-
sauceSession = new SauceSession(caps);
116+
@Test(expected = InvalidSauceOptionsArgumentException.class)
117+
public void errorsBadMutableCapability() {
118+
mutableCapabilities.setCapability("invalid", "capability");
119+
120+
sauceSession = new SauceSession(mutableCapabilities);
121+
}
122+
123+
@Test(expected = InvalidSauceOptionsArgumentException.class)
124+
public void errorsBadSauceMutableCapability() {
125+
mutableCapabilities.setCapability("sauce:options", ImmutableMap.of("invalid", "value"));
126+
127+
sauceSession = new SauceSession(mutableCapabilities);
128+
}
129+
130+
@Test(expected = InvalidSauceOptionsArgumentException.class)
131+
public void errorsBadMutableCapabilityValue() {
132+
mutableCapabilities.setCapability("unhandledPromptBehavior", "invalid");
133+
134+
sauceSession = new SauceSession(mutableCapabilities);
135+
}
136+
137+
@Test(expected = InvalidSauceOptionsArgumentException.class)
138+
public void errorsBadSauceMutableCapabilityValue() {
139+
mutableCapabilities.setCapability("sauce:options", ImmutableMap.of("jobVisibility", "invalid"));
140+
141+
sauceSession = new SauceSession(mutableCapabilities);
142+
}
143+
144+
@Ignore("Current code does not parse by browser making this a more difficult implementation at this time")
145+
@Test//(expected = InvalidSauceOptionsArgumentException.class)
146+
public void errorsBadNameSpacedValues() {
147+
mutableCapabilities.setCapability("foo:bar", ImmutableMap.of("invalid", "prefix"));
148+
149+
sauceSession = new SauceSession(mutableCapabilities);
150+
}
151+
152+
@Test(expected = InvalidSauceOptionsArgumentException.class)
153+
public void invalidOptionsMutableCap() {
154+
MutableCapabilities caps = new MutableCapabilities();
155+
caps.setCapability("invalid", "capability");
156+
new SauceSession(caps);
157+
}
158+
159+
@Test(expected = InvalidSauceOptionsArgumentException.class)
160+
public void invalidValueMutableCap() {
161+
MutableCapabilities caps = new MutableCapabilities();
162+
caps.setCapability("invalidPromptBehavior", "value");
163+
new SauceSession(caps);
98164
}
99165

100166
@Test
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.saucelabs.saucebindings.examples;
2+
3+
import com.saucelabs.saucebindings.SauceSession;
4+
import com.saucelabs.saucebindings.UnhandledPromptBehavior;
5+
import com.saucelabs.saucebindings.options.SauceOptions;
6+
import org.junit.Test;
7+
import org.openqa.selenium.chrome.ChromeOptions;
8+
import org.openqa.selenium.remote.RemoteWebDriver;
9+
10+
import java.net.MalformedURLException;
11+
import java.net.URL;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
public class ConversionTest {
16+
17+
public ChromeOptions optionsFromPlatformConfigurator() {
18+
ChromeOptions browserOptions = new ChromeOptions();
19+
browserOptions.setPlatformName("Windows 10");
20+
browserOptions.setBrowserVersion("latest");
21+
Map<String, Object> sauceOptions = new HashMap<>();
22+
browserOptions.setCapability("sauce:options", sauceOptions);
23+
24+
return browserOptions;
25+
}
26+
27+
@Test
28+
public void noSauceBindingsExampleForComparison() throws MalformedURLException {
29+
String username = System.getenv("SAUCE_USERNAME");
30+
String accessKey = System.getenv("SAUCE_ACCESS_KEY");
31+
String url = "https://" + username + ":" + accessKey + "@ondemand.us-west-1.saucelabs.com/wd/hub";
32+
33+
RemoteWebDriver driver = new RemoteWebDriver(new URL(url), optionsFromPlatformConfigurator());
34+
35+
driver.get("https://www.saucedemo.com/");
36+
37+
driver.executeScript("sauce:job-result=passed");
38+
driver.quit();
39+
}
40+
41+
@Test
42+
public void seleniumOptionsWithSauceSession() {
43+
SauceSession session = new SauceSession(optionsFromPlatformConfigurator());
44+
RemoteWebDriver driver = session.start();
45+
46+
driver.get("https://www.saucedemo.com/");
47+
48+
session.stop(true);
49+
}
50+
51+
@Test
52+
public void addSauceOptionsToSeleniumOptions() {
53+
SauceOptions sauceBindingsOptions = SauceOptions.chrome(optionsFromPlatformConfigurator())
54+
.setUnhandledPromptBehavior(UnhandledPromptBehavior.IGNORE)
55+
.setTimeZone("Alaska")
56+
.build();
57+
58+
SauceSession session = new SauceSession(sauceBindingsOptions);
59+
RemoteWebDriver driver = session.start();
60+
61+
driver.get("https://www.saucedemo.com/");
62+
63+
session.stop(true);
64+
}
65+
}

0 commit comments

Comments
 (0)