Skip to content

Commit 51f1a5c

Browse files
Merge pull request #21 from LambdaTest/stage
Release 1.0.12 version
2 parents 4b69c92 + ecc222b commit 51f1a5c

19 files changed

+1246
-37
lines changed

README.md

+63-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,63 @@
1-
# smartui-sdk-utils
1+
# LambdaTest Java SDK
2+
3+
Run the following command to install the dependencies of the project mentioned in `pom.xml`:
4+
5+
```sh
6+
mvn clean install
7+
```
8+
9+
Set the required environment variables:
10+
11+
```sh
12+
export PROJECT_TOKEN=<add-your-project-token>
13+
export LT_ACCESS_KEY=<add-your-access-key>
14+
export LT_USERNAME=<add-your-username>
15+
```
16+
17+
## Usage
18+
19+
### To Take SmartUI App Snapshot
20+
`import io.github.lambdatest.SmartUIAppSnapshot;`
21+
#### 1. Create an Object of `SmartUIAppSnapshot`
22+
23+
```java
24+
SmartUIAppSnapshot smartUIAppSnapshot = new SmartUIAppSnapshot();
25+
Map<String, String> screenshotConfig = new HashMap<>();
26+
screenshotConfig.put("deviceName","Google pixel 9");
27+
screenshotConfig.put("platform","Android 15");
28+
29+
smartUIAppSnapshot.start();
30+
smartUIAppSnapshot.smartuiAppSnapshot(driver, "screenshot1", screenshotConfig);
31+
smartUIAppSnapshot.stop();
32+
33+
```
34+
35+
36+
### To Take SmartUI Snapshot
37+
38+
#### 1. Install the `smartui-cli` Dependencies
39+
40+
```sh
41+
npm i @lambdatest/smartui-cli
42+
```
43+
44+
#### 2. Create and Configure SmartUI Config
45+
46+
```sh
47+
npx smartui config:create smartui-web.json
48+
```
49+
```java
50+
import io.github.lambdatest.SmartUISnapshot;
51+
52+
public class SmartUISDK {
53+
54+
private RemoteWebDriver driver;
55+
56+
@Test
57+
public void basicTest() throws Exception {
58+
driver.get("https://www.lambdatest.com/support/docs/smartui-selenium-java-sdk");
59+
SmartUISnapshot.smartuiSnapshot(driver, "visual-regression-testing");
60+
}
61+
62+
}
63+
```

build.gradle

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group = 'io.github.lambdatest'
9-
version = '1.0.7'
9+
version = '1.0.12'
1010
description = 'lambdatest-java-sdk'
1111

1212
repositories {
@@ -21,6 +21,10 @@ dependencies {
2121
implementation 'com.google.code.gson:gson:2.10.1'
2222
implementation 'io.netty:netty-transport-native-epoll:4.1.104.Final'
2323
implementation 'io.netty:netty-transport-native-kqueue:4.1.104.Final'
24+
25+
// New dependencies from POM file
26+
implementation 'org.apache.httpcomponents:httpmime:4.5.13'
27+
implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1'
2428
}
2529

2630
shadowJar {
@@ -34,6 +38,8 @@ shadowJar {
3438
}
3539

3640
java {
41+
sourceCompatibility = JavaVersion.VERSION_1_8
42+
targetCompatibility = JavaVersion.VERSION_1_8
3743
withSourcesJar()
3844
withJavadocJar()
3945
}
@@ -77,7 +83,7 @@ afterEvaluate {
7783
mavenJava(MavenPublication) {
7884
groupId = 'io.github.lambdatest'
7985
artifactId = 'lambdatest-java-sdk'
80-
version = '1.0.7'
86+
version = '1.0.12'
8187

8288
pom {
8389
name.set('LambdaTest Java SDK')

pom.xml

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<project
3-
xmlns="http://maven.apache.org/POM/4.0.0"
4-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
66
<modelVersion>4.0.0</modelVersion>
77
<groupId>io.github.lambdatest</groupId>
88
<artifactId>lambdatest-java-sdk</artifactId>
9-
<version>1.0.0</version>
9+
<version>1.0.12</version>
1010
<name>lambdatest-java-sdk</name>
1111
<description>LambdaTest SDK in Java</description>
1212
<url>https://www.lambdatest.com</url>
1313
<properties>
1414
<maven.compiler.source>1.8</maven.compiler.source>
1515
<maven.compiler.target>1.8</maven.compiler.target>
16+
<gpg.skip>true</gpg.skip>
1617
</properties>
1718
<licenses>
1819
<license>
@@ -40,7 +41,12 @@
4041
<dependency>
4142
<groupId>org.apache.httpcomponents</groupId>
4243
<artifactId>httpclient</artifactId>
43-
<version>4.5.13</version>
44+
<version>4.5.14</version>
45+
</dependency>
46+
<dependency>
47+
<groupId>org.apache.httpcomponents</groupId>
48+
<artifactId>httpmime</artifactId>
49+
<version>4.5.14</version>
4450
</dependency>
4551
<dependency>
4652
<groupId>org.json</groupId>
@@ -57,6 +63,11 @@
5763
<artifactId>gson</artifactId>
5864
<version>2.10.1</version>
5965
</dependency>
66+
<dependency>
67+
<groupId>com.fasterxml.jackson.core</groupId>
68+
<artifactId>jackson-databind</artifactId>
69+
<version>2.16.1</version>
70+
</dependency>
6071
</dependencies>
6172
<build>
6273
<plugins>
@@ -127,10 +138,10 @@
127138
<plugin>
128139
<groupId>org.apache.maven.plugins</groupId>
129140
<artifactId>maven-compiler-plugin</artifactId>
130-
<version>2.3.2</version>
141+
<version>3.8.1</version>
131142
<configuration>
132-
<source>8</source>
133-
<target>8</target>
143+
<source>1.8</source>
144+
<target>1.8</target>
134145
</configuration>
135146
</plugin>
136147
<plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package io.github.lambdatest;
2+
3+
import com.google.gson.Gson;
4+
import io.github.lambdatest.constants.Constants;
5+
import io.github.lambdatest.models.*;
6+
import io.github.lambdatest.utils.GitUtils;
7+
import io.github.lambdatest.utils.SmartUIUtil;
8+
import org.openqa.selenium.Dimension;
9+
import org.openqa.selenium.OutputType;
10+
import org.openqa.selenium.TakesScreenshot;
11+
import org.openqa.selenium.WebDriver;
12+
13+
import java.io.File;
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
import java.util.Objects;
17+
import java.util.logging.Logger;
18+
import io.github.lambdatest.utils.LoggerUtil;
19+
20+
public class SmartUIAppSnapshot {
21+
private final Logger log = LoggerUtil.createLogger("lambdatest-java-app-sdk");
22+
private final SmartUIUtil util;
23+
private final Gson gson = new Gson();
24+
private String projectToken;
25+
26+
private BuildData buildData;
27+
28+
public SmartUIAppSnapshot() {
29+
this.util = new SmartUIUtil();
30+
}
31+
32+
public SmartUIAppSnapshot(String proxyHost, int proxyPort) throws Exception {
33+
this.util = new SmartUIUtil(proxyHost, proxyPort);
34+
}
35+
36+
public SmartUIAppSnapshot(String proxyHost, int proxyPort, boolean allowInsecure) throws Exception {
37+
this.util = new SmartUIUtil(proxyHost, proxyPort, allowInsecure);
38+
}
39+
40+
public SmartUIAppSnapshot(String proxyProtocol, String proxyHost, int proxyPort, boolean allowInsecure)
41+
throws Exception {
42+
this.util = new SmartUIUtil(proxyProtocol, proxyHost, proxyPort, allowInsecure);
43+
}
44+
45+
public void start(Map<String, String> options) throws Exception {
46+
try {
47+
this.projectToken = getProjectToken(options);
48+
log.info("Project token set as: " + this.projectToken);
49+
} catch (Exception e) {
50+
log.severe(Constants.Errors.PROJECT_TOKEN_UNSET);
51+
throw new Exception("Project token is a mandatory field", e);
52+
}
53+
54+
try {
55+
Map<String, String> envVars = new HashMap<>(System.getenv());
56+
GitInfo git = GitUtils.getGitInfo(envVars);
57+
BuildResponse buildRes = util.build(git, this.projectToken, options);
58+
this.buildData = buildRes.getData();
59+
log.info("Build ID set : " + this.buildData.getBuildId() + "for Build name : " + this.buildData.getName());
60+
options.put("buildName", this.buildData.getName());
61+
} catch (Exception e) {
62+
log.severe("Couldn't create smartui build: " + e.getMessage());
63+
throw new Exception("Couldn't create smartui build: " + e.getMessage());
64+
}
65+
}
66+
67+
public void start() throws Exception {
68+
this.start(new HashMap<>());
69+
}
70+
71+
private String getProjectToken(Map<String, String> options) {
72+
if (options != null && options.containsKey(Constants.PROJECT_TOKEN)) {
73+
String token = options.get(Constants.PROJECT_TOKEN).trim();
74+
if (!token.isEmpty()) {
75+
return token;
76+
}
77+
}
78+
String envToken = System.getenv("PROJECT_TOKEN");
79+
if (envToken != null && !envToken.trim().isEmpty()) {
80+
return envToken.trim();
81+
}
82+
throw new IllegalArgumentException(Constants.Errors.PROJECT_TOKEN_UNSET);
83+
}
84+
85+
public void smartuiAppSnapshot(WebDriver appiumDriver, String screenshotName, Map<String, String> options)
86+
throws Exception {
87+
try {
88+
if (appiumDriver == null) {
89+
log.severe(Constants.Errors.SELENIUM_DRIVER_NULL + " during take snapshot");
90+
throw new IllegalArgumentException(Constants.Errors.SELENIUM_DRIVER_NULL);
91+
}
92+
if (screenshotName == null || screenshotName.isEmpty()) {
93+
log.info(Constants.Errors.SNAPSHOT_NAME_NULL);
94+
throw new IllegalArgumentException(Constants.Errors.SNAPSHOT_NAME_NULL);
95+
}
96+
97+
TakesScreenshot takesScreenshot = (TakesScreenshot) appiumDriver;
98+
File screenshot = takesScreenshot.getScreenshotAs(OutputType.FILE);
99+
log.info("Screenshot captured: " + screenshotName);
100+
101+
UploadSnapshotRequest uploadSnapshotRequest = new UploadSnapshotRequest();
102+
uploadSnapshotRequest.setScreenshotName(screenshotName);
103+
uploadSnapshotRequest.setProjectToken(projectToken);
104+
Dimension d = appiumDriver.manage().window().getSize();
105+
int w = d.getWidth(), h = d.getHeight();
106+
uploadSnapshotRequest.setViewport(w + "x" + h);
107+
log.info("Device viewport set to: " + uploadSnapshotRequest.getViewport());
108+
String platform = "", deviceName = "", browserName = "";
109+
if (options != null && options.containsKey("platform")) {
110+
platform = options.get("platform").trim();
111+
}
112+
if (options != null && options.containsKey("deviceName")) {
113+
deviceName = options.get("deviceName").trim();
114+
}
115+
if (deviceName == null || deviceName.isEmpty()) {
116+
throw new IllegalArgumentException(Constants.Errors.DEVICE_NAME_NULL);
117+
}
118+
if (platform == null || platform.isEmpty()) {
119+
if (deviceName.toLowerCase().startsWith("i")) {
120+
browserName = "iOS";
121+
} else {
122+
browserName = "Android";
123+
}
124+
}
125+
uploadSnapshotRequest.setOs(platform != null && !platform.isEmpty() ? platform : browserName);
126+
if (platform != null && !platform.isEmpty()) {
127+
uploadSnapshotRequest.setDeviceName(deviceName + " " + platform);
128+
} else {
129+
uploadSnapshotRequest.setDeviceName(deviceName + " " + browserName);
130+
}
131+
132+
if (platform.toLowerCase().contains("ios")) {
133+
uploadSnapshotRequest.setBrowserName("safari");
134+
} else {
135+
uploadSnapshotRequest.setBrowserName("chrome");
136+
}
137+
if (Objects.nonNull(buildData)) {
138+
uploadSnapshotRequest.setBuildId(buildData.getBuildId());
139+
uploadSnapshotRequest.setBuildName(buildData.getName());
140+
}
141+
UploadSnapshotResponse uploadSnapshotResponse = util.uploadScreenshot(screenshot, uploadSnapshotRequest,
142+
this.buildData);
143+
log.info("For uploading: " + uploadSnapshotRequest.toString() + " received response: "
144+
+ uploadSnapshotResponse.getData());
145+
} catch (Exception e) {
146+
log.severe(Constants.Errors.UPLOAD_SNAPSHOT_FAILED + " due to: " + e.getMessage());
147+
throw new Exception("Couldnt upload image to Smart UI due to: " + e.getMessage());
148+
}
149+
}
150+
151+
public void stop() throws Exception {
152+
try {
153+
if (this.buildData != null) {
154+
log.info("Stopping session for buildId: " + this.buildData.getBuildId());
155+
if (Objects.nonNull(this.buildData.getBuildId())) {
156+
util.stopBuild(this.buildData.getBuildId(), projectToken);
157+
log.info("Session ended for token: " + projectToken);
158+
} else {
159+
log.info("Build ID not found to stop build for " + projectToken);
160+
}
161+
}
162+
} catch (Exception e) {
163+
log.severe("Couldn't stop the build due to an exception: " + e.getMessage());
164+
throw new Exception(Constants.Errors.STOP_BUILD_FAILED + " due to : " + e.getMessage());
165+
}
166+
}
167+
}

src/main/java/io/github/lambdatest/constants/Constants.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,27 @@
33
public interface Constants {
44

55
String SMARTUI_SERVER_ADDRESS = "SMARTUI_SERVER_ADDRESS";
6+
public static final String PROJECT_TOKEN = "projectToken";
67
String LOCAL_SERVER_HOST = "http://localhost:8080";
78

89
//SmartUI API routes
910
interface SmartUIRoutes {
11+
public static final String HOST_URL = "https://api.lambdatest.com/visualui/1.0";
1012
public static final String SMARTUI_HEALTHCHECK_ROUTE = "/healthcheck";
1113
public static final String SMARTUI_DOMSERIALIZER_ROUTE = "/domserializer";
12-
public static final String SMARTUI_SNPASHOT_ROUTE = "/snapshot";
14+
public static final String SMARTUI_SNAPSHOT_ROUTE = "/snapshot";
15+
public static final String SMARTUI_AUTH_ROUTE = "/token/verify";
16+
public static final String SMARTUI_CREATE_BUILD = "/build";
17+
public static final String SMARTUI_FINALISE_BUILD_ROUTE = "/build?buildId=";
18+
public static final String SMARTUI_UPLOAD_SCREENSHOT_ROUTE = "/screenshot";
19+
1320
}
1421

1522
//Request methods
1623
interface RequestMethods {
1724
public static final String POST = "POST";
1825
public static final String GET = "GET";
26+
public static final String DELETE = "DELETE";
1927
}
2028

2129
//Logger colors
@@ -46,7 +54,13 @@ interface Errors {
4654
public static final String MISSING_HTML_KEY = "DOM map is null or missing 'html' key.";
4755
public static final String FETCH_DOM_FAILED = "fetch DOMSerializer failed";
4856
public static final String POST_SNAPSHOT_FAILED = "Post snapshot failed: %s";
57+
public static final String UPLOAD_SNAPSHOT_FAILED = "Upload snapshot failed: ";
4958
public static final String INVALID_RESPONSE_DATA = "Invalid response from fetchDOMSerializer";
5059
public static final String SMARTUI_SNAPSHOT_FAILED = "SmartUI snapshot failed %s";
60+
public static final String PROJECT_TOKEN_UNSET = "projectToken cant be empty";
61+
public static final String USER_AUTH_ERROR = "User authentication failed";
62+
public static final String STOP_BUILD_FAILED = "Failed to stop build";
63+
public static final String NULL_OPTIONS_OBJECT = "Options object is null or missing in request.";
64+
public static final String DEVICE_NAME_NULL = "Device name is a mandatory parameter.";
5165
}
5266
}

0 commit comments

Comments
 (0)