How to write a nightwatch.js test for keys that works for both Chromium and Firefox driver? - nightwatch.js

I'm trying to write a test for Gridmapper. This is a an application that uses ordinary ASCII keys to control the application. I'm trying to write a test to determine whether 'w' does what it is intended to do. Sadly, I can't write a test that works for both ChromeDriver and FirefoxDriver.
This is how I accept key events in my app:
document.onkeydown = keyPressed; // capture arrow keys
document.onkeypress = keyPressed; // capture character keys
This is a test that works for Chrome:
module.exports = {
'walls' : function (browser) {
browser
.url('file://' + process.cwd() + '/gridmapper.svg')
.assert.elementPresent('#walls0')
.keys('w')
.waitForElementPresent('#wall_0_0', 1000)
.end();
}
};
This is the same test such that it works for Firefox:
module.exports = {
'walls' : function (browser) {
browser
.url('file://' + process.cwd() + '/gridmapper.svg')
.assert.elementPresent('#walls0')
.sendKeys('#ui', 'w')
.waitForElementPresent('#wall_0_0', 1000)
.end();
}
};
What am I doing wrong? I tried all sorts of combinations, tried sending the event to the document root element and a few more options, but I'm running out of ideas.

You'll want to get the browserName and that's stored in the capabilities object. You may or may not need to do further operations on the string, but toUpperCase should work.
You can add conditionals, you will just need to use the 'browser.' notation for each subsequent command.
Something like this should do the trick.
module.exports = {
'walls' : function (browser) {
var runtimeBrowser = browser.capabilities.browserName.toUpperCase()
browser
.url('file://' + process.cwd() + '/gridmapper.svg')
.assert.elementPresent('#walls0')
if(runtimeBrowser === "CHROME"){
browser.keys('w')
} elseif(runtimeBrowser === "FIREFOX") {
browser.sendKeys('#ui', 'w')
} else {
// do other default thing
}
browser.waitForElementPresent('#wall_0_0', 1000)
browser.end();
}
};

I didn't find a way to do it so now I'm generating test files for Firefox from the test files for Chrome.
nightwatch.json uses two test directories:
{
"src_folders" : ["tests/chrome", "tests/firefox"],
"output_folder" : "reports",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"page_objects_path" : "",
"globals_path" : "",
"selenium" : {
"start_process" : true,
"server_path" : "./bin/selenium-server-standalone-3.0.1.jar",
"log_path" : "",
"port" : 4444,
"cli_args" : {
"webdriver.chrome.driver" : "./bin/chromedriver",
"webdriver.gecko.driver" : "./bin/geckodriver"
}
},
"test_settings" : {
"default" : {
"launch_url" : "http://localhost",
"selenium_port" : 4444,
"selenium_host" : "localhost"
},
"chrome" : {
"desiredCapabilities": {
"browserName": "chrome"
},
"filter" : "tests/chrome/*.js"
},
"firefox" : {
"desiredCapabilities": {
"browserName": "firefox",
"marionette": true
},
"filter" : "tests/firefox/*.js"
}
}
}
Makefile allows me to run Chrome tests or Firefox tests. Firefox tests are generated from Chrome tests using a search and replace with sed:
chrome-test-files := $(wildcard tests/chrome/*.js)
firefox-test-files := $(patsubst tests/chrome/%,tests/firefox/%,$(chrome-test-files))
all:
#echo "Did you want to run 'make tests'?"
test: test-firefox test-chrome
test-firefox: $(firefox-test-files)
node_modules/.bin/nightwatch --env firefox
test-chrome: $(chrome-test-files)
node_modules/.bin/nightwatch --env chrome
tests/firefox/%.js: tests/chrome/%.js
#mkdir -p tests/firefox
sed -e "s/\.keys(/.sendKeys('#ui',/" < $< > $#
And now it all works and I'm still disappointed that there was no easy answer within Nightshift.

Related

Webpack dev server: issue mapping paths local to remote. Output/bundle files load in IDE/Chrome

I'm trying to line up my dev server output with a local project for debugging. PhpStorm support couldn't find out what the issue was as we worked on it though.
The issue with the current config is that it seems to pull up the output / bundle file in the IDE, instead of keeping to the source code files.
I'm mapping "remote" urls to what I see in Chrome under sources > webpack > .
The result (see top left pane):
And before the above, the bundle file is the first stop in the debugger before I click resume (it opens on its own in the editor):
On the browser side, Chrome pauses script execution, but also jumps to the sources tab into a hard to read file, probably something compiled by webpack.
Here is my webpack config. Does anyone see what settings I have misconfigured? This is a React.js project (custom webpack config, create-react-app not used)
const webpack = require("webpack");
const dotenvWebpack = require("dotenv-webpack");
const path = require("path");
module.exports = {
entry : {
adminArea :
['./adminSettingsArea/src/index.jsx']
},
output : {
filename : 'shared/[name].bundle.js',
path : path.resolve(__dirname, ''),
publicPath : "/",
},
devtool: 'source-map',
devServer : {
contentBase : './adminSettingsArea/src',
hot : true,
historyApiFallback : true
},
plugins : [
new webpack.HotModuleReplacementPlugin(),
new dotenvWebpack()
],
module : {
rules : [
{
test : /\.(js|jsx)$/,
exclude : [/node_modules/, /vendor/],
use : {
loader : "babel-loader",
options : {
presets : [
'#babel/preset-env',
"#babel/preset-react"
]
},
}
}, {
test : /\.css$/i,
use : ['style-loader', 'css-loader'],
}
],
},
};

How to run tests programmatically in Nightwatch.js?

I'm using Nightwatch.js and trying to run E2E tests using the programmatic API as described here.
Here is my nightwatch.json file:
{
"src_folders": ["tests"],
"webdriver": {
"start_process": true,
"server_path": "node_modules/.bin/chromedriver",
"port": 9515
},
"test_settings": {
"default": {
"desiredCapabilities": {
"browserName": "chrome"
}
}
}
}
and index.js script:
const Nightwatch = require('nightwatch');
Nightwatch.runTests(require('./nightwatch.json')).then(() => {
console.log('All tests has been passed!');
}).catch(err => {
console.log(err);
});
When I run the script I get the error:
Error: An error occurred while retrieving a new session: "Connection refused to 127.0.0.1:9515". If the Webdriver/Selenium service is managed by Nightwatch, check if "start_process" is set to "true".
I feel it needs some configuration but the documentation isn't very helpful here.

Detailed Reporting Cypress/Mochawesome

Has anyone had much experience of generating good detailed reports from Cypress tests using Mochawesome as the report engine?
I've followed the info on the Mochawesome GIT page but what I get is rather dull!!
I'd like to be able to include the odd screen-shot and the output from the assertions - here's the current cypress.json file......
{
"projectId": "haw8v6",
"baseUrl": "https://obmng.dbm.guestline.net/",
"chromeWebSecurity": false,
"reporter" : "mochawesome",
"reporterOptions" : {
"reportFilename" : "DBM Smoke-Test",
"overwrite": true,
"inline": true
}
}
I've been toying with var addContext = require('mochawesome/addContext'); but with little joy.
Suggestions gratefully received.
Thanks
As per request below - very basic example of addContext
var addContext = require('mochawesome/addContext');
describe('DBM Smoketests', function() {
it('E2E Hotel2 WorldPay System', function() {
cy.visit('https://obmng.dbm.guestline.net/');
cy.url().should('include','/obmng.dbm');
addContext(this,'URL is correct');
//loads hotel 2
cy.get('.jss189 > div > .jss69 > .jss230').click();
After much hacking about, I found a way to use Mochawesome addContext in Cypress.
Note, you can only make one addContext call per test (this is a Mochawesome limitation).
describe('DBM Smoketests', function() {
it('E2E Hotel2 WorldPay System', function() {
cy.visit('https://obmng.dbm.guestline.net/');
cy.url().should('include','/obmng.dbm');
Cypress.on('test:after:run', (test) => {
addContext({ test }, {
title: 'This is my context title',
value: 'This is my context value'
})
});
});
});
The second param is the context to be attached to the test, and it must have non-empty title and a value properties.
What you get in the mochawesome.json output is
...
"suites": [
{
...
"tests": [
{
"title": "E2E Hotel2 WorldPay System",
...
"context": "{\n \"title\": \"This is my context title\",\n \"value\": \"This is my context value\"\n}",
"code": "...",
...
}
],
In mochawesome.html, on clicking the test you get
Additional Test Context
This is my context title:
This is my context value
I have not tried it out with value types other than string.
Note for anyone starting out with Mochawesome in Cypress, it looks like you can only get a Mochawesome report with running cypress run, not with cypress open - although there may be a way around this using mocha's multiple reporter functionality.
Yes confirmed work! It's possible to call once in each test like this:
it('Should shine the test report!!!', () => {
cy.get('li').should('have.length.greaterThan', 0);
addTestContext('String','giphy');
addTestContext('Link','https://giphy.com');
addTestContext('Image','https://media.giphy.com/media/tIIdsiWAaBNYY/giphy.gif');
addTestContext('Image','https://media.giphy.com/media/tIIdsiWAaBNYY/giphy.gif');
});
function addTestContext(title, value) {
cy.once('test:after:run', test => addContext({ test }, { title, value }));
}

Protractor proxy settings configuration is not passed to Saucelabs

To enable saucelabs proxy to work in older version of protractor, we were overriding sendRequest method by setting host and port in below index.js:
protractor\node_modules\selenium-webdriver\http\index.js
Now protractor allows you set the proxy through capabilities object (as shown below) which should be passed to index.js sendRequest new parameter called 'opt_proxy'.
capabilities: {
"browserName": "chrome",
'proxy': {
'proxyType': 'manual',
'httpProxy': 'appproxy.web.abc.com:84'
},
"chromeOptions": {
"args": [
"--disable-extensions",
"--test-type"
]
},
"customData": {
"usageBracket" : "1",
"displayName" : "Chrome",
"id" : "CH"
}
}
However, when I am still getting null for opt_proxy. Is there anything I am doing wrong? I even tried passing through CLI using --proxy="" but it still get null.
I have gotten my proxy configuration to work with Sauce Labs using the sauceAgent util provided within Protractor. Here is a code snippet from my protractor config file.
var HttpsProxyAgent = require("https-proxy-agent");
var agent = new HttpsProxyAgent('http://localhost:56193'); //Insert your proxy info here
exports.config = {
sauceUser: process.env.SAUCE_USERNAME,
sauceKey: process.env.SAUCE_ACCESS_KEY,
sauceAgent: agent,
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: [
'--proxy-server=socks5://host:port',
]
},
},

How to skip login on each nightwatch test

Each of my Nightwatch.js tests requires authentication in order to run and for the time being I can't make authentication to be done via cookies (of course if test fill in a username and password it logs in, but it takes time this way)
I have a working PHPSESSID (tested in Fiddler) cookie and trying to set it via nightwatch setCookie function like this:
browser
.setCookie({
name : "PHPSESSID",
value : "gfnpqlflvlrkd2asj18ja2ewrt",
path : "/admin", //(Optional)
domain : "example.com", //(Optional)
secure : true, //(Optional)
httpOnly : false // (Optional)
})
.url("www.example.com/admin")
however www.example.com/admin redirects me back to www.example.com/login meaning authentication didn't pass.
Is there any solution?
I had this issue as well and just ended up creating a custom command. You'll need to create a new folder called custom-commands within your nightwatch test folder. In your nightwatch.JSON file you will need to specify the path to this folder like so:
"custom_commands_path" : "./nightwatch-tests/custom-commands"
Create a new test filed in this new folder with the login steps and use the name as your new command at the beginning of each test. For example, my file is called "login.js" and it looks like this:
var load_speed = 5000,
local_login_url = "https://";
exports.command = function(username, password) {
this
.url(local_login_url)
.waitForElementVisible('.login', load_speed)
.setValue('input[type=text]', username)
.setValue('input[type=password]', password)
.click('input[type=submit]')
.pause(load_speed)
.assert.elementPresent('.dashboard')
return this;
};
When I call the custom command in my test, it looks like this:
.login(username, password)
Maybe you can use the "before" or "beforeEach" hook.
http://nightwatchjs.org/guide#using-before-each-and-after-each-hooks
module.exports = {
before : function(browser) {
console.log('before all tests');
},
beforeEach : function(browser) {
console.log('before each test');
},
afterEach : function(browser) {
},
"test one" : function (browser) {
browser
// ...
},
"test two" : function (browser) {
browser
// ...
.end();
}
};

Resources