Protractor file download test fails when headless chrome - download

I am having an issue with a protractor test. It was working, but now (even thought nothing has changed) it is not.
The test is just opening the app (web application) and clicking on a button to download an image. The download should start straight away.
The problem is that the next instruction after the download event throws an exception, Failed: chrome not reachable. I am using the latest chrome and chrome driver versions.
The capabilites section for protractor is like this:
capabilities: {
browserName: 'chrome',
loggingPrefs: { browser: 'ALL' },
chromeOptions: {
args: ['--headless', '--window-size=1240,780'],
},
}
I am reading about using DevTools to enable downloads in headless mode (Page.setDownloadBehavior), but so far no luck.
Does anybody have this issue too? Any clue how to fix it?
Thanks.

There could be another easy way to do it, but this is what I have done in my test suite.
I used got library, however, you can use any library to send an HTTP post request.
Discussion about setting download directory in headless chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=696481
let got = require('got');
let session = await browser.getSession();
let sessionId = session['id_'];
let params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': downloadDir }}
await got.post('http://localhost:4444/wd/hub/session/'+ sessionId + '/chromium/send_command', {body: JSON.stringify(params)})
If you have not disabled ControlFlow in your protractor config, change ASync/Await to .then.

An easier solution is to add these lines to your protractor.conf.js:
exports.config = {
...
onPrepare() {
...
browser.driver.sendChromiumCommand('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: downloadsPath
});
}
};
From: https://bugs.chromium.org/p/chromium/issues/detail?id=696481#c196
Appendix
If you are to lazy to find a Download Path just paste this at the top of your protractor.conf.js:
var path = require('path');
var downloadsPath = path.resolve(__dirname, './downloads');
It will download the file to the e2e/downloads folder. Just use the same code in your tests to find out if the file downloaded.

This works for me:
chromeOptions: {
'args': [
'--headless',
'--disable-gpu',
'--test-type=browser',
'--disable-extensions',
'--no-sandbox',
'--disable-infobars',
'--window-size=1920,1080',
//'--start-maximized'
"--disable-gpu",
],
prefs: {
'download.default_directory': 'C:\\downloads',
'download.prompt_for_download':false,
'download.directory_upgrade':true,
"safebrowsing.enabled":false,
"safebrowsing.disable_download_protection":true
},
},

Related

VuePress: How can I use https in dev server?

Is there any hook to enable https in VuePress dev server?
1. Current solution.
I directly add one line to node_modules/#vuepress/core/lib/node/dev/index.js. This works well, but nasty.
createServer () {
const contentBase = path.resolve(this.context.sourceDir, '.vuepress/public')
const serverConfig = Object.assign({
https: true, // <--- Added this line.
disableHostCheck: true,
compress: true,
clientLogLevel: 'error',
vuejs/vuepress - /packages/#vuepress/core/lib/node/dev/index.js#L197-L237
2. Background
Because Chrome has changed it's security policy, CORS.
3. What I've tried.
I've tried but not working.
webpack - devServer.https
docs/.vuepress/config.js
configureWebpack: (config, isServer) => {
if (!config.devServer) {
config.devServer = {}
}
Object.assign(config.devServer, {
https: true,
})
}
No proper hook
VuePress - Plugin Option API - beforeDevServer
VuePress - Plugin Option API - afterDevServer
No command option for https.
vuejs/vuepress - /packages/vuepress/lib/registerCoreCommands.js#L18-L31
module.exports = function (cli, options) {
cli
.command(`dev [targetDir]`, 'start development server')
.option('-p, --port <port>', 'use specified port (default: 8080)')
.option('-t, --temp <temp>', 'set the directory of the temporary file')
.option('-c, --cache [cache]', 'set the directory of cache')
.option('--host <host>', 'use specified host (default: 0.0.0.0)')
.option('--no-cache', 'clean the cache before build')
.option('--no-clear-screen', 'do not clear screen when dev server is ready')
.option('--debug', 'start development server in debug mode')
.option('--silent', 'start development server in silent mode')
.option('--open', 'open browser when ready')
.action((sourceDir = '.', commandOptions) => {
const { debug, silent } = commandOptions
4. Related links.
vuejs/vuepress - Support devServer.proxy in configureWebpack #858
vuejs/vuepress - Sunsetting webpack-serve #1195
Add the following settings to config.js.
//
// docs/.vuepress/config.js
//
module.exports = {
devServer: {
https: true
},
}
How to run Vue.js dev serve with https? - Stackoverflow
Thank you for your guidance in many ways.

In e2e testing, blank page is opened in Chromium Edge (New Edge Browser) using Protractor

1.Open the MS Chromium edge and type the command "edge://settings/help" to check the version
2. Download the MS Chromium edge webdriver and placed it into project directory
3. Set the desired capabilities in conf.js file
4. Start the server using command "webdriver-manager start --edge msedgedriver.exe"
5. Run the test using the "protractor conf.js"
Environment:
Chromium Edge Version = 83.0.478.37
Chromium web driver = 83.0.478.37
Selenium server version = 3.141.59
JDK =1.8.191
conf.js
exports.config = {
// The address of a running selenium server.
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
'browserName': 'chrome',
'goog:chromeOptions': {
// Faked out chrome binary
'binary':'C:\\Program Files (x86)\\Microsoft\\Edge Beta\\Application\\msedge.exe'
}
},
//Path of Chromium edge driver
chromeDriver:'./msedgedriver.exe',
specs: ['spec.js'],
}
};
Also tried with using desired capabilities in spec.js file as well but still blank page is opened
describe('slow calculator', function() {
beforeEach(function() {
let options = new edge.Options();
options.setEdgeChromium(true);
//options.setBinaryPath("C:\\Program Files (x86)\\Microsoft\\Edge Beta\\Application\\msedge.exe");
let browser = edge.Driver.createSession(options);
browser.get('http://juliemr.github.io/protractor-demo/');
});
});
While starting webdriver-manager, ensure the path to msedgedriver is specified.
webdriver-manager start --edge "pathToEdgeDriver/msedgedriver.exe"
The capabilities object should have MicrosoftEdge as browserName.
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
'browserName': 'MicrosoftEdge'
}

Change to desiredCapabilities in beforeEach not reflecting

I am trying to record all browser request and responses. This can be done via browsermob-proxy api's.
For this, I have to change desired capabilities and change httpProxy for browser.
In beforeEach at global or file level, I am trying to change this. Though it reflects in browser object, actual browser is not initiated with those settings.
Simple example:
globalhook file
module.exports = {
before : function (done) {
},
beforeEach: function(browser, done){
browser.options.desiredCapabilities = {
"browserName": "chrome",
"proxy": {
"proxyType": "manual",
"httpProxy": "127.0.0.1:" + someport,
"sslProxy": "127.0.0.1:" + someport
},
"javascriptEnabled": true,
"acceptSslCerts": true,
}
done()
},
afterEach: function(browser, done){
//some code
}
after : function (done) {
//some code
},
}
If i change desired capabilities in before hook, chrome browser is taking those changes. Problem is with beforeEach [global, file level].
Further debugging, I've found setCapabilities function is run just before beforeEach Hook.
Could anyone please have a look or suggest if I am doing something wrong.
Thanks for moving the issue here.
The issue is that the desiredCapabilities are applied to a browser session.
beforeEach and afterEach run on the same browser session therefore any change in the desiredCapabilities won't be applied unless the session is restarted.
If you need to dynamically change the desiredCapabilities you have to structure your tests in the different way, e.g. split your tests in separate test classes
First of all, you probably want to use before() hook instead of beforeEach(), since beforeEach() will run before each test case and you won't be able to modify already started browser session. before() will run before browser session is initiated.
To solve your issue you need to define desiredCapabilities property on your test run module and in case you need to set some dynamic values, use before() hook to modify that object:
module.exports = {
desiredCapabilities: {
"browserName": "chrome",
"proxy": {
"proxyType": "manual",
"httpProxy": "127.0.0.1",
"sslProxy": "127.0.0.1"
},
"javascriptEnabled": true,
"acceptSslCerts": true,
},
before: function(client, done) {
this.desiredCapabilities.proxy.sslProxy = '127.0.0.1' + someport;
done();
}
}
I've searched official docs on this feature but couldn't find anything, though we used this in our tests and it worked well.
Update:
Since you only need to change proxy on desiredCapabilities object, there is a little hack:
// global hooks file:
module.exports = {
beforeEach: function(client, done) {
client.options.desiredCapabilities.proxy = {
"proxyType": "manual",
"httpProxy": "127.0.0.1:" + someport,
"sslProxy": "127.0.0.1:" + someport
};
done(client);
}
};
Changing desiredCapabilities object won't work, since reference to original object is already stored somewhere under the hood of Nightwatch. But nothing stops you from overriding proxy property on that object.
After checking sources and tests in Nightwatch I believe this is the only solution for your case.

Nightwatch.js navigate behaves differently across drivers

I want to use Nightwatch.js v.0.9.8 for E2E testing.
My page object:
module.exports = {
url() {
return path.join(this.api.launchUrl, 'Home/Index');
}
};
My test:
module.exports = {
'Sample 1'(client) {
client.page.home()
.navigate()
.expect.element('body').to.be.present;
},
'Sample 2'(client) {
client.page.home()
.navigate()
.expect.element('header').to.be.present;
client.end();
}
};
This works flawlessly in Chrome.
However in Firefox (geckodriver 0.11.1 x64), Sample 2 ends up with running at http://localhost:3535/localhost:3535/Home/Index.
IE (IEDriverServer 2.53.1 x64) opens with a dialog window:
Cannot find path 'http:\localhost:3535\Home\Index'. Make sure the path or Internet address is correct.
Am I missing something obvious?
Solved it - my mistake. The problem is that path.join(this.api.launchUrl, 'Home/Index') flips slashes. I replaced it with simple string concatenation and it works correctly.

Webstorm Karma test debugging - breakpoint not hit

I have installed the chrome jet brains extension
I have tests like this:
describe('Service tests', function () {
beforeEach(module('app'));
it('should have a Service', inject(function($injector) {
var exist = $injector.has('dataService');
etc
but no luck getting breakpoints to hit any where in the tests. I can get the debugger to break when writing debugger, but an unable to step through.
Do you have karma-coverage set up in your karma config? It uses instrumented code, so debugging is not possible. Related tickets: http://github.com/karma-runner/karma/issues/630, http://youtrack.jetbrains.com/issue/WEB-8443
If you are building with Webpack you might need to specify the devtools option in your webpack config property in karma.conf.js like this:
module.exports = (config) => {
config.set({
webpack: {
...,
devtool: 'inline-source-map'
}
})
};
This solution works for me with Webpack v3.
If by any chance you are using Angular and you have removed all the coverage related stuff from your karma.config file and are still unable to hit the breakpoints, look into the angular.json. It might be having the codeCoverage bit set to true.
"test": {
...
"options": {
...
"codeCoverage": false,
...
}
...
}

Resources