While running grunt server for developing, How can I separately use the grunt qunit task to run the tests.
While trying to pass ["test/**/*.html"] to the all property, but that fails to run and returns (Warning: 0/0 assertions ran (0ms) Use)
It looks like, it doesn't fire off a phantomjs instance and doesn't find these pates.
So I tried the following
grunt.initConfig({
....
qunit: {
all: {
options: {
urls: ['http://localhost:<%= connect.options.port %>/test/tests/foo.html']
}
}
}
....
});
It only works if when manually include all test html pages (like in the example).
The problem is
My Question is, can grunt qUnit work properly even while using grunt server.
And how can i have ["test/**/*.html"] syntax work correctly. I am sure there must be a better way this should work!
Also, how can use grunt.file.expand be utilized to programmatically add matching files to run in the grunt qunit task.
I've done something like this:
grunt.initConfig({
...
'qunit': {
'files': ['test/**/*.html']
}
...
});
...
// Wrap the qunit task
grunt.renameTask('qunit', 'contrib-qunit');
grunt.registerTask('qunit', function(host, protocol) {
host = host || 'localhost';
protocol = protocol || 'http';
// Turn qunit.files into urls for conrib-qunit
var urls = grunt.util._.map(grunt.file.expand(grunt.config.get('qunit.files')), function(file) {
return protocol + '://' + host + '/' + file;
});
var config = { 'options': { 'urls' : urls } };
grunt.config.set('contrib-qunit.all', config);
grunt.task.run('contrib-qunit');
});
Related
In the code presented below, I am trying to interact with a database through the use of a js function within the karate framework. The query used to get some data works as expected, likewise auxiliary information is accessible. The same function within the js file can be ran through groovy just fine but seems to explode when ran within karate.
JS Function to be ran in karate through a callSingle():
function() { let dbUser = Java.type('dev.dao.dbUser') return dbUser.getId(karate.properties['username'])
dbUser:
class dbUser {
static Integer getId(String email) {
db.sql.firstRow("select user_id from table.db_user where email = ?", [email]).userId
}
}
Karate-config.js
function fn() {
let config = {
project: karate.properties['vs.project'],
environment: karate.properties['vs.environment'],
baseUrl: karate.properties['vs.baseUrl'],
timeZoneId: karate.properties['vs.timeZoneId'],
env: karate.properties['vs.env'],
proxy: {
...
]
},
demoUserId: 1,
userId: karate.callSingle('classpath:proj/dev/js/dao/getDbUserId.js'),
createDBuid: karate.read('classpath:proj/dev/js/createDBuid.js'),
DBuid: karate.callonce('classpath:proj/dev/js/createDBuid.js')
}
}
Error returned calling the getDbUserId.js:
PolyglotError
<<<<
org.graalvm.polyglot.PolyglotException
com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:243)
com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:187)
.fn(Unnamed:18)
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
My publicPath is /static/dist. How i can proxy static/dist to / when my dev server running?
I know i can:
let publicPath;
if (process.env.NODE_BUILD_DEPLOYMENT_PATH) {
// Change process.env.NODE_BUILD_DEPLOYMENT_PATH to match the path to your files
// in production (could be S3, CloudFront, etc.)
publicPath = process.env.NODE_BUILD_DEPLOYMENT_PATH;
} else {
publicPath = 'http://localhost:8099/';
}
But i need proxy. It's for pre-render. After render i need static/dist prefix for all my static files. But when my dev server running i want proxy static/dist to /.
For example: static/dist/js -> /js.
Solution is:
server: {
port: options.devServer.port,
proxy: {
'/static/dist/*': {
target: 'http://localhost:8099',
pathRewrite: {'^/static/dist/': ''}
}
}
},
I have a Vue.js CLI project working.
It accesses data via AJAX from localhost port 8080 served by Apache.
After I build the project and copy it to a folder served by Apache, it works fine and can access data via AJAX on that server.
However, during development, since the Vue.js CLI website is being served by Node.js which is serving on a different port (8081), I get a cross-site scripting error) and want to avoid cross-site scripting in general.
What is a way that I could emulate the data being provided, e.g. some kind of server script within the Vue.js-CLI project that would serve mock data on port 8081 for the AJAX calls during the development process, and thus avoid all cross-site scripting issues?
Addendum
In my config/index.js file, I added a proxyTable:
dev: {
env: require("./dev.env"),
port: 8081,
autoOpenBrowser: true,
assetsSubDirectory: "static",
assetsPublicPath: "/",
proxyTable: {
"/api": {
target: "http://localhost/data.php",
changeOrigin: true
}
},
And now I make my AJAX call like this:
axios({
method: 'post',
url: '/api',
data: {
smartTaskIdCode: 'activityReport',
yearMonth: '2017-09',
pathRewrite: {
"^/api": ""
}
}
But now I see in my JavaScript console:
Error: Request failed with status code 404
Addendum 2
Apparent axios has a problem with rerouting, so I tried it with vue-resource but this code is showing an error:
var data = {
smartTaskIdCode: 'pageActivityByMonth',
yearMonth: '2017-09'
}
this.$http.post('/api', data).then(response => {
this.pageStatus = 'displaying';
this.activity = response.data['activity'];
console.log(this.activity);
}, response => {
this.pageStatus = 'displaying';
console.log('there was an error');
});
The webpack template has its own documentation, and it has a chapter about API proxying during development:
http://vuejs-templates.github.io/webpack/proxy.html
If you use that, it means that you will request your data from the node server during development (and the node server will proxy< the request to your real backend), and the real backend directly in production, so you will have to use different hostnames in each environment.
For that, you can define an env variable in /config/dev.env.js & /config.prod.env.js
I need to write multiple tests (e.g. login test, use application once logged in tests, logout test, etc.) and need them all to be in separate files. The issue I run into is after each test, at the beginning of the next test being run, a new browser session start and it is no longer logged in due to the new session, so all my tests will fail except the login test.
So, is there a way to use the same browser session to run all of my tests sequentially without having to duplicate my login code? Sorry if this is a repost but I have searched and researched and not found any answers.
OR, is there a way to chain the test files somehow? Like having one file that you run that just calls all the other test files?
Using this function to chain together files:
extend = function(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
and adding files to this master file like this:
require("./testName.js");
module.exports = extend(module.exports,testName);
and having the test file look like this:
testName = {
"Test" : function(browser) {
browser
// Your test code
}
};
allowed me to have one file that could link all the tests to, and keep the same browser session the entire time. It runs the tests in the order you require them in the master file and if you do not call browser.end() until the last test is finished it will use one browser window for all tests.
Reuse of session is not good idea as you may run tests in different oreder, but
You could place login code into before function or even extract it into custom commands.
Example:
https://github.com/dimetron/backbone_app/blob/master/nightwatch/custom-commands/login.js
1 - In nightwatch config add
"custom_commands_path" : "nightwatch/custom-commands",
2 - Create custom-commands/login.js
exports.command = function(username, password, callback) {
var self = this;
this
.frame(null)
.waitForElementPresent('input[name=username]', 10000)
.setValue('input[name=username]', username)
.waitForElementPresent('input[name=password]', 10000)
.setValue('input[name=password]', password)
.click('#submit');
if( typeof callback === "function"){
callback.call(self);
}
return this; // allows the command to be chained.
};
3 - Test code - Before using .login(user, apssword)
module.exports = {
before: function(browser) {
console.log("Setting up...");
browser
.windowSize('current', 1024, 768)
.url("app:8000/")
.waitForElementVisible("body", 1000)
.login('user', 'password')
},
after : function(browser) {
browser.end()
console.log("Closing down...");
},
beforeEach: function(browser) {
browser
.pause(2000)
.useCss()
},
"Test 1": function(browser) {
browser
.assert.containsText("#div1", "some tex")
.pause(5000);
},
"Test 2": function(browser) {
browser
.assert.containsText("#div2", "some text")
.pause(5000);
}
}