Karate - Nested JSON object schema validation causes KarateException - karate

Feature: Test Karate schema validation
Scenario: Test nested json objects
* def response = read('tasks.json')
* def schema = { ab: "##[] string", c: "##[] string" }
* match response ==
"""
{
id: '#string',
name: '#string',
obj1: '#(schema)' ,
obj2: '##(schema)' ,
obj3: '#(schema)' ,
obj4: '#null'
}
"""
Following is json file used (tasks.json)
{
"id": "ad:p2:53456:4634:yu",
"name": "name",
"obj1": {
"ab": [
"test"
],
"c": null
},
"obj2": null,
"obj3": {
"ab": [
"tester"
],
"c": [
"t1", "t2"
]
},
"obj4": null
}
Error: com.intuit.karate.exception.KarateException: javascript evaluation failed: string, ReferenceError: "string" is not defined in at line number 1
I have tried multiple ways like :
obj1: '#(^schema)',
obj1: '#object schema'
but not able to fix the issue.

It should be ##[] #string , read the docs: https://github.com/intuit/karate#schema-validation

Related

Having issues reusing a stored variable in Graphql query in Karate framework

I have an issue with the variable usage. Tried different options(storing variable differently, declaring, using text for defining the query, storing the query as a variable).
Still have the below error:
"errors": [
{
"message": "invalid input syntax for type uuid: \"#(queueID)\"",
"locations": [
{
"line": 1,
"column": 11
}
],
"path": [
"deleteQueue"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"name": "SequelizeDatabaseError",
"parent": {
"length": 109,
"name": "error",
"severity": "ERROR",
"code": "22P02",
"position": "34",
"file": "uuid.c",
"line": "137",
"routine": "string_to_uuid",
"sql": "DELETE FROM \"Queue\" WHERE \"id\" = '#(queueID)'"
This are my Gherkin steps:
Given request { query: 'mutation {createQueue(input: {name: "BDD-delete" }) {id} }'}
When method POST
Then status 200
And match response.data.createQueue.name == "BDD-delete"
* def queueID = response.data.createQueue.id
* print queueID
Given request { query: 'mutation {deleteQueue (id:"#(queueID)")} '}
And this is the output, when I print the queueID:
13:14:16.745 [main] INFO com.intuit.karate - [print] 758c0524-b18d-41f6-96aa-9db5eb8a7ac8
Tried using variable for the query
Given text payload =
"""
mutation {
createQueue(input: {name: "BDD-delete" })
{id, name}
}
"""
And the same tried for the deleteQueue
Feels like the issue is related with str and uuid. I must pass a uuid between the brackets in "#(queueID)"
First read this to get a sense of why this is happening: https://github.com/karatelabs/karate#rules-for-embedded-expressions
So try this:
Given request `{ query: 'mutation {deleteQueue (id:"${queueID}")} '}`
The good thing is that Karate supports JS-style placeholder replacement in strings within back-ticks.
Also refer: https://stackoverflow.com/a/69349118/143475

Karate- How can I pass a param as a key?

I have the following case and need to use firstKeyStr as a key, my code now is seeing "#firstKeyStr" as the key not the one stored in it
Code
Given path '/api/v1/sites'
When method get
Then status 200
And match response.success == true
And match response.data == "#object"
* def keys = karate.keysOf(response.data)
* def firstKeyStr = keys[0]
And match response.data."#firstKeyStr" == "#object"
Json Response Body
{
"success": true,
"data": {
"5ef34d0ca5a3c56ae14d2a23": {
"devices": [
"5f03192010a47f3e5b714193"
],
"groups": [
"5f0d9f30ef89e22778a2d230"
],
"users": [],
"triggers": [],
"alerts": [
"5f0d92b967bac60b84d3989b"
],
"name": "test",
"country": "US",
]
}
}
I'm looking for a way to pass this dynamic key (5ef34d0ca5a3c56ae14d2a23) in this line (And match response.data."#firstKeyStr" == "#object")
Since you are new to stack overflow, please read the following to best get help:
https://stackoverflow.com/help/how-to-ask
https://stackoverflow.com/help/someone-answers
As Peter said, your JSON is not well formed and the order of keys is not guaranteed (unless you have just a single key). The following code should get you going.
Sample Code:
Feature: firstKey
Scenario: firstKey
* def resp =
"""
{
"success": true,
"data": {
"5ef34d0ca5a3c56ae14d2a23": {
"devices": [
"5f03192010a47f3e5b714193"
],
"groups": [
"5f0d9f30ef89e22778a2d230"
],
"users": [],
"triggers": [],
"alerts": [
"5f0d92b967bac60b84d3989b"
],
"name": "test",
"country": "US"
}
}
}
"""
And match resp.data == "#object"
* def keys = karate.keysOf(resp.data)
* def firstKeyStr = keys[0]
* print firstKeyStr
* print (resp.data[firstKeyStr])
And match (resp.data[firstKeyStr]) == "#object"
Use round brackets so that JS is used instead of JsonPath:
* def response = { data: { a: 1, b: 2 } }
* def keys = karate.keysOf(response.data)
* def first = keys[0]
* match (response.data[first]) == 1

Extract data from json array in Karate

In the below JSON response, I need to extract the 'cid' for the record that has the 'nationalityDecription' as 'USA'. By using this query as a reference, I used the below loc in the karate feature file, but 1st line itself fails with syntax error(tried different combinations). For now, I'm using the custom javascript as a workaround which is working fine. I need help to check if i'm missing anything in syntax. Thanks
Response:
{
"header": {
"Id": "12345678",
"timeStamp": "2018-09-17T10:09:812.000"
},
"dataRecords": [
{
"cid": "31H678",
"cidMeta": "00",
"nationalityDecription": "CHINA"
},
{
"cid": "31S421",
"cidMeta": "01",
"nationalityDecription": "USA"
}
]
}
Feature file:
* def record= $response.dataRecords[?(#.nationalityDecription=='USA')]
* def cid = record.cid
* def response = { "header": { "Id": "12345678", "timeStamp": "2018-09-17T10:09:812.000" }, "dataRecords": [ { "cid": "31H678", "cidMeta": "00", "nationalityDecription": "CHINA" }, { "cid": "31S421", "cidMeta": "01", "nationalityDecription": "USA" } ] }
* def cid = get[0] response.dataRecords[?(#.nationalityDecription=='USA')].cid
* match cid == '31S421'

How to access a particular set of keys in array of Json values which i get as response?

For a particular API , I get a response which is similar to the following .
[
{ "name":"Ford", "model":"Mustang" },
{ "name":"BMW", "model": "320" },
{ "name":"Fiat", "model": "500" }
]
I want to store the values for the key 'name' in a separate variable .
Please read the documentation on using JsonPath carefully: https://github.com/intuit/karate#get
Here is an example which works with your data:
* def response =
"""
[
{ "name":"Ford", "model":"Mustang" },
{ "name":"BMW", "model": "320" },
{ "name":"Fiat", "model": "500" }
]
"""
* def names = $[*].name
* match names == ['Ford', 'BMW', 'Fiat']

Karate - Validating schema for the entire json response

I am working on validating the entire json response for a GET request using Karate.
Here is the sample json response from the request (I have shown only two elements for items )
[
{
"items": [
{
"createdById": "ADMIN",
"createdByName": "ADMIN",
"changedByName": "ADMIN",
"oid": "121212fgfg2123",
"links": {
"self": {
"href": "/internal/organiz/12345"
},
"subcom": []
},
"name": "NewETLTesting"
},
{
"createdById": "ADMIN",
"createdByName": "ADMIN",
"changedByName": "ADMIN",
"oid": "1212dfffg45",
"links": {
"self": {
"href": "/internal/organiz/5a6e0"
},
"subcom": []
},
"name": "FromKarateModified"
}
]
}
]
Here is how I am trying to validate:
And match response.*.* ==
"""
{
"createdById" : '#string',
"createdByName" : '#string',
"changedByName" : '#string',
"oid" : '#string',
"links" : '#object',
"name" : '#string'
}
"""
However, I am getting an assertion error:reason: actual value is not map-like. If I try putting square brackets around the curly braces, I get reason: actual and expected arrays are not the same size. Also I tried to play around with response like $.[*]. etc but couldn't get it working.
Thanks in advance!!
You need to pay attention to your JSON structure and also understand JsonPath better. You can cut and paste the below and see it working:
* def response =
"""
[
{
"items": [
{
"createdById": "ADMIN",
"createdByName": "ADMIN",
"changedByName": "ADMIN",
"oid": "121212fgfg2123",
"links": {
"self": {
"href": "/internal/organiz/12345"
},
"subcom": []
},
"name": "NewETLTesting"
},
{
"createdById": "ADMIN",
"createdByName": "ADMIN",
"changedByName": "ADMIN",
"oid": "1212dfffg45",
"links": {
"self": {
"href": "/internal/organiz/5a6e0"
},
"subcom": []
},
"name": "FromKarateModified"
}
]
}
]
"""
And match each response[0].items ==
"""
{
"createdById" : '#string',
"createdByName" : '#string',
"changedByName" : '#string',
"oid" : '#string',
"links" : '#object',
"name" : '#string'
}
"""
The below Schema will validate the entire reponse properly
* def refSubcom = {<object schema>}
* def refself = {href : '#string'}
* def refLinks = {self : '#object refself', subcom:'##[] refSubcom'}
* def optionalItemArr =
"""
{
createdById:'#string',
createdByName:'#string',
changedByName:'#string',
oid: '#string',
links: '#object refLinks',
name:'#string'
}
###
* def itemData =
"""
{
item : '##[] optionalItemArr'
}
"""
* def reponseSchema = '##object itemData'
* def SuccessSchema = '##[] reponseSchema'
you can refer the below link : karate : Complex JSON Schema matching