How do I parameterize the baseUrl property of the protractor config file - protractor

I need to run my protractor tests in different contexts with different baseUrls in the config files. I don't want to use separate config files for each situation since that is more difficult to maintain. Rather, I want to pass the base url in as a command line parameter. Here is what I have tried so far:
The protractor.conf.js:
exports.config = {
onPrepare : {
...
exports.config.baseUrl = browser.params.baseUrl;
...
}
}
And to invoke protractor:
protractor protractor.conf.js --params.baseUrl 'http://some.server.com'
This does not work since it seems like the browser instance is already configured before onPrepare is called.
Similarly, I have tried this:
exports.config = {
baseUrl : browser.params.baseUrl
}
But this doesn't work either since it seems like the browser instance is not available when the config is being generated.
It looks like I can use standard node process.argv to access all command line arguments, but that seems to be going against the spirit of protractor.
What is the best way for me to do what I need to do?

Seems like this is already possible, but the documentation is spotty in this area. Looking at the code, however, protractor does support a number of seemingly undocumented command line arguments.
So, running something like this will work:
protractor --baseUrl='http://some.server.com' my.conf.js

The other option is to use gruntfile.js and have it call the protractor config file.
//gruntfile.js
module.exports = function (grunt) {
grunt.registerTask("default", "", function () {
});
//Configure main project settings
grunt.initConfig({
//Basic settings and infor about our plugins
pkg: grunt.file.readJSON('package.json'),
//Name of plugin
cssmin: {
},
protractor: {
options: {
configFile: "conf.js", // Default config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:6034/'
}
},
your_target: { // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
options: {
configFile: "conf.js", // Target-specific config file
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:63634/'
}
}
},
},
//uglify
uglify: {
}
});
//Load the plugin
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-protractor-runner');
//Do the Task
grunt.registerTask('default', ['cssmin']);
};
the Protractor config file: conf.js
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox']
}
},
chromeOnly: true,
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['specs/*/*_spec.js'],
suites : {
abcIdentity : 'specs/abcIdentity/*_spec.js' //picks up all the _spec.js files
},
params: {
UserName: 'abc#test.com',
Password: '123'
},
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000,
includeStackTrace: true
},
onPrepare: function () {
browser.driver.manage().window().maximize();
if (process.env.TEAMCITY_VERSION) {
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.TeamCityReporter());
}
}
};
//To run with default url http://localhost:6034
grunt protractor
//To run with any other url
grunt protractor --baseUrl:"http://dev.abc.com/"

I know, old one. but if anyone is still looking for a way to define a url based on capability (I had to do this because Ionic 5 will run in browser on port 8100, but in the app - unchangable - without port declaration on port 80, I use Appium)
add a baseUrl parameter inside your capability declaration.
{
browserName: 'chrome',
baseUrl: 'http://localhost:8100' //not required but as example
}
{
...
app: 'path to app.apk',
baseUrl: 'http://localhost'
...
}
and then configure your onPrepare method as follows.
async onPrepare() {
const config = await browser.getProcessedConfig();
if(config.capabilities.hasOwnProperty('baseUrl')) {
browser.baseUrl = config.capabilities.baseUrl;
}
}
OnPrepare runs for each capability you define in your multiCapabilities array. the getProcessedConfig returns the config as you defined it, with the addition of the current capability. Since that method returns a promise, I use async/await for readability.
This way, you can have multiple capabilities running, with each different a different host.

Base url should be declared baseUrl: "", in config.ts
I am using cucumber hooks and the below code is added in hooks file to pass the required url based upon the environments
if(browser.params.baseUrl==="QA"){
console.log("Hello QA")
await browser.get("https://www.google.com");
} else {
console.log("Hi Dev")
await browser.get("https://www.gmail.com");
}
run the tests using protractor command
protractor --params.baseUrl 'QA' typeScript/config/config.js --cucumberOpts.tags="#CucumberScenario"

Related

How can we use the On Prepare function in config File while i am trying to run multiple Spec files

In the Config File i am using the On Prepare Function for the purpose of assigning the property data test id as value
But for the first spec file execution the on prepare is picked up
but on the next execution of the Spec , the on prepare function is not getting picked up
import { Config } from "protractor/built/config";
import { by } from "protractor";
// import { encode } from "punycode";
function encode(file) {
var stream = require('fs').readFileSync(file);
return new Buffer(stream).toString('base64');
}
export let config: Config = {
// The address of a running selenium server.
//seleniumAddress: 'http://localhost:4444/wd/hub',
directConnect:true,
allScriptsTimeout:1500000,
// Capabilities to be passed to the webdriver instance.
capabilities: {
browserName: 'chrome',
'chromeOptions': {
'extensions': [encode('C:/Users/koanand/Documents/Protractor/ASR/2.2.9_0.crx')]
}
},
onPrepare: function () {
by.addLocator('testId', function(value, parentElement) {
parentElement = parentElement || document;
var nodes = parentElement.querySelectorAll('[data-test-id]');
return Array.prototype.filter.call(nodes, function(node) {
return (node.getAttribute('data-test-id') === value);
});
});
},
// Spec patterns are relative to the configuration file location passed
// to protractor (in this example conf.js).
// They may include glob patterns.
specs: ['C:/Users/anand/Documents/Protractor/ASR/TS-Output/specs/directasr.js',
'C:/Users/anand/Documents/Protractor/ASR/TS-Output/specs/products.js'
],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true, // Use colors in the command line report.
defaultTimeoutInterval : 150000
}
};
i am observing the below error
Message:
Failed: protractor_1.by.testID is not a function
Stack:
TypeError: protractor_1.by.testID is not a function
at new productlist (C:\Users\koanand\Documents\Protractor\ASR\pageobject\productlist.ts:19:45)
at product.selectingproductlist (C:\Users\koanand\Documents\Protractor\ASR\specs\classproductlist.ts:14:32)
at UserContext.<anonymous> (C:\Users\koanand\Documents\Protractor\ASR\specs\products.ts:21:21)
at C:\Users\koanand\Documents\Protractor\ASR\node_modules\jasminewd2\index.js:108:15
at new ManagedPromise (C:\Users\koanand\Documents\Protractor\ASR\node_modules\selenium-webdriver\lib\promise.js:1077:7)
at ControlFlow.promise (C:\Users\koanand\Documents\Protractor\ASR\node_modules\selenium-webdriver\lib\promise.js:2505:12)
at schedulerExecute (C:\Users\koanan
d\Docume
Use BeforeAll() in each spec file & write whatever you want to execute before each spec starts
May following link help you to clear your doubts for onPrepare and what to use in pace of it.
OnPrepare function in Protractor

Protractor to dynamically choose browser based on input

I am new to protractor and I want to be able to run my chrome browser painted or headless.
So I set up something like this
let chrome = {
browserName: 'chrome',
platform: 'MAC',
'max-duration': '1800',
};
let chromeHeadless = {
browserName: 'chrome',
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=800,600" ]
}
};
browserDefault = browser.params.browserToUse
exports.config = {
params: {
'browserToUse': "get from user'
},
capabilities: browserDefault,
}
and i ran this code as
protractor config.js --params.browserToUse='chromeHeadless'
But this does not work. Protractor fails saying it does not understand "browser.params.browserInput". Whats the right way to make protractor dynamically choose chrome or chromeheadless based on the input
The global variable browser is only init when code run into onPrepare(). You used browser outside onPrepare() function, browser have not been inited, it is undefined, so you met the error.
Another point you need to get it's when the variable browser inited, a browser window has been opened, means protractor has know which capabilities to launch the browser. Therefore you can't use browser.params.xxx to specify which capabilities, you need to tell protractor the capabilities before it init the browser variable.
let capabilitiesMap = {
'chrome-headful' : {
browserName: 'chrome',
platform: 'MAC',
'max-duration': '1800',
},
'chrome-headless': {
browserName: 'chrome',
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=800,600" ]
}
}
};
let browserToUse = 'chrome-headful'; // set default value
// extract the browserToUse value from cli
process.argv.slice(3).forEach(function(arg) {
var name = arg.split('=')[0];
var value = arg.split('=')[1];
var name = name.replace('--', '');
if (name === 'browserToUse') {
if (Object.prototype.hasOwnProperty.call(capabilitiesMap, value) ) {
browserToUse = value;
}
}
});
let config = {
seleniumAddress: '',
specs: [],
onPrepare: function() {}
};
config.capabilities = capabilitiesMap[browserToUse];
exports.config = config;
CLI example: protractor conf.js --browserToUse=chrome-headless
I also came across this issue and soleved it using the getMultiCapabilities() function in your conf.js
const _ = require('lodash');
let capabilities = {
chrome: {
browserName: 'chrome',
platform: 'MAC',
'max-duration': '1800',
},
chromeHeadless : {
browserName: 'chrome',
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=800,600" ]
}
}
}
getMultiCapabilities() {
const browsers = this.params.browserToUse.split(',');//if you pass more than one browser e.g chrome,chromeHeadless
const cap = _(capabilities).pick(browsers).values().value(); //this uses the lodash npm module
return cap;
},
In a testing context working with just Chrome, I did the following. In capabilities:
chromeOptions: {
args: []
}
beforeLaunch: function() {
//at this point browser is not yet defined, so process command line directly
if (process.argv[process.argv.length-1].search('headless=true')>-1){
config.capabilities.chromeOptions.args.push("--headless");
config.capabilities.chromeOptions.args.push("--disable-gpu");
config.capabilities.chromeOptions.args.push("--window-size=1600,1000");
}
}
That way by the time the browser was launched, it had the right configuration. Where I have "headless=true", you might want "Chrome-headless."
And then on the command line I call it like you do with --params.headless=falseso that should I want to find it in the script itself later (after the browser has launched), it is readily available.
Note I had just one command line parameter and control of the command line, so it felt okay to assume this parameter was the last.

how can Parametrize protractor-config file for different browsers and test suites

I am running my Protractor Test from command npm run e2e
I want a way so that if I pass npm run e2e firefox then my test will get executed on Firefox browser.
Or if I run npm run e2e chrome then it should run on chrome
if I pass both npm run e2e firefox chrome then my test should run on both the browser in parallel.
Is it possible to parametrize protractor config file?
Similarly if I can pass test suite name via command and it should execute only tests under that particular test suite.
Here is my config file and this is what I want to achieve:
`//var HtmlReporter = require('protractor-html-screenshot-reporter');
exports.config = {
allScriptsTimeout: 30000,
//Add parameters for browser names
params:{
pass: {
browserName : 'chrome',
testSuitName : 'e2e/TestSuites/_BVT/*.js',
}
},
suites: {
//Define here List of Sanity Test Scenarios:
BVT : testSuitName,
},
// configure multiple browsers to run tests
multiCapabilities: [
shardTestFiles: true,
maxInstances: 2
{'browserName': browserName}
],
baseUrl: 'http://mytestUrl/',
framework: 'jasmine2',
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
},
onPrepare: function() {
var jasmineReporters = require('jasmine-reporters');
browser.driver.manage().window().maximize();
return browser.getProcessedConfig().then(function(config) {
var browserName = config.capabilities.browserName;
var junitReporter = new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
savePath: 'tests/test-results',
filePrefix: browserName + '-xmloutput',
modifySuiteName: function(generatedSuiteName, suite) {
return browserName + '.' + generatedSuiteName;
}
});
jasmine.getEnv().addReporter(junitReporter);
});
},
resultJsonOutputFile: 'tests/test-results/output.json'
};`
Would appreciate any help on this.
Thanks in advance.
I know this post is a bit old now, but this solution may help people having a similar problem.
Use multiple config files, one for each browser type, setup a base config file, and require that into each of the other config files, and then create an npm script for each config file. No need for parameters and everything stacks nicely.
so the base config (called something like "protractor_base.js")would look something like:
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
rootElement: '[ng-app]',
allScriptsTimeout: 60000,
framework: 'jasmine',
specs: ['example-spec.js']
};
And then your other configs (ie "protractor_chrome.conf.js") would look something like:
protractor = require('./protractor_base.js');
var config = protractor.config;
config.capabilities: {
'browserName': 'chrome'
};
exports.config = config;
You can then specify a multi browser config, just a chrome one, etc.
--capabilities.chromeOptions.args=headless --capabilities.chromeOptions.args=disable-gpu --capabilities.chromeOptions.args=window-size=1200,600
The above code should work for you.
I was looking for passing parameters from command line to protractor config file and found a way to do this:
npm run e2e -- --baseUrl=http://testurl:8080 --suite=suite_name_defined_in_config --capabilities.browserName=browser_Name
where my npm package.json :
"e2e": "protractor tests/protractor-conf.js",
and config file contains :
suites: {
BVT: 'e2e/TestSuites/_BVT/*.js',
Full: 'e2e/TestSuites/Full/**/*.js',
},
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8080/',

Maximize nw.js window from protractor doesn't work

I want to maximise the window from protractor. I am testing a nw.js app.
I added the below line in onPrepare statement in protractor-conf.js, but nothing worked
browser.driver.manage().window().maximize();
setSize also doesn't work
browser.driver.manage().window().setSize(800, 600);
In all the cases I am getting the below error.
var template = new Error(this.message);
^
UnknownError: unknown error: cannot get automation extension
from unknown error: page could not be found: chrome-extension://aapnijgdinlhnhlmodcfapnahmbfebeb/_generated_background_page.html
This is the e2e configuration,
protractor-conf.js
'use strict';
var path = require('path');
var nw = require('nw');
exports.config = {
chromeDriver: './support/chromedriver',
directConnect: true,
specs: ['e2e/**/*.js'],
rootElement: 'html',
capabilities: {
browserName: 'chrome',
chromeOptions: {
binary: nw.findpath()
}
},
onPrepare: function() {
// By default, Protractor use data:text/html,<html></html> as resetUrl, but
// location.replace (see http://git.io/tvdSIQ) from the data: to the file: protocol is not allowed
// (we'll get ‘not allowed local resource’ error), so we replace resetUrl with one
// with the file: protocol (this particular one will open system's root folder)
browser.resetUrl = 'file://';
// This isn't required and used to avoid ‘Cannot extract package’ error showed
// before Protractor have redirected node-webkit to resetUrl.
browser.driver.get('file://' + path.resolve('app/index.html'));
}
};
Is there a way to resolve this ?
I am testing this on Ubuntu.
Did you try to set the arguments for chrome inside capabilities ?
http://peter.sh/experiments/chromium-command-line-switches/
chromeOptions: {
args: [
'--start-maximized',
]
}

grunt.initConfig in a callback does not work

I want to use grunt for deployment and therefore want to read in configuration of remote hosts based on the already existing ~/.ssh/config file.
To load that configuration I'm using sshconf but need to include the grunt.initConfig() call in the callback to have the configuration when defining environments.
var sshconf = require('sshconf');
module.exports = function(grunt) {
// Read in ssh configuration
sshconf.read(function(err, sshHosts) {
if (err)
console.log(err);
// SSH config loaded, now init grunt
grunt.initConfig({
sshconfig: {
staging: {
privateKey: grunt.file.read(sshHosts['project_staging'].properties.IdentityFile),
host: sshHosts['project_staging'].properties.HostName,
username: sshHosts['project_staging'].properties.User,
port: sshHosts['project_staging'].properties.Port || 22,
path: "/var/www/project"
},
production: {
// ...
}
},
// Tasks to be executed on remote server
sshexec: {
example_task: {
command: 'uptime && hostname'
}
},
sftp: {
deploy: {
files: {
"./": ["*.json", "*.js", "config/**", "controllers/**", "lib/**", "models/**", "public/**", "views/**"]
},
options: {
//srcBasePath: "test/",
createDirectories: true
}
}
}
// More tasks
// ...
});
grunt.loadNpmTasks('grunt-ssh');
// More plugins ...
});
};
When I call grunt --help it states:
> grunt --help
Grunt: The JavaScript Task Runner (v0.4.1)
…
Available tasks
(no tasks found)
If I do not wrap the grunt initiation in that callback (sshconf.read(function(err, sshHosts) {})) everything is working fine (except for the ssh config not loaded or not yet ready to be used).
Is what I am trying even possible and if so, how? Am I missing something obvious?
Grunt init cannot be used in an async fashion like this. Either read the sshconf synchronously, or use a task, as described in this answer: How can I perform an asynchronous operation before grunt.initConfig()?