Skip to content

Commit

Permalink
[ui] added ways for raw http / websocket requests
Browse files Browse the repository at this point in the history
to be made from a test, which should be very useful for users to implement
any missing or vendor-specifc web-driver api-s or troubleshoot
  • Loading branch information
ptrthomas committed Apr 10, 2020
1 parent f8fb7bd commit 8e69607
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 22 deletions.
39 changes: 36 additions & 3 deletions examples/ui-test/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Karate UI Test
This project is designed to be the simplest way to replicate issues with the [Karate UI framework](https://github.com/intuit/karate/tree/master/karate-core) for web-browser testing. It includes an HTTP mock that serves HTML and JavaScript, which you can easily modify to simulate complex situations such as a slow-loading element.
This project is designed to be the simplest way to replicate issues with the [Karate UI framework](https://github.com/intuit/karate/tree/master/karate-core) for web-browser testing. It includes an HTTP mock that serves HTML and JavaScript, which you can easily modify to simulate complex situations such as a slow-loading element. To submit an issue after you have a way to replicate the scenario, follow these instructions: [How to Submit an Issue](https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue).

## Overview
To point to a specifc version of Karate, edit the `pom.xml`. If you are working with the source-code of Karate, follow the [developer guide](https://github.com/intuit/karate/wiki/Developer-Guide).
Expand All @@ -14,7 +14,7 @@ The `test.feature` is a simple [Karate UI test](https://github.com/intuit/karate
## Debugging
You should be able to use the [Karate extension for Visual Studio Code](https://github.com/intuit/karate/wiki/IDE-Support#vs-code-karate-plugin) for stepping-through a test for troubleshooting.

## Advanced
## WebDriver Tips
If you are targeting a WebDriver implementation, you may need to experiment with HTTP calls. Don't forget that that is Karate's core competency ! So you can use a "scratchpad" Karate test on the side, like this:

```cucumber
Expand All @@ -27,4 +27,37 @@ Scenario:
* method post
```

And note that the [VS Code "Karate Runner"](https://github.com/intuit/karate/wiki/IDE-Support#vs-code-karate-plugin) plugin is really convenient for re-running the above, once you have say - started the driver executable manually.
Within a test script, as a convenience, the `driver` object, exposes an `http` property, which makes it easy to make custom-crafted WebDriver requests using [this class](../../karate-core/src/main/java/com/intuit/karate/Http.java).

Here is an example of [getting the page title](https://w3c.github.io/webdriver/#get-title):

```cucumber
* def temp = driver.http.path('title').get().body().asMap()
* print 'temp:', temp
```

Which results in a GET request to: `http://localhost:9515/session/{sessionId}/title` - and the response body will be printed. Now you can easily extract data out of the response JSON.

And note that the [VS Code "Karate Runner"](https://github.com/intuit/karate/wiki/IDE-Support#vs-code-karate-plugin) plugin is really convenient for re-running tests - or you can pause a test using a break-point and [type in interactive commands](https://twitter.com/KarateDSL/status/1167533484560142336).

## DevTools Protocol Tips
When using the driver type `chrome`, you can call the `send()` method and pass a raw JSON message that will be sent to the Chrome browser using a WebSocket connection. For example here is how to get the [metadata about frames](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-getFrameTree):

```cucumber
* def temp = driver.send({ method: 'Page.getFrameTree' })
* print 'temp:', temp
```

This will result in the following raw message sent (Karate will supply the `id` automatically):

```
{"method":"Page.getFrameTree","id":7}
```

Chrome will respond with something like this, which should be viewable in the log / console:

```
{"id":7,"result":{"frameTree":{"frame":{"id":"11B3A5ABDEE5802201D84389EE0215B8","loaderId":"D2241AD7B86ED533F095F907A78A1208","url":"http://localhost:52664/page-01","securityOrigin":"http://localhost:52664","mimeType":"text/html"}}}}
```

You can do more, but this should be sufficient for exploring the possible commands and troubleshooting via trial and error. And suggest / contribute changes to be made to the code, e.g. the [DevToolsDriver](../../karate-core/src/main/java/com/intuit/karate/driver/DevToolsDriver.java).
6 changes: 6 additions & 0 deletions karate-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,12 @@ And an extra convenience third argument is a time-delay (in milliseconds) that w
* input('input[name=someName]', ['a', 'b', 'c', Key.ENTER], 200)
```

If you need to send input to the "whole page" (not a specific input field), just use `body` as the selector:

```cucumber
* input('body', Key.ESCAPE)
```

### Special Keys
Special keys such as `ENTER`, `TAB` etc. can be specified like this:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,18 @@ public int waitSync() {
public DevToolsMessage method(String method) {
return new DevToolsMessage(this, method);
}


// this can be used for exploring / sending any raw message !
public Map<String, Object> send(Map<String, Object> map) {
DevToolsMessage dtm = new DevToolsMessage(this, map);
dtm.setId(nextId());
return sendAndWait(dtm, null).toMap();
}

public void send(DevToolsMessage dtm) {
String json = JsonUtils.toJson(dtm.toMap());
logger.debug(">> {}", json);
client.send(json);
client.send(json);
}

public DevToolsMessage sendAndWait(DevToolsMessage dtm, Predicate<DevToolsMessage> condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,21 +163,23 @@ public DevToolsMessage(DevToolsDriver driver, Map<String, Object> map) {
method = (String) map.get("method");
params = (Map) map.get("params");
Map temp = (Map) map.get("result");
if (temp != null && temp.containsKey("result")) {
Object inner = temp.get("result");
if (inner instanceof List) {
result = new ScriptValue(toMap((List) inner));
} else {
Map innerMap = (Map) inner;
String subtype = (String) innerMap.get("subtype");
if ("error".equals(subtype) || innerMap.containsKey("objectId")) {
result = new ScriptValue(innerMap);
} else { // Runtime.evaluate "returnByValue" is true
result = new ScriptValue(innerMap.get("value"));
if (temp != null) {
if (temp.containsKey("result")) {
Object inner = temp.get("result");
if (inner instanceof List) {
result = new ScriptValue(toMap((List) inner));
} else {
Map innerMap = (Map) inner;
String subtype = (String) innerMap.get("subtype");
if ("error".equals(subtype) || innerMap.containsKey("objectId")) {
result = new ScriptValue(innerMap);
} else { // Runtime.evaluate "returnByValue" is true
result = new ScriptValue(innerMap.get("value"));
}
}
} else {
result = new ScriptValue(temp);
}
} else {
result = new ScriptValue(temp);
}
error = (Map) map.get("error");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ protected WebDriver(DriverOptions options) {
}
}

// can be used directly if you know what you are doing !
public Http getHttp() {
return http;
}

private String getSubmitHash() {
return getUrl() + elementId("html");
}
Expand Down
10 changes: 6 additions & 4 deletions karate-demo/src/test/java/driver/core/test-04.feature
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ Scenario Outline: <type>

* driver webUrlBase + '/page-01'

* def temp = locate('#eg01').locateAll('input')
* karate.forEach(temp, function(x, i){ karate.log(i, x.html) })
* def temp = driver.send({ method: 'Page.getFrameTree' })
* print 'temp:', temp
* delay(3000)


Examples:
| type |
# | chrome |
| chromedriver |
| chrome |
#| chromedriver |
#| geckodriver |
#| safaridriver |

0 comments on commit 8e69607

Please sign in to comment.