How to rerun failed step/secnario of a feature file in cucumber using webdriverio - selenium

Please help on this. I am using the following cucumber opts:
cucumberOpts: {
backtrace: false,
failAmbiguousDefinitions: true,
failFast: false,
ignoreUndefinedDefinitions: false,
name: [],
snippets: true,
source: true,
profile: [],
require: [
'./features/step_definitions/given.js',
'./features/step_definitions/when.js',
'./features/step_definitions/then.js',
],
snippetSyntax: undefined,
strict: true,
tagExpression: '#Test',
tagsInTitle: false,
timeout: 20000000,
},

https://www.npmjs.com/package/wdio-rerun-service Was recently released specifically for WebdriverIO and it works well with Cucumber Features/Scenarios.

I'm assuming you're using the wdio-cucumber-framework then you can only rerun individual steps a specific number of times, like so:
module.exports = function () {
/**
* The following STEP DEFINITION will run maximum 3 times!
* => 1 actual run + 2 reruns (on failure)
*/
this.Given(/^Your step definition here$/, { wrapperOptions: { retry: 2 } }, () => {
// ...
});
});
!Note: wrapperOptions are step-specific options that are passed to the definition function wrapper. In our case, the retry option. You can read more about it in the Cucumber DOCS.
If you need control over the retry of a test-case, or test-suite, then unfortunately there isn't such a feature yet with Cucumber. But, if you want something like that, maybe use Mocha instead. Here are a few examples.

Add this code to your wdio config file. It will retry the fail test two more time (total 3 time)
specFileRetries: 2,
specFileRetriesDelay: 5,
specFileRetriesDeferred: false,

Related

Global timeout doesn't work in WebDriverIO

I was trying to setup global delay with waitforTimeout as per below classes
wdio.conf.ts
export const config: WebdriverIO.Config = {
specs: ['./features/**/*.feature'],
baseUrl: process.env.UI_PROJECT_HOST || 'http://localhost:4001',
waitforTimeout: 50000,
maxInstances: 1,
framework: 'cucumber',
specFileRetries: 1,
reporters: [
'spec',
['cucumberjs-json-fix', {
jsonFolder: '../reports',
language: 'en',
}]
],
cucumberOpts: {
..........
wdio.chrome.conf.js
require('ts-node').register({ transpileOnly: true });
require('tsconfig-paths/register');
module.exports = require('./config/wdio.chrome.chromedriver.conf.ts');
wdio.chrome.chromedriver.conf.ts
import { config } from './wdio.conf';
import {join} from 'path';
const CHROME_ARGS = [
'--disable-background-networking',
'--enable-features=NetworkService,NetworkServiceInProcess',
.
.
.
With above I expect to have mentioned delay for all the user interactions when I run the script. Is my understanding correct?
However I can't see this when run the script with wdio run ./wdio.chrome.conf.js
I tried this too, but no luck wdio run ./wdio.chrome.conf.js --waitforTimeout=50000
Timeout-1
Timeout-2
I think you misunderstood the property. waitforTimeout is the MAXIMUM time the driver waits before throwing timeout exception if an element is not found. It does not mean that it will wait for the given time with every action. If the element is found immediately, the execution continues.

responsive-loader with nuxt.js

I want to integrate responsive-loader into my Nuxt.js project which runs in SPA mode. (Optional I want to add Vuetify Progressive Image support also).
It will be a static hosting with Netlify.
Versions:
"nuxt": "^2.3.4"
"responsive-loader": "^1.2.0"
"sharp": "^0.21.1"
I found some solutions how to do it (https://stackoverflow.com/a/51982357/8804871) but this is not working for me.
When I run npm run build
I get an error message: "TypeError: Cannot set property 'exclude' of undefined"
My build section looks the following:
build: {
transpile: [/^vuetify/],
plugins: [
new VuetifyLoaderPlugin()
],
extractCSS: true,
/*
** Run ESLint on save
*/
extend(config, { isDev, isClient, isServer }) {
// Default block
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
if (isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vuetify/]
})
]
}
// Default block end
// here I tell webpack not to include jpgs and pngs
// as base64 as an inline image
config.module.rules.find(
rule => rule.loader === "url-loader"
).exclude = /\.(jpe?g|png)$/;
/*
** Configure responsive-loader
*/
config.module.rules.push({
test: /\.(jpe?g|png)$/i,
loader: "responsive-loader",
options: {
min: 350,
max: 2800,
steps: 7,
placeholder: false,
quality: 60,
adapter: require("responsive-loader/sharp")
}
});
}
}
The error is probably found in this section:
config.module.rules.find(
rule => rule.loader === "url-loader"
).exclude = /\.(jpe?g|png)$/;
Like said I get this error message: "TypeError: Cannot set property 'exclude' of undefined".
I run this project along with vuetify. I also would like to enable the Progressive image support together with responsive loader. Does anybody know how to setup both rules together?
https://github.com/vuetifyjs/vuetify-loader#progressive-images
The easiest way to integrate responsive-loader into a Nuxt.js project is to use this module: https://www.npmjs.com/package/nuxt-responsive-loader
Disclaimer: I created the module
The problem with your config that it relies on rule.loader property but rule can be defined in use or oneOf config sections as well.
Another one problem is that nuxt internal config has several rules with url-loader(for images, videos, fonts ...).
In your case the rule, you tried to find, has use section and url-loader is defined there, that's why your find function found nothing and threw this error:
{
"test": /\.(png|jpe?g|gif|svg|webp)$/,
"use": [{
"loader": "url-loader",
"options": {
"limit": 1000,
"name": "img/[hash:7].[ext]"
}
}]
}
About responsive-loader, you should remove extensions you want to process with responsive-loader from url-loader rule to avoid unexpected behavior and conflicts, here is extend function working example:
extend(config, ctx) {
let imgTest = '/\\.(png|jpe?g|gif|svg|webp)$/';
// find by reg ex string to not rely on rule structure
let urlRule = config.module.rules.find(r => r.test.toString() === imgTest);
// you can use also "oneOf" section and define both loaders there.
// removed images from url-loader test
urlRule.test = /\.(svg|webp)$/;
config.module.rules.push({
test: /\.(png|jpe?g|gif)$/,
loader: "responsive-loader",
options: {
// place generated images to the same place as url-loader
name: "img/[hash:7]-[width].[ext]",
min: 350,
max: 2800,
steps: 7,
placeholder: false,
quality: 60,
adapter: require("responsive-loader/sharp")
}
})
}
Yes, it looks dirty, but I think it's only way for now to change some loader.
What about vuetify - I think both loaders will conflict with each other and probably the solution is to use single loader that will work with your images.
Hope it helps.
Update for Nuxt >= 2.4.0:
They modified the rules array please update the following line:
let imgTest = '/\\.(png|jpe?g|gif|svg|webp)$/i';
Then the code should work normally again.

r.js minified optimized file not running

BEFORE, I was using r.js to optimize and minify my javascript successfully. I had a main.js file that looked something like this:
require.config({
baseUrl: "scripts/lib",
paths: {
jquery: "http://code.jquery.com/jquery-1.11.2.min",
underscore: "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min",
d3: "d3-for-development",
katex: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min", // or 0.2.0
mathjax: "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML&delayStartupUntil=configured",
etc...
},
shim: {
underscore: { exports: "_" },
chosen: { deps: ["jquery"] },
mathjax: {
exports: "MathJax",
init: function (){
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
processEscapes: true,
},
});
MathJax.Hub.Startup.onload();
return MathJax;
}
},
},
});
require( [
"jquery",
"underscore",
"browser-detect",
"check-types",
"katex",
"mathjax",
etc
], function(
$,
_,
browser,
check,
katex,
mathjax,
etc
){
/////////////////////////// INITIALIZATION ///////////////////////////
loginInit()
show('#login')
etc...
and I could successfully run node build/r.js -o mainConfigFile=www/scripts/main.js baseUrl=www/scripts/lib name=../main out=www/scripts/main-optimized.min.js generateSourceMap=true preserveLicenseComments=false optimize=uglify2 to minify. Everything worked.
NOW, I have a config.js file that looks like this:
require.config({
urlArgs: "bust=" + new Date().getTime(),
baseUrl: "scripts/lib",
paths: {
jquery: ["jquery-min", "http://code.jquery.com/jquery-1.11.2.min"],
underscore: ["underscore-min", "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min"],
d3: "d3-for-development", // if we add patches separately, then we can just use https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min
katex: ["katex-min", "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.3.0/katex.min"], // or 0.2.0
mathjax: "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML&delayStartupUntil=configured",
main: "../main",
etc...
},
shim: {
underscore: { exports: "_" },
chosen: { deps: ["jquery"] },
mathjax: {
exports: "MathJax",
init: function init() {
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
processEscapes: true }
});
MathJax.Hub.Startup.onload();
return MathJax;
}
}
}
});
require(["main"], function (main) {
// pass. by loading main, we run main.js
});
Instead of passing the minify/optimize arguments straight into the command line, I've created a rbuild.js file for that:
({
mainConfigFile: "../www/scripts/config.js",
baseUrl: "../www/scripts/lib",
name: "../config",
out: "../www/scripts/config-optimized.min.js",
generateSourceMap: true,
preserveLicenseComments: false, // this is necessary for generateSourceMap to work
optimize: "uglify2",
// removeCombined: true,
// findNestedDependencies: true,
paths: {
// https://github.com/jrburke/requirejs/issues/791
// http://www.anthb.com/2014/07/04/optimising-requirejs-with-cdn-fallback
jquery: "jquery-min",
underscore: "underscore-min",
d3: "d3-for-development",
katex: "katex-min",
mathjax: "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML&delayStartupUntil=configured",
marked: "marked",
chosen: "chosen-min",
jsnetworkx: "jsnetworkx-min",
main: "../main",
},
})
and I run it with node build/r.js -o build/rbuild.js in the command line. It appears to run successfully and makes the config-optimized.min.js file, as expected. The output is:
Tracing dependencies for: ../config
Cannot optimize network URL, skipping: http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML&delayStartupUntil=configured
Uglify2 file: /Users/Matthew/programming/prove-math/www/scripts/config-optimized.min.js
/Users/Matthew/programming/prove-math/www/scripts/config-optimized.min.js
----------------
/Users/Matthew/programming/prove-math/www/scripts/lib/jquery-min.js
/Users/Matthew/programming/prove-math/www/scripts/lib/underscore-min.js
/Users/Matthew/programming/prove-math/www/scripts/lib/browser-detect.js
/Users/Matthew/programming/prove-math/www/scripts/lib/check-types.js
/Users/Matthew/programming/prove-math/www/scripts/lib/katex-min.js
/Users/Matthew/programming/prove-math/www/scripts/lib/profile.js
/Users/Matthew/programming/prove-math/www/scripts/lib/marked.js
/Users/Matthew/programming/prove-math/www/scripts/lib/d3-for-development.js
/Users/Matthew/programming/prove-math/www/scripts/lib/user.js
/Users/Matthew/programming/prove-math/www/scripts/lib/graph-animation.js
/Users/Matthew/programming/prove-math/www/scripts/lib/graph.js
/Users/Matthew/programming/prove-math/www/scripts/lib/node.js
/Users/Matthew/programming/prove-math/www/scripts/lib/blinds.js
/Users/Matthew/programming/prove-math/www/scripts/lib/chosen-min.js
/Users/Matthew/programming/prove-math/www/scripts/main.js
/Users/Matthew/programming/prove-math/www/scripts/lib/../config.js
But when I visit index.html via my server, the page is blank. The JS console gives no errors or log messages, which suggests that no JS is being run. My server gives no errors, which suggests that everything has been sent to the client successfully, and the client JS is not running.
So I'm pretty convinced the JS is there but not running. Is there something wrong with my setup that causes config.js to not run the code? With no error messages, I am having trouble troubleshooting :)
So I commented out
generateSourceMap: true,
preserveLicenseComments: false, // this is necessary for generateSourceMap to work
optimize: "uglify2",
and it worked! THEN, I uncommented that stuff, and it STILL worked!
It seems that as of requireJS 2.2 (I was using RequireJS 2.1.6 BEFORE), you can now use
optimize: "uglify",
or nothing at all, since this is the default setting. As of requireJS 2.2, it DOES use uglify2 in this case. This is the closest thing to an explanation that I can give :/

How to run a specific test case from a test suite using InternIO

Currently, I have a few test suites. To avoid running an entire test suite - how can I run just a single test case from a suite. My current workaround is to comment out test cases I don't want.
My intern.js file:
define({
environments: [
{ browserName: 'chrome'},
],
useSauceConnect: false,
//functionalSuites: ['tests/projects/projectA/main.js'],
tunnel: 'NullTunnel',
excludeInstrumentation: /./
});
The following is my main.js file:
define([
'intern',
'intern!object',
'intern/chai!assert'
],
function (intern, registerSuite, assert) {
registerSuite(function () {
var someLib;
return {
setup: function () {
},
'TC001 - Functionality 1': function () {
},
'TC002 - Functionality 2': function() {
},
'TC003 - Functionality 3': function() {
},
};
});
});
I am running this by using the command-line: To run - I issue the following command:
$ node_modules/.bin/intern-runner config=tests/intern functionalSuites=tests/projects/projectA/main.js
Is there a way to run say only "TC001 - Functionality 1" and other selected test cases without commenting out the other tests cases from the suite?
You can use the grep command line option. The grep option specifies a regular expression that filters on test ID (test IDs that match are run), giving you a lot of flexibility when specifying which tests will run. At it's simplest, you can just provide a short string, and Intern will run any tests with IDs containing that string:
$ node_modules/.bin/intern-runner config=tests/intern functionalSuites=tests/projects/projectA/main grep=TC001

Protractor pointing to Sauce Labs Selenium Server

I'm trying to integrate Protractor with Sauce Labs from Travis. I can get the sauce_connect server running correctly but am unable to get Travis to point to that particular remote server.
Travis will get to the point where it initiates sauce_connect but when I run "protractor:analytics" it doesn't point to the correct server and fails.
Travis.yml:
language: python
python:
- 3.2_with_system_site_packages
branches:
only:
- develop
before_install:
- sudo apt-get update -qq
- sudo apt-get install python-numpy
install:
- cd lib && python setup.py install
- cd .. && pip install -r requirements/travis_requirements.txt
- npm install
script:
- grunt karma:single
- grunt protractor:analytics
env:
global:
- secure: <string>
- secure: <string>
sauce_connect: true
Gruntfile:
protractor: {
options: {
configFile: './webapp/static/test/e2e/protractor.conf.js',
keepAlive: true
},
singlerun: {},
analytics: {
options: {
//debug : true,
args:{
specs: ['./webapp/static/test/e2e/analytics_spec.js']
}
}
},
},
Protractor Conf:
exports.config = {
chromeOnly: false,
seleniumArgs: [],
// If sauceUser and sauceKey are specified, seleniumServerJar will be ignored.
// The tests will be run remotely using SauceLabs.
sauceUser: process.env.SAUCE_USER,
sauceKey: process.env.SAUCE_KEY,
baseUrl: 'http://localhost:8000',
specs: [
'./*_spec.js',
],
// Patterns to exclude.
exclude: [],
multiCapabilities: [],
// ----- More information for your tests ----
//
// A base URL for your application under test. Calls to protractor.get()
// with relative paths will be prepended with this.
baseUrl: process.env.SN_BASE_URL,
// Selector for the element housing the angular app - this defaults to
// body, but is necessary if ng-app is on a descendant of <body>
rootElement: 'body',
// A callback function called once protractor is ready and available, and
// before the specs are executed
// You can specify a file containing code to run by setting onPrepare to
// the filename string.
onPrepare: function() {
// At this point, global 'protractor' object will be set up, and jasmine
// will be available. For example, you can add a Jasmine reporter with:
// jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter(
// 'outputdir/', true, true));
},
// The params object will be passed directly to the protractor instance,
// and can be accessed from your test. It is an arbitrary object and can
// contain anything you may need in your test.
// This can be changed via the command line as:
// --params.login.user 'Joe'
params: {
login: {
user: process.env.SN_TEST_USERNAME,
password: process.env.SN_TEST_PASSWORD
}
},
framework: 'jasmine',
// ----- Options to be passed to minijasminenode -----
//
// See the full list at https://github.com/juliemr/minijasminenode
jasmineNodeOpts: {
// onComplete will be called just before the driver quits.
onComplete: null,
// If true, display spec names.
isVerbose: false,
// If true, print colors to the terminal.
showColors: true,
// If true, include stack traces in failures.
includeStackTrace: true,
// Default time to wait in ms before a test fails.
defaultTimeoutInterval: 30000
},
onCleanUp: function() {}
};
If I did understand well : Sauce connect tool is not used by protractor/selenium when running a test suite.
Well I had this problem, travis requires sauce credentials and protractor requires those credentials and a tunnel id:
.travis.yml:
addons:
sauce_connect:
username: xxx
access_key: xxx
protractor.conf.js:
exports.config = {
...
sauceUser: process.env.SAUCE_USERNAME,
sauceKey: process.env.SAUCE_ACCESS_KEY,
capabilities: {
...
'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
}
}