Used userDataDir: 'path' in driver configure file but still files are not downloading in the specific location
Expected file to be downloaded in specific location
Can someone help me how to setup a specific path to download file in Karate in chrome like in selenium Chrome preference
You could use the experimental Browser.setDownloadBehavior Chrome DevTools Protocol method.
Here is a full example:
Feature:
Background:
* def waitForDownload = function(downloadPath) { while (!new java.io.File(downloadPath).isFile()) java.lang.Thread.sleep(1000) }
Scenario:
* configure driver = { type: 'chrome' }
* driver 'https://github.com/karatelabs/karate/releases/tag/v1.3.0'
* driver.send({ method: 'Browser.setDownloadBehavior', params: { behavior: 'allow', downloadPath: karate.toAbsolutePath('./someDir') } })
# scroll to bottom of page to ensure download link is created
* script('let x = (document.scrollingElement || document.body); x.scrollTop = x.scrollHeight')
* waitFor("a[href='/karatelabs/karate/archive/refs/tags/v1.3.0.tar.gz']").click()
* call waitForDownload karate.toAbsolutePath('./someDir/karate-1.3.0.tar.gz')
Related
Used userDataDir: 'path' in driver configure file but still files are not downloading in the specific location
Expected file to be downloaded in specific location
Can someone help me how to setup a specific path to download file in Karate in chrome like in selenium Chrome preference
You could use the experimental Browser.setDownloadBehavior Chrome DevTools Protocol method.
Here is a full example:
Feature:
Background:
* def waitForDownload = function(downloadPath) { while (!new java.io.File(downloadPath).isFile()) java.lang.Thread.sleep(1000) }
Scenario:
* configure driver = { type: 'chrome' }
* driver 'https://github.com/karatelabs/karate/releases/tag/v1.3.0'
* driver.send({ method: 'Browser.setDownloadBehavior', params: { behavior: 'allow', downloadPath: karate.toAbsolutePath('./someDir') } })
# scroll to bottom of page to ensure download link is created
* script('let x = (document.scrollingElement || document.body); x.scrollTop = x.scrollHeight')
* waitFor("a[href='/karatelabs/karate/archive/refs/tags/v1.3.0.tar.gz']").click()
* call waitForDownload karate.toAbsolutePath('./someDir/karate-1.3.0.tar.gz')
Used userDataDir: 'path' in driver configure file but still files are not downloading in the specific location
Expected file to be downloaded in specific location
Can someone help me how to setup a specific path to download file in Karate in chrome like in selenium Chrome preference
You could use the experimental Browser.setDownloadBehavior Chrome DevTools Protocol method.
Here is a full example:
Feature:
Background:
* def waitForDownload = function(downloadPath) { while (!new java.io.File(downloadPath).isFile()) java.lang.Thread.sleep(1000) }
Scenario:
* configure driver = { type: 'chrome' }
* driver 'https://github.com/karatelabs/karate/releases/tag/v1.3.0'
* driver.send({ method: 'Browser.setDownloadBehavior', params: { behavior: 'allow', downloadPath: karate.toAbsolutePath('./someDir') } })
# scroll to bottom of page to ensure download link is created
* script('let x = (document.scrollingElement || document.body); x.scrollTop = x.scrollHeight')
* waitFor("a[href='/karatelabs/karate/archive/refs/tags/v1.3.0.tar.gz']").click()
* call waitForDownload karate.toAbsolutePath('./someDir/karate-1.3.0.tar.gz')
Used userDataDir: 'path' in driver configure file but still files are not downloading in the specific location
Expected file to be downloaded in specific location
Can someone help me how to setup a specific path to download file in Karate in chrome like in selenium Chrome preference
You could use the experimental Browser.setDownloadBehavior Chrome DevTools Protocol method.
Here is a full example:
Feature:
Background:
* def waitForDownload = function(downloadPath) { while (!new java.io.File(downloadPath).isFile()) java.lang.Thread.sleep(1000) }
Scenario:
* configure driver = { type: 'chrome' }
* driver 'https://github.com/karatelabs/karate/releases/tag/v1.3.0'
* driver.send({ method: 'Browser.setDownloadBehavior', params: { behavior: 'allow', downloadPath: karate.toAbsolutePath('./someDir') } })
# scroll to bottom of page to ensure download link is created
* script('let x = (document.scrollingElement || document.body); x.scrollTop = x.scrollHeight')
* waitFor("a[href='/karatelabs/karate/archive/refs/tags/v1.3.0.tar.gz']").click()
* call waitForDownload karate.toAbsolutePath('./someDir/karate-1.3.0.tar.gz')
I was trying to find a way to launch all features in Karate testing through maven using an external variable to set up the browser (with a local webdriver or using a Selenium grid).
So something like:
mvn test -Dbrowser=chrome (or firefox, safari, etc)
or using a Selenium grid:
mvn test -Dbrowser=chrome (or firefox, safari, etc) -Dgrid="grid url"
With Cucumber and Java this was quite simple using a singleton for setting up a global webdriver that was then used in all tests. In this way I could run the tests with different local or remote webdrivers.
In Karate I tried different solution, the last was to:
define the Karate config file a variable "browser"
use the variable "browser" in a single feature "X" in which I set up only the Karate driver
from all the other features with callonce to re-call the feature "X" for using that driver
but it didn't work and to be honest it doesn't seem to me to be the right approach.
Probably being able to set the Karate driver from a Javascript function inside the features is the right way but I was not able to find a solution of that.
Another problem I found with karate is differentiating the behavior using a local or a remote webdriver as in the features files they're set in different ways.
So does anyone had my same needs and how can I solve it?
With the suggestions of Peter Thomas I used this karate-config.js
function fn() {
// browser settings, if not set it takes chrome
var browser = karate.properties['browser'] || 'chrome';
karate.log('the browser set is: ' + browser + ', default: "chrome"');
// grid flag, if not set it takes false. The grid url is in this format http://localhost:4444/wd/hub
var grid_url = karate.properties['grid_url'] || false;
karate.log('the grid url set is: ' + grid_url + ', default: false');
// configurations.
var config = {
host: 'http://httpstat.us/'
};
if (browser == 'chrome') {
if (!grid_url) {
karate.configure('driver', { type: 'chromedriver', executable: 'chromedriver' });
karate.log("Selected Chrome");
} else {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Chrome in grid");
}
} else if (browser == 'firefox') {
if (!grid_url) {
karate.configure('driver', { type: 'geckodriver', executable: 'geckodriver' });
karate.log("Selected Firefox");
} else {
karate.configure('driver', { type: 'geckodriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Firefox in grid");
}
}
return config;
}
In this way I was able to call the the test suite specifying the browser to use directly from the command line (to be used in a Jenkins pipeline):
mvn clean test -Dbrowser=firefox -Dgrid_url=http://localhost:4444/wd/hub
Here are a couple of principles. Karate is responsible for starting the driver (the equivalent of the Selenium WebDriver). All you need to do is set up the configure driver as described here: https://github.com/intuit/karate/tree/master/karate-core#configure-driver
Finally, depending on your environment, just switch the driver config. This can easily be done in karate-config.js actually (globally) instead of in each feature file:
function fn() {
var config = {
baseUrl: 'https://qa.mycompany.com'
};
if (karate.env == 'chrome') {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: 'http://somehost:9515/wd/hub' });
}
return config;
}
And on the command-line:
mvn test -Dkarate.env=chrome
I suggest you get familiar with Karate's configuration: https://github.com/intuit/karate#configuration - it actually ends up being simpler than typical Java / Maven projects.
Another way is to set variables in the karate-config.js and then use them in feature files.
* configure driver = { type: '#(myVariableFromConfig)' }
Keep these principles in mind:
Any driver instances created by a "top level" feature will be available to "called" features
You can even call a "common" feature, create the driver there, and it will be set in the "calling" feature
Any driver created will be closed when the "top level" feature ends
You don't need any other patterns.
EDIT: there's some more details in the documentation: https://github.com/intuit/karate/tree/develop/karate-core#code-reuse
And for parallel execution or trying to re-use a single browser for all tests, refer: https://stackoverflow.com/a/60387907/143475
I have just started implementing karate UI (v0.9.5). Have already implemented api testing using karate and it works perfectly.
Following the HTTP basic auth strategy on this page - https://github.com/intuit/karate#http-basic-authentication-example the basic auth handling works for api tests. I set the HTTP headers once and run all api tests.
Now for the UI testing, the URL that I open brings up the basic auth pop-up as shown below:
So I thought that I could use the same strategy that I used for api tests to handle this. In the background section of my feature file, i call the feature file that does the authentication and sets headers as below:
The called feature file to set headers (admin-headers.feature). This feature file gets the token after admin user login is performed via karate-config.js. Then assigns the token along with the Base64 encoded basic auth to the headers calling headers.js. The Base64 user and password are being input as maven arguments and read via karate-config variables.
(/admin-headers.feature)
Feature: karate-config.js will perform one time login for admin and
set the session token for all subsequent requests
Background:
* def session = adminAuthInfo.authSession
* def basic_auth = call read('classpath:basic-auth.js') { username: '#(basicAuthUser)', password: '#(basicAuthPassword)' }
* configure headers = read('classpath:headers.js')
Scenario: One-time login for user and set the
session token in request header
The js code for returning Auth and Cookie to above feature file (/headers.js).
function() {
var session = karate.get('session');
var basic_auth = karate.get('basic_auth');
if(session){
return {
Authorization: basic_auth,
Cookie: "SESSION=" + session
};
} else {
return {};
}
}
My UI test feature file (/ui-test.feature):
Feature: Login test
Background:
# Authorise via api
* callonce read('classpath:common/headers/admin-headers.feature')
* configure driver = { type: 'chrome' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
Running the above feature file still shows the auth pop-up.
I then tried to set the cookies while I am initialising the driver (which I think is probably not the right way?) as below:
Feature: Login test
Background:
# Authorise via api
* def login = callonce read('classpath:common/headers/admin-headers.feature')
* def uiCookie = { name: 'SESSION', value: '#(login.userAuthInfo.authSession)', domain: 'test.internal.mysite.com' }
* configure driver = { type: 'chrome', cookie: '#(uiCookie)' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
The above also does not work. What is it that I am doing wrong here? the pop-up keeps coming up because the cookie is not set when the driver is initialised and then opens the specified url?
Help is much appreciated.
I think you raised a very good feature request, that configure driver should take cookies also, so that you can navigate to the page and set cookies in one-shot, and I opened a feature request: https://github.com/intuit/karate/issues/1053
So try this sequence, refer docs for cookie(): https://github.com/intuit/karate/tree/master/karate-core#cookieset
* driver 'about:blank'
* cookie(uiCookie)
* driver 'https://test.internal.mysite.com/names'
And now it should work !
Feature: Windows Authentication feature
Background:
* configure driver = { type: 'chrome' }
Scenario: Windows Authentication Valid Login test case
Given driver 'http://the-internet.herokuapp.com/basic_auth'
And delay(3000)
And screenshot()
* robot {}
* robot.input('admin' + Key.TAB)
* robot.input('admin')
* robot.click('Sign in')
And delay(3000)
And screenshot()
works fine with chrome, edge