This question already has an answer here:
How to pass multiple parameters to callSingle karate on karate-config.js
(1 answer)
Closed 1 year ago.
As the title says I'm experiencing issues when trying to pass a config item to the feature file I call from callSingle() in karate-config.js. Everything works as expected if I only pass 1 parameter which is the path to the feature file. I tried copying the entire config from the example karate-config.js and yet was still getting the same error. Would appreciate any explanation.
karate-config.js:
function fn() {
var env = karate.env; // get system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'kermit';
}
karate.log('karate.env system property was:', env);
var config = {
env: env,
base_url: 'https://api.'+env+'.chdev.org',
account_url: 'https://account.'+env+'.chdev.org'
}
var result = karate.callSingle('classpath:authorization/authorization.feature', config);
karate.log(result);
return config;
}
Error I'm getting:
16:48:10.548 [main] ERROR com.intuit.karate - evaluation of 'karate-config.js' failed: javascript function call failed: unexpected feature call arg type: class jdk.nashorn.internal.scripts.JO4
Exception in thread "main" java.lang.NullPointerException
at com.intuit.karate.core.ScenarioExecutionUnit.init(ScenarioExecutionUnit.java:147)
at com.intuit.karate.core.ScenarioExecutionUnit.run(ScenarioExecutionUnit.java:236)
at com.intuit.karate.core.FeatureExecutionUnit.run(FeatureExecutionUnit.java:164)
at com.intuit.karate.core.FeatureExecutionUnit.run(FeatureExecutionUnit.java:73)
at com.intuit.karate.core.Engine.executeFeatureSync(Engine.java:109)
at com.intuit.karate.IdeUtils.exec(IdeUtils.java:64)
at cucumber.api.cli.Main.main(Main.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
In fact no matter what I pass as 2nd arg I always get a variation of class jdk.nashorn error.
config} definitely looks like a typo to me.
Sorry but I think the best option for you is to follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
MR Peter Thomas has confirmed the project I've sent to him as a github issue works as expected which proved it is an environmental issue.
It was resolved by updating the maven and jdk8 to the latest releases.
Related
I'm trying to create a dynamic request that should receive 2 parameters (username and password). To do so, I defined the below JSON file:
{
"grant_type": "password",
"client_id": "myClient",
"username": "#(username)",
"password": "#(password)"
}
To call my JSON, I set the below feature file where my intention is to define a variable for each parameter i want to send
Scenario: Get Sugar access token
Given url baseUrl
And path 'oauth2/token'
And def username = 'user'
And def password = 'password'
And def requestBody = read('classpath:jsonFiles/requests/authRequest.json')
When request requestBody
And method POST
Then status 200
* print 'Response: ', response
Unfortunately, when I run the scenario, i'm getting below error message
10:59:59.111 [main] INFO com.intuit.karate - Karate version: 1.4.0-SNAPSHOT
10:59:59.286 [main] INFO com.intuit.karate.Suite - backed up existing 'target\karate-reports' dir to: target\karate-reports_1672160399285
10:59:59.303 [main] INFO c.intuit.karate.core.FeatureRuntime - found scenario at line: 4
11:00:00.174 [main] ERROR com.intuit.karate - src/test/java/myCompany/testautomation/features/auth/getToken.feature:11
And def requestBody = read('classpath:jsonFiles/requests/authRequest.json')
js failed:
>>>>
01: read('classpath:jsonFiles/requests/authRequest.json')
<<<<
org.graalvm.polyglot.PolyglotException: not found: jsonFiles/requests/seugarAuth/authRequest.json
- com.intuit.karate.resource.ResourceUtils.getResource(ResourceUtils.java:126)
- com.intuit.karate.core.ScenarioFileReader.toResource(ScenarioFileReader.java:129)
- com.intuit.karate.core.ScenarioFileReader.readFileAsStream(ScenarioFileReader.java:99)
- com.intuit.karate.core.ScenarioFileReader.readFileAsString(ScenarioFileReader.java:95)
- com.intuit.karate.core.ScenarioFileReader.readFile(ScenarioFileReader.java:54)
- com.intuit.karate.core.ScenarioEngine.lambda$new$0(ScenarioEngine.java:120)
- <js>.:program(Unnamed:1)
src/test/java/myCompany/testautomation/features/auth/getToken.feature:11
The use of classpath: makes more sense for Java projects. It looks like you are using the Visual Studio code extension, in which case your workspace root folder will be the classpath unless to switch to "Maven mode" or equivalent: https://marketplace.visualstudio.com/items?itemName=karatelabs.karate#run-mode
Or another option is to use a Java "runner" and use the Java extension for VS Code.
If all that above doesn't make sense, for now just keep things simple and use relative paths. For example if authRequest.json is side-by-side with your feature file, this would work:
* def requestBody = read('authRequest.json')
Relative paths and the this: prefix can be used, but I leave that to you to research: https://github.com/karatelabs/karate#path-prefixes
I'm trying use karate for e2e tests and have started with a minimal setup. I want to create some config items in karate-config.js for use in the tests but karate is reporting that file is not a js function and hence the test fails trying to get the config:
Warning: Nashorn engine is planned to be removed from a future JDK release
12:16:35.264 [Test worker] WARN com.intuit.karate - not a js function or feature file: read('classpath:karate-config.js') - [type: NULL, value: null]
---------------------------------------------------------
feature: classpath:karate/insurer.feature
scenarios: 1 | passed: 0 | failed: 1 | time: 0.0163
---------------------------------------------------------
HTML report: (paste into browser to view) | Karate version: 0.9.1
file:/Users/srowatt/dev/repos/api/price-service/build/surefire-reports/karate.insurer.html
---------------------------------------------------------
-unknown-:4 - javascript evaluation failed: priceBaseUrl, ReferenceError: "priceBaseUrl" is not defined in <eval> at line number 1
org.opentest4j.AssertionFailedError: -unknown-:4 - javascript evaluation failed: priceBaseUrl, ReferenceError: "priceBaseUrl" is not defined in <eval> at line number 1
This is my karate-config.js:
function fn() {
return {
priceBaseUrl: "http://localhost:8080"
};
}
This is my insurer.feature test:
Feature: which creates insurers
Background:
* url priceBaseUrl
* configure logPrettyRequest = true
* configure logPrettyResponse = true
Scenario: basic roundtrip
# create a new insurer
Given path 'insurers'
And request { name: 'Sammy Insurance', companyCode: '99' }
When method post
Then status 201
And match response == { resourceId: '#number', version: 0, createdBy: 'anonymousUser' }
* def insurerId = response.resourceId
# get insurer by resource id
Given path 'insurers', insurerId
When method get
Then status 200
And match response == { id: '#(id)', name: 'Sammy Insurance', companyCode: '99' }
This is the InsurerTest.java test runner:
package karate;
import com.intuit.karate.junit5.Karate;
class InsurerTest {
#Karate.Test
public Karate testInsurer() {
return new Karate().feature("classpath:karate/insurer.feature");
}
}
Please use below code in the karate-config.js
function() {
return priceBaseUrl='http://localhost:8080';
}
When I see this:
Warning: Nashorn engine is planned to be removed from a future JDK release
I suspect you are on Java 9 or 11 ? To be honest, we haven't fully tested Karate on those versions of Java yet. Would it be possible for you to confirm that Java 8 (maybe 9 / 10 also) is OK.
That said, we are interested in resolving this as soon as possible, so if you can submit a sample project where we can replicate this, please do so: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
EDIT: Karate 1.0 will use GraalVM instead of Nashorn and will run on even JDK 16: https://software-that-matters.com/2021/01/27/7-new-features-in-karate-test-automation-version-1_0/
I have succesfully written a simple use-case to unmarshal a JSON response from the Quickbooks oAuth API to refresh tokens.
With that working, I need to go and fetch the actual data:
https://quickbooks.api.intuit.com/v3/company/XXXXXXXXXXXXXX/query?query=SELECT * FROM Invoice WHERE Metadata.LastUpdatedTime%3E='2020-07-01T01:00:00' ORDERBY Metadata.LastUpdatedTime, Id STARTPOSITION 1 MAXRESULTS 1000 &minorversion=47
The HTTP call works OK:
// make the HTTP REST call, without C10y* & Camel* headers:
.toD("https://${header." + Headers.IEP_API_HOST + "}?headerFilterStrategy=C10yHeaderFilterStrategy")
I can check that the JSON returned is OK:
.log(LoggingLevel.DEBUG, API_LOG, "JSON returned: ${body}")
But from here it goes pear-shaped:
.unmarshal().json(JsonLibrary.Jackson, Payload.class)
This is what happens:
With the above log statement a MismatchedInputException is raised with the message "No content to map due to end-of-input".
Without the above log statement a ClassNotFoundException is raised with the message "Payload.class".
Re. 1.
My understanding is that responses are cached by default so it should be possible to read the inputstream multiple times. By default the HTTP endpoint option disableStreamCache is set to false, so it's enabled.
The stack trace is:
com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (org.apache.camel.converter.stream.CachedOutputStream$WrappedInputStream); line: 1, column: 0]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4624) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4469) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3471) ~[jackson-databind-2.11.0.jar:2.11.0]
at org.apache.camel.component.jackson.JacksonDataFormat.unmarshal(JacksonDataFormat.java:188) ~[camel-jackson-3.4.0.jar:3.4.0]
at org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:64) ~[camel-support-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:702) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:616) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:203) ~[camel-timer-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76) ~[camel-timer-3.4.0.jar:3.4.0]
at java.base/java.util.TimerThread.mainLoop(Timer.java:556) ~[na:na]
at java.base/java.util.TimerThread.run(Timer.java:506) ~[na:na]
Re. 2.
The stack trace for this is:
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-WIN-10-DM-1594724136485-0-1]
at org.apache.camel.CamelExecutionException.wrapCamelExecutionException(CamelExecutionException.java:47) ~[camel-api-3.4.0.jar:3.4.0]
at org.apache.camel.language.simple.SimpleExpressionBuilder$26.evaluate(SimpleExpressionBuilder.java:590) ~[camel-core-languages-3.4.0.jar:3.4.0]
at org.apache.camel.support.ExpressionAdapter.evaluate(ExpressionAdapter.java:36) ~[camel-support-3.4.0.jar:3.4.0]
at org.apache.camel.reifier.language.SimpleExpressionReifier$1.evaluate(SimpleExpressionReifier.java:42) ~[camel-core-engine-3.4.0.jar:3.4.0]
at org.apache.camel.processor.SetHeaderProcessor.process(SetHeaderProcessor.java:48) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:702) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:616) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:203) ~[camel-timer-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76) ~[camel-timer-3.4.0.jar:3.4.0]
at java.base/java.util.TimerThread.mainLoop(Timer.java:556) ~[na:na]
at java.base/java.util.TimerThread.run(Timer.java:506) ~[na:na]
Caused by: java.lang.ClassNotFoundException: Payload.class
at org.apache.camel.impl.engine.DefaultClassResolver.resolveMandatoryClass(DefaultClassResolver.java:87) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.language.simple.SimpleExpressionBuilder$26.evaluate(SimpleExpressionBuilder.java:588) ~[camel-core-languages-3.4.0.jar:3.4.0]
... 13 common frames omitted
All of this is running within an Eclipse/Maven project, so I have cleaned, refreshed, compiled, rebuilt, etc, etc, to no avail.
I have written a simple jUnit and it works absolutely fine using the JSON from the above log, saved to a file:
/**
* POJO Jackson unmarshalling
*/
#Test
public void pojoUnmarshallTest() {
ObjectMapper om = new ObjectMapper();
try {
Payload payload = om.readValue(getFile("qb.Payload.Invoice.json"), Payload.class);
assertTrue(payload.toString().startsWith("c10y.model.qb.Payload"));
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
Lastly, I'm using the latest versions of Camel & Spring Boot:
<properties>
<!-- latest versions # Jul 2020 -->
<java.version>11</java.version>
<camel.version>3.4.0</camel.version> <!-- latest long term support version -->
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<run.profiles>dev</run.profiles>
</properties>
As ever, thanks in advance for your help!
PS:
The POJO classes that receive the unmarshalled JSON were generated at http://www.jsonschema2pojo.org/. The POJO for the working route was hand-cranked. I mention it just in case it could make a difference (it shouldn't IMHO).
The entire route can be obtained here: https://drive.google.com/file/d/1Qu0vwJaSlggH6BrIgUFMU_BZNpmMQYuh/view?usp=sharing.
I have tried the Gson library and get the same ClassNotFoundException: Payload.class error. This is looking like less of an unmarshalling problem and more of a classpath issue.
Having two .log() statements gives the following output:
2020-07-15 10:06:27.108 DEBUG 6720 --- [mer://startHere] c.c.r.qb.fetch.delta : JSON returned: {"QueryResponse":{"Invoice":[{"AllowIPNPayment":false, ...removed... ,"Balance":0}],"startPosition":1,"maxResults":1,"totalCount":1},"time":"2020-07-15T02:06:21.869-07:00"}
2020-07-15 10:06:27.108 DEBUG 6720 --- [mer://startHere] c.c.r.qb.fetch.delta : JSON returned:
Contrary to the documentation, it looks like the input stream is not, in fact, cached.
PS2:
Adding .streamCaching() to the route and &disableStreamCache=false to the endpoint URI didn't make any difference to the second .log(); it remained empty.
I also tried the following Java Config approach:
#Configuration
public class Config {
#Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext context) {
System.out.println("****** beforeApplicationStart ******");
}
#Override
public void afterApplicationStart(CamelContext context) {
System.out.println("****** afterApplicationStart ******");
context.setStreamCaching(true);
}
};
}
}
I can see the sysout in the console but this didn't work either.
I downloaded jsonschema2pojo-1.0.2 and ran it against a much bigger JSON sample with the following arguments:
--annotation-style JACKSON2
--big-decimals
--date-class java.util.Date
--format-dates
--format-date-times
--package c10y.model.qb.jxon
--remove-old-output
--source C:\Users\...\src\test\resources\qb.Payload.Invoice.json
--source-type JSON
--target c:\temp
--target-language JAVA
--target-version 11
This created the root/base POJO called QbPayloadInvoice, which looks like it's taken from the input file name. I updated my route:
.unmarshal().json(JsonLibrary.Jackson, QbPayloadInvoice.class)
It still raises the java.lang.ClassNotFoundException: Payload.class.
There's nothing in the JSON response, or in any of the other generated POJOs, called Payload.
At the same time, my updated jUnit works fine:
QbPayloadInvoice payload = om.readValue(getFile("qb.Payload.Invoice.json"), QbPayloadInvoice.class);
expected = "c10y.model.qb.jxon.QbPayloadInvoice";
assertEquals(expected, payload.toString().substring(0, expected.length()));
Go figure!
The clue exists above where I wrote "There's nothing in the JSON response, or in any of the other generated POJOs, called Payload." This statement turned out to be absolutely correct.
The unmarshalling had been working all along:
.unmarshal().json(JsonLibrary.Jackson, QbPayloadInvoice.class)
It was the following line that was failing:
.setHeader(QB_START_POS, simple("${bodyAs(Payload.class).QueryResponse.startPosition}"))
This was made more obvious given that I'd changed the unmarshalling class from Payload to QbPayloadInvoice.
I am trying to make a simplified version of test report where I am generating a single HTML file report containing only assertion and error response message when there is any (attempting to not publish all the logs and steps).
I understand that we have hooks in karate. However I have looked for karate objects in the github but unable to found any objects where I can extract the response from (to be passed to the js function called on hook)
What I am doing right now is this:
Config:
//karate-config.js
karate.configure('afterScenario', karate.call('classpath:hooks.js'));
Hook:
//hooks.js
//Looking on how to extract the response and log it here
function(){
var info = karate.tags;
karate.log('Tags', info);
}
Am I missing anything on the karate objects? Or this should be achieved in another way?
Thanks a lot!
Try this:
var response = karate.get('response');
EDIT better example:
Background:
* configure afterScenario = function(){ karate.log('***', karate.get("response.headers['X-Karate']")) }
Scenario:
Given url 'http://httpbin.org'
And path 'headers'
And header X-Karate = 'test'
When method get
# this will fail
Then status 400
I have tried with both karate.get('response') and response directly, and both work. If you use karate.call() pass the response as a parameter.
I'm trying to make spiderable works on my meteor app hosted on modulus with SSL.
I have Meteor 1.0, iron:router 1.0, spiderable and node package of phantomjs
All is working on localhost. But once I deploy on Modulus, first I had the error
spiderable: phantomjs failed: null
Then, I added the following environment variable in the modulus panel:
METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS = --ssl-protocol=tlsv1 --ignore-ssl-errors=yes --debug=true
This is still not working and the debug is outputting multiple times (like it's looping over an error) the following message in the modulus console:
2014-12-03T17:01:00 [DEBUG] WebPage - evaluateJavaScript "(function() { return (function () {
if (typeof Meteor === 'undefined'
|| Meteor.status === undefined
|| !Meteor.status().connected) {
return false;
}
if (typeof Package === 'undefined'
|| Package.spiderable === undefined
|| Package.spiderable.Spiderable === undefined
|| !Package.spiderable.Spiderable._initialSubscriptionsStarted) {
return false;
}
Tracker.flush();
return DDP._allSubscriptionsReady();
})(); })()"
2014-12-03T17:01:00 [DEBUG] WebPage - evaluateJavaScript result QVariant(bool, false)
If anyone knows how to solve this or succeeded to deploy a meteor project on modulus.io with SSL and spiderable. Let's me know the good way to do it :)
Thank a lot !
I solved my problem as follows:
I installed phantomjs locally and run the test script available at http://www.meteorpedia.com/read/spiderable/
phantomjs phantomtest.js
This gave me more details about the error: Parse Error.
Then, it was a javascript file that once compiled/minified, rendered an error caused by select2. The js library that was using it was flat-ui.js (http://designmodo.github.io/Flat-UI/).
I discover this by testing many deploys on *.meteor.com and by adding/removing .js file.
I edit the flat-ui.js library to avoid Parsing Error.
I redeployed on both modulus.io and *.meteor.com. All was working fine on *.meteor.com but still didn't work on modulus.io. That let me thinking about an SSL error but I only saw "spiderable: phantomjs failed: null" in the modulus.io logs.
I add the following environment variable in the modulus panel:
METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS = --debug=true
and it appears that it was a "SSL Handshake error":
[DEBUG] Network - Resource request error: 6 ( "SSL handshake failed" )
I add another option to the METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS environment variable:
METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS = --ignore-ssl-errors=yes --debug=true
Now everything is working fine on modulus.io.
To sumup:
solve javascript errors
add METEOR_PKG_SPIDERABLE_PHANTOMJS_ARGS = --ignore-ssl-errors=yes
I hope this will help some dudes,