karate.exec() breaks the argument by space when passed via table - karate

When I pass a text or string as a variable from table to feature, for some reason karate.exec is breaking the argument based on space.
I have main feature where the code is
#Example 1
* def calcModel = '":: decimal calcModel = get_calc_model();"'
#Example 2
* text calcModel =
"""
:: decimal calcModel = get_calc_model();
return calcModel;
"""
* table calcDetails
| field | code | desc |
| 31 | '":: return get_name();" | '"this is name"' |
| 32 | calcModel | '"this is the calc model"' |
* call read('classpath:scripts/SetCalcModel.feature') calcDetails
Inside SetCalcModel.feature the code is
* def setCalcModel = karate.exec('/opt/local/SetCalcModel.sh --timeout 100 -field ' + field + ' -code ' + code + ' -description '+desc)
For row 1 of the table it works fine and executes following command:
command: [/opt/local/SetCalcModel.sh, --timeout, 100, -field, 31, -code, :: decimal calcModel = get_calc_model();, -description, this is the calc model], working dir: null
For row 2 it breaks with following command:
command: [/opt/local/SetCalcModel.sh, --timeout, 100, -field, 32, -code, ::, decimal, calcModel, =, get_calc_model();, -description, this is the calc model], working dir: null
I have tried this with example 1 and 2 and it keeps doing the same.
I have also tried passing line json as argument to karate.exec(), that also has same issue.
Is there a workaround here??

There is a way to pass arguments as an array of strings, use that approach instead.
For example:
* karate.exec({ args: [ 'curl', 'https://httpbin.org/anything' ] })
Refer: https://stackoverflow.com/a/73230200/143475

Related

How to pass dynamic variable in Scenario outline in Karate DSL

I have a situation where I need to pass a different variety of Date type variables in Karate.
For this, I created a JAVA method and calling it in a feature file as shown below.
I read that its cucumber limitation which can not support dynamic variables in Scenario Outline. I also read https://github.com/intuit/karate#the-karate-way but somehow, I am not getting any idea how to solve the below situation.
Scenario Outline: test scenario outline
* def testData = Java.type('zoomintegration.utils.DataGenerator')
* def meetDate = testData.futureDate(2)
* def jsonPayLoad =
"""
{
"meetingSource": <meetingSource>,
"hostId": <host>,
"topic": <topic>,
"agenda": <topic>,
"startDateTime": <meetingDate>",
"timeZone": "Asia/Calcutta",
"duration": <duration>
}
"""
* print jsonPayLoad
Examples:
|meetingSource|host|topic|duration|meetingDate|
|ZOOM | abc |Quarter meeting|30|0|
|SKYPE | abc |Quarter meeting|30|'1980-08-12'|
|MS | abc |Quarter meeting|30|'2030-12-12'|
Below code works for me:
Scenario Outline: test scenario outline
* def testData = Java.type('zoomintegration.utils.DataGenerator')
* def meetDate = testData.futureDate(<meetingDate>)
* def jsonPayLoad =
"""
{
"meetingSource": <meetingSource>,
"hostId": <host>,
"topic": <topic>,
"agenda": <topic>,
"startDateTime": #(meetDate),
"timeZone": "Asia/Calcutta",
"duration": <duration>
}
"""
* print jsonPayLoad
Examples:
| meetingSource | host | topic | duration | meetingDate |
| ZOOM | abc | Quarter meeting | 30 | 1 |
| SKYPE | abc | Quarter meeting | 30 | 2 |
| MS | abc | Quarter meeting | 30 | 3 |
Feature: test something
Scenario Outline: test scenario outline
* def testData = Java.type('zoomintegration.utils.DataGenerator')
* def meetDate = testData.futureDate(2)
* def jsonPayLoad =
"""
{
"meetingSource": <meetingSource>,
"hostId": <host>,
"topic": <topic>,
"agenda": <topic>,
"startDateTime": <meetingDate>,
"timeZone": "Asia/Calcutta",
"duration": <duration>
}
"""
* eval if (jsonPayLoad.startDateTime == 0) jsonPayLoad.startDateTime = meetDate
* print jsonPayLoad
Examples:
|meetingSource|host|topic|duration|meetingDate|
|ZOOM | abc |Quarter meeting|30|0|
|SKYPE | abc |Quarter meeting|30|'1980-08-12'|
|MS | abc |Quarter meeting|30|'1999-08-12'|
You must be missing something, and it looks like you have a few typos.
Let's take a simple example that works for me:
Feature:
Background:
* def fun = function(x){ return 'hello ' + x }
Scenario Outline:
* match fun(name) == 'hello foo'
Examples:
| name |
| foo |
So the point is - you can plug in a function that uses data from your Examples table to dynamically generate more data.
If you are still stuck, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

Using karate.set to change value of an array

I want to change the values present in an array using karate.set as i am using it in if condition
my code is:
> * def name = ["ankit"]
> * def value = 2
> * eval if ( value == 2) karate.set('name', 'ANKIT_DESAI')
but the value of name is not changing
Assume that as a list and modify value based on index
* def name = ["ankit"]
* def value = 2
* eval if ( value == 2) name[0] = "ANKIT_DESAI"

Karate - Can i send multiple dynamic data in Scenario Outline

Below is the code :
Feature:
Background:
* def Json = Java.type('Json')
* def dq = new Json()
* def result = dq.makeJson()
* def Sku = dq.makeSku()
Scenario Outline: id : <id>
* print '<id>' #From result
* print '<abc>' #From Sku
Examples:
|result|Sku|
The following is the output I need. Is it possible in Karate?
If i have id = {1,2} and abc = {3,4} i want output to be
id = 1 and abc = 3
id = 1 and abc = 4
id = 2 and abc = 3
id = 2 and abc = 4
Also can this be done for more than 2 variable inputs as well?
Write the permutation logic yourself, build an array with the results.
Note that you can iterate over key-value pairs of a JSON using karate.forEach()
Then either use a data-driven loop call (of a second feature file):
# array can be [{ id: 1, abc: 3 }, {id: 1, abc: 4 }] etc
* def result = call read('second.feature') array
Or a dynamic scenario outline:
Scenario Outline:
* print 'id = <id> and abc = <abc>'
Examples:
| array |
Refer:
https://github.com/intuit/karate#data-driven-features
https://github.com/intuit/karate#dynamic-scenario-outline

Confused about behavior of setResultsName in Pyparsing

I am trying to parse a few SQL statements. Here is a sample:
select
ms.member_sk a,
dd.date_sk b,
st.subscription_type,
(SELECT foo FROM zoo) e
from dim_member_subscription_all p,
dim_subs_type
where a in (select moo from t10)
I am interested in getting tables only at this time. So I would like to see
[zoo, dim_member_subscription_all, dim_subs_type] & [t10]
I have put together a small script looking at Paul McGuire's example
#!/usr/bin/env python
import sys
import pprint
from pyparsing import *
pp = pprint.PrettyPrinter(indent=4)
semicolon = Combine(Literal(';') + lineEnd)
comma = Literal(',')
lparen = Literal('(')
rparen = Literal(')')
update_kw, volatile_kw, create_kw, table_kw, as_kw, from_kw, \
where_kw, join_kw, left_kw, right_kw, cross_kw, outer_kw, \
on_kw , insert_kw , into_kw= \
map(lambda x: Keyword(x, caseless=True), \
['UPDATE', 'VOLATILE', 'CREATE', 'TABLE', 'AS', 'FROM',
'WHERE', 'JOIN' , 'LEFT', 'RIGHT' , \
'CROSS', 'OUTER', 'ON', 'INSERT', 'INTO'])
select_kw = Keyword('SELECT', caseless=True) | Keyword('SEL' , caseless=True)
reserved_words = (update_kw | volatile_kw | create_kw | table_kw | as_kw |
select_kw | from_kw | where_kw | join_kw |
left_kw | right_kw | cross_kw | on_kw | insert_kw |
into_kw)
ident = ~reserved_words + Word(alphas, alphanums + '_')
table = Combine(Optional(ident + Literal('.')) + ident)
column = Combine(Optional(ident + Literal('.')) + (ident | Literal('*')))
column_alias = Optional(Optional(as_kw).suppress() + ident)
table_alias = Optional(Optional(as_kw).suppress() + ident).suppress()
select_stmt = Forward()
nested_table = lparen.suppress() + select_stmt + rparen.suppress() + table_alias
table_list = delimitedList((nested_table | table) + table_alias)
column_list = delimitedList((nested_table | column) + column_alias)
txt = """
select
ms.member_sk a,
dd.date_sk b,
st.subscription_type,
(SELECT foo FROM zoo) e
from dim_member_subscription_all p,
dim_subs_type
where a in (select moo from t10)
"""
select_stmt << select_kw.suppress() + column_list + from_kw.suppress() + \
table_list.setResultsName('tables', listAllMatches=True)
print txt
for token in select_stmt.searchString(txt):
pp.pprint(token.asDict())
I am getting the following nested output. Can anybody please help me understand what I am doing wrong?
{ 'tables': ([(['zoo'], {}), (['dim_member_subscription_all', 'dim_subs_type'], {})], {})}
{ 'tables': ([(['t10'], {})], {})}
searchString will return a list of all matching ParseResults - you can see the tables value of each using:
for token in select_stmt.searchString(txt):
print token.tables
Giving:
[['zoo'], ['dim_member_subscription_all', 'dim_subs_type']]
[['t10']]
So searchString found two SELECT statements.
Recent versions of pyparsing support summing this list into a single consolidated using Python builtin sum. Accessing the tables value of this consolidated result looks like this:
print sum(select_stmt.searchString(txt)).tables
[['zoo'], ['dim_member_subscription_all', 'dim_subs_type'], ['t10']]
I think the parser is doing all you want, you just need to figure out how to process the returned results.
For further debugging, you should start using the dump method on ParseResults to see what you are getting, which will print the nested list of returned tokens, and then a hierarchical tree of all named results. For your example:
for token in select_stmt.searchString(txt):
print token.dump()
print
prints:
['ms.member_sk', 'a', 'dd.date_sk', 'b', 'st.subscription_type', 'foo', 'zoo', 'dim_member_subscription_all', 'dim_subs_type']
- tables: [['zoo'], ['dim_member_subscription_all', 'dim_subs_type']]
['moo', 't10']
- tables: [['t10']]

Get all rows where 2 fields exist In Array for PDO SQL?

I have an array structured like this:
Array
(
[0] => Array
(
[0] => 1 //x
[1] => 3 //y
)
[1] => Array
(
[0] => 8 //x
[1] => 7 //y
)
[2] => Array
(
[0] => 9 //x
[1] => 9 //y
)
)
What I want to know is there a way to make a query to get all rows where 2 fields match any pair of values for the second level of arrays for example say i have 2 rows with:
| uid | id | x | y |
- - - - - - - - - - - - -
| 1 | 1 | 1 | 3 | //both x and y exist together
| 1 | 1 | 9 | 9 | //both x and y exist together
| 1 | 1 | 9 | 5 | //no combination do not select this
I'm trying to avoid looping the array and using SELECT every iteration, but would rather some way to do it directly in my query to lower the amount of looping.
IS this at all possible or is my only option to loop the array and query each one at a time...this to me seems quite intensive as the array grows in length!!
I was hoping maybe there is some in_array method for SQL?
My suggestion would be to generate a long query from the array you've provided.
<?php
$arr = array(
array(1,3),
array(8,7),
array(9,9)
);
function wherify($val) {
return "(`x` = ".$val[0]." AND `y` = ".$val[1].")";
}
$criteria = implode(" OR ", array_map("wherify", $arr));
$query = "SELECT * FROM `table` WHERE $criteria";
echo $query;
This would create a query that would look something like the following.
SELECT * FROM `table`
WHERE (`x` = 1 AND `y` = 3)
OR (`x` = 8 AND `y` = 7)
OR (`x` = 9 AND `y` = 9)
(execution)