Karate: match with parametrized regex - karate

I didn't find the right way to write a match with regexp cointaining a variable:
* def getYear =
"""
function() {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var sdf = new SimpleDateFormat('yyyy');
var date = new java.util.Date();
return sdf.format(date);
}
"""
* def currentYear = getYear()
* def testmatch = { gencode: '#("000" + currentYear + "0000012345")' }
* match testmatch == { gencode: '#regex "[0-9]{3}" + currentYear + "[0-9]{10}"' }
There is a way to do this?
Thanks,
Lorenzo

First, normally when you are doing matches like this, regex is un-necessary, because you might as well do an exact match.
But anyway this is the solution, refer: https://github.com/intuit/karate#self-validation-expressions
* def isValidYear = function(x){ return new RegExp("[0-9]{3}" + currentYear + "[0-9]{10}").test(x) }
* assert isValidYear('00020190000012345')
* match testmatch == { gencode: '#? isValidYear(_)' }

Related

How do I invoke my JS Function for a particular column in a csv file in the Karate Framework?

I have a feature file that reads a csv file with multiple rows and I need to validate that if two of the columns meet certain conditions, the third column needs to be mandatory. I have tried using a js function however I am unsure as to how I should call this function for the third column. So based on the example below, if the name is Chicken, the unit kg then the cost needs to be mandatory.
#
noinspection CucumberTableInspection
Feature: Serverless
Scenario Outline: Per Row *
def row =
""
" {
name: '<Name>',
unit: '<Unit>',
cost: '<Cost>',
}
#FunctionComparison
""
" *
def name = '<Name>' *
def unit = '<Unit>' *
def cost = '<Cost>' *
def checkMandatory =
""
"
function(arg1, arg2, arg3) {
if (arg1 in ('Chicken')) {
if (arg2 in ('kg')) {
if (arg3.length < 0) {
return false;
}
return true;
}
return true;
}
return true;
}
""
" *
match row ==
""
" {
name: '#ignore',
unit: '#regex ea|kg|ml',
cost: 'checkMandatory(name, unit, cost) == true'
}
""
"
Examples:
|
read('input' + '.csv') |
The input.csv is simply a csv file with the following:
Line,Name,Unit,Cost (Columns)
1,Cheese,ea,34.50
2,Cake,ea,55.54
3,Chicken,kg,
4,Cement,ml,4.32
Your validation function can be a lot simpler, try this:
* def third = { name: 'foo', unit: 'bar', cost: '' }
* def isValid = function(x){ return (x.name && x.unit) ? x.cost.length != 0 : true }
* assert !isValid(third)
Note that Scenario Outlines will inject the variables, so there is no need for the < and > placeholders: https://github.com/intuit/karate#scenario-outline-enhancements
You can try this self-contained working example:
Feature:
Background:
* text data =
"""
name,unit,cost
Cheese,ea,34.50
Cake,ea,55.54
Chicken,kg,
Cement,ml,4.32
"""
* csv data = data
* def isValid = function(x){ return (x.name && x.unit) ? x.cost.length != 0 : true }
Scenario Outline:
* assert isValid(__row)
Examples:
| data |

How do I extract current date, month and year in the format yyyy-mm-dd in karate dsl?

* def date =
"""
function(s) {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
return sdf.parse(s).time;
}
"""
Currently, I'm using this. Any help is much appreciated.
You can also archive the following by using javascript as follows:
* def todaysDate =
"""
function()
{
var d=new Date();
var month = String(d.getMonth() + 1);
var day = String(d.getDate());
var year = String(d.getFullYear());
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return year+'/'+month+'/'+day
}
"""
* print todaysDate()
Here you go:
* def today =
"""
function() {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var sdf = new SimpleDateFormat('yyyy-MM-dd');
return sdf.format(new java.util.Date());
}
"""
* print today()

what to use in place of Object.keys and hasOwnProperty when using karate version 0.9.5?

* def a =
"""
function(ths,tsa,hcia) {
karate.log(JSON.stringify(tsa[hcia[0]],null,2))
var fas = (Object.keys(tsa[hcia[0]]))[0]
karate.log("fas " + fas)
var art = null
for(prtsj in ths[hcia[0]]) {
karate.log(JSON.stringify(ths[hcia[0]][prtsj].sku,null,2))
if((Object.keys(ths[hcia[0]][prtsj].sku)).indexOf(fas) > -1) {
art = ths[hcia[0]][prtsj].type
}
}
return art
}
"""
Please use karate.keysOf() - which will return a JSON array of strings.
Now you can do whatever you want.
Also see: https://stackoverflow.com/a/61139167/143475

Date formatting in Karate

I have the the below date returned from the SQL query in Karate feature file:
2020-01-31 00:00:00.0
I need to convert it to: 31-JAN-20 format. I have tried the below:
* def effectiveDt =
"""
function(s) {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var sdf = new SimpleDateFormat("dd-mon-yy");
return return sdf.format(s)
}
"""
but its not working for me.
but the below worked and returns 31-00-19, but I want 31-JAN-20 format
var sdf = new SimpleDateFormat("dd-mm-yy");
Any help would be appreciated!
Here is an example that worked for me:
* def getSubtractedYear =
"""
function(s) {
var DateTimeFormatter = Java.type("java.time.format.DateTimeFormatter");
var LocalDate = Java.type("java.time.LocalDate");
var ChronoUnit = Java.type("java.time.temporal.ChronoUnit");
var dtf = DateTimeFormatter.ofPattern("MM/dd/yyyy");
try {
var adj = LocalDate.parse('02/02/2020', dtf).minusMonths(12);
return dtf.format(adj);
} catch(e) {
karate.log('*** date parse error: ', s);
}
}
"""
And call like:
* string subtracted = call getSubtractedYear aDate

Programally multi-value param

I need to make a request with a multi-value param,its value must be a very big array to test an api param validation. One of my implementation:
Scenario: filter_too_long_multivalue
* def localPath = endPointBase + 'filter'
* def generateLongParam =
"""
function(){
var paramValue = [];
for(var idx = 0; idx<1002; idx++){
paramValue.push('r')
}
var params = {};
params.pl = paramValue;
return params;
}
"""
* def tooLongParam = generateLongParam()
* print tooLongParam
Given path localPath
And params tooLongParam
When method get
Then match response == authorizationSchema.empty
Then the request is:
GET http://XXXXXXXXXXXXX?pl=%5Bobject+Array%5D
I have tried differents ways, but always the same result...
How can I obtain a weel formed request?
Thank you.
Yes, you have hit one of those edge cases, can you let me know if this works, I'll also see if this can be improved.
Sometimes what is returned by a JS function is not exactly the format that Karate likes. The workaround is to use json instead of def to type-convert - refer doc: https://github.com/intuit/karate#type-conversion
* def fun =
"""
function(){
var temp = [];
for(var i = 0; i < 5; i++) {
temp.push('r');
}
return temp;
}
"""
* json array = fun()
Given url demoBaseUrl
And path 'echo'
And params { pl: '#(array)' }
When method get
Then status 200
Which resulted in:
1 > GET http://127.0.0.1:60146/echo?pl=r&pl=r&pl=r&pl=r&pl=r