Karate - Exception raises for invalid jsonpath - karate

I have a Json response like below. The difference here is my Json body has a number as the parent node.
def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
I want to return the mobileNumber attribute value from the response body. In this scenario I don't have that attribute in my response. So here I want to get a null value.
So when I use * def mobile = $.22388043[0].mobileNumber, I'm getting below error.
No results for path: $['22388043'][0]['mobileNumber']
Please advise on this.

Karate does give you a way to get the values of JSON keys.
Hopefully this example answers all your other questions as well:
* def response =
"""
{
"22388043":[
{
"firstName":"Romin",
"lastName":"Irani",
"phoneNumber":"408-1234567",
"emailAddress":"romin.k.irani#gmail.com"
}
]
}
"""
* def id = karate.keysOf(response)[0]
* match id == '22388043'
* def person = response[id][0]
* match person contains { firstName: 'Romin', lastName: 'Irani' }
* match person.mobileNumber == '#notpresent'

Related

Karate: How to paste and run scenario for each param from array response inside scenario?

I have a range of values, like taskId, extracted from DB.
* def getTasks = db.readRows('SELECT task_id from tasks t WHERE t.status = \'IN_PROGRES\'
')
* def getIds = get getTasks[*].task_id
* 'task', 'setUser'
* request
"""
[{
"task_id": " ",
"assignedUser": {
"user": "someValue"
}
}
]
"""
* method post
* status 200
* def responseResult =
"""
{
"totalCount": '#number',
"successCount": '#number',
"skippedCount": '#number',
"failedCount": '#number',
}
"""
* match response == responseResult
I need to get each value from the list response and paste in into a "task_id"
Could you please clarify this case?
If you mean trying to create a JSON array from a bunch of values that is easy.
* def response = { foo: 1, bar: 2 }
* def task_ids = []
* task_ids.push(response.foo)
* task_ids.push(response.bar)
* match task_ids == [1, 2]
When it comes to JSON manipulation, think of Karate as just like JavaScript.

Karate Nested Schema contains "Not Required" not working?

i'm trying to understand karat schema fuzsy validation with contains but is not working
if I use ##string for not required it validates required when is null
this is my example
Scenario: Test
* def payload =
"""
{
nested: {
field: 'not required'
}
}
"""
* def payload2 =
"""
{
nested: null
}
"""
* def schema =
"""
{
nested: {
field: '##string'
}
}
"""
* match payload contains schema
* match payload2 contains schema
I get this error in console
path: $.nested, actual: null, expected: {field=##string}, reason: actual value is null
Thanks for help
Pay attention to the structure. I think this is what you are trying:
* def part = { field: '#string' }
* def schema = { nested: '##(part)' }
* def payload = { nested: { field: 'not required' } }
* match payload == schema
* def payload2 = { nested: null }
* match payload2 == schema
And please refer the docs: https://github.com/intuit/karate#schema-validation
yes thanks, also this works
* def schema =
"""
{
'nested.field': '##string'
}
"""

How to pass dynamic value in request of API in Karate tool? [duplicate]

I have a scenario :
Call API - Capture Response - Get ID from response and call another API which takes input ID from response 1.
Ex :
Feature: test graphql end point
Background:
* url baseUrl + '/graphql'
Scenario: Create Org Call
Given text query =
"""
mutation {
test: createOrganization(
name: "Org Name"
)
{
Id
name
}
}
"""
And request { query: '#(query)' }
When method post
Then status 200
* def res = response
* def id = res.data.test.Id
* print 'response:', response
* print 'Id:', id
Given text query =
"""
mutation {
createBackendHistory(orgId: '#(id)') {
orgId
}
}
"""
And request { query: '#(query)' }
When method post
Then status 200
How to pass value(Id from call 1) is createBackendHistory API
When i try orgId: '#(id)' i am getting error.
Since query is text you can't use the #() embedded expressions. Please refer to the docs: https://github.com/intuit/karate#replace
Try this:
Given text query =
"""
mutation {
createBackendHistory(orgId: '<id>') {
orgId
}
}
"""
And replace query.id = id
And request { query: '#(query)' }
When method post
Then status 200

Karate: Write to a text file

I have the following feature file that reads the input and appends the input id with the response and writes to a text file in the below format:
|123|{"products": [ { "pid": "1a"} ] }|
|124|{"products": [ { "pid": "1b"} ] }|
|125|{"products": [ { "pid": "1c"} ] }|
so that I can make the input table with it and dont need copy each response in text format and paste to make Examples:
I have tried the below:
Feature: sample karate test script
Background:
* url BaseUrl
* configure headers = read('classpath:headers.js')
* def jsonFromCsv = read('data.csv')
* def size = karate.sizeOf(jsonFromCsv)
* print size
Scenario Outline: Get All Tests
* def doStorage =
"""
function(args) {
var DataStorage = Java.type('DataStorage.DataStorage'); // Java class that writes to a text file
var dS = new DataStorage();
return dS.write(args);
}"""
Given path '/v1/path'
When method get
Then status 200
* def json = __row.expected
* def id = __row.id
* def app = '|'+<id>+'|'+json+'|'
* print app # prinst it in the expected format
* def result = call doStorage app
Examples:
| jsonFromCsv |
But the issue is only the last read data is being written to the file.
I had tried the below as well but gives the same result as above:
* def js = function (app){karate.write(app,'input.txt')}
DataStorage.java:
package DataStorage;
import java.io.*;
public class DataStorage {
public void write( String text) throws IOException {
BufferedWriter output = null;
try {
File file = new File("input");
output = new BufferedWriter(new FileWriter(file));
output.append(text);
output.close();
} catch ( IOException e ) {
e.printStackTrace();
} finally {
if ( output != null ) {
output.close();
}
}
}
}
You can use CSV files (have to be comma delimited): https://github.com/intuit/karate#csv-files
Also see this example:
Scenario Outline: cat name: <name>
Given url demoBaseUrl
And path 'cats'
And request { name: '<name>', age: <age> }
When method post
Then status 200
And match response == { id: '#number', name: '<name>' }
# the single cell can be any valid karate expression
# and even reference a variable defined in the Background
Examples:
| read('kittens.csv') |

How to retrieve all values for a particular key in karate

How to retrieve partNumbers from below response. In below response
"10000061","10000062","10000063"
are dynamic in nature. I have to match these partNumbers with data table partnumbers.( In a response there could be more than 10 part numbers(based on input) and i have to validate them.)
{ "added": true, "lineItems": { "1111111": { "itemCore": { "partNumber":
"10000061" } }, "222222": { "itemCore": { "partNumber": "10000061" } },
"3333333": { "itemCore": { "partNumber": "10000063" } } } }
Tried below
def partNum= get[0] response..itemCore.partNumber[*] but getting empty array.
def partNum= get[0] response..itemCore.partNumber but getting empty value.
My below second approach also giving me empty value.
* def keys = function(obj){ return response.lineItems.keySet() }
* json dynamicValue= keys(response)
* print 'dynamic value '+dynamicValue
* def first = dynamicValue[0]
* print response.lineItems.dynamicValue[0].itemCore.partNumber
* print response.lineItems.first.itemCore.partNumber
For retrieving data for a particular key, you can use deep scan operator in jsonPath,
* def partNumbers = karate.jsonPath(response,"$..partNumber")
Here's another solution, using karate.forEach() which can also operate on a map, not just a list:
* def keys = []
* eval karate.forEach(response.lineItems, function(k){ keys.add(k) })
* print keys