├── .gitattributes ├── .gitignore ├── GIPHY CAPTURE.zip ├── README.md ├── data ├── cat.png └── durian.png ├── driver ├── chromedriver └── chromedriver.exe ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── sahajamit │ │ ├── Exceptions │ │ └── MessageTimeOutException.java │ │ ├── messaging │ │ ├── CDPClient.java │ │ ├── Message.java │ │ ├── MessageBuilder.java │ │ └── ServiceWorker.java │ │ └── utils │ │ ├── SSLUtil.java │ │ ├── UINotificationService.java │ │ ├── UIUtils.java │ │ └── Utils.java └── resources │ └── log4j.properties └── test ├── java └── com │ └── sahajamit │ ├── ClipboardTests.java │ ├── DemoTests.java │ └── NotificationTests.java └── resources └── log4j.properties /.gitattributes: -------------------------------------------------------------------------------- 1 | *.gz filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | target -------------------------------------------------------------------------------- /GIPHY CAPTURE.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahajamit/chrome-devtools-webdriver-integration/231ba34e54b09cd1439c88f2d897f476faf71ed4/GIPHY CAPTURE.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This is the demo code for the following blogs: 2 | 3 | https://medium.com/@sahajamit/selenium-chrome-dev-tools-makes-a-perfect-browser-automation-recipe-c35c7f6a2360 4 | 5 | https://medium.com/@sahajamit/automated-testing-of-web-push-notifications-ffc8a2d85e3c 6 | 7 | https://medium.com/@sahajamit/can-selenium-chrome-dev-tools-recipe-works-inside-a-docker-container-afff92e9cce5 8 | 9 | https://medium.com/@sahajamit/getting-clipboard-content-from-remote-selenium-chrome-nodes-67a4c4d862bd -------------------------------------------------------------------------------- /data/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahajamit/chrome-devtools-webdriver-integration/231ba34e54b09cd1439c88f2d897f476faf71ed4/data/cat.png -------------------------------------------------------------------------------- /data/durian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahajamit/chrome-devtools-webdriver-integration/231ba34e54b09cd1439c88f2d897f476faf71ed4/data/durian.png -------------------------------------------------------------------------------- /driver/chromedriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahajamit/chrome-devtools-webdriver-integration/231ba34e54b09cd1439c88f2d897f476faf71ed4/driver/chromedriver -------------------------------------------------------------------------------- /driver/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahajamit/chrome-devtools-webdriver-integration/231ba34e54b09cd1439c88f2d897f476faf71ed4/driver/chromedriver.exe -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.sahajamit 8 | webdriver-chrome-dev-tools 9 | 1.0-SNAPSHOT 10 | 11 | src/main/java 12 | src/test/java 13 | 14 | 15 | resources 16 | 17 | 18 | 19 | 20 | org.apache.maven.plugins 21 | maven-compiler-plugin 22 | 23 | 8 24 | 8 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | org.seleniumhq.selenium 34 | selenium-java 35 | 3.7.1 36 | 37 | 38 | commons-io 39 | commons-io 40 | 2.6 41 | 42 | 43 | com.jayway.jsonpath 44 | json-path 45 | 2.4.0 46 | 47 | 48 | com.jayway.jsonpath 49 | json-path-assert 50 | 2.4.0 51 | 52 | 53 | org.json 54 | json 55 | 20160810 56 | 57 | 58 | com.neovisionaries 59 | nv-websocket-client 60 | 2.8 61 | 62 | 63 | commons-io 64 | commons-io 65 | 2.6 66 | 67 | 68 | com.google.code.gson 69 | gson 70 | 2.8.5 71 | 72 | 73 | junit 74 | junit 75 | 4.12 76 | test 77 | 78 | 79 | org.slf4j 80 | slf4j-api 81 | 1.7.5 82 | 83 | 84 | org.slf4j 85 | slf4j-log4j12 86 | 1.7.5 87 | 88 | 89 | com.fasterxml.jackson.core 90 | jackson-core 91 | 2.9.8 92 | 93 | 94 | com.fasterxml.jackson.core 95 | jackson-databind 96 | 2.9.8 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/Exceptions/MessageTimeOutException.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.Exceptions; 2 | 3 | public class MessageTimeOutException extends Exception{ 4 | public MessageTimeOutException() { 5 | super(); 6 | } 7 | public MessageTimeOutException(String message) { 8 | super(message); 9 | } 10 | public MessageTimeOutException(String message, Throwable cause) { 11 | super(message,cause); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/messaging/CDPClient.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.messaging; 2 | 3 | import com.jayway.jsonpath.DocumentContext; 4 | import com.jayway.jsonpath.JsonPath; 5 | import com.neovisionaries.ws.client.WebSocket; 6 | import com.neovisionaries.ws.client.WebSocketAdapter; 7 | import com.neovisionaries.ws.client.WebSocketException; 8 | import com.neovisionaries.ws.client.WebSocketFactory; 9 | import com.sahajamit.Exceptions.MessageTimeOutException; 10 | import com.sahajamit.utils.SSLUtil; 11 | import com.sahajamit.utils.Utils; 12 | import org.json.JSONArray; 13 | import org.json.JSONException; 14 | import org.json.JSONObject; 15 | 16 | import java.io.IOException; 17 | import java.util.Base64; 18 | import java.util.Objects; 19 | import java.util.concurrent.*; 20 | 21 | public class CDPClient { 22 | private String wsUrl; 23 | private WebSocket ws = null; 24 | private WebSocketFactory factory; 25 | private BlockingQueue blockingQueue = new LinkedBlockingDeque(100000); 26 | public CDPClient(String wsURL){ 27 | factory = new WebSocketFactory(); 28 | SSLUtil.turnOffSslChecking(factory); 29 | factory.setVerifyHostname(false); 30 | this.wsUrl = wsURL; 31 | } 32 | 33 | private void connect() throws IOException, WebSocketException { 34 | if(Objects.isNull(ws)){ 35 | System.out.println("Making the new WS connection to: " + wsUrl); 36 | ws = factory 37 | .createSocket(wsUrl) 38 | .addListener(new WebSocketAdapter() { 39 | @Override 40 | public void onTextMessage(WebSocket ws, String message) { 41 | // Received a response. Print the received message. 42 | System.out.println("Received this ws message: "+message); 43 | blockingQueue.add(message); 44 | } 45 | }) 46 | .connect(); 47 | } 48 | } 49 | 50 | public void sendMessage(String message) throws IOException, WebSocketException { 51 | if(Objects.isNull(ws)) 52 | this.connect(); 53 | System.out.println("Sending this ws message: " + message); 54 | ws.sendText(message); 55 | } 56 | 57 | public String getResponseMessage(String jsonPath, String expectedValue) throws InterruptedException { 58 | while(true){ 59 | String message = blockingQueue.poll(5, TimeUnit.SECONDS); 60 | if(Objects.isNull(message)) 61 | return null; 62 | DocumentContext parse = JsonPath.parse(message); 63 | String value = parse.read(jsonPath.trim()).toString(); 64 | if(value.equalsIgnoreCase(expectedValue)) 65 | return message; 66 | } 67 | } 68 | 69 | public String getResponseMessage(String methodName) throws InterruptedException { 70 | return getResponseMessage(methodName,5); 71 | } 72 | 73 | public String getResponseMessage(String methodName, int timeoutInSecs) throws InterruptedException { 74 | try{ 75 | while(true){ 76 | String message = blockingQueue.poll(timeoutInSecs, TimeUnit.SECONDS); 77 | if(Objects.isNull(message)) 78 | throw new RuntimeException(String.format("No message received with this method name : '%s'",methodName)); 79 | JSONObject jsonObject = new JSONObject(message); 80 | try{ 81 | String method = jsonObject.getString("method"); 82 | if(method.equalsIgnoreCase(methodName)){ 83 | return message; 84 | } 85 | }catch (JSONException e){ 86 | //do nothing 87 | } 88 | } 89 | }catch (Exception e1){ 90 | throw e1; 91 | } 92 | } 93 | 94 | public String getResponseBodyMessage(int id) throws InterruptedException { 95 | try{ 96 | while(true){ 97 | String message = blockingQueue.poll(5, TimeUnit.SECONDS); 98 | if(Objects.isNull(message)) 99 | throw new RuntimeException(String.format("No message received with this id : '%s'",id)); 100 | JSONObject jsonObject = new JSONObject(message); 101 | try{ 102 | int methodId = jsonObject.getInt("id"); 103 | if(id == methodId){ 104 | return jsonObject.getJSONObject("result").getString("body"); 105 | } 106 | }catch (JSONException e){ 107 | //do nothing 108 | } 109 | } 110 | }catch (Exception e1){ 111 | throw e1; 112 | } 113 | } 114 | 115 | public String getResponseDataMessage(int id) throws Exception { 116 | return getResponseMessage(id,"data"); 117 | } 118 | 119 | public String getResponseMessage(int id, String dataType) throws InterruptedException, MessageTimeOutException { 120 | while(true){ 121 | String message = blockingQueue.poll(10, TimeUnit.SECONDS); 122 | if(Objects.isNull(message)) 123 | throw new MessageTimeOutException(String.format("No message received with this id : '%s'",id)); 124 | JSONObject jsonObject = new JSONObject(message); 125 | try{ 126 | int methodId = jsonObject.getInt("id"); 127 | if(id == methodId){ 128 | return jsonObject.getJSONObject("result").getString(dataType); 129 | } 130 | }catch (JSONException e){ 131 | //do nothing 132 | } 133 | } 134 | } 135 | 136 | public void mockResponse(String mockMessage){ 137 | new Thread(() -> { 138 | try{ 139 | String message = this.getResponseMessage("Network.requestIntercepted",5); 140 | JSONObject jsonObject = new JSONObject(message); 141 | String interceptionId = jsonObject.getJSONObject("params").getString("interceptionId"); 142 | int id = Utils.getInstance().getDynamicID(); 143 | this.sendMessage(MessageBuilder.buildGetContinueInterceptedRequestMessage(id,interceptionId,mockMessage)); 144 | return; 145 | }catch (Exception e){ 146 | //do nothing 147 | } 148 | }).start(); 149 | } 150 | 151 | public void mockFunResponse(String encodedMessage){ 152 | new Thread(() -> { 153 | try{ 154 | while(true){ 155 | String message = this.getResponseMessage("Network.requestIntercepted",10); 156 | JSONObject jsonObject = new JSONObject(message); 157 | String interceptionId = jsonObject.getJSONObject("params").getString("interceptionId"); 158 | // int id1 = Utils.getInstance().getDynamicID(); 159 | // this.sendMessage(MessageBuilder.buildGetResponseBodyForInterceptionMessage(id1,interceptionId)); 160 | // String interceptedResponse = this.getResponseBodyMessage(id1); 161 | int id = Utils.getInstance().getDynamicID(); 162 | this.sendMessage(MessageBuilder.buildGetContinueInterceptedRequestEncodedMessage(id,interceptionId,encodedMessage)); 163 | } 164 | }catch (Exception e){ 165 | //do nothing 166 | } 167 | }).start(); 168 | } 169 | 170 | public ServiceWorker getServiceWorker(String workerURL, int timeoutInSecs, String expectedStatus) throws InterruptedException { 171 | while(true){ 172 | String message = getResponseMessage("ServiceWorker.workerVersionUpdated",timeoutInSecs); 173 | if(Objects.isNull(message)) 174 | return null; 175 | JSONObject jsonObject = new JSONObject(message); 176 | JSONArray jsonArray = jsonObject.getJSONObject("params").getJSONArray("versions"); 177 | try{ 178 | String scriptURL = jsonArray.getJSONObject(0).getString("scriptURL"); 179 | String status = jsonArray.getJSONObject(0).getString("status"); 180 | if(scriptURL.contains(workerURL) && status.equalsIgnoreCase(expectedStatus)){ 181 | String targetId = jsonArray.getJSONObject(0).getString("targetId"); 182 | String versionId = jsonArray.getJSONObject(0).getString("versionId"); 183 | String registrationId = jsonArray.getJSONObject(0).getString("registrationId"); 184 | String runningStatus = jsonArray.getJSONObject(0).getString("registrationId"); 185 | ServiceWorker serviceWorker = new ServiceWorker(versionId,registrationId,targetId); 186 | serviceWorker.setRunningStatus(runningStatus); 187 | serviceWorker.setStatus(status); 188 | return serviceWorker; 189 | } 190 | }catch (Exception e){ 191 | //do nothing 192 | } 193 | } 194 | } 195 | 196 | public void disconnect(){ 197 | ws.disconnect(); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/messaging/Message.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.messaging; 2 | 3 | import com.google.gson.Gson; 4 | import org.json.JSONObject; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.Objects; 9 | 10 | public class Message { 11 | private int id; 12 | private String method; 13 | private Map params; 14 | 15 | public Message(int id, String method) { 16 | this.id = id; 17 | this.method = method; 18 | } 19 | 20 | public void addParam(String key, Object value){ 21 | if(Objects.isNull(params)) 22 | params = new HashMap<>(); 23 | params.put(key,value); 24 | } 25 | 26 | public String toJson(){ 27 | Gson gson = new Gson(); 28 | return gson.toJson(this); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/messaging/MessageBuilder.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.messaging; 2 | 3 | import com.sahajamit.utils.Utils; 4 | import org.apache.commons.codec.binary.Base64; 5 | import org.json.JSONObject; 6 | 7 | public class MessageBuilder { 8 | public static String buildGeoLocationMessage(int id, double latitude, double longitude){ 9 | Message msg = new Message(id,"Emulation.setGeolocationOverride"); 10 | msg.addParam("latitude",latitude); 11 | msg.addParam("longitude",longitude); 12 | msg.addParam("accuracy",100); 13 | String message = msg.toJson(); 14 | // String message = String.format("{\"id\":%s,\"method\":\"Emulation.setGeolocationOverride\",\"params\":{\"latitude\":%s,\"longitude\":%s,\"accuracy\":100}}",id,latitude,longitude); 15 | return message; 16 | } 17 | 18 | public static String buildGetResponseBodyMessage(int id, String requestID){ 19 | String message = String.format("{\"id\":%s,\"method\":\"Network.getResponseBody\",\"params\":{\"requestId\":\"%s\"}}",id,requestID); 20 | return message; 21 | } 22 | 23 | public static String buildNetWorkEnableMessage(int id){ 24 | String message = String.format("{\"id\":%s,\"method\":\"Network.enable\",\"params\":{\"maxTotalBufferSize\":10000000,\"maxResourceBufferSize\":5000000}}",id); 25 | return message; 26 | } 27 | 28 | public static String buildRequestInterceptorPatternMessage(int id, String pattern, String resourceType){ 29 | String message = String.format("{\"id\":%s,\"method\":\"Network.setRequestInterception\",\"params\":{\"patterns\":[{\"urlPattern\":\"%s\",\"resourceType\":\"%s\",\"interceptionStage\":\"HeadersReceived\"}]}}",id,pattern,resourceType); 30 | return message; 31 | } 32 | 33 | public static String buildGetResponseBodyForInterceptionMessage(int id, String interceptionId){ 34 | String message = String.format("{\"id\":%s,\"method\":\"Network.getResponseBodyForInterception\",\"params\":{\"interceptionId\":\"%s\"}}",id,interceptionId); 35 | return message; 36 | } 37 | 38 | public static String buildGetContinueInterceptedRequestMessage(int id, String interceptionId, String response){ 39 | String encodedResponse = new String(Base64.encodeBase64(response.getBytes())); 40 | String message = String.format("{\"id\":%s,\"method\":\"Network.continueInterceptedRequest\",\"params\":{\"interceptionId\":\"%s\",\"rawResponse\":\"%s\"}}",id,interceptionId,encodedResponse); 41 | return message; 42 | } 43 | 44 | public static String buildGetContinueInterceptedRequestEncodedMessage(int id, String interceptionId, String encodedResponse){ 45 | String message = String.format("{\"id\":%s,\"method\":\"Network.continueInterceptedRequest\",\"params\":{\"interceptionId\":\"%s\",\"rawResponse\":\"%s\"}}",id,interceptionId,encodedResponse); 46 | return message; 47 | } 48 | 49 | public static String buildServiceWorkerEnableMessage(int id){ 50 | String message = String.format("{\"id\":%s,\"method\":\"ServiceWorker.enable\"}",id); 51 | return message; 52 | } 53 | 54 | public static String buildServiceWorkerInspectMessage(int id, String versionId){ 55 | String message = String.format("{\"id\":%s,\"method\":\"ServiceWorker.inspectWorker\",\"params\":{\"versionId\":\"%s\"}}",id,"versionId"); 56 | return message; 57 | } 58 | 59 | public static String buildEnableLogMessage(int id){ 60 | String message = String.format("{\"id\":%d,\"method\":\"Log.enable\"}",id); 61 | return message; 62 | } 63 | 64 | public static String buildEnableRuntimeMessage(int id){ 65 | String message = String.format("{\"id\":%d,\"method\":\"Runtime.enable\"}",id); 66 | return message; 67 | } 68 | 69 | public static String buildSendPushNotificationMessage(int id, String origin, String registrationId, String data){ 70 | String message = String.format("{\"id\":%s,\"method\":\"ServiceWorker.deliverPushMessage\",\"params\":{\"origin\":\"%s\",\"registrationId\":\"%s\",\"data\":\"%s\"}}",id,origin,registrationId,data); 71 | return message; 72 | } 73 | 74 | public static String buildObserveBackgroundServiceMessage(int id){ 75 | String message = String.format("{\"id\":%s,\"method\":\"BackgroundService.startObserving\",\"params\":{\"service\":\"%s\"}}",id,"pushMessaging"); 76 | return message; 77 | } 78 | 79 | public static String buildGetBrowserContextMessage(int id){ 80 | String message = String.format("{\"id\":%d,\"method\":\"Target.getBrowserContexts\"}",id); 81 | return message; 82 | } 83 | 84 | public static String buildClearBrowserCacheMessage(int id){ 85 | String message = String.format("{\"id\":%d,\"method\":\"Network.clearBrowserCache\"}",id); 86 | return message; 87 | } 88 | 89 | public static String buildClearBrowserCookiesMessage(int id){ 90 | String message = String.format("{\"id\":%d,\"method\":\"Network.clearBrowserCookies\"}",id); 91 | return message; 92 | } 93 | 94 | public static String buildClearDataForOriginMessage(int id, String url){ 95 | String message = String.format("{\"id\":%s,\"method\":\"Storage.clearDataForOrigin\",\"params\":{\"origin\":\"%s\",\"storageTypes\":\"all\"}}",id,url); 96 | return message; 97 | } 98 | 99 | public static String buildTakeElementScreenShotMessage(int id, long x, long y, long height, long width, int scale){ 100 | String message = String.format("{\"id\":%s,\"method\":\"Page.captureScreenshot\",\"params\":{\"clip\":{\"x\":%s,\"y\":%s,\"width\":%s,\"height\":%s,\"scale\":%s}}}",id,x,y,width,height,scale); 101 | return message; 102 | } 103 | public static String buildTakePageScreenShotMessage(int id){ 104 | Message msg = new Message(id,"Page.captureScreenshot"); 105 | String message = msg.toJson(); 106 | // String message = String.format("{\"id\":%s,\"method\":\"Page.captureScreenshot\"}",id); 107 | return message; 108 | } 109 | 110 | 111 | 112 | private String buildRequestInterceptorEnabledMessage(){ 113 | String message = String.format("{\"id\":4,\"method\":\"Network.setRequestInterception\",\"params\":{\"enabled\":true}}"); 114 | System.out.println(message); 115 | return message; 116 | } 117 | 118 | 119 | private String buildBasicHttpAuthenticationMessage(String username,String password){ 120 | byte[] encodedBytes = Base64.encodeBase64(String.format("%s:%s",username,password).getBytes()); 121 | String base64EncodedCredentials = new String(encodedBytes); 122 | String message = String.format("{\"id\":2,\"method\":\"Network.setExtraHTTPHeaders\",\"params\":{\"headers\":{\"Authorization\":\"Basic %s\"}}}",base64EncodedCredentials); 123 | System.out.println(message); 124 | return message; 125 | } 126 | 127 | 128 | 129 | private String buildSendObservingPushMessage(){ 130 | int id = Utils.getInstance().getDynamicID(); 131 | String message = String.format("{\"id\":%d,\"method\":\"BackgroundService.clearEvents\",\"params\":{\"service\":\"backgroundFetch\"}}",id); 132 | System.out.println(message); 133 | return message; 134 | } 135 | 136 | 137 | 138 | private String buildAttachToTargetMessage(String targetId){ 139 | int id = Utils.getInstance().getDynamicID(); 140 | String message = String.format("{\"id\":%d,\"method\":\"Target.attachToTarget\",\"params\":{\"targetId\":\"%s\"}}",id,targetId); 141 | System.out.println(message); 142 | return message; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/messaging/ServiceWorker.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.messaging; 2 | 3 | public class ServiceWorker { 4 | private String versionId; 5 | private String registrationId; 6 | private String targetId; 7 | private String status; 8 | private String runningStatus; 9 | 10 | public ServiceWorker(String versionId, String registrationId, String targetId) { 11 | this.versionId = versionId; 12 | this.registrationId = registrationId; 13 | this.targetId = targetId; 14 | } 15 | 16 | public String getVersionId() { 17 | return versionId; 18 | } 19 | 20 | public String getRegistrationId() { 21 | return registrationId; 22 | } 23 | 24 | public String getTargetId() { 25 | return targetId; 26 | } 27 | 28 | public String getStatus() { 29 | return status; 30 | } 31 | 32 | public void setStatus(String status) { 33 | this.status = status; 34 | } 35 | 36 | public String getRunningStatus() { 37 | return runningStatus; 38 | } 39 | 40 | public void setRunningStatus(String runningStatus) { 41 | this.runningStatus = runningStatus; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "ServiceWorker{" + 47 | "versionId='" + versionId + '\'' + 48 | ", registrationId='" + registrationId + '\'' + 49 | ", targetId='" + targetId + '\'' + 50 | ", status='" + status + '\'' + 51 | ", runningStatus='" + runningStatus + '\'' + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/utils/SSLUtil.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.utils; 2 | 3 | import com.neovisionaries.ws.client.WebSocketFactory; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.net.ssl.HttpsURLConnection; 8 | import javax.net.ssl.SSLContext; 9 | import javax.net.ssl.TrustManager; 10 | import javax.net.ssl.X509TrustManager; 11 | import java.security.KeyManagementException; 12 | import java.security.NoSuchAlgorithmException; 13 | import java.security.cert.X509Certificate; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | public class SSLUtil { 18 | private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{ 19 | new X509TrustManager() { 20 | public X509Certificate[] getAcceptedIssuers(){ 21 | return null; 22 | } 23 | public void checkClientTrusted( X509Certificate[] certs, String authType ){} 24 | public void checkServerTrusted( X509Certificate[] certs, String authType ){} 25 | } 26 | }; 27 | 28 | public static void turnOffSslChecking() { 29 | try{ 30 | // Install the all-trusting trust manager 31 | final SSLContext sc = SSLContext.getInstance("SSL"); 32 | sc.init( null, UNQUESTIONING_TRUST_MANAGER, null ); 33 | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 34 | }catch(Exception e){ 35 | System.out.println("Error in SSL Utils"); 36 | } 37 | } 38 | 39 | public static void turnOffSslChecking(WebSocketFactory factory) { 40 | try{ 41 | // Install the all-trusting trust manager 42 | final SSLContext sc = SSLContext.getInstance("SSL"); 43 | sc.init( null, UNQUESTIONING_TRUST_MANAGER, null ); 44 | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 45 | factory.setSSLContext(sc); 46 | }catch(Exception e){ 47 | System.out.println("Error in SSL Utils"); 48 | } 49 | } 50 | 51 | public static void turnOnSslChecking() throws KeyManagementException, NoSuchAlgorithmException { 52 | // Return it to the initial state (discovered by reflection, now hardcoded) 53 | SSLContext.getInstance("SSL").init( null, null, null ); 54 | } 55 | 56 | private SSLUtil(){ 57 | throw new UnsupportedOperationException( "Do not instantiate libraries."); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/utils/UINotificationService.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.utils; 2 | 3 | import org.openqa.selenium.JavascriptExecutor; 4 | import org.openqa.selenium.WebDriver; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Map; 10 | import java.util.concurrent.atomic.AtomicBoolean; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | public class UINotificationService { 14 | private static final Logger logger = LoggerFactory.getLogger(UINotificationService.class); 15 | private WebDriver driver; 16 | private static UINotificationService ourInstance = new UINotificationService(); 17 | private static final String startWebNotificationJsScript = "window.notifications = []; window.DefaultNotification = window.Notification; (function () { function notificationCallback(title, opt) { console.log(\"notification title: \", title); console.log(\"notification body: \", opt.body); console.log(\"notification tag: \", opt.tag); console.log(\"notification icon: \", opt.icon); } const handler = { construct(target, args) { notificationCallback(...args); var notification = new target(...args); window.notifications.push(notification); return notification; } }; const ProxifiedNotification = new Proxy(Notification, handler); window.Notification = ProxifiedNotification; })();"; 18 | private static final String stopWebNotificationJsScript = "window.notifications = []; window.Notification = window.DefaultNotification;"; 19 | 20 | private static final String startPushNotificationJsScript = "window.notificationsMap = Object.create(null); async function getServiceWorkerRegistration(){ window.myServiceWorkerRegistration = await navigator.serviceWorker.getRegistration(\"%s\"); return window.myServiceWorkerRegistration;}; async function getNotifications() { window.myNotifications = await window.myServiceWorkerRegistration.getNotifications();}; window.notificationListener = setInterval(async function() { console.log(\"checking for notifications...\"); await getServiceWorkerRegistration(); await getNotifications(); for(var key in window.myNotifications){ window.notificationsMap[window.myNotifications[key].tag] = window.myNotifications[key]; }; }, 2000);"; 21 | private static final String stopPushNotificationJsScript = "clearInterval(window.notificationListener); window.notificationsMap = Object.create(null); window.notifications = [] ;"; 22 | private static final String getPushNotificationsJsScript = "function getCollectedNotifications(){ window.notifications = [] ; var count = 0; for (var prop in window.notificationsMap) { count++; window.notifications.push(window.notificationsMap[prop]); } console.log(\"Total notifications count is: \" + count); return window.notifications;}; return getCollectedNotifications();"; 23 | 24 | public static UINotificationService getInstance(WebDriver driver) { 25 | ourInstance.driver = driver; 26 | return ourInstance; 27 | } 28 | 29 | private UINotificationService() { 30 | } 31 | 32 | public void startWebNotificationListener(){ 33 | UIUtils.getInstance().executeJavaScript(startWebNotificationJsScript); 34 | } 35 | 36 | public void startPushNotificationListener(String notificationServiceURL){ 37 | UIUtils.getInstance().executeJavaScript(String.format(startPushNotificationJsScript,notificationServiceURL)); 38 | } 39 | 40 | public void stopWebNotificationListener(){ 41 | UIUtils.getInstance().executeJavaScript(stopWebNotificationJsScript); 42 | } 43 | public void stopPushNotificationListener(){ 44 | UIUtils.getInstance().executeJavaScript(stopPushNotificationJsScript); 45 | } 46 | 47 | 48 | public boolean isNotificationPresent(Map filter, String notificationType){ 49 | ArrayList notifications; 50 | if(notificationType.equalsIgnoreCase("web")) 51 | notifications = (ArrayList) UIUtils.getInstance().executeJavaScript("return window.notifications;"); 52 | else 53 | notifications = (ArrayList) UIUtils.getInstance().executeJavaScript(getPushNotificationsJsScript); 54 | 55 | AtomicInteger ai = new AtomicInteger(0); 56 | AtomicBoolean ab = new AtomicBoolean(false); 57 | notifications.stream() 58 | .forEach(n->{ 59 | logger.info("Closing this UI Notification : " + n.toString()); 60 | String closeScript = String.format("window.notifications[%d].close();",ai.get()); 61 | ((JavascriptExecutor) driver).executeScript(closeScript); 62 | ai.addAndGet(1); 63 | if(matchNotification(n,filter)) { 64 | ab.set(true); 65 | logger.info("Notification found with this criteria: " + n.toString()); 66 | return; 67 | } 68 | }); 69 | return ab.get(); 70 | } 71 | 72 | private boolean matchNotification(Map actual, Map expected){ 73 | AtomicBoolean ab = new AtomicBoolean(true); 74 | expected.entrySet() 75 | .forEach(e->{ 76 | if(!actual.get(e.getKey()).equalsIgnoreCase(e.getValue())){ 77 | ab.set(false); 78 | return; 79 | } 80 | }); 81 | return ab.get(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/utils/UIUtils.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.utils; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | import org.openqa.selenium.*; 5 | import org.openqa.selenium.remote.Augmenter; 6 | import org.openqa.selenium.support.ui.FluentWait; 7 | import org.openqa.selenium.support.ui.Wait; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.text.SimpleDateFormat; 14 | import java.util.Date; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | public class UIUtils { 18 | private static UIUtils instance = null; 19 | private static final Logger LOGGER = LoggerFactory.getLogger(UIUtils.class); 20 | private WebDriver driver; 21 | 22 | public static UIUtils getInstance() { 23 | if (instance == null) { 24 | instance = new UIUtils(); 25 | } 26 | 27 | return instance; 28 | } 29 | 30 | public UIUtils() { 31 | } 32 | 33 | public void setDriver(WebDriver driver){ 34 | this.driver = driver; 35 | } 36 | 37 | public WebElement findElement(By locator, int loadTimeout) { 38 | Wait wait = (new FluentWait(driver)).withTimeout((long)loadTimeout, TimeUnit.SECONDS).pollingEvery(1L, TimeUnit.SECONDS).ignoring(NoSuchElementException.class); 39 | WebElement element = (WebElement)wait.until((driver) -> { 40 | return driver.findElement(locator); 41 | }); 42 | return element; 43 | } 44 | 45 | public void takeScreenShot() { 46 | try { 47 | String start_time = (new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")).format(new Date()); 48 | String imageName = "selenium_img_" + start_time + ".png"; 49 | File imageFolder = new File(System.getProperty("user.dir") + "/target"); 50 | if (!imageFolder.exists()) { 51 | imageFolder.mkdir(); 52 | } 53 | String imagePath = imageFolder.getAbsolutePath() + "/" + imageName; 54 | driver = (new Augmenter()).augment(this.driver); 55 | File scrFile = (File)((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); 56 | FileUtils.copyFile(scrFile, new File(imagePath)); 57 | } catch (IOException var9) { 58 | LOGGER.error("Error", var9); 59 | throw new IllegalStateException("Error taking screenshot"); 60 | } 61 | } 62 | 63 | public Object executeJavaScript(String script) { 64 | Object obj = ((JavascriptExecutor)driver).executeScript(script,new Object[0]); 65 | return obj; 66 | } 67 | 68 | public Object executeJavaScript(String script, WebElement element) { 69 | Object obj = ((JavascriptExecutor)driver).executeScript(script, new Object[]{element}); 70 | return obj; 71 | } 72 | 73 | public void scrollToElement(WebElement element) { 74 | this.executeJavaScript("arguments[0].scrollIntoView(true);", element); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/sahajamit/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.json.JSONArray; 6 | import org.json.JSONObject; 7 | import org.openqa.selenium.WebDriver; 8 | import org.openqa.selenium.chrome.ChromeDriverService; 9 | import org.openqa.selenium.chrome.ChromeOptions; 10 | import org.openqa.selenium.logging.LogEntries; 11 | import org.openqa.selenium.logging.LogEntry; 12 | import org.openqa.selenium.logging.LogType; 13 | import org.openqa.selenium.logging.LoggingPreferences; 14 | import org.openqa.selenium.remote.CapabilityType; 15 | import org.openqa.selenium.remote.DesiredCapabilities; 16 | import org.openqa.selenium.remote.RemoteWebDriver; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.io.*; 21 | import java.net.HttpURLConnection; 22 | import java.net.URL; 23 | import java.util.*; 24 | import java.util.concurrent.TimeUnit; 25 | import java.util.logging.Level; 26 | 27 | public class Utils { 28 | private Utils Utils; 29 | private String os; 30 | private ChromeDriverService service; 31 | private LoggingPreferences loggingPreferences = null; 32 | private WebDriver driver; 33 | private String wsURL; 34 | private static ThreadLocal instance = new ThreadLocal(); 35 | private static final Logger logger = LoggerFactory.getLogger(Utils.class); 36 | public static Utils getInstance() { 37 | if (instance.get() == null) { 38 | instance.set(new Utils()); 39 | } 40 | return instance.get(); 41 | } 42 | 43 | public Utils(){ 44 | loggingPreferences = new LoggingPreferences(); 45 | loggingPreferences.enable(LogType.PERFORMANCE, Level.ALL); 46 | loggingPreferences.enable(LogType.BROWSER, Level.ALL); 47 | loggingPreferences.enable(LogType.DRIVER, Level.ALL); 48 | } 49 | public WebDriver launchBrowser() throws IOException { 50 | return launchBrowser(false); 51 | } 52 | 53 | public WebDriver launchBrowser(boolean isHeadless) throws IOException { 54 | return launchBrowser(isHeadless,null); 55 | } 56 | public WebDriver launchBrowser(boolean isHeadless, URL remoteDriverURL) throws IOException { 57 | logger.info("Launching the Chrome..."); 58 | os = System.getProperty("os.name").toLowerCase(); 59 | Map prefs=new HashMap(); 60 | //1-Allow, 2-Block, 0-default 61 | prefs.put("profile.default_content_setting_values.notifications", 1); 62 | 63 | //0 is default , 1 is enable and 2 is disable 64 | prefs.put("profile.content_settings.exceptions.clipboard", getClipBoardSettingsMap(1)); 65 | 66 | LoggingPreferences logPrefs = new LoggingPreferences(); 67 | logPrefs.enable(LogType.BROWSER, Level.ALL); 68 | ChromeOptions options = new ChromeOptions(); 69 | options.addArguments(Arrays.asList("--start-maximized")); 70 | options.addArguments(Arrays.asList("--ssl-protocol=any")); 71 | options.addArguments(Arrays.asList("--ignore-ssl-errors=true")); 72 | options.addArguments(Arrays.asList("--disable-extensions")); 73 | options.addArguments(Arrays.asList("--ignore-certificate-errors")); 74 | options.addArguments(Arrays.asList("--remote-debugging-port=9222")); 75 | options.addArguments(Arrays.asList("--remote-debugging-address=0.0.0.0")); 76 | 77 | options.setExperimentalOption("useAutomationExtension", false); 78 | if(isHeadless){ 79 | options.addArguments(Arrays.asList("--headless","--disable-gpu")); 80 | } 81 | options.setExperimentalOption("prefs",prefs); 82 | options.setCapability("goog:loggingPrefs", loggingPreferences); 83 | 84 | DesiredCapabilities crcapabilities = DesiredCapabilities.chrome(); 85 | crcapabilities.setCapability(ChromeOptions.CAPABILITY, options); 86 | crcapabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); 87 | crcapabilities.setCapability(CapabilityType.LOGGING_PREFS, logPrefs); 88 | 89 | // System.setProperty(ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY, "/dev/shm/chromedriver.log"); 90 | System.setProperty(ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY, System.getProperty("user.dir") + "/target/chromedriver.log"); 91 | 92 | if(os.indexOf("mac") >= 0) 93 | System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, System.getProperty("user.dir") + "/driver/chromedriver"); 94 | else 95 | System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, System.getProperty("user.dir") + "/driver/chromedriver.exe"); 96 | service = new ChromeDriverService.Builder() 97 | .usingAnyFreePort() 98 | .withVerbose(true) 99 | .build(); 100 | if(Objects.isNull(remoteDriverURL)) 101 | service.start(); 102 | 103 | try{ 104 | if(Objects.isNull(remoteDriverURL)) 105 | driver = new RemoteWebDriver(service.getUrl(),crcapabilities); 106 | else 107 | driver = new RemoteWebDriver(remoteDriverURL,crcapabilities); 108 | }catch (Exception e){ 109 | throw e; 110 | } 111 | 112 | UIUtils.getInstance().setDriver(driver); 113 | return driver; 114 | } 115 | 116 | public String getWsURL(){ 117 | return wsURL; 118 | } 119 | 120 | public void stopChrome(){ 121 | driver.close(); 122 | driver.quit(); 123 | service.stop(); 124 | } 125 | 126 | public void waitFor(long time){ 127 | try { 128 | TimeUnit.SECONDS.sleep(time); 129 | Thread.sleep(time); 130 | } catch (InterruptedException e) { 131 | e.printStackTrace(); 132 | } 133 | } 134 | 135 | public int getDynamicID() { 136 | int min = 100000; 137 | int max = 999999; 138 | Random r = new Random(); 139 | return r.nextInt((max - min) + 1) + min; 140 | } 141 | 142 | public String getSWURL(String wsURL, String targetID){ 143 | String[] arr = wsURL.split("page/"); 144 | String id = arr[1]; 145 | return wsURL.replace(id,targetID); 146 | } 147 | 148 | public String getWebSocketDebuggerUrlFromDriverLogs() throws IOException { 149 | String webSocketDebuggerUrl = ""; 150 | String urlString = "http://localhost:9222/json"; 151 | 152 | URL url = new URL(urlString); 153 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 154 | BufferedReader reader = 155 | new BufferedReader(new InputStreamReader(conn.getInputStream())); 156 | String json = org.apache.commons.io.IOUtils.toString(reader); 157 | JSONArray jsonArray = new JSONArray(json); 158 | for(int i=0; i getClipBoardSettingsMap(int settingValue) throws JsonProcessingException { 177 | Map map = new HashMap<>(); 178 | map.put("last_modified",String.valueOf(System.currentTimeMillis())); 179 | map.put("setting", settingValue); 180 | Map cbPreference = new HashMap<>(); 181 | cbPreference.put("[*.],*",map); 182 | ObjectMapper objectMapper = new ObjectMapper(); 183 | String json = objectMapper.writeValueAsString(cbPreference); 184 | logger.info("clipboardSettingJson: " + json); 185 | return cbPreference; 186 | } 187 | } 188 | 189 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | 7 | # A1 uses PatternLayout. 8 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n -------------------------------------------------------------------------------- /src/test/java/com/sahajamit/ClipboardTests.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit; 2 | 3 | import com.sahajamit.utils.UIUtils; 4 | import com.sahajamit.utils.Utils; 5 | import org.junit.After; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.openqa.selenium.By; 10 | import org.openqa.selenium.WebDriver; 11 | import org.openqa.selenium.chrome.ChromeDriverService; 12 | 13 | import java.awt.*; 14 | import java.awt.datatransfer.DataFlavor; 15 | import java.net.URL; 16 | import java.util.Objects; 17 | 18 | public class ClipboardTests { 19 | 20 | private WebDriver driver; 21 | private String wsURL; private Utils utils; 22 | private UIUtils uiUtils; 23 | private ChromeDriverService chromeDriverService; 24 | 25 | @Before 26 | public void beforeTest(){ 27 | this.utils = Utils.getInstance(); 28 | this.uiUtils = UIUtils.getInstance(); 29 | } 30 | 31 | @After 32 | public void afterTest(){ 33 | utils.stopChrome(); 34 | if(!Objects.isNull(chromeDriverService)) 35 | chromeDriverService.stop(); 36 | } 37 | @Test 38 | public void doLocalClipboardReadTest() throws Exception { 39 | String text = "Mussum ipsum cacilds, vidis litro abertis. Consetis adipiscings elitis. Pra lá , depois divoltis porris, paradis. Paisis, filhis, espiritis santis. Mé faiz elementum girarzis, nisi eros vermeio, in elementis mé pra quem é amistosis quis leo. Manduma pindureta quium dia nois paga."; 40 | driver = utils.launchBrowser(); 41 | driver.navigate().to("https://googlechrome.github.io/samples/async-clipboard/"); 42 | 43 | driver.findElement(By.cssSelector("textarea#out")).sendKeys(text); 44 | utils.waitFor(1); 45 | uiUtils.takeScreenShot(); 46 | driver.findElement(By.cssSelector("button#copy")).click(); 47 | utils.waitFor(1); 48 | String localClipboardData = (String) Toolkit.getDefaultToolkit() 49 | .getSystemClipboard().getData(DataFlavor.stringFlavor); 50 | Assert.assertEquals(text,localClipboardData); 51 | 52 | } 53 | 54 | @Test 55 | public void doRemoteClipboardReadTest() throws Exception { 56 | String text = "Mussum ipsum cacilds, vidis litro abertis. Consetis adipiscings elitis. Pra lá , depois divoltis porris, paradis. Paisis, filhis, espiritis santis. Mé faiz elementum girarzis, nisi eros vermeio, in elementis mé pra quem é amistosis quis leo. Manduma pindureta quium dia nois paga."; 57 | driver = utils.launchBrowser(true,new URL("http://127.0.0.1:4444/wd/hub")); 58 | driver.navigate().to("https://googlechrome.github.io/samples/async-clipboard/"); 59 | 60 | driver.findElement(By.cssSelector("textarea#out")).sendKeys(text); 61 | utils.waitFor(1); 62 | uiUtils.takeScreenShot(); 63 | driver.findElement(By.cssSelector("button#copy")).click(); 64 | utils.waitFor(1); 65 | String localClipboardData = this.getCBContents(); 66 | Assert.assertEquals(text,localClipboardData); 67 | } 68 | 69 | public String getCBContents(){ 70 | UIUtils.getInstance().executeJavaScript("async function getCBContents() { try { window.cb = await navigator.clipboard.readText(); console.log(\"Pasted content: \", window.cb); } catch (err) { console.error(\"Failed to read clipboard contents: \", err); window.cb = \"Error : \" + err; } } getCBContents();"); 71 | Object content = UIUtils.getInstance().executeJavaScript("return window.cb;"); 72 | return Objects.isNull(content) ? "null" : content.toString(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/com/sahajamit/DemoTests.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit; 2 | 3 | import com.neovisionaries.ws.client.WebSocketException; 4 | import com.sahajamit.messaging.CDPClient; 5 | import com.sahajamit.messaging.MessageBuilder; 6 | import com.sahajamit.messaging.ServiceWorker; 7 | import com.sahajamit.utils.UINotificationService; 8 | import com.sahajamit.utils.UIUtils; 9 | import com.sahajamit.utils.Utils; 10 | import org.apache.commons.io.FileUtils; 11 | import org.json.JSONObject; 12 | import org.junit.After; 13 | import org.junit.Assert; 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | import org.openqa.selenium.By; 17 | import org.openqa.selenium.WebDriver; 18 | import org.openqa.selenium.WebElement; 19 | import org.openqa.selenium.chrome.ChromeDriverService; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.net.URL; 24 | import java.nio.file.Files; 25 | import java.text.SimpleDateFormat; 26 | import java.util.*; 27 | 28 | public class DemoTests { 29 | private WebDriver driver; 30 | private String wsURL; private Utils utils; 31 | private UIUtils uiUtils; 32 | private CDPClient CDPClient; 33 | private ChromeDriverService chromeDriverService; 34 | 35 | @Before 36 | public void beforeTest(){ 37 | this.utils = Utils.getInstance(); 38 | this.uiUtils = UIUtils.getInstance(); 39 | } 40 | 41 | @After 42 | public void afterTest(){ 43 | if(!Objects.isNull(CDPClient)) 44 | CDPClient.disconnect(); 45 | utils.stopChrome(); 46 | if(!Objects.isNull(chromeDriverService)) 47 | chromeDriverService.stop(); 48 | } 49 | 50 | @Test 51 | public void doFakeGeoLocation() throws IOException, WebSocketException, InterruptedException { 52 | driver = utils.launchBrowser(); 53 | wsURL = utils.getWebSocketDebuggerUrl(); 54 | CDPClient = new CDPClient(wsURL); 55 | int id = Utils.getInstance().getDynamicID(); 56 | CDPClient.sendMessage(MessageBuilder.buildGeoLocationMessage(id,37.422290,-122.084057)); //google HQ 57 | utils.waitFor(3); 58 | driver.navigate().to("https://www.google.com.sg/maps"); 59 | uiUtils.findElement(By.cssSelector("div.widget-mylocation-button-icon-common"),3).click(); 60 | utils.waitFor(10); 61 | uiUtils.takeScreenShot(); 62 | } 63 | 64 | @Test 65 | public void doNetworkTracking() throws IOException, WebSocketException, InterruptedException { 66 | driver = utils.launchBrowser(true); 67 | wsURL = utils.getWebSocketDebuggerUrl(); 68 | CDPClient = new CDPClient(wsURL); 69 | int id = Utils.getInstance().getDynamicID(); 70 | CDPClient.sendMessage(MessageBuilder.buildNetWorkEnableMessage(id)); 71 | driver.navigate().to("http://petstore.swagger.io/v2/swagger.json"); 72 | utils.waitFor(3); 73 | String message = CDPClient.getResponseMessage("Network.requestWillBeSent"); 74 | JSONObject jsonObject = new JSONObject(message); 75 | String reqId = jsonObject.getJSONObject("params").getString("requestId"); 76 | int id2 = Utils.getInstance().getDynamicID(); 77 | CDPClient.sendMessage(MessageBuilder.buildGetResponseBodyMessage (id2,reqId)); 78 | String networkResponse = CDPClient.getResponseBodyMessage(id2); 79 | System.out.println("Here is the network Response: " + networkResponse); 80 | utils.waitFor(1); 81 | uiUtils.takeScreenShot(); 82 | } 83 | 84 | @Test 85 | public void doResponseMocking() throws Exception { 86 | driver = utils.launchBrowser(); 87 | wsURL = utils.getWebSocketDebuggerUrl(); 88 | CDPClient = new CDPClient(wsURL); 89 | int id = Utils.getInstance().getDynamicID(); 90 | CDPClient.sendMessage(MessageBuilder.buildRequestInterceptorPatternMessage (id,"*","Document")); 91 | CDPClient.mockResponse("This is mocked!!!"); 92 | driver.navigate().to("http://petstore.swagger.io/v2/swagger.json"); 93 | utils.waitFor(3); 94 | } 95 | 96 | @Test 97 | public void doFunMocking() throws Exception { 98 | byte[] fileContent = FileUtils.readFileToByteArray(new File(System.getProperty("user.dir") + "/data/durian.png")); 99 | String encodedString = Base64.getEncoder().encodeToString(fileContent); 100 | driver = utils.launchBrowser(); 101 | wsURL = utils.getWebSocketDebuggerUrl(); 102 | CDPClient = new CDPClient(wsURL); 103 | int id = Utils.getInstance().getDynamicID(); 104 | CDPClient.sendMessage(MessageBuilder.buildRequestInterceptorPatternMessage (id,"*","Image")); 105 | CDPClient.mockFunResponse(encodedString); 106 | driver.navigate().to("https://sg.carousell.com/"); 107 | utils.waitFor(300); 108 | } 109 | 110 | @Test 111 | public void doClearSiteData() throws Exception { 112 | String URL = "https://framework.realtime.co/demo/web-push"; 113 | driver = utils.launchBrowser(); 114 | wsURL = utils.getWebSocketDebuggerUrl(); 115 | CDPClient CDPClient = new CDPClient(wsURL); 116 | driver.navigate().to(URL); 117 | driver.manage().deleteAllCookies(); 118 | int id = Utils.getInstance().getDynamicID(); 119 | CDPClient.sendMessage(MessageBuilder.buildClearBrowserCookiesMessage(id)); 120 | CDPClient.sendMessage(MessageBuilder.buildClearDataForOriginMessage(id,"https://framework.realtime.co")); 121 | utils.waitFor(3); 122 | } 123 | 124 | @Test 125 | public void doElementScreenshot() throws Exception{ 126 | String URL = "https://www.meetup.com/"; 127 | driver = utils.launchBrowser(); 128 | wsURL = utils.getWebSocketDebuggerUrl(); 129 | CDPClient = new CDPClient(wsURL); 130 | driver.navigate().to(URL); 131 | WebElement logo = uiUtils.findElement(By.cssSelector("img[alt='Meetup logo']"),5); 132 | int x = logo.getLocation().getX(); 133 | int y = logo.getLocation().getY(); 134 | int width = logo.getSize().getWidth(); 135 | int height = logo.getSize().getHeight(); 136 | int scale = 1; 137 | int id = Utils.getInstance().getDynamicID(); 138 | CDPClient.sendMessage(MessageBuilder.buildTakeElementScreenShotMessage(id,x,y,height,width,scale)); 139 | String encodedBytes = CDPClient.getResponseDataMessage(id); 140 | byte[] bytes = Base64.getDecoder().decode(encodedBytes); 141 | File f = new File(System.getProperty("user.dir") + "/target/img.png"); 142 | if(f.exists()) 143 | f.delete(); 144 | Files.write(f.toPath(), bytes); 145 | uiUtils.takeScreenShot(); 146 | } 147 | 148 | @Test 149 | public void doFullPageScreenshot() throws Exception{ 150 | String URL = "https://www.meetup.com/"; 151 | driver = utils.launchBrowser(); 152 | wsURL = utils.getWebSocketDebuggerUrl(); 153 | CDPClient = new CDPClient(wsURL); 154 | driver.navigate().to(URL); 155 | long docWidth = (long) uiUtils.executeJavaScript("return document.body.offsetWidth"); 156 | long docHeight = (long) uiUtils.executeJavaScript("return document.body.offsetHeight"); 157 | int scale = 1; 158 | int id = Utils.getInstance().getDynamicID(); 159 | CDPClient.sendMessage(MessageBuilder.buildTakeElementScreenShotMessage(id,0,0,docHeight,docWidth,scale)); 160 | String encodedBytes = CDPClient.getResponseDataMessage(id); 161 | byte[] bytes = Base64.getDecoder().decode(encodedBytes); 162 | String start_time = (new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")).format(new Date()); 163 | String imageName = "cdp_img_" + start_time + ".png"; 164 | File f = new File(System.getProperty("user.dir") + "/target/" + imageName); 165 | if(f.exists()) 166 | f.delete(); 167 | Files.write(f.toPath(), bytes); 168 | uiUtils.takeScreenShot(); 169 | } 170 | 171 | @Test 172 | public void doServiceWorkerTesting() throws Exception { 173 | String URL = "https://www.meetup.com/"; 174 | driver = utils.launchBrowser(); 175 | wsURL = utils.getWebSocketDebuggerUrl(); 176 | CDPClient = new CDPClient(wsURL); 177 | int id = Utils.getInstance().getDynamicID(); 178 | CDPClient.sendMessage(MessageBuilder.buildServiceWorkerEnableMessage(id)); 179 | driver.navigate().to(URL); 180 | ServiceWorker serviceWorker = CDPClient.getServiceWorker(URL,10, "activated"); 181 | System.out.println(serviceWorker.toString()); 182 | Assert.assertEquals(serviceWorker.getStatus(),"activated"); 183 | } 184 | 185 | @Test 186 | public void doPushNotificationTesting() throws Exception { 187 | String URL = "https://framework.realtime.co/demo/web-push"; 188 | driver = utils.launchBrowser(); 189 | wsURL = utils.getWebSocketDebuggerUrl(); 190 | CDPClient = new CDPClient(wsURL); 191 | int id = Utils.getInstance().getDynamicID(); 192 | CDPClient.sendMessage(MessageBuilder.buildServiceWorkerEnableMessage(id)); 193 | driver.navigate().to(URL); 194 | utils.waitFor(2); 195 | utils.waitFor(3); 196 | ServiceWorker serviceWorker = CDPClient.getServiceWorker(URL,5, "activated"); 197 | int id1 = Utils.getInstance().getDynamicID(); 198 | int id2 = Utils.getInstance().getDynamicID(); 199 | 200 | CDPClient.sendMessage(MessageBuilder.buildEnableLogMessage(id1)); 201 | CDPClient.sendMessage(MessageBuilder.buildEnableRuntimeMessage(id2)); 202 | 203 | CDPClient.sendMessage(MessageBuilder.buildServiceWorkerInspectMessage(id2,serviceWorker.getVersionId())); 204 | WebElement elem = uiUtils.findElement(By.cssSelector("button#sendButton"),3); 205 | uiUtils.scrollToElement(elem); 206 | elem.click(); 207 | utils.waitFor(3); 208 | utils.waitFor(60); 209 | } 210 | 211 | @Test 212 | public void dockerTest() throws Exception { 213 | String URL = "https://framework.realtime.co/demo/web-push"; 214 | // driver = utils.launchBrowser(); 215 | driver = utils.launchBrowser(true,new URL("http://127.0.0.1:4444/wd/hub")); 216 | wsURL = utils.getWebSocketDebuggerUrlFromDriverLogs(); 217 | // String wsURL1 = wsURL.replace("localhost","127.0.0.1"); 218 | CDPClient = new CDPClient(wsURL); 219 | int id = Utils.getInstance().getDynamicID(); 220 | CDPClient.sendMessage(MessageBuilder.buildServiceWorkerEnableMessage(id)); 221 | driver.navigate().to(URL); 222 | ServiceWorker serviceWorker = CDPClient.getServiceWorker(URL,10, "activated"); 223 | System.out.println(serviceWorker.toString()); 224 | Assert.assertEquals(serviceWorker.getStatus(),"activated"); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/test/java/com/sahajamit/NotificationTests.java: -------------------------------------------------------------------------------- 1 | package com.sahajamit; 2 | 3 | import com.sahajamit.utils.UINotificationService; 4 | import com.sahajamit.utils.UIUtils; 5 | import com.sahajamit.utils.Utils; 6 | import org.junit.After; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.openqa.selenium.By; 10 | import org.openqa.selenium.WebDriver; 11 | import org.openqa.selenium.chrome.ChromeDriverService; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Objects; 16 | 17 | public class NotificationTests { 18 | 19 | private WebDriver driver; 20 | private String wsURL; private Utils utils; 21 | private UIUtils uiUtils; 22 | private ChromeDriverService chromeDriverService; 23 | 24 | @Before 25 | public void beforeTest(){ 26 | this.utils = Utils.getInstance(); 27 | this.uiUtils = UIUtils.getInstance(); 28 | } 29 | 30 | @After 31 | public void afterTest(){ 32 | utils.stopChrome(); 33 | if(!Objects.isNull(chromeDriverService)) 34 | chromeDriverService.stop(); 35 | } 36 | @Test 37 | public void doWebNotificationTesting() throws Exception { 38 | driver = utils.launchBrowser(); 39 | driver.navigate().to("https://pushjs.org/#"); 40 | UINotificationService uiNotificationService = UINotificationService.getInstance(driver); 41 | uiNotificationService.startWebNotificationListener(); 42 | driver.findElement(By.id("demo_button")).click(); 43 | utils.waitFor(2); 44 | 45 | Map notificationFilter = new HashMap<>(); 46 | notificationFilter.put("title", "Hello world!"); 47 | boolean flag = uiNotificationService.isNotificationPresent(notificationFilter,"web"); 48 | uiNotificationService.stopWebNotificationListener(); 49 | } 50 | 51 | @Test 52 | public void doWebPushNotificationTesting() throws Exception { 53 | driver = utils.launchBrowser(); 54 | driver.navigate().to("https://framework.realtime.co/demo/web-push"); 55 | UINotificationService uiNotificationService = UINotificationService.getInstance(driver); 56 | uiNotificationService.startPushNotificationListener("https://framework.realtime.co/demo/web-push"); 57 | driver.findElement(By.cssSelector("#sendButton")).click(); 58 | utils.waitFor(4); 59 | 60 | Map notificationFilter = new HashMap<>(); 61 | notificationFilter.put("title", "Web Push Notification"); 62 | 63 | boolean flag = uiNotificationService.isNotificationPresent(notificationFilter,"push"); 64 | uiNotificationService.stopPushNotificationListener(); 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | 7 | # A1 uses PatternLayout. 8 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n --------------------------------------------------------------------------------