Protractor - How to pass variable inside browser.get() function? - protractor

I have saved a url in config.js file in runtime, now i have my url in "browser.params.tempVar". If i use it directly in script like browser2.get(browser.params.tempVar); it is not working, Could someone suggest how to use variable in browser.get() function.

What you're doing is the correct way.
Double check that you've got the param set up correctly in config.js:
exports.config = {
...
params: {
...
tempVar: "tempVar"
...
}
...
}
Then use the default protractor browser to retrieve the value:
...
const prot = require("protractor");
const browser = prot.browser;
const myParam = browser.params.tempVar;
browser2.get(myParam);
or in TS:
...
import {browser} from 'protractor';
const myParam = browser.params.tempVar;
browser2.get(myParam);
Could can also override this param value by command-line argument if needed:
Normal run:
npx protractor conf.js
Override param:
npx protractor conf.js --params.tempVar="newVar"

Related

Passing parameters to browser.get - protractor

Context :
#angular/cli 7.3.9
protractor 5.4.0
karma 4.0.0
Issue :
How do protractor's browser method get takes url parameters query ?
browser.get('${browser.baseUrl}?p=2') is redirecting to http://localhost:4200/&p=2 instead of http://localhost:4200&p=2.
When i supress last character of browser.baseUrl, the redirected url is http://localhost:420/&p=2 ...
Any idea ?
Edit :
I tried edit protractor.conf.js by adding baseUrl but i does not change anything ...
If you set a baseUrl in the config file, then there is no need to add browser.baseUrl in the get method, you can omit it.
For instance, in the config you have:
exports.config = {
// ...
baseUrl: 'https://github.com/search',
}
In the test, you can just add the query parameters like this:
it('should open the URL with the query parameter', async () => {
await browser.get('?q=test'); // will open the 'https://github.com/search?q=test' page
});

How we can pass the browser name through command prompt in protractor

I am using protractor-cucumber frame work with protractor 5.2.2. and cucumber 3.2.1. i have to pass browser name through command prompt instead of hard coding in config file.
Case 1: Specify the browser name in cmd line only to make script run on that browser.
// conf.js
capabilities: {
browserName: 'chrome'
}
protractor conf.js --browser=firefox // will run on firefox
protractor conf.js // with run on chrome
Case 2: Want to use the browser name for some code logic before protractor runner launched
You can use process.argv to get all stuff in command and extract the browser name you passed-in.
// cmd.params.js
// parse cmd parameters
var params = {};
process.argv.slice(3).forEach(function (arg) {
let flag = arg.split('=')[0];
let value = arg.split('=')[1];
let name = flag.replace('--', '');
params[name] = value;
});
module.exports = params;
// conf.js
var params = require('./cmd.params.js');
var browser = params.browser;
// now you can use the variable: browser anywhere in conf.js
var multiCapabilities = browser.split(',').map(function(browserName){
return {
browserName: browserName.trim()
};
})
exports.config = {
multiCapabilities: multiCapabilities
....
};
protractor conf.js --browser=firefox // will run only on firefox
protractor conf.js --browser="firefox, chrome" // will run on firefox and chrome

How we can generate html report in cucumber latest version(3.2.0) with protractor-cucumber framework

Since cucumber 3 removed the registerHandler and registerListener , how we can generate html report in cucumber 3.2.0.I have used below code for generating json report in cucumber 2.
defineSupportCode(function({ registerListener }) {
var JsonFormatter = new Cucumber.JsonFormatter();
JsonFormatter.log = function(string) {
var outputDir = 'testreports/report';
var fileName = 'cucumber-report.json';
var targetJson = path.resolve(outputDir, fileName);
if (fse.existsSync(outputDir)) {
fse.moveSync(outputDir, outputDir + '_' + moment().format('YYYYMMDD_HHmmss'), {
overwrite: true
});
}
fse.outputFileSync(targetJson, string);
};
registerListener(JsonFormatter);
});
and used below code for html report
defineSupportCode(function({ registerHandler }) {
registerHandler('AfterFeatures', function(features, callback) {
var options = {
theme: 'bootstrap',
jsonFile: 'testreports/report/cucumber-report.json',
output: 'testreports/report/cucumber-report.html',
reportSuiteAsScenarios: true,
};
reporter.generate(options);
callback();
});
});
Thanks in advance.
You have to do following changes:
1) set cucumberOpts.format in protractor conf file
cucumberOpts: {
format: ["json:reports/report/cucumber/cucumber-report.json"],
here reports/report/cucumber/cucumber-report.json is the cucumber json file path, you must specify a path at here.
framework will generate it automatically with results' json data as file content when all scenarios execute complete.
2) create parent folder of cucumber json file path before test framework load if parent folder not exist
Option 1: put create parent folder code at head of protractor conf file.
Option 2: create a Protractor plugin implement interface: setup(), which will be executed before test framework load.
// plugin: create-report-folder.js
var moment = require("moment");
var fse = require("fs-extra");
module.exports = {
setup: function() {
var reportDir = this.config.options.reportDir;
if (fse.existsSync(reportDir)) {
fse.moveSync(
reportDir,
reportDir + "_" + moment().format("YYYYMMDD_HHmmss"),
{ overwrite: true}
);
}
fse.mkdirsSync(reportDir);
}
};
Note: both options need to use Sync api to create folder.
3) create Protractor plugin implement interface: postResults which will be executeed after all scenarios execute complete.
// plugin: cucumber-html-reporter.js
var reporter = require("cucumber-html-reporter");
module.exports = {
postResults: function() {
var options = {
theme: "bootstrap",
jsonFile: this.config.options.jsonFile,
output: this.config.options.htmlFile,
reportSuiteAsScenarios: true
};
reporter.generate(options);
}
};
Note: I tried generate cucumber html report in cucumber AfterAll hook, but failed, seems Cucumber JsonFormater generate cucumber json file is Async, when AfterAll hook start execute, cucumber json file have not create yet.
I'm keeping look into formatOption, should be a way to change JsonFormater generate cucumber json file to Sync, then we can use AfterAll hook.
4) set plugins in protractor conf file
// protractor conf file
exports.config = {
plugins: [
// plugin to create report parent folder
{
path: "supports/create-report-folder.js",
options: {
reportDir: "reports/report/cucumber"
}
}
// plugin to generate cucumber html report
{
path: "supports/cucumber-html-reporter.js",
options: {
jsonFile: "reports/report/cucumber/cucumber-report.json",
htmlFile: "reports/report/cucumber/cucumber-report.html"
}
}
]
A workable scaffold for Protractor + Cucumber4 + HTML Report at my github
The scaffold for Protractor + Cucumber3 + HTML Report on my local has some dependency campatible issue, I'm looking into that in case you must use Cucumber 3.
5) If you use multiCapabilities, you can use below package to generate report:
protractor-multiple-cucumber-html-reporter-plugin
If the location of protractor.conf.js is not at the same level as node_modules then the cucumberOpts.format path would be relative to its current file location and the protractor-multiple-cucumber-html-reporter-plugin looks for the json files relative to parent root folder and warns about json file is not found.
To solve this provide absolute path of the json file to cucumberOpts.format like below. This is applicable if you're using cucumber for e2e testing in Angular applications where the protractor.conf.js is normally present inside e2e folder.
cucumberOpts: {
require: [path.resolve(process.cwd(), 'e2e/steps/*.ts')],
format: 'json:'+ path.resolve(process.cwd() + '/reports/cucumber-ui-reports.json')
}

How to call global env variable for gulp protractor

This is gulpfile:
gulp.task(
'protractor', function () {
var configObj = {
configFile: config.test + 'protractor.conf.js'
};
configObj['args'] =[];//to be able to add multiple parameters
if (argv.suite) {
configObj['args'].push (
'--suite',
argv.suite
);
}
if (argv.env) {
if(argv.env.includes("q")){//qa
argv.baseUrl = "http://xx.qa.yy.com:8080";
}
else{//prod
if(argv.env.includes("p")){
argv.baseUrl = "https://xx.yy.com";
}
else{//local
argv.baseUrl = "localhost:8080";
}
}
configObj['args'] .push(
'--baseUrl',
argv.baseUrl
);
}
return gulp.src([])
.pipe(plumber({errorHandler: handleErrors}))
.pipe(protractor(configObj))
.on(
'error', function () {
gutil.log('E2E Tests failed');
process.exit(1);
}
);
}
);
so, in protractor test classes, i can get baseurl with that for exaple
this.getBaseUrl = function () {
return browser.baseUrl;
};
,
because i set here
configObj['args'] .push(
'--baseUrl',
argv.baseUrl
);
but i cant get env. it is set here
from console command
gulp protractor --env l --suite logout
i can see in consloeoutput of that
argv.env
but i cant call from protractor it. I tried browser.env
but did not work. how can i do this?
also i use yargs
var argv = require('yargs')//setting default enviroment to qa for testing
.default({ env : 'qa' })
.argv;
There is no env global variable or command line option in protractor, You have to pass it as a paramater using params. You can do something like this-
if (argv.params.env) {
if(argv.params.env.includes("q")){//qa
argv.baseUrl = "http://xx.qa.yy.com:8080";
}
else{//prod
if(argv.params.env.includes("p")){
argv.baseUrl = "https://xx.yy.com";
}
else{//local
argv.baseUrl = "localhost:8080";
}
}
Now from console command you can invoke it
gulp protractor --params.env 'test' --suite logout
You can also access it calling browser.params.env
You can always set globals in protractor in config file:
exports.config = {
//other config options
params: {
env: 'qa'
}
};
And pass values to the global variables through command line as-
protractor conf.js --params.env 'dev'

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

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"