I want to test that the array that I get back from an endpoint is in a particular order, based on a field in the object, using Karate. For example, I might have data that looks like this:
[
{ seconds: 20 },
{ seconds: 15 },
{ seconds: 12 }
]
My goal is to test that the objects are listed in descending order.
I have a successful implementation of this test, but I am looking for a better way of doing it, if possible. Here is what I did to test the order:
* def orderTest = function() { for(var i = 0; i < response.length; i++) { if(i !== 0 && response[i].seconds > response[i-1].seconds) return false; } return true; }
Then assert orderTest()
While this seems to work as expected, it is ugly. Is there a better way to test the array's order?
Yes ! It becomes simple if you extract the numbers alone into an array - which behind the scenes is just a Java List so you can apply the Collections methods on it:
* def Collections = Java.type('java.util.Collections')
* def response =
"""
[
{ seconds: 20 },
{ seconds: 15 },
{ seconds: 12 }
]
"""
* def before = $response[*].seconds
* copy after = before
* Collections.sort(after, Collections.reverseOrder())
* match before == after
Related
need help, i have this vuex action that get list of products by category id:
async GET_PRODUCTS({commit}, {cat}) {
let products = []
for (let i = 0; i < 2; i++) {
let arr = await axios.get(
`https://example.com/api/get-items.php`, {
params: {
cat,
token: "0e94e09856a22496613b325473b7de8cb0a",
p: i
}
}
)
console.log(arr);
commit('SET_PRODUCTS', products.push(arr.data))
}
console.log(products);
return products
},
api gives only 100 products, I need to pass a parameter: p=0 its first 100 products, p=1 next 100, p=2 next 100, etc,
how i can stop a loop when api returns less than 100 products in array?
upd:
now i have array of arrays, need to concat them in 1
Instead of pushing new sub-array to the master array, just concatenate them. And then break the cycle when you receive less than 100 items:
async GET_PRODUCTS({commit}, {cat}) {
let products = []
for (let i = 0; true; i++) { // <--- loop forever
let arr = await axios.get(
`https://example.com/api/get-items.php`, {
params: {
cat,
token: "0e94e09856a22496613b325473b7de8cb0a",
p: i
}
}
)
products = products.concat(arr.data) // <--- concatenate new array to the old one
commit('SET_PRODUCTS', products)
if (arr.data.length < 100) break // <--- exit the cycle
}
console.log(products);
return products
},
my code for finding index as below
* def list = nestActual #this is API response value which is given at the end
* def searchFor = { category_name: 'books3'}
* def foundAt = []
* def fun = function(x, i){ if (karate.match(x, searchFor).pass) foundAt.add(i) }
* eval karate.forEach(list, fun)
* print "==========foundAt=======" +foundAt
i have tried the above code for finding index where im getting foundAt index as null.
Below is my response where i want to find index of "category_name":"books3"
[
{
"category_id":1, "parent_cat_id":0, "category_name":"books", "slug_name":"books_1", "popular":true,
}, {
"category_id":2, "parent_cat_id":1, "category_name":"books2", "slug_name":"books_2", "popular":false,
}, {
"category_id":3, "parent_cat_id":1, "category_name":"books3", "slug_name":"books3_2", "popular":false,
}, {
"category_id":4, "parent_cat_id":3, "category_name":"mp3", "slug_name":"mp_3", "popular":false, }, {
"category_id":5, "parent_cat_id":3, "category_name":"mp4", "slug_name":"humoristiska_deckare_mysi_deck_3", "popular":false, }, {
"category_id":6, "parent_cat_id":3, "category_name":"video", "slug_name":"video3", "popular":false,
} ]
Please let me know how to find index of "category_name":"books3" using karate
Guess what, there is a far simpler way, the trick is to convert your search target into an array of primitives. Then you can use the List.indexOf() Java method:
Scenario: using the java indexOf api (will change with graal)
* def response = [{ name: 'a' }, { name: 'b' }, { name: 'c' }]
* def names = $[*].name
* def index = names.indexOf('b')
* match index == 1
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
I was wondering if it is possible for me to get the elements of the array by the name of property than the position. For example, this is my incoming data:
{
"salesdata": {
"productsbyzone": {
"zones": [{
"eastzone": "shirts, trousers"
},
{
"westzone": "slacks"
},
{
"northzone": "gowns"
},
{
"southzone": "maxis"
}
]
}
}
}
I intend to move this to a SQL database and I have columns within the database for each zone. The problem is that the order of different zones changes within each json. I was successfully using the following query until I realized that the position of the zones changes within each json:
WITH
salesData AS
(
SELECT
(c.salesdata.productsbyzone.zone,0) as eastzone,
(c.salesdata.productsbyzone.zone,1) as westzone,
(c.salesdata.productsbyzone.zone,2) as northzone,
(c.salesdata.productsbyzone.zone,3) as sourthzone,
FROM [sales-data] as c
)
SELECT
eastzone.eastzone as PRODUCTS_EAST,
westzone.westzone as PRODUCTS_WEST,
northzone.northzone as PRODUCTS_NORTH,
southzone.southzone as PRODUCTS_SOUTH
INTO PRODUCTSDATABASE
FROM salesData
Need a way to reference these fields by the name rather than by the position.
I recommend a solution: Use the JavaScript UDF in the azure stream job to complete the columns sort.
Please refer to my sample:
Input data(upset the order):
{
"salesdata": {
"productsbyzone": {
"zones": [{
"westzone": "slacks"
},
{
"eastzone": "shirts, trousers"
},
{
"northzone": "gowns"
},
{
"southzone": "maxis"
}
]
}
}
}
js udf code:
function test(arg) {
var z = arg;
var obj = {
eastzone: "",
westzone: "",
northzone: "",
southzone: ""
}
for(var i=0;i<z.length;i++){
switch(Object.keys(z[i])[0]){
case "eastzone":
obj.eastzone = z[i]["eastzone"];
continue;
case "westzone":
obj.westzone = z[i]["westzone"];
continue;
case "northzone":
obj.northzone = z[i]["northzone"];
continue;
case "southzone":
obj.southzone = z[i]["southzone"];
continue;
}
}
return obj;
}
You can define the order you want in the obj parameter
SQL:
WITH
c AS
(
SELECT
udf.test(jsoninput.salesdata.productsbyzone.zones) as result
from jsoninput
),
b AS
(
SELECT
c.result.eastzone as east,c.result.westzone as west,c.result.northzone as north,c.result.southzone as south
from c
)
SELECT
b.east,b.west,b.north,b.south
INTO
jaycosmos
FROM
b
Output:
Hope it helps you.
You can use GetArrayElement to return array element then access to each property. Please refer the below query
WITH
salesData AS
(
SELECT
GetArrayElement(zones,0) as z
FROM [sales-data] as s
)
SELECT
z.eastzone
z.westzone
z.northzone
z.southzone
FROM PRODUCTSDATABASE
FROM salesData
Sorting Image Issue
Greeting,
I am writing a code in dojo that compares the date column in grid for the sorting. below is the code :
function(a,b){
var a1=new Date(a);
var a2=new Date(b);
var x = dojo.date.locale.format(a1, {datePattern: "yyyy-MM-dd", selector: "date"});
var y = dojo.date.locale.format(a2, {datePattern: "yyyy-MM-dd", selector: "date"});
if((a!=null)&&(b!=null)){
if (x.toLowerCase() < y.toLowerCase())
{
debugger;
return -1;
}
else if (x.toLowerCase() > y.toLowerCase())
{
debugger;
return 1;
}
else
{
debugger;
return 0;
}
}
Code works fine for me when the Language in the browser is English but when I changes to Dutch or any other then it doesnt sorts the values properly.
Please guide.
Thanks
I'm not sure why you're having this problem since those format calls ought to be returning the same result regardless, but that code seems severely overcomplicated.
If you are simply trying to sort dates in chronological order, you should merely need to compare them as numbers.
var a = [ '2015-10-18', '2015-10-12', '2015-10-16' ];
a.sort(function (a, b) {
a = new Date(a);
b = new Date(b);
if (a > b) {
return 1;
}
if (a < b) {
return -1;
}
return 0;
});
console.log(a); // ["2015-10-12", "2015-10-16", "2015-10-18"]