Skip to content

Commit f03a056

Browse files
committed
repo init
1 parent a6eabd4 commit f03a056

File tree

20 files changed

+585
-2
lines changed

20 files changed

+585
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea/

README.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,34 @@
1-
# java-playwright-browserstack
2-
Creating a sample repo for different Playwright languages and runners
1+
## java-playwright-browserstack
2+
3+
## Setup
4+
* Clone the repo
5+
* Install dependencies `mvn install`
6+
* Update credentials in the `/src/test/resources/*.conf.json` file with your [BrowserStack Username and Access Key](https://www.browserstack.com/accounts/settings).
7+
* For parallel testing, control the concurrency by setting the value for `parallel.count`. Junit 5 uses the following properties for parallelism:
8+
```
9+
junit.jupiter.execution.parallel.enabled = true
10+
junit.jupiter.execution.parallel.mode.default = concurrent
11+
junit.jupiter.execution.parallel.config.strategy=fixed
12+
junit.jupiter.execution.parallel.config.fixed.parallelism=${parallel.count}
13+
```
14+
## Running your tests
15+
* To run a sample tests, run `mvn test -P sample-test`
16+
* To run sample tests with local, run `mvn test -P sample-local-test`
17+
18+
Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/automate/parallel-calculator?ref=github)
19+
20+
## Notes
21+
* You can view your test results on the [BrowserStack Automate dashboard](https://www.browserstack.com/automate)
22+
* You can export the environment variables for the Username and Access Key of your BrowserStack account.
23+
24+
* For Unix-like or Mac machines:
25+
```
26+
export BROWSERSTACK_USERNAME=<browserstack-username> &&
27+
export BROWSERSTACK_ACCESS_KEY=<browserstack-access-key>
28+
```
29+
30+
* For Windows:
31+
```
32+
set BROWSERSTACK_USERNAME=<browserstack-username>
33+
set BROWSERSTACK_ACCESS_KEY=<browserstack-access-key>
34+
```

pom.xml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<groupId>org.example</groupId>
6+
<artifactId>Junit5Basics</artifactId>
7+
<version>1.0-SNAPSHOT</version>
8+
<properties>
9+
<maven.compiler.source>8</maven.compiler.source>
10+
<maven.compiler.target>8</maven.compiler.target>
11+
<junit-jupiter-engine>5.8.1</junit-jupiter-engine>
12+
<junit-vintage-engine>5.4.0</junit-vintage-engine>
13+
<json-simple>1.1</json-simple>
14+
<selenium-java>4.1.0</selenium-java>
15+
<maven-surefire-plugin>3.0.0-M5</maven-surefire-plugin>
16+
<browserstack-local-java>1.0.6</browserstack-local-java>
17+
<httpclient>4.5.13</httpclient>
18+
<parallel.count>5</parallel.count>
19+
<tests.single>**/tests.SingleTest.java</tests.single>
20+
</properties>
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.junit.jupiter</groupId>
24+
<artifactId>junit-jupiter-engine</artifactId>
25+
<version>${junit-jupiter-engine}</version>
26+
<scope>test</scope>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.junit.vintage</groupId>
30+
<artifactId>junit-vintage-engine</artifactId>
31+
<version>${junit-vintage-engine}</version>
32+
<scope>test</scope>
33+
</dependency>
34+
<dependency>
35+
<groupId>com.microsoft.playwright</groupId>
36+
<artifactId>playwright</artifactId>
37+
<version>1.19.0</version>
38+
<scope>compile</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>com.googlecode.json-simple</groupId>
42+
<artifactId>json-simple</artifactId>
43+
<version>${json-simple}</version>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.seleniumhq.selenium</groupId>
47+
<artifactId>selenium-java</artifactId>
48+
<version>${selenium-java}</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.apache.maven.plugins</groupId>
52+
<artifactId>maven-surefire-plugin</artifactId>
53+
<version>${maven-surefire-plugin}</version>
54+
<type>maven-plugin</type>
55+
</dependency>
56+
<dependency>
57+
<groupId>com.browserstack</groupId>
58+
<artifactId>browserstack-local-java</artifactId>
59+
<version>${browserstack-local-java}</version>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.apache.httpcomponents</groupId>
63+
<artifactId>httpclient</artifactId>
64+
<version>${httpclient}</version>
65+
</dependency>
66+
</dependencies>
67+
<profiles>
68+
<profile>
69+
<id>sample-local-test</id>
70+
<build>
71+
<plugins>
72+
<plugin>
73+
<groupId>org.apache.maven.plugins</groupId>
74+
<artifactId>maven-surefire-plugin</artifactId>
75+
<version>3.0.0-M5</version>
76+
<configuration>
77+
<includes>
78+
<include>${tests.single}</include>
79+
</includes>
80+
<systemPropertyVariables>
81+
<config>parallel.conf.json</config>
82+
<local>true</local>
83+
</systemPropertyVariables>
84+
<properties>
85+
<configurationParameters>
86+
junit.jupiter.execution.parallel.enabled = true
87+
junit.jupiter.execution.parallel.mode.default = concurrent
88+
junit.jupiter.execution.parallel.config.strategy=fixed
89+
junit.jupiter.execution.parallel.config.fixed.parallelism=${parallel.count}
90+
</configurationParameters>
91+
</properties>
92+
<testFailureIgnore>false</testFailureIgnore>
93+
</configuration>
94+
</plugin>
95+
</plugins>
96+
</build>
97+
</profile>
98+
<profile>
99+
<id>sample-test</id>
100+
<build>
101+
<plugins>
102+
<plugin>
103+
<groupId>org.apache.maven.plugins</groupId>
104+
<artifactId>maven-surefire-plugin</artifactId>
105+
<version>3.0.0-M5</version>
106+
<configuration>
107+
<includes>
108+
<include>${tests.single}</include>
109+
</includes>
110+
<systemPropertyVariables>
111+
<config>parallel.conf.json</config>
112+
<local>false</local>
113+
</systemPropertyVariables>
114+
<properties>
115+
<configurationParameters>
116+
junit.jupiter.execution.parallel.enabled = true
117+
junit.jupiter.execution.parallel.mode.default = concurrent
118+
junit.jupiter.execution.parallel.config.strategy=fixed
119+
junit.jupiter.execution.parallel.config.fixed.parallelism=${parallel.count}
120+
</configurationParameters>
121+
</properties>
122+
<testFailureIgnore>false</testFailureIgnore>
123+
</configuration>
124+
</plugin>
125+
</plugins>
126+
</build>
127+
</profile>
128+
</profiles>
129+
</project>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package runners;
2+
3+
import org.json.simple.JSONArray;
4+
import org.json.simple.JSONObject;
5+
import org.json.simple.parser.JSONParser;
6+
import org.junit.jupiter.api.AfterEach;
7+
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.extension.*;
9+
10+
import com.microsoft.playwright.*;
11+
import com.google.gson.JsonObject;
12+
import java.net.URLEncoder;
13+
14+
import org.openqa.selenium.MutableCapabilities;
15+
import org.openqa.selenium.WebDriver;
16+
import org.openqa.selenium.remote.RemoteWebDriver;
17+
18+
import utils.SetupLocalTesting;
19+
20+
import java.io.FileReader;
21+
import java.net.MalformedURLException;
22+
import java.net.URL;
23+
import java.util.*;
24+
import java.util.stream.Stream;
25+
26+
public class BstackRunner implements TestTemplateInvocationContextProvider {
27+
public Browser browser;
28+
public String username, accessKey, wss;
29+
private JSONObject mainConfig;
30+
private JSONArray platformConfig;
31+
private Map<String, Object> commonCapsConfig;
32+
33+
34+
public BstackRunner() {
35+
this.username = setupCredsAndServer().get("username");
36+
this.accessKey = setupCredsAndServer().get("accesskey");
37+
this.wss = setupCredsAndServer().get("wss");
38+
}
39+
40+
public HashMap<String, String> setupCredsAndServer() {
41+
try {
42+
if (System.getProperty("config") != null) {
43+
JSONParser parser = new JSONParser();
44+
mainConfig = (JSONObject) parser
45+
.parse(new FileReader("src/test/resources/conf/" + System.getProperty("config")));
46+
}
47+
wss = (String) mainConfig.get("wss");
48+
username = System.getenv("BROWSERSTACK_USERNAME");
49+
if (username == null) {
50+
username = (String) mainConfig.get("userName");
51+
}
52+
accessKey = System.getenv("BROWSERSTACK_ACCESS_KEY");
53+
if (accessKey == null) {
54+
accessKey = (String) mainConfig.get("accessKey");
55+
}
56+
} catch (Exception e) {
57+
System.out.println(e.getMessage());
58+
}
59+
HashMap<String, String> creds = new HashMap();
60+
creds.put("username", username);
61+
creds.put("accesskey", accessKey);
62+
creds.put("wss", wss);
63+
return creds;
64+
}
65+
66+
@Override
67+
public boolean supportsTestTemplate(ExtensionContext extensionContext) {
68+
return true;
69+
}
70+
71+
@Override
72+
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext extensionContext) {
73+
List<TestTemplateInvocationContext> desiredCapsInvocationContexts = new ArrayList<>();
74+
75+
try {
76+
platformConfig = (JSONArray) mainConfig.get("environments");
77+
commonCapsConfig = (Map<String, Object>) mainConfig.get("capabilities");
78+
79+
for (int i = 0; i < platformConfig.size(); i++) {
80+
JSONObject platform = (JSONObject) platformConfig.get(i);
81+
platform.putAll(commonCapsConfig);
82+
platform.put("browserstack.username", username);
83+
platform.put("browserstack.accessKey", accessKey);
84+
if(System.getProperty("local") == "true") {
85+
platform.put("browserstack.local", "true");
86+
HashMap<String, String> localOptions = new HashMap<>();
87+
localOptions.put("key", accessKey);
88+
//Add more local options here, e.g. forceLocal, localIdentifier, etc.
89+
SetupLocalTesting.createInstance(localOptions);
90+
}
91+
desiredCapsInvocationContexts.add(invocationContext(platform));
92+
}
93+
} catch (Exception e) {
94+
e.printStackTrace();
95+
}
96+
return desiredCapsInvocationContexts.stream();
97+
}
98+
99+
private TestTemplateInvocationContext invocationContext(JSONObject capabilitiesObject) {
100+
return new TestTemplateInvocationContext() {
101+
102+
@Override
103+
public List<Extension> getAdditionalExtensions() {
104+
105+
return Collections.singletonList(new ParameterResolver() {
106+
@Override
107+
public boolean supportsParameter(ParameterContext parameterContext,
108+
ExtensionContext extensionContext) {
109+
return parameterContext.getParameter().getType().equals(Browser.class);
110+
}
111+
112+
@Override
113+
public Object resolveParameter(ParameterContext parameterContext,
114+
ExtensionContext extensionContext) {
115+
try(Playwright playwright = Playwright.create()) {
116+
BrowserType browserType = playwright.chromium();
117+
String caps = URLEncoder.encode(capabilitiesObject.toString(), "utf-8");
118+
System.out.println(capabilitiesObject.toString());
119+
String ws_endpoint = wss + "?caps=" + caps;
120+
browser = browserType.connect(ws_endpoint);
121+
} catch (Exception e) {
122+
e.printStackTrace();
123+
}
124+
return browser;
125+
}
126+
});
127+
}
128+
};
129+
}
130+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package runners;
2+
3+
import org.apiguardian.api.API;
4+
import org.junit.jupiter.api.TestTemplate;
5+
import org.junit.jupiter.api.extension.ExtendWith;
6+
import org.junit.platform.commons.annotation.Testable;
7+
8+
import java.lang.annotation.*;
9+
10+
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Documented
13+
@API(status = API.Status.STABLE)
14+
@TestTemplate
15+
@Testable
16+
@ExtendWith(BstackRunner.class)
17+
public @interface PlaywrightTest {
18+
}

src/test/java/tests/SingleTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package tests;
2+
3+
import com.microsoft.playwright.Browser;
4+
import com.microsoft.playwright.Page;
5+
import org.openqa.selenium.By;
6+
import org.openqa.selenium.WebDriver;
7+
import org.openqa.selenium.WebElement;
8+
import org.openqa.selenium.remote.RemoteWebDriver;
9+
import org.openqa.selenium.remote.SessionId;
10+
import org.openqa.selenium.support.ui.ExpectedConditions;
11+
import org.openqa.selenium.support.ui.WebDriverWait;
12+
import runners.PlaywrightTest;
13+
14+
import java.time.Duration;
15+
16+
public class SingleTest {
17+
18+
@PlaywrightTest
19+
void singleTest(Browser browser) {
20+
Page page = browser.newPage();
21+
try {
22+
page.navigate("https://bstackdemo.com/");
23+
String product_name = page.locator("//*[@id='1']/p").textContent();
24+
page.locator("//*[@id='1']/div[4]").click();
25+
page.locator(".float\\-cart__content");
26+
String product_in_cart = page.locator("//*[@id='__next']/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]").textContent();
27+
if (product_name.equals(product_in_cart)) {
28+
page.evaluate("_ => {}", "browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"" + "passed" + "\", \"reason\": \"" + "Product has been successfully added to the cart!" + "\"}}");
29+
} else {
30+
page.evaluate("_ => {}", "browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"" + "failed" + "\", \"reason\": \"" + "There was some issue!" + "\"}}");
31+
}
32+
} catch (Exception e) {
33+
page.evaluate("_ => {}", "browserstack_executor: { \"action\": \"setSessionStatus\", \"arguments\": { \"status\": \"" + "failed" + "\", \"reason\": \"" + "There was some issue!" + "\"}}");
34+
System.out.println("Exception: " + e.getMessage());
35+
}
36+
browser.close();
37+
}
38+
}

0 commit comments

Comments
 (0)