How to access karate ui automation driver details like sessionid in afterScenario? [duplicate] - karate

This question already has an answer here:
KARATE integration with SauceLabs
(1 answer)
Closed 1 year ago.
I am reading the json file which contains the array of configurations of browserstack browsers or devices on which I want run my UI automation tests and defining it in karate-config.js as a global variable, for ex: config.envrironments. That variable I am calling it in Examples Table as envrironments and using it in dynamic scenario outline to initialize driver for different browser/device sessions as envrironments[__num]. The execution is working fine as expected.
After execution, I want to call the browserstack api which updates the test scenario status as passed or failed with a reason in their dashboard or in the browserstack report integrated in jenkins for clear understanding. The api requires driver sessionId as api path param, status(passed or failed) and reason(if failed) as body.
I am able to get the status and reason from karate.info.errorMessage after configuring afterScenario for the feature. But my problem is to get the browserstack sessionId.
To get the driver.sessionId in afterScenario, i'm getting error as "driver" is not defined. I guess driver object is getting killed in between each execution of scenario outline and the afterScenario.
Is there any way to keep the driver alive until the afterScenario is completed?
or
any other alternatives like implementing ExecutionHook class or any other class through which we can get the driver details?
Please help. Thanks in advance.
UPDATE:
I'm using Java 8 and karate version 0.9.6
Below is my code:
Test Feature -
Feature: Test Feature
Background:
* def scenarioStatus =
"""
{
"status": "passed",
"reason": ""
}
"""
* configure afterScenario =
"""
function(){
if(karate.info.errorMessage){
scenarioStatus.status = 'failed';
scenarioStatus.reason = karate.info.errorMessage;
}
karate.log('session id : ' + karate.get('sessionId'));
// karate.call('browserstack.feature', scenarioStatus);
}
"""
#dummyMobileBrowser
Scenario Outline: Dummy Scenario
* def browserTestName = karate.info.scenarioName + ' - '
* call read('driver.feature#initializeDriver')
* def sessionId = driver.sessionId
* call read('loginPage.feature#login')
# I'm defining array of device or browser configs in karate-config.js
Examples:
| deviceConfigs |
driver.feature
Feature: Driver Related Feature
Background:
* def jsUtils = read('classpath:jsUtils.js')
* def getDriverConfig =
"""
function(){
if(browserstack == "yes"){
var configResult = karate.call('driver.feature#createBrowserStackConfig');
var browserstackConfig = configResult.browserstackConfig;
return browserstackConfig;
}else{
return deviceConfigs[__num];
}
}
"""
#initializeDriver
Scenario: Initialize Driver
* def driverConfig = getDriverConfig()
* configure driver = driverConfig
* print 'Driver Config: ', driverConfig
* driver envHost
# also tried to def here
# * def sessionId = driver.sessionId
# * eval scenarioStatus.browserstackSessionId = sessionId
# * karate.write(sessionId, 'classpath:browserstackSessionId.txt')
* driver.fullscreen()
#takeScreenshot
Scenario: Take screenshot
* driver.screenshot()
#createBrowserStackConfig
Scenario: Create Browserstack Config
* def deviceCapabilities = deviceConfigs[__num]
* def driverUrl = 'https://' + browserstackUsername + ':' + browserstackKey + '#' + browserstackUrl + '/wd/hub'
* eval commonCapabilities.build = (karate.match(typeof browserstackBuildName, 'undefined').pass) ? commonCapabilities.build + currentEpochTime : browserstackBuildName
* def desiredCapabilities = karate.merge(deviceCapabilities, commonCapabilities)
* def driverType = (karate.match(desiredCapabilities.browserName, "#notnull").pass) ? desiredCapabilities.browserName : desiredCapabilities.browser + 'driver'
* eval driverType = (karate.match(driverType, 'firefoxdriver').pass) ? 'geckodriver' : driverType
* eval desiredCapabilities.name = (karate.match(desiredCapabilities.browserName, "#notnull").pass) ? desiredCapabilities.browserName : desiredCapabilities.browser
* eval desiredCapabilities.name = browserTestName + desiredCapabilities.name
* def capabilities = karate.merge(deviceCapabilities, commonCapabilities)
* eval capabilities.name = (karate.match(capabilities.browserName, "#notnull").pass) ? capabilities.browserName : capabilities.browser
* eval capabilities.name = browserTestName + capabilities.name
* def browserSession = { desiredCapabilities: '#(desiredCapabilities)', capabilities: '#(capabilities)' }
* def browserstackConfig = { type: '#(driverType)', webDriverSession: '#(browserSession)', start: false, webDriverUrl: '#(driverUrl)' }

Even if the driver is not callable - you should be able to access variables, right ?
So if you did this within the normal test-flow:
* def sessionId = driver.sessionId
Then the sessionId variable should be directly accessible in the after-hooks. Do karate.get('sessionId') if needed, try it and please comment below if it works.

Related

In Karate - Feature file calling from another feature file along with variable value

My apologies it seems repetitive question but it is really troubling me.
I am trying to call one feature file from another feature file along with variable values. and it is not working at all.
Below is the structure I am using.
my request json having variable name. Filename:InputRequest.json
{
"transaction" : "123",
"transactionDateTime" : "#(sTransDateTime)"
}
my featurefile1 : ABC.Feature
Background:
* def envValue = env
* def config = { username: '#(dbUserName)', password: '#(dbPassword)', url: '#(dbJDBCUrl)', driverClassName: "oracle.jdbc.driver.OracleDriver"};
* def dbUtils = Java.type('Common.DbUtils')
* def request1= read(karate.properties['user.dir'] + 'InputRequest.json')
* def endpoint= '/v1/ABC'
* def appDb = new dbUtils(config);
Scenario: ABC call
* configure cookies = null
Given url endpoint
And request request1
When method Post
Then status 200
Feature file from which I am calling ABC.Feature
#tag1
**my featurefile1: XYZ.Feature**
`Background`:
* def envValue = env
Scenario: XYZ call
* def sTransDateTime = function() { var SimpleDateFormat = Java.type('java.text.SimpleDateFormat'); var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'+00:00'"); return sdf.format(new java.util.Date()); }
* def result = call read(karate.properties['user.dir'] + 'ABC.feature') { sTransDateTime: sTransDateTime }
Problem is,
While executing it, runnerTest has tag1 configured to execute.
Currently, it is ignoring entire ABC.feature to execute and also not generating cucumber report.
If I mention the same tag for ABC.feature (Which is not expected for me as this is just reusable component for me ) then it is being executed but sTransDateTime value is not being passed from XYZ.feature to ABC.feature. Eventually, InputRequest.json should have that value while communicating with the server as a part of the request.
I am using 0.9.4 Karate version. Any help please.
Change to this:
{ sTransDateTime: '#(sTransDateTime)' }
And read this explanation: https://github.com/intuit/karate#call-vs-read
I'm sorry the other part doesn't make sense and shouldn't happen, please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue

Karate Mocks- `How to create a mocks to get a value from json using the key

Karate Mocks- `How to create a mocks to get a value from json using the key.
In below example, i want to get the name using the id, iam not able to retrieve
response.json
{
"2727": "siva",
"2728": "kavi"
}
demo-mock.feature
Feature: stateful mock server
Background:
* def company = read('response.json')
Scenario: pathMatches('/companies/search/{id}}')
* def name = company.id
* def response = name
test.feature
Feature: integration test
Background:
* def port = karate.env == 'mock' ? karate.start('demo-mock.feature').port : 8080
* url 'http://localhost:' + port + '/companies/search'
#mock
Scenario: get company name
Given path '2727'
When method get
Then status 200
Read the docs: https://github.com/intuit/karate/tree/master/karate-netty#pathparams
* def id = pathParams.id

Can execute JS function in the browser at KarateDriver?

When using KarateDriver, I want to define and execute JS function in the browser.
Is is possible?
I want to define it like:
* def someFn =
"""
function(param) {
// DOM operation in the browser
// Event handling in the browser
return
}
"""
* assert someFn('param1') == '<span>param1</span>'
Edit1:
I define and execute;
* def keyword = 'karate'
* def formSubmit =
"""
function(formId) {
var formElem = document.getElementById(formId);
formElem.submit();
}
"""
Given driver 'https://github.com/search'
And driver.input('input[name=q]', keyword)
When driver.eval(formSubmit('search_form'))
Then eval driver.waitUntil(driver.location == 'https://github.com/search?utf8=%E2%9C%93&q=' + keyword + '&ref=simplesearch')
but this feature is failure.
javascript evaluation failed: driver.eval(formSubmit('search_form')), ReferenceError: "document" is not defined in <eval> at line number 2
Can it use DOM operations?
Edit2:
I can define and execute the JS function:
* def getSubmitFn =
"""
function(formId) {
return "var formElem = document.getElementById('" + formId + "');"
+ "formElem.submit();"
}
"""
You can do driver.eval() where the argument is raw javascript code as a string. I think this is sufficient for your needs:
* match driver.eval("location.href") == webUrlBase + '/page-01'
* assert driver.eval('1 + 2') == 3
EDIT: the JS engine for Karate and the Browser JS engine is different and there is no connection. So you have to pass JS as raw strings to driver.eval() here is an example that works for submitting a form.
* def getSubmitFn =
"""
function(formId) {
return "document.getElementById('" + formId + "').submit()"
}
"""
* def temp = getSubmitFn('eg02FormId')
* print temp
* driver.eval(temp)
EDIT: I just remembered, * driver.eval() is valid, no need to do * eval karate.eval()
Typically what you pass to driver.eval() can be simple, but it has to be a string, and you cannot use Karate variables (you have to hard-code them when creating the JS dynamically). You can use DOM objects and functions. You can have multiple statements of JS separated by ;.

call the first feature from the second feature file, failed without specified clue

Run the first.feature file successfully,however, call it from the second.feature failed without any clue to analysis. Do you have any idea help me find the root cause?
The source of my first.feature:
Feature: 采样管理-样本登记
Background: 读取随机生成的条形码、手机号、采样类型等作为入参
* url baseURL
* def randomData = Java.type('utils.RandomData')
* def barcode = randomData.getRandom(11)
* def randomPhone = randomData.getTelephone()
* def sampletype = randomData.getNum(0,1)
Scenario: 输入合法参数进行正常样本登记,确认能够登记成功
Given path 'iEhr/PersonSample'
# * header Content-type = 'application/x-www-form-urlencoded; charset=UTF-8'
* cookies { JSESSIONID: '#(jsessionID)',SESSION: '#(sessionID)', ACMETMP: '#(acmetmpID)'}
* def autoMotherName = "autoMname"+ barcode
# * def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"#(sampletype)" }
# 设置sampletype为1,已被采样
* def confData = {mothername: "#(autoMotherName)", barcode: "#(barcode)", mobile: '#(randomPhone)', sampletype:"1" }
# 打印入参变量输出
* print confData
# 用例与数据分离
* def paramObj = read('classpath:mainFlow/sampleSaveReqTest.json')
* print paramObj
* form field param = paramObj
When method post
Then status 200
* json result = response[0].result
* def personId = result[0].personid
* def sampleid = result[0].sampleid
* print personId
* print sampleid
The source of my second.feature:
Feature: 提交递送样本
Background:
* def sampleResult = call read('classpath:mainFlow/first.feature')
* print sampleResult
I run the first.feature singly, it works. However, karate reports the error below after running the second.feature. Any idea how can I debug to find the root cause? I have no idea what's wrong with the second read. Many thanks!
* def sampleResult = call read('classpath:mainFlow/first.feature')
-unknown-:14 - javascript evaluation failed: read('classpath:mainFlow/first.feature'), null
Look for some issue with karate-config.js. As Babu said in the comments, it is very hard to make out what the problem is, I suggest you follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
Also try if the latest preview version 0.9.3.RC2 is better at showing what the error is.
If you can replicate the problem as a small example, it will help us - because we really need to do better at showing more useful error logs, instead of just null.

How to call a specific function from JS file to feature file in karate [duplicate]

I need to perform two operations on the result of JSON responses.so can we have those different operations inside single JS file? or do we need to have mapping like one JS file for one operation.
Please help on this
I don't recommend trying to create complicated JavaScript in Karate, it just leads to maintainability issues. If you really want an object with multiple utility methods on it, write a Java class with static methods, and it will be much easier to maintain / debug.
That said, if you really insist - look at this answer: https://stackoverflow.com/a/47002604/143475
But this is what I recommend for most projects. In one "common" feature file, define multiple methods like this:
Scenario:
* def now = function(){ return java.lang.System.currentTimeMillis() }
* def uuid = function(){ return java.util.UUID.randomUUID() + '' }
You can now call this feature like this:
* call read('common.feature')
And now all the functions in that feature are available for use:
* def time = now()
* def id = uuid()
#kmancusi This is how I did a common.feature file with my common functions and then the following my.test.feature shows how I import that to use it in another feature.
common.feature
#ignore
Feature:
Scenario:
* def now =
"""
function() {
return java.lang.System.currentTimeMillis()
}
"""
* def uuid =
"""
function() {
return java.util.UUID.randomUUID() + ''
}
"""
my.test.feature
Feature: my tests
Background:
* configure logPrettyRequest = true
* configure logPrettyResponse = true
* configure ssl = true
Scenario: basic test
* def util = call read('common.feature')
* def sessionId = util.uuid()
* print sessionId