Karate: How to remove dynamic element based on value from JSON? - karate

I have a requirement, in the below JSON I have to delete all the id elements,
[
{
"id": "0a7936ed",
"code": "test",
"label": "test",
"type": "sell"
},
{
"id": "7bc1909b2",
"code": "test2",
"label": "test2",
"type": "Buy"
}
]
My JSON should be as below,
[
{
"code": "test",
"label": "test",
"type": "sell"
},
{
"code": "test2",
"label": "test2",
"type": "Buy"
}
]

Standard JS Array operations will work in Karate 1.0 onwards:
* def dest = source.map(x => { delete x.id; return x })
For older versions of Karate, a hint is that you can loop over any JS object key-values using karate.forEach() and you could write conditional logic to ignore id etc.

Related

Get the value from the response based on a condition and store it to a variable

I would like to get the value from the response based on a condition and store it to a variable.
In the below JSON, I would like to store the value when the name matches to something I prefer. Is there a way to achieve this using Karate API?
{
"results": [
{
"name": "Sample1",
"email": "sample1#text.com",
"id": "U-123"
},
{
"name": "Sample2",
"email": "sample2#text.com",
"id": "U-456"
},
{
"name": "Sample3",
"email": "sample3#text.com",
"id": "U-789"
}
]
}
So after reading the comment, my interpretation is to "find" the id where name is Sample2. Easy, just use a filter() operation, refer the docs: https://github.com/karatelabs/karate#jsonpath-filters
Instead of using a filter, I'm using the JS Array find() method as a very concise example below:
* def response =
"""
{ "results": [
{ "name": "Sample1", "email": "sample1#text.com", "id": "U-123" },
{ "name": "Sample2", "email": "sample2#text.com", "id": "U-456" },
{ "name": "Sample3", "email": "sample3#text.com", "id": "U-789" }
]
}
"""
* def id = response.results.find(x => x.name == 'Sample2').id
* match id == 'U-456'
Take some time to understand how it works. Talk to someone who knows JS if needed.

oneOf nested in array

I am currently testing JSON Forms on my schema (as is, without a UI definition), and I am running into the following problem: I can generate lists of options with oneOf (as shown in this_works below), but I am not able to do so within an array (this_does_not_work in the minimal example below). Instead, the array will simply offer simple text fields that validate against the options listed in oneOf.
Is there a way to achieve what I am trying to achieve here? Ideally, the UI of this_works (a list that users can select from) would appear for each line of the array:
{
"$id": "schema_test",
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Minimal example",
"type": "object",
"properties": {
"this_works": {
"type": "string",
"oneOf": [
{
"const": "a",
"title": "Option A"
},
{
"const": "b",
"title": "Option B"
}
]
},
"this_does_not_work": {
"type": "array",
"items": {
"type": "string",
"oneOf": [
{
"const": "a",
"title": "Option A"
},
{
"const": "b",
"title": "Option B"
}
]
}
}
}
}```

How to match field value in response when there are multiple fields with the same name?

[
{
"key": "test1",
"category": "test",
"name": "test1",
"translations":
{
"english": "eng"
}
},
{
"key": "test2",
"category": "test",
"name": "test1",
"translations":
{
"english": "eng2",
"german": "German"
}
},
{
"key": "test3",
"category": "power",
"name": "test1",
"translations":
{
"EN_lang": "jik"
}
}
]
Here, we have multiple field's are with different values and we have to match value in translations (field position will change on every call)
You have to be clear about what you want to assert. Hint, the new contains deep (available in 0.9.6.RC4) can help:
* match response contains deep { key: 'test2', translations: { english: 'eng2' } }
Else you should look at transforming the JSON into a shape where it is easier to do the assertions you want: https://github.com/intuit/karate#json-transforms

How to remove an object from an jsonarray based on filter in karate

I want to remove an object from json array based on a filter, tried below code but didn't work
* def json = [ { "id": "0a7936ed", "code": "test", "label": "test", "type": "sell" }, { "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" } ]
I want remove object where code is equal to test
* def fun = function(){ karate.remove('json', $.[?(#.code=='test')]") }
* call fun
Getting exception as below:
com.intuit.karate.exception.KarateException: javascript function call failed: String index out of range: -1
at com.intuit.karate.Script.evalFunctionCall(Script.java:1622)
at com.intuit.karate.Script.call(Script.java:1573)
at com.intuit.karate.Script.callAndUpdateConfigAndAlsoVarsIfMapReturned(Script.java:1690)
at com.intuit.karate.StepDefs.callAndUpdateConfigAndVars(StepDefs.java:582)
Please suggest me how to filter it and remove the object.
Thanks inadvance..
This use-case is exactly what karate.filter() is designed for:
* def json = [ { "id": "0a7936ed", "code": "test", "label": "test", "type": "sell" }, { "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" } ]
* def condition = function(x){ return x.code != 'test' }
* def filtered = karate.filter(json, condition)
* match filtered == [{ "id": "7bc1909b2", "code": "test2", "label": "test2", "type": "Buy" }]
Here is the documentation: https://github.com/intuit/karate#the-karate-object

How to invert the MQL query (for freebase)?

I am trying to list all the types for a particular id:
{
"id": "/en/sony",
"type": [{
"name": "Topic",
"id": null
}]
}
This query giving me the following result:
http://tinyurl.com/lubavey
{
"result": {
"type": [
{
"id": "/common/topic",
"name": "Topic"
},
{
"id": "/base/audiobase/topic",
"name": "Topic"
},
{
"id": "/base/fblinux/topic",
"name": "Topic"
},
{
"id": "/base/digitalcameras/topic",
"name": "Topic"
},
{
"id": "/base/popstra/topic",
"name": "Topic"
},
{
"id": "/base/televisions/topic",
"name": "Topic"
},
{
"id": "/base/ps3games/topic",
"name": "Topic"
},
{
"id": "/base/filmcameras/topic",
"name": "Topic"
},
{
"id": "/m/04mny2g",
"name": "Topic"
}
],
"id": "/en/sony"
}
}
I want exactly the opposite result. I want all the types which do not have name as "Topic" with them.
How can I achieve this? I tried to use ! operator with property name which is suggested in reference guide of MQL, but it's giving me error:
"Can't use unqualified property names with ! reversing".
What should I do to remove this error with ! and to obtain opposite result of the query?
Try with !=:
{
"id": "/en/sony",
"type": [{
"name!=": "Topic",
"id": null
}]
}
The != operator says that the constrained property can be anything but
the specified value. (It does require that the property be something,
however: it does not match object for which the property is null.)
Read more about != operator here: http://wiki.freebase.com/wiki/MQL_operators#The_.22but_not.22_Operator_.21.3D