WaitFor 2 different results in Karate tests - karate

We have a component which takes more time to build and we want to test it with Karate:
retry(120, 1000).waitForText('h1', 'Successful')
There can be more states in the h1 element (Waiting, Building), but error is usually shown almost immediately. How can we put waitForText to the condition and diferenciace between these 2 final states? Something like this
retry(120, 1000).if (waitForText('h1', 'Successful')) { ...continue with tests } elseif(waitForText('h1', 'Error')) { karate.fail('Error occured') }

Please read the docs for optional() and exists(): https://github.com/intuit/karate/tree/master/karate-core#optional
Also it is quite likely waitForAny() will solve this: https://github.com/intuit/karate/tree/master/karate-core#waitforany
* retry(120, 1000).waitForAny('{h1}Successful', '{h1}Error')
* if exists('{h1}Error') karate.fail('error occurred')
The first line above will actually return the Element so you can be smarter on the second line. There are many options, find the way that suits you best.

Related

How to properly create and use dynamic Xpath in JSON (Page Object Model) - Karate DSL

For example, I have this sample JSON object in pages folder which contains all the XPaths for specific page.
{
"pageTitle1": "//*[#class='page-title' and text()='text1']",
"pageTitle2": "//*[#class='page-title' and text()='text2']",
"pageTitle_x" : "//*[#class='page-title' and text()='%s']"
}
* def pageHome = read('classpath:/pages/pageHome.json')
* click(pageHome.pageTitle_x) <-- how to properly replace %s in the string?
Update: I tried the replace function, not sure if this is the proper way.
* click(pageHome.pageTitle_x.replace("%s","new value"))
First a bit of advice. Trying to be "too clever" like this causes maintainability problems in the long run. I have said a lot about this here, please read it: https://stackoverflow.com/a/54126724/143475
That said, you can write re-usable JS functions that will do all these things:
* def pageTitle = function(x){ return "//*[#class='page-title' and text()='" + x "']" }
Now using that you can do this:
* click(pageTitle('foo'))
If you redesign the function even this may be possible:
* click(pageTitle(pageHome.pageTitle_x, 'foo'))
But see how things become more complicated and less readable. The choice is yours. Note that anything you can do in JS (e.g. String.replace()) will be possible, it is up to you and your creativity.

Karate Netty - CallSingle but not so single

What I had till today:
I have get_jwt.feature and I call it as a part of karate-config.js. Since I have used one account test#test.com I needed only one jwt and I can reuse it across scenarios. callSingle worked as a charm in this case.
Today:
Suddenly I have need for jwt's from two accounts which I dont want to generate for each scenario, callSingle falls short of this task as it does exactly what its supposed to be doing. Now I have hacky idea, I can simply make two files, get_jwt.feature and get_jwt_user2.feature, and single call them each.
So my question: Is there a better way of doing this?
You can use "2 levels" of calls. So point the callSingle() to a JS function that calls get_jwt.feature 2 times, maybe with different arguments and then return a JSON. Pseudo-code below. First is get_jwts.js:
function fn(users) {
var jwt1 = karate.call('get_jwt.feature', users.user1);
var jwt2 = karate.call('get_jwt.feature', users.user2);
return { jwt1: jwt1, jwt2: jwt2 };
};
Then in karate-config.js
config.jwts = karate.callSingle('classpath:get_jwts.js', users);
And now you should be able to do this:
* print jwts.jwt1
* print jwts.jwt2
You can also do a feature-->feature call chain. Do let me know if this works !
EDIT: see Babu's answer in the comments, looks like you can pass an array to callSingle() ! so that may be quite convenient :)

How to Set Postman Test Equal to This or That

I am writing an API test in Postman, and I would like it to succeed if a Number is returned or the string "NA".
Based on my current understanding one condition can be tested at a time, like:
pm.test('Qty returned is number', () => {
pm.expect(typeof parseInt(pm.response.json().qty)).to.be.not.equal('NaN');
});
Writing as two separate tests, one will pass and one will fail.
How can I code this exception into a single test?
Worked for my case, wanted the test to pass if one of two values is returned:
.to.be.oneOf(["value1","value2"]);
answer from jaikl

Can we use '#ContinueNextStepsOnException' to run all the steps in the Karate script instead of karate.match(actual, expected)

I have a response with hundreds of attributes while matching the attributes the scripts getting failed and further steps are not getting executed. because of this we have to validate the same case multiple times to validate the attribute values. is they a option like #ContinueNextStepsOnException to execute all the steps and it is hard to script using karate.match(actual, expected) for more than 100 attributes I have give actual and expected values if in case of any failure to continue.
No, there is no such option. If your scripts are getting failed - it is because Karate is doing its job correctly !
If you feel you want to skip certain fields, you can easily do so by using match ... contains syntax.
I think you are using multiple lines instead of matching the entire JSON in one-line which you can easily do in Karate. For example:
* def response = { a: 1, b: 2 }
# not recommended
* match response.a == 1
* match response.b == 2
# recommended
* match response == { a: 1, b: 2 }
Is it so hard to create the above match, even in development mode ? Just cut and paste valid JSON, and you are done ! I have hardly ever heard users complain about this.

How do I assert to accept one of multiple possible values in JUnit

I have a test that returns some value after completion. The returned value is a String and can have one of several possible values based on some if condition in the test.
But in the assert statement I can check only one of the Expected values not both.
How can I do this? Thank you.
I will use AssertJ for this
assertThat(value).isIn(expected1, expected2, expected3);
The code is much simpler than with Hamcrest.
My solution was to save the result and then run a Jtest that the result was in an array of accepted solutions.
E.g:
`it("Test Message", () => {
const result = testFunction(inputValue);
assert.equal((result in [possibeResult1, possibleResult2, ...]), true);
});`