com.dev9.sauce.SauceREST Maven / Gradle / Ivy
package com.dev9.sauce;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.HttpClients;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import sun.misc.BASE64Encoder;
import java.io.IOException;
/**
* Used to access the Sauce Labs rest API.
*
* Based on Sauce Labs code, on github: https://github.com/saucelabs/saucerest-java.
*/
@Log4j2
public class SauceREST {
protected String username;
protected String accessKey;
/**
* Constructs a SauceREST object with all necessary authentication information.
*
* @param username A Sauce Labs user name.
* @param accessKey The Sauce Labs key corresponding to the user name.
*/
public SauceREST(String username, String accessKey) {
this.username = username;
this.accessKey = accessKey;
}
/**
* Returns details for a given Sauce Labs account, including minutes used.
* @return the result of the request
*/
public JSONObject getAccountDetails() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUsersToPath()
.addUserIdToPath(username)
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Returns detailed usage data for the Sauce Labs account, including minutes
* used on a daily basis.
* @return the result of the request
*/
public JSONObject getUsageData() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUsersToPath()
.addUserIdToPath(username)
.addGenericSuffix("/usage")
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Gets a list of all jobs ever for the user, not just current jobs.
* @return the result of the request
*/
public JSONArray getAllJobs() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUserIdToPath(username)
.addJobsToPath()
.build();
return (JSONArray) sendRestRequest(request);
}
/**
* Returns status details for a given job, including pass/fail and
* all tags.
*
* @param jobId The session id for a Sauce job.
* @return the result of the request
*/
public JSONObject getJobStatus(String jobId) {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUserIdToPath(username)
.addJobsToPath()
.addJobIdToPath(jobId)
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Marks a job as passed; will appear as such in jobs list in Sauce Labs.
* @param jobId The session id for the Sauce Job that passed.
* @return the result of the request
*/
public JSONObject jobPassed(String jobId) {
return updateJob(jobId, "passed", true);
}
/**
* Marks a job as failed; will appear as such in jobs list in Sauce Labs.
* @param jobId The session id for the Sauce Job that failed.
* @return the result of the request
*/
public JSONObject jobFailed(String jobId) {
return updateJob(jobId, "passed", false);
}
/**
* Updates a job in Sauce Labs with an arbitrary JSON key/value pair. Note that
* Sauce Labs will not accept arbitrary values; see documentation on their site.
*
* @param jobId The session id for the Sauce job to update.
* @param jsonKey A String key for the json object.
* @param jsonValue A value for the json object (discrete, a list, or a map, for instance).
* @return the result of the request
*/
public JSONObject updateJob(String jobId, String jsonKey, Object jsonValue) {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.addJSON(jsonKey, jsonValue)
.setHTTPMethod("PUT")
.addUserIdToPath(username)
.addJobsToPath()
.addJobIdToPath(jobId)
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Stop a currently running job. Should not be necessary to use in parallel-webtest.
*
* @param jobId The session id for the Sauce job to update.
* @return the result of the request
*/
public JSONObject stopJob(String jobId) {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("PUT")
.addUserIdToPath(username)
.addJobsToPath()
.addJobIdToPath(jobId)
.addGenericSuffix("/stop")
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Verifies that one or more tunnels exist (but does not check tunnel state).
* @return true if tunnel is present
*/
public boolean isTunnelPresent() {
JSONArray tunnels = getAllTunnels();
return (!tunnels.isEmpty());
}
public JSONArray getAllTunnels() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUserIdToPath(username)
.addGenericSuffix("/tunnels")
.build();
return (JSONArray) sendRestRequest(request);
}
public JSONObject getTunnelStatus(String tunnelId) {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addUserIdToPath(username)
.addGenericSuffix("/tunnels/")
.addGenericSuffix(tunnelId)
.build();
return (JSONObject) sendRestRequest(request);
}
public JSONObject deleteTunnel(String tunnelId) {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("DELETE")
.addUserIdToPath(username)
.addGenericSuffix("/tunnels/")
.addGenericSuffix(tunnelId)
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Not currently supported by Sauce Labs, but will one day return status of Sauce Labs services.
* @return the result of the request
*/
public JSONObject getSauceStatus() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addGenericSuffix("/info/status")
.build();
return (JSONObject) sendRestRequest(request);
}
/**
* Gets a list of all currently supported browser/os combinations.
* @return the result of the request
*/
public JSONArray getSauceBrowsers() {
SauceRESTRequest request = new SauceRESTRequestBuilder()
.setHTTPMethod("GET")
.addGenericSuffix("/info/browsers")
.build();
return (JSONArray) sendRestRequest(request);
}
/**
* Send a request to Sauce Labs configured using a SauceRESTRequest object.
*
* @param request An object containing all details for the REST request.
* @return the result of the request
*/
public Object sendRestRequest(SauceRESTRequest request) {
Object result = null;
HttpClient client = HttpClients.createDefault();
HttpUriRequest httpRequest = MethodFactory.getRequest(request.getMethod(),
request.getRequestUrl().toExternalForm(),
request.getJsonParameters());
String auth = username + ":" + accessKey;
BASE64Encoder encoder = new BASE64Encoder();
auth = "Basic " + encoder.encode(auth.getBytes());
httpRequest.addHeader("Authorization", auth);
String response = getResponse(client, httpRequest);
if (response != null) {
result = JSONValue.parse(response);
}
return result;
}
static String getResponse(HttpClient client, HttpUriRequest request) {
String responseMessage = null;
try {
HttpResponse response = client.execute(request);
Integer responseCode = response.getStatusLine().getStatusCode();
if (responseCode == 200) {
responseMessage = IOUtils.toString(response.getEntity().getContent());
if (responseMessage != null) {
log.trace("Raw result: {}", response);
}
}
else {
log.error("Request [{}] failed: {} error: {}",
request.getURI().toString(),
responseCode,
response);
}
} catch (IOException e) {
log.error("Exception while trying to execute rest request: {}\n{}", e.getMessage(), e.getStackTrace());
}
return responseMessage;
}
}