Protractor set global variables - javascript

I am trying to set a global variable on protractor to use in all describe blocks.
var glob = 'test';
describe('glob test', function () {
it('should set glob', function () {
browser.get('http://example.com/test');
browser.executeScript(function () {
window.glob = glob;
});
});
});
But this returns me the following error:
Message:
[firefox #2] UnknownError: glob is not defined
I also looked at this question: protractor angularJS global variables
so i tried to set the variable glob in conf.js in this way:
exports.config = {
...,
onPrepare: function () {
global.glob = 'test';
}
};
Still, having the same error.
How can i add properly global variables in protractor tests?

It is possible to set globals from the Protractor config file with the help of params property:
exports.config = {
// ...
params: {
glob: 'test'
}
// ...
};
And you can access it in the specs using browser.params.glob.
See the reference config file.
The params object will be passed directly to the Protractor instance, and can be accessed from your test as browser.params. It is an arbitrary object and can contain anything you may need in your test. This can be changed via the command line as:
protractor conf.js --params.glob 'other test'
Update:
From the docs for browser.executeScript:
If the script is provided as a function object, that function will be converted to a string for injection into the target window. Any arguments provided in addition to the script will be included as script arguments and may be referenced using the arguments object.
So, JavaScript scope in this case does not work, you function that is passed to browser.executeScript won't have any closure variables from spec like browser. But you can pass these variables explicitly:
browser.executeScript(function (glob) {
// use passed variables on the page
console.log(glob);
}, browser.params.glob);

You can also set global variables in onPrepare() using global:
onPrepare: function () {
global.myVariable = "test";
},
Then, you would just use myVariable throughout the tests as is.
This is actually how protractor, browser and other built-in global variables were made available globally:
Runner.prototype.setupGlobals_ = function(browser_) {
// Export protractor to the global namespace to be used in tests.
global.protractor = protractor;
global.browser = browser_;
global.$ = browser_.$;
global.$$ = browser_.$$;
global.element = browser_.element;
global.by = global.By = protractor.By;
// ...
}
Note that with this approach you are polluting your global scope/namespace, be careful.

Another option is to use a process variable
Protractor is a node process. Any node process can be started with custom node variables. Not sure how it's done in windows (please comment if you know how) but for mac and any linux/unix OS you can
Start protractor with environment variable like this
MY_VAR=Dev protractor tmp/config.js
And then it will be available anywhere within your process and even in your config
console.log(process.env.MY_VAR)

I know I'm a bit late to the answer but here's another way of setting global variables that can be used throughout the file
describe("Some Global most outer describe", function(){
var glob = "some global variable";
var blob = "some other global variable";
it('should test glob', function(){
expecte(glob).toEqual("some global variable");
});
it('should test blob', function(){
expecte(glob).toEqual("some other global variable");
});
describe('Some inner describe', function(){
//Some other inner tests can also see glob and blob
});
});

Related

Protractor is not able to find a function from JS file

I created a function which return the new Browser object from the JS function browser.forkNewDriverInstance() and i created a global variable in my config file and i'm calling a function from that file by using this global variable. but here when i'm calling that function it is throwing error like utility.openNewBrowser is not a function error.
Config File:
onPrepare: function () {
global.utility=require("../src/test/resources/com.learnFramework.utility/timeOutConfig.js");
}
Cucumber Opts functions
cucumberOpts: {
//i'm using the same file for setting up the timeout.. is this creating the issue??
require:['../src/test/resources/com.learnFramework.utility/timeOutConfig.js'],
tags: false,
profile: false,
format:'json:../Reports/jsonResult/results.json',
'no-source': true
}
Function
var configure = function () {
this.setDefaultTimeout(100 * 1000);
this.openNewBrowser=function(){
return browser.forkNewDriverInstance(true);
}
};
module.exports = configure;
Error Log
TypeError: utility.openNewBrowser is not a function
When i called the forkNewBrowserInstance method directly i'm getting the below error.
both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details
can some help me to resolve this issue.. i got this error because the first browser ignoring synchronization but second browser how can i ignore the synchronization?
What you did above is the correct way of defining a global variable. But I think the global variable name should be configure instead of utility that is why it is throwing the TypeError.
And wherever you want to call it, use that variable name as is. This is actually how protractor, browser and other built-in global variables were made available globally. The following posting was helpful and also the protractor doc where it's explaining the property: params?: any;
Hope this helps, please let me know.
I faced the same issue but with jasmine.
so i had done the following workaround and issue was resolved.
class abc{
constructor() {
var configure = function () {
this.setDefaultTimeout(100 * 1000);
this.openNewBrowser=function(){
return browser.forkNewDriverInstance(true);
}
};
}
}
module.exports = new abc();

Adding global variables via a require Common Function file

I am doing a POC on switching to Protractor and Jasmine to perform our automated scripting. I'm trying to build a preliminary framework, but I'm having issues trying to translate my concept to reality.
I've set up three files: conf.js, spec.js, and cf.js. Conf.js is testplan-specific configuration file, spec.js contains the actual tests, and cf.js contains the common functions that I will be using through all test plans. I am trying to include a variable in cf.js to contain the starting URL to be used in the browser.get call. So far, I have not been able to get that to work. I've tried declaring it in cf.js before the //commonfunctions// function declaration, as well as within the function itself. What is the proper way to do this?
cf.js
var commonfunctions = function () {
global.StartPage = 'http://google.com/';
this.ccClick = function (clickElement) {
browser.wait(protractor.ExpectedConditions.visibilityOf(clickElement),
this.defaultWait);
browser.wait(protractor.ExpectedConditions.elementToBeClickable(clickElement),
this.defaultWait);
clickElement.click();
};
// Common text search
this.ConfirmText = function(testElement, compareString) {
browser.wait(protractor.ExpectedConditions.visibilityOf(testElement),
10000);
expect(testElement.getText()).toEqual(compareString);
};
};
module.exports = new commonfunctions();
spec.js
beforeEach(function() {
browser.waitForAngularEnabled(false);
browser.get(commonfunctions.StartPage);
});
Right now, it does not navigate to the webpage.
This should be possible, I have posted a similar answer before but let me know if you have further concerns about the approach. The approach I took was to require the common function file in the onPrepare as a global variable. This way anything exported from the file is accessible throughout all the tests.
Storing global variable in a separate file for Protractor Tests
Your made a mistake at following code:
// cf.js
var commonfunctions = function () {
global.StartPage = 'http://google.com/';
// spec.js
beforeEach(function() {
browser.waitForAngularEnabled(false);
browser.get(commonfunctions.StartPage);
});
// you define `StartPage` to a global variable, not a property of `commonfunctions`,
thus you shouldn't refer it from `commonfunctions`, but from `global` as following:
browser.get(global.StartPage)
or you define StartPage to be a property of commonfunctions
// cf.js
var commonfunctions = function () {
this.StartPage = 'http://google.com/';
// use `this` at here, rather than `global`
// spec.js
beforeEach(function() {
browser.waitForAngularEnabled(false);
browser.get(commonfunctions.StartPage);
});
Add the below one to your config.js
baseUrl: 'http://google.com/',
To use it in your test as below
browser.get(browser.baseUrl);
Hope this helps you

Jasmine - How To Mock Global Variables & Functions

I have a script I would like to test that includes global variables with some of them being initialized with functions calls. For example
var g_count = 0;
var g_util = addLibrary( "util.lib" );
I would like to mock both g_count and g_util
If I have a function call within my testing function I can easily mock it with addLibrary = jasmine.createSpy(); but once it is in global scope, the mock fails and I get an error message
Reference Error: addLibrary is not defined.
Edit: I figured out how to mock the variable. I added it to a global property,
var globals = {
g_count : null
}
Exported it
module.exports = {
globals: globals
}
Then spied on it
spyOnProperty(util.globals, 'g_count').and.returnValue(5);
I still can't figure out the addLibrary function
I fixed the error for the addLibrary. Since it is used to initialize a global variable it was being called when I required the script. Adding addLibrary = jasmine.createSpy(); above the require(...) fixed it.

Inject node module variable to scope

Is it possible to do achieve this behavior using node modules?
module.js:
module.exports = function () {
var test.fn = function () {
console.log("$test.fn()");
}
var test.fn2 = function () {
console.log("$test.fn2()");
}
var variable = "test";
};
app.js:
require("./module.js")();
test.fn();
test.fn2();
otherFunction(variable);
I dont want to do anything like this $ = require("./module.js")(); $.test.fn();
I want to inject this variables into app.js scope without wrapper variable.
Edit:
I have ended up using this:
module.js:
module.exports = function () {
eval(String(inject));
var inject = (
this.$module1 = {},
this.$module1.fn = function () {
console.log("$module1.fn()");
}
);
};
app.js:
require("./module.js")();
$module1.fn();
The top level scope in a module is actually a function scope (the node.js loader wraps each module in a function that it then calls to execute the code in the module). Thus, there is no publicly available "root" object that we can programmatically assign properties to.
So, that means that it is not possible in a module to programmatically add new variables at the top level of the module scope without using eval() in a fairly big hack. Function scopes just don't work that way in Javascript.
You could also have the module assign things to the global object where they can be used without a prefix, but this is NOT a recommended practice in any way. The whole point of node.js modules is to avoid using any globals and to make code entirely self contained with little chance of global collisions.
Or, you could have your module export a giant string of Javascript and then eval() it inside of app.js in order to define new variables in the module scope. Again - not recommended.
Your best best is do things the "node.js way" and put everything on an object and export that object. Here's one variation:
app.js
var test = require("./module.js")();
test.fn(); // "executing fn"
test.fn2(); // "executing fn2"
console.log(test.myVar); // "test"
module.js
module.exports = function () {
return {
fn: function () {
console.log("executing fn");
},
fn2: function() {
console.loog("executing fn2");
},
myVar: "test"
}
};
You can do something like that using an IIFE. The method, when required, will automatically run and return an object, which you can then use in your application.
module.js:
global.test = (function() {
return {
fn: function() {
console.log("executing fn");
},
fn2: function() {
console.log("executing fn2");
},
variable: "test"
}
})();
app.js
require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);
Note that this technique will overwrite the global variable test if it already exists.
This answer should not encourage you to use global within your node.js modules (see jfriend00's comments above) as it makes your code vulnerable for name collisions with other modules and thus your modules less portable.
Within module.js you have access to the global object of node.js runtime environment.
module.js:
global.test = {
fn: function() {
//Do something
},
fn2: function() {
//Do something different
},
variable: "test variable"
}
app.js
require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);
Note that this technique will overwrite the global variable test if it already exists.

Access for global variables JavaScript unit testing

Hello I am new JavaScript unit testing and I'm using Mocha.js and Chai.js
What I want to do is simply figure out how to check the value of a global variable in a seperate js file. Here is my code
Here is the main.js file (code to be tested) Just has the variable I want to test against.
//main.js
var foo = 9;
Here is my test file
var assert = require("assert")
var expect = require('chai').expect
var fs = require("fs")
var vm = require("vm")
function include(path){
var code = fs.readFileSync(path,'utf-8');
vm.runInThisContext(code,path);
}
describe('Global', function(){
include('lib/main.js');
it('Should check if value is matching', function(){
expect(foo).to.equal(9);
});
});
Again, I'm new to unit testing in JavaScript. Any help will be greatly appreciated. The error I get back is foo is not defined which tells me that it can't access the variable, so how can I access it? Thank you in advance for the help.
var foo = 9; does not declare a global variable, it declares a local variable. In Node.js, a local variable declared in the outermost scope of a module will be local to that module.
If you want to test the value of a local variable declared in another file, your best bet is probably to read the contents of that file into a string (using fs.readFileSync, perhaps) and then eval() the string, which should define the variable in the current scope.
That will only work if the local variable is declared in the file's outermost scope. If it's a local variable inside a function, for example, you're out of luck (unless you want to do some gnarly string parsing, which would stretch the bounds of sanity).
Your global object is usually window
a global var foo = "test"; is the same as window.foo = "test"; or window['foo'] = "test";
Window is not defined when mocha is run in node, but this blog post uses "this" combined with a self-invoking function to get the same result.

Categories