based on feedback, team wants to do hybrid tests and port all cookies from the API http-client to the UI tests
we potentially need the reverse as well. right now thinking that making the JSON the same should be good enough so they can be passed around. to investigate
@ptrthomas - as discussed, Pls assign this to me. Thank you.
@ptrthomas - can you pls help me with some of the requirements for this issue? From my very limited knowledge, the Http Client is used for API testing and you possibly have something similar for UI testing - is the goal to have same cookies apply to both http clients as well as UI frameworks? Currently the cookies can be set via header[Set-Cookie] or set in DSL as following:
And cookie foo = {value:'bar', max-age:'0', path:'/search'}
Is the goal to have a common DSL to make the cookie available both to Http Clients as well as UI?
Thank you for you help in advance, looking forward to working on it.
@chaudharydeepak no worries. first have a look at how cookies work for UI tests: https://github.com/intuit/karate/tree/master/karate-core#cookieset and there is an example of creating a UI cookie one at a time
so the requirement is a simple way to just take ALL HTTP client responseCookies and add them to the UI driver. today it has to be done manually using a loop
the driver has getCookies() but is missing a setCookies(List<Map>) - ideally this line should be possible
* driver.setCookies(responseCookies)
OR
* driver.cookies = responseCookies
what I am not sure is if responseCookies shape is ready for UI, and may need a little bit of testing
@ptrthomas Thank you - I will checkout all above details and update here in a few days.
@ptrthomas - spend sometime today - I think I got gist of basic requirement - made some changes and tested out with following test case -
Scenario: pass cookie from API call to UI call
Given path 'search', 'cookies'
And cookie foo = {value:'bar', path:'/search'}
When method get
Then status 200
And match response == '#[1]'
And match response[0] contains { name: 'foo', value: 'bar' }
Given driver demoBaseUrl + '/search/cookies'
* print responseCookies
When setCookies(responseCookies)
Then match driver.cookies == '#[1]'
Now, we can see the cookie set in API call is passed over to driver UI call.
I am not done yet with this - the commits are in my repo at https://github.com/chaudharydeepak/karate/commit/7f70e216b3b2052e5bb5f3af9307281d0665c429
I plan on further refactoring and will keep you posted. Thank you.
@ptrthomas - today I spent sometime trying to reverse the hybrid test scenario - i.e. set cookie in UI call and then make that available to api call -
Scenario: pass cookie from a UI call to a certain API call
Given driver demoBaseUrl + '/search/cookies'
Given def cookie2 = { name: 'hello', value: 'world' }
When cookie(cookie2)
Then match driver.cookies contains '#(^cookie2)'
Given path 'search', 'cookies'
* cookies driver.cookies
When method get
Then status 200
And match response == '#[1]'
And match response[0] contains { name: 'hello', value: 'world' }
Now, frankly I struggled a bit with coming up with a clean way to set driver.cookies to cookies for API call :). So instead, I wrote a bit of hack to deserialize driver.cookies [ which is a list of multiple cookies set in UI calls ] inside cookies method as following -
public void cookies(String expr) {
if ( expr.trim().equalsIgnoreCase("driver.cookies"))
{
ScriptValue scriptValue = eval("driver.cookies");
List<Map> mapList = scriptValue.getAsList();
mapList.forEach( currCookieSet ->
{
Cookie cookie = new Cookie(String.valueOf(currCookieSet.get("name")),String.valueOf(currCookieSet.get("value")));
request.setCookie(cookie);
});
}
so overall this is working.
Can you pls share any pointers / guidance around this scenario? I am thinking there is an easy way out already there before we try anything complex. Thank you.
@chaudharydeepak driver.cookies which is the same as driver.getCookies() should already return a List<Map> right - I thought it would "just work"
@ptrthomas Yeah it returns that - though because the way public void cookies(String expr) is currently written, it ends up throwing exception because of this line Map<String,Object> map = evalMapExpr(expr); - tries to evaluate the expression to a map vs its a list of map. https://github.com/chaudharydeepak/karate/blob/master/karate-core/src/main/java/com/intuit/karate/core/ScenarioContext.java#L657
@chaudharydeepak ah I got it. okay, you can do a conditional, does this help ? you can do this inside void cookies(expr)
ScriptValue value = Script.evalKarateExpression(expr, this);
if (value.isMapLike()) {
} else if (value.isListLike()) {
}
@ptrthomas - yup, i took care of that already as exactly you mentioned - removed the hard-coded text etc 馃憤 ! will do some more testing / validations and push this for your review. Thank you.
I think this works now, here is the new, improved test-suite: https://github.com/intuit/karate/blob/develop/karate-e2e-tests/src/test/java/driver/04.feature