From e5248778402d162693ded90faa3e2dd86c65b0f0 Mon Sep 17 00:00:00 2001 From: David Leonhartsberger Date: Fri, 5 Apr 2019 22:44:13 +0200 Subject: [PATCH] Added signal and listen back to karate object --- README.md | 2 + .../intuit/karate/core/ScenarioContext.java | 49 +++++++++++++++++-- .../com/intuit/karate/core/ScriptBridge.java | 15 ++++++ .../java/demo/websocket/websocket.feature | 8 --- pom.xml | 10 +++- 5 files changed, 71 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a0ad1de62..9d59bc434 100755 --- a/README.md +++ b/README.md @@ -3066,6 +3066,7 @@ Operation | Description karate.get(name) | get the value of a variable by name (or JsonPath expression), if not found - this returns `null` which is easier to handle in JavaScript (than `undefined`) karate.info | within a test (or within the [`afterScenario`](#configure) function if configured) you can access metadata such as the `Scenario` name, refer to this example: [`hooks.feature`](karate-demo/src/test/java/demo/hooks/hooks.feature) karate.jsonPath(json, expression) | brings the power of [JsonPath](https://github.com/json-path/JsonPath) into JavaScript, and you can find an example [here](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/js-arrays.feature). +karate.listen(timeout) | wait until [`karate.signal(result)`](#karate-signal) has been called or time-out after `timeout` milliseconds. see examples: [websocket](karate-demo/src/test/java/demo/websocket/websocket.feature) / [message-queue](karate-demo/src/test/java/mock/contract/payment-service.feature) karate.log(... args) | log to the same logger (and log file) being used by the parent process, logging can be suppressed with [`configure printEnabled`](#configure) set to `false` karate.lowerCase(object) | useful to brute-force all keys and values in a JSON or XML payload to lower-case, useful in some cases, see [example](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/lower-case.feature) karate.map(list, function) | functional-style 'map' operation useful to transform list-like objects (e.g. JSON arrays), see [example](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/js-arrays.feature), the second argument has to be a JS function (item, [index]) @@ -3080,6 +3081,7 @@ Operation | Description karate.set(name, value) | sets the value of a variable (immediately), which may be needed in case any other routines (such as the [configured headers](#configure-headers)) depend on that variable karate.set(name, path, value) | only needed when you need to conditionally build payload elements, especially XML. This is best explained via [an example](karate-junit4/src/test/java/com/intuit/karate/junit4/xml/xml.feature#L211), and it behaves the same way as the [`set`](#set) keyword. Also see [`eval`](#eval). karate.setXml(name, xmlString) | rarely used, refer to the example above +karate.signal(result) | trigger an event that [`karate.listen(timeout)`](#karate-listen) is waiting for, and pass the data, see examples: [websocket](karate-demo/src/test/java/demo/websocket/websocket.feature) / [message-queue](karate-demo/src/test/java/mock/contract/payment-service.feature) karate.tags | for advanced users - scripts can introspect the tags that apply to the current scope, refer to this example: [`tags.feature`](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/tags.feature) karate.tagValues | for even more advanced users - Karate natively supports tags in a `@name=val1,val2` format, and there is an inheritance mechanism where `Scenario` level tags can over-ride `Feature` level tags, refer to this example: [`tags.feature`](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/tags.feature) karate.toBean(json, className) | converts a JSON string or map-like object into a Java object, given the Java class name as the second argument, refer to this [file](karate-junit4/src/test/java/com/intuit/karate/junit4/demos/type-conv.feature) for an example diff --git a/karate-core/src/main/java/com/intuit/karate/core/ScenarioContext.java b/karate-core/src/main/java/com/intuit/karate/core/ScenarioContext.java index 7b1ee37a5..89a11af98 100755 --- a/karate-core/src/main/java/com/intuit/karate/core/ScenarioContext.java +++ b/karate-core/src/main/java/com/intuit/karate/core/ScenarioContext.java @@ -50,8 +50,13 @@ import com.intuit.karate.netty.WebSocketClient; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; - -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; @@ -99,7 +104,9 @@ public class ScenarioContext { private Function callable; // websocket - private List webSocketClients = new ArrayList<>(); + private final Object LOCK = new Object(); + private List webSocketClients; + private Object signalResult; public void logLastPerfEvent(String failureMessage) { if (prevPerfEvent != null && executionHooks != null) { @@ -313,6 +320,7 @@ private ScenarioContext(ScenarioContext sc, ScenarioInfo info, Logger logger) { prevPerfEvent = sc.prevPerfEvent; callResults = sc.callResults; webSocketClients = sc.webSocketClients; + signalResult = sc.signalResult; } public void configure(Config config) { @@ -795,7 +803,40 @@ public WebSocketClient webSocket(String url, String subProtocol, Optional Script.evalFunctionCall(som, null, context)); + } + + public Object listen(long timeout) { + return context.listen(timeout, null); + } + private ScriptValue getValue(String name) { ScriptValue sv = context.vars.get(name); return sv == null ? ScriptValue.NULL : sv; diff --git a/karate-demo/src/test/java/demo/websocket/websocket.feature b/karate-demo/src/test/java/demo/websocket/websocket.feature index 607a3288a..9c252c030 100644 --- a/karate-demo/src/test/java/demo/websocket/websocket.feature +++ b/karate-demo/src/test/java/demo/websocket/websocket.feature @@ -24,11 +24,3 @@ Scenario: using the websocket instance to send as well as receive messages * eval ws.send('Billie') * def result = ws.listen(5000) * match result == 'hello Billie !' - -Scenario: perform custom action when message is received - * def ws = karate.webSocket(demoBaseUrl + '/websocket') - # will call the function myJavaScriptFunction (which is defined elsewhere) for each text message that is received - * eval ws.setTextHandler(function(msg){ myJavaScriptFunction() }) - * eval ws.send('Billie') - * def result = ws.listen(5000) - * match result == 'hello Billie !' diff --git a/pom.xml b/pom.xml index 545bd12ef..768190a45 100755 --- a/pom.xml +++ b/pom.xml @@ -159,10 +159,18 @@ + + + + artifactory-snapshots + artifactory-snapshots + https://artifactory.betr.app/artifactory/bluelabs-maven-snapshots-local + + \ No newline at end of file