Use If condition in Karate to extract values - bdd

I have the following JSON response -
{
"type": "StudentSchema",
"version": 1,
"students": [
{
id: 1,
name: "John",
roll: "1234"
},
{
id: 2,
name: "David",
roll: "4434"
}
]
}
Then how can I extract the array in Karate with name John to do further validation?
e.g. I want to say if name == John then save the id
I am trying below but it does not seem to work -
* def userId = get[0] response $[?(#students.name == 'John')].id
* match userId == 2

Let say your JSON is
MyJson = {
"type": "StudentSchema",
"version": 1,
"students": [
{
id: 1,
name: "John",
roll: "1234"
},
{
id: 2,
name: "David",
roll: "4434"
}
]
}
Now as you want to get the ID for the student whose name is john you can get it by using JSON path
* def JSONpath = '$..students[?(#.name=='John')].id'
* def userId = karate.jsonPath(MyJson,JSONpath)
It will give you an array of ID which satisfy the json path condition and you can do your assertion from that.

Related

Merge object and add keys from JSON format using Ruby on Rails

I have a list of array that is queried that needs to be merged with the same location_id based on the objects.
**this are the code for generating array **
filled = Product.on_hand_location(pid).to_a
empty = Product.on_hand_location_empty_cylinder(pid).to_a
data = filled + empty
result = data.map{ |k|
{
details: {
location_id: k['location_id'],
"location_name"=>k['location_name'],
"onhandcylynder"=>k['onhand'] == nil ? 0 : k['onhand'],
"emptycylynder"=> k['emptyonhand'] == nil ? 0 : k['emptyonhand']
} ,
}
}
respond_with [ onhand: result ]
This JSON format below is the output of code above. which has location_id that needs to be merge
[{
"onhand": [{
"details": {
"location_id": 1,
"location_name": "Capitol Drive",
"onhandcylynder": "4.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 2,
"location_name": "SM City Butuan",
"onhandcylynder": "5.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 1,
"location_name": null,
"onhandcylynder": 0,
"emptycylynder": "2.0"
}
}
]
}]
My desired output
[{
"onhand": [{
"details": {
"location_id": 1,
"location_name": "Capitol Drive",
"onhandcylynder": "4.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 2,
"location_name": "SM City Butuan",
"onhandcylynder": "5.0",
"emptycylynder": "2.0"
}
}
]
}]
I think instead of data = filled + empty you should try
data = Product.on_hand_location(pid).to_a
empty = Product.on_hand_location_empty_cylinder(pid).to_a
empty.each do |location|
data.push(location) if data.none? { |item| item['location_id'] == product['location_id'] }
end
result = ...
or
hash = {}
Product.on_hand_location_empty_cylinder(pid).map { |l| hash[l['location_id']] = l }
Product.on_hand_location(pid).map { |l| hash[l['location_id']] = l }
data = hash.values
and if you need some data from both of the queries you should try
hash = {}
Product.on_hand_location_empty_cylinder(pid).map { |l| hash[l['location_id']] = l }
Product.on_hand_location(pid).map { |l| hash[l['location_id']].merge!(l) }
data = hash.values
to merge in place
I refactor my code and able to get my desired result
filled = Product.on_hand_location(pid).to_a
emptyTank = Product.on_hand_location_empty_cylinder(pid).to_a
data = filled + emptyTank
cylinder = data.map(&:dup)
.group_by { |e| e.delete('location_id') }
finalResult = cylinder.map{|_, location_id | location_id.reduce({}) { |result, location_id|
result.merge(location_id)
} }
respond_with [ onhand: finalResult]
The result already merge with the same location id and emptyonhand keys are merge already in corresponding to its location ID
[
{
"onhand": [
{
"onhand": "1.0",
"location_name": "Capitol Drive",
"emptyonhand": "5.0"
},
{
"onhand": "5.0",
"location_name": "SM City Butuan"
}
]
}
]

Is parent definition in API request body required if it's partial sub child properties are marked required?

Suppose I have the following OpenAPI definition (ignore the indentation or missing attributes):
FooData:
type: object
additionalProperties: false
description: Holds the foo data Information.
required:
- id
- contact
properties:
id:
description: Identifier
type: string
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\-]{1,255}$
identity:
description: Holds customer identity info.
$ref: '#/MyIdentity' ....
MyIdentity:
type: object
additionalProperties: false
description: Holds the customer identity information.
required:
- userId
properties:
userId:
type: integer
format: int64
minimum: 0
maximum: 9223372036854775807
description: Unique Identification Number which is specific to individual user.
firstName:
type: string
description: user's First name.
maxLength: 32
minLength: 1
pattern: ^[a-zA-Z\s]{1,32}$ ....
As you see, MyIdentity is not required in FooData however its property userID is marked as required.
Can we ignore the full MyIdentity object in the request body while hitting the API?
Assuming the request body schema is FooData:
Can we ignore the full MyIdentity object in the request body while hitting the API?
Yes - because the FooData.identity property is not required so it can be omitted. However, if the FooData.identity property is present, it must be an object and contain at least the userId property.
In other words, the following FooData payloads are valid:
{
"id": "abc",
"contact": "..."
}
{
"id": "abc",
"contact": "...",
"identity": {
"userId": 12345
}
}
but these payloads are invalid:
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {}
}
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {
"firstName": "Alex"
}
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": null
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": "blah"
}

how to return specific set of data from from array of hashes

I have following data contract available in constant variable data
[
{
id: 1,
name: "class1",
start_at: "2017-08-15T10:00:00.000Z",
end_at: "2017-08-15T10:30:00.000Z",
},
{
id: 2,
name: "class2",
start_at: "2017-08-15T10:00:00.000Z",
end_at: "2017-08-15T10:30:00.000Z",
},
......more data here.....
]
I want to return the specific set of data.
e.g data.select {|e| e[:id] = 1} should return following but instead it returns all data.
[
{
id: 1,
name: "class1",
start_at: "2017-08-15T10:00:00.000Z",
end_at: "2017-08-15T10:30:00.000Z",
}
]
Any idea what is wrong?
extracted_data = data.select {|e| e[:id] == 1}
== for comparison

How do I use .map to parse response when response has inconsistent values?

So I'm using the yelp API, and after I make a GET request I get back a response of businesses. In order to work with that response I'm using .map
Example:
mappedResults = yelpSearch.businesses.map {|l| {id: l.id, name: l.name, categories:l.categories, rating: l.rating, review_count: l.review_count, url: l.url, phone: l.phone}}
My problem is that sometimes l.phone is not returned for some records in the response, and I get the error:
undefined method `phone' for #<BurstStruct::Burst:0x007fba47c7a228>
My question is how do I refactor this code so that if a record doesn't have phone it will either leave it null (or worst cast empty string)
Any help is appreciated
JSON structure is as such for each business in the response
{
region: {
span: {
latitude_delta: 0,
longitude_delta: 0
},
center: {
latitude: 38.054117,
longitude: -84.439002
}
},
total: 23,
businesses: [
{
is_claimed: false,
rating: 5,
mobile_url: "http://m.yelp.com/biz/vineyard-community-church-lexington",
rating_img_url: "http://s3-media1.ak.yelpcdn.com/assets/2/www/img/f1def11e4e79/ico/stars/v1/stars_5.png",
review_count: 2,
name: "Vineyard Community Church",
snippet_image_url: "http://s3-media4.ak.yelpcdn.com/photo/VoeMtbk7NRFi6diksSUtOQ/ms.jpg",
rating_img_url_small: "http://s3-media1.ak.yelpcdn.com/assets/2/www/img/c7623205d5cd/ico/stars/v1/stars_small_5.png",
url: "http://www.yelp.com/biz/vineyard-community-church-lexington",
phone: "8592582300",
snippet_text: "I have been a member of Vineyard Community Church since 2004. Here you will find a modern worship service with a full band, witty speakers who teach...",
image_url: "http://s3-media3.ak.yelpcdn.com/bphoto/D71eikniuaHjdOC8DB6ziA/ms.jpg",
categories: [
[
"Churches",
"churches"
]
],
display_phone: "+1-859-258-2300",
rating_img_url_large: "http://s3-media3.ak.yelpcdn.com/assets/2/www/img/22affc4e6c38/ico/stars/v1/stars_large_5.png",
id: "vineyard-community-church-lexington",
is_closed: false,
location: {
city: "Lexington",
display_address: [
"1881 Eastland Pwky",
"Lexington, KY 40505"
],
geo_accuracy: 8,
postal_code: "40505",
country_code: "US",
address: [
"1881 Eastland Pwky"
],
coordinate: {
latitude: 38.054117,
longitude: -84.439002
},
state_code: "KY"
}
}
]
}
If you're using Rails 4.0 or newer, the #presence method is really helpful for this. You would use it like this:
mappedResults = yelpSearch.businesses.map {|l| {id: l.id.presence, #... etc
or like this
mappedResults = yelpSearch.businesses.map {|l| {id: l.id.presence || "default id", # ...
Update
Reading your code again, #presence might not work in this case, since the method isn't defined. Here's a longer (uglier) snippet that should work:
mappedResults = yelpSearch.businesses.map do |l|
id: l.respond_to(:id) ? l.id : "default id",
# ... other properties
end
Update from OP
This worked - thank you! Note I had to tweak syntax a bit to respond_to?('method_name')
mappedResults = yelpSearch.businesses.map {|l|
{
name: l.respond_to?("name") ? l.name : "nameless",
rating: l.respond_to?("rating") ? l.rating : "unrated",
# ... other properties
}}

How do I return unnamed JSON string array from asp.net mvc2 json result?

I have the following code:
var json = MyObject
.Select(p => new
{
id = p.MyObjectId,
name = p.MyObjectName
});
return Json(new { json }, JsonRequestBehavior.AllowGet);
This returns a JSON object as follows:
{ json: [ { id: 1, name: "Bob" }, { id: 2, name: "Fred" }, { id: 3, name: "James" } ] }
However, I need it to return the data as:
[ { id: 1, name: "Bob" }, { id: 2, name: "Fred" }, { id: 3, name: "James" } ]
Is this possible using the JSON result?
return Json(json, JsonRequestBehavior.AllowGet);
Try this:
return Json(json, JsonRequestBehavior.AllowGet);

Resources