Nightwatch: Using nightwatch, is there a possibility to pass a global property from command line?

Created on 11 Jun 2015  ·  21Comments  ·  Source: nightwatchjs/nightwatch

The app I'm testing has different domains (for development, testing, acceptance, etc.). Is it possible to set a global property (preferably as param for nightwatch) so that I can easily kick off tests for those different domains/environments?

Most helpful comment

Sure you are. example solution:

Firstly lets create Global.js file. Add path to the file inside nightwatch.json:

"globals_path": "Global.js"

In Global.js define before method (it is executed once before any of test):

var self = module.exports = {
    environment: undefined,
    before: function (done) {
       // parseArgumentsAndGetEnv is function you need to implement on your own to find your env param
        self.environment = parseArgumentsAndGetEnv(process.argv);
        console.log("Run against: " + self.environment);

        done();
    }
};

Now in tests you can use this variable:

if (browser.globals.environment == 'Test') {
   // do something
} else if (browser.globals.environment == 'Prod') {
  // do something else
}

All 21 comments

Sure you are. example solution:

Firstly lets create Global.js file. Add path to the file inside nightwatch.json:

"globals_path": "Global.js"

In Global.js define before method (it is executed once before any of test):

var self = module.exports = {
    environment: undefined,
    before: function (done) {
       // parseArgumentsAndGetEnv is function you need to implement on your own to find your env param
        self.environment = parseArgumentsAndGetEnv(process.argv);
        console.log("Run against: " + self.environment);

        done();
    }
};

Now in tests you can use this variable:

if (browser.globals.environment == 'Test') {
   // do something
} else if (browser.globals.environment == 'Prod') {
  // do something else
}

Thanks a lot! Will implement this today!

Perhaps this is worth checking out https://www.npmjs.com/package/yargs

You can also define per-environment globals like so:

module.exports = {
  globalVar : 'test-value',
  // for development environment have a different value set
  development : {
    globalVar : 'dev-value'
  },

  acceptance : {
    globalVar : 'other-value'
  }
}

If this doesn't work for you, feel free to re-open.

Oh man... thank you @beatfactor, been trying to figure out something like this for ages.

@MateuszJeziorski I'm trying to use your example, but unfortunately in tests the variable environment is undefind, maybe you can suggest me something?

@AnastasiaPetrovskaya: could you post your globals.js, test code and nightwatch.config you're using?
also are you running tests parallel using test workers or it does not work for you even without parallel runner?
what version of nightwatch you're using, is before called at all in your case?

my globals.js file:

var self = module.exports = {
  someGlobal : 'Here I am',
  totalAm : undefined,

  before: function(done) {
    var my_env = {};
    for (e in process.env) my_env[e] = process.env[e];
    my_env["LOTO_ENV"] = "test";
    api = spawn('nodejs', ['index.js'], {cwd : '../api', env : my_env, detached: true, stdio: 'ignore'});
    sadmin = spawn('python', ['server.py'], {cwd : '../sadmin', env : my_env, detached: true, stdio: 'ignore'});
    api.unref();
    sadmin.unref();

    db.prepareDb(url, insertedClient1, insertedClient2, insertedClient3, totalAmounts, 
        function(insertedClient1, insertedClient2, insertedClient3, totalAmount) {
      self.totalAm = totalAmount;
      console.log('self',self.totalAm);
      done();
    });
  },

  after : function() {
    fs.readFile('../sadmin/tmp/pids/server.pid', 'utf8', function (err, data) {
      if (err) {
        console.log(err);
      } else {
        process.kill(data, 'SIGTERM');
      }
    });
    fs.readFile('../api/tmp/pids/server.pid', 'utf8', function (err, data) {
      if (err) {
        console.log(err);
      } else {
        process.kill(data, 'SIGTERM');
      }
    });
  }
};

my nightwatch.json

{
  "src_folders": ["Sadmin"],
  "output_folder" : "reports",
  "custom_commands_path" : "./js/commands",
  "custom_assertions_path" : "",
  "page_objects_path" : "",
  "globals_path" : "globals.js",
  "globals" : "",
  "test_workers": {"enabled": true, "workers" : "auto"},
  "live_output": true,

  "selenium" : {
    "start_process" : true,
    "server_path" : "./selenium-server-standalone-2.43.1.jar",
    "log_path" : "",
    "host" : "127.0.0.1",
    "port" : 4448,
    "cli_args": {
      "webdriver.chrome.driver" : "./chromedriver"
    }
  },
  "test_settings" : {
    "jenkins" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4445,
      "selenium_host"  : "127.0.0.1",
      "disable_colors" : true,
      "skip_testcases_on_fail": false,
      "end_session_on_fail":false,
      "screenshots" : {
        "enabled" : true,
        "on_failure" : true,
        "path" : "reports"
      },
      "desiredCapabilities": {
        "browserName": "chrome",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      }
    },

    "default" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4448,
      "selenium_host"  : "127.0.0.1",
      "skip_testcases_on_fail": false,
      "end_session_on_fail":false,
      "screenshots" : {
        "enabled" : true,
        "on_failure" : true,
        "path" : "reports"
      },
      "filter": "Sadmin/sadmin.js",
      "desiredCapabilities": {
        "browserName": "chrome",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      }
    },

    "sales" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4448,
      "selenium_host"  : "127.0.0.1",
      "skip_testcases_on_fail": false,
      "end_session_on_fail":false,
      "screenshots" : {
        "enabled" : true,
        "on_failure" : true,
        "path" : "reports"
      },
      "filter": "Sadmin/sadmin_sales.js",
      "desiredCapabilities": {
        "browserName": "chrome",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      }
    }
  }
}

before is called and I'm running tests parallel using test workers, and the example of the test

  'LogIn As Owner': function(client) {
    //проверка главной страницы
    client.logIn(BASE_URL + '/logout', 'owner' , 'user');
    client.pause(2000);
    client.checkMenu('owner', DEFAULT_TIMEOUT);
    client.mainPage('owner', DEFAULT_TIMEOUT);
    console.log('globals', client.globals);
  },

the result of console.log is

globals { someGlobal: 'Here I am',
  totalAm: undefined,
  before: [Function],
  after: [Function] }

nightwatch v0.8.4

I have similar problem using test workers, seems each worker gets his own copy of global.js but before is triggered in just of them

my workaround is to use getter instead property and check if environment was set, if not I'm setting it once again

var args = require('minimist')(process.argv);
var environment;

function getEnvironment() {
    return args["e"] || "default";
}

var self = module.exports = {
    get environment() {
        if (!environment) {
            environment = getEnvironment();
        }
        return environment;
    }
};

and in tests I'm doing:

var env = browser.globals.environment;

in your case you could do something silimar

var totalAm;

var self = module.exports = {
    getTotalAm: function(callback) {
        if (totalAm === undefined) {
            // async call to get totalAm from DB and return it using callback
        } else {
            callback(totalAm);
        } 
    }
};

and in your test:

client.globals.getTotalAm(function(totalAm) {
  console.log("TotalAm:", totalAm);
});

Hi, i don't solve the similar problem. Need to pass a global variable to line command.

In Global.js implements @MateuszJeziorski comments.

var args = require('minimist')(process.argv);
var globalSite = '',

function getSite() {
    return args["site"] || "default";
}

module.exports = {
    get site() {
        if (!site) {
            globalSite = getSite();
        }
        return site;
    }
};

In mi test named coreSpecs.js

module.exports = {
before: function(browser) {
        var site = browser.globals.globalSite;
        console.log(site);
}
};

In console execute

nightwatch -site mla -t tests/e2e/groups/mobile/coreSpecs.js

But not works... :(. The console log

ERROR There was an error while starting the test runner:


Error: Invalid testing environment specified: mla
    at Object.CliRunner.parseTestSettings (/usr/local/lib/node_modules/nightwatch/lib/runner/cli/clirunner.js:447:15)
    at Object.CliRunner.setup (/usr/local/lib/node_modules/nightwatch/lib/runner/cli/clirunner.js:51:8)
    at Object.exports.runner (/usr/local/lib/node_modules/nightwatch/lib/index.js:540:17)
    at /usr/local/lib/node_modules/nightwatch/bin/runner.js:9:16
    at Object.exports.cli (/usr/local/lib/node_modules/nightwatch/lib/index.js:534:5)
    at Object.<anonymous> (/usr/local/lib/node_modules/nightwatch/bin/runner.js:8:14)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)

Thanks guys

1) In Global.js change your code to:

module.exports = {
    get site() {
        if (!globalSite) {
            globalSite = getSite();
        }
        return globalSite;
    }
};

my example may be misleading, because I have there
a) method environment
b) property environment

2) In your test file

module.exports = { 
   before: function(browser) {
        var site = browser.globals.site;
        console.log(site);
   }
};

3) I'm not sure if this works

nightwatch -site mla -t tests/e2e/groups/mobile/coreSpecs.js

please try:

nightwatch --site mla --t tests/e2e/groups/mobile/coreSpecs.js

4) You're missing nightwatch environment

nightwatch --env chrome --site mla --t tests/e2e/groups/mobile/coreSpecs.js

assuming you have defined chrome in nightwatch.json. Check
http://nightwatchjs.org/guide#test-settings

Thanks @MateuszJeziorski Its works!
You're the best :+1:

Hi I am trying to use globals in test as said by @MateuszJeziorski but getting environment as undefined in test
below is my global.js
var self = (module.exports = {
environment: undefined,
before: function(done) {
self.environment = process.env.TEST_ENV;
if (self.environment == "CI") {
console.log("Run against: CI");
self.environment= “CI_URL”;
} else if (self.environment == "PROD") {
self.environment= “Prod_URL”;
} else if (self.environment == "SBX") {
console.log("Run against: SBX");
self.environment= “SBX_URL”;
} else {
console.log("No execution environment is specified running against: QA");
self.environment= “QA_URL;
// }
done();
}
});

In my nightwatch configuration i have used
"globals_path": "configuration/globals.js",

In test i am trying
console.log("In Test File environment:"+ browser.globals.environment);
and it is coming as undefined.

Output of execution

Run against: CI (Value is set in global.js)
Starting selenium server... started - PID: 74046

[Cup Login] Test Suite

In Test File environment:undefined (Undefined in test env)

Anyone please suggest if i am missing anything?

A bit late in the dance...

On the "client", you have the

client.options.desiredCapabilities

which come out from your nightwatch.js. That allow you to configure your variable by browser, if of any use :-)

@jehon how exactly do you use it? is it something like

client.options.desiredCapabilities(property,value)

I tried using it and got an error stating

client.options.desiredCapabilities is not a function

@anyone : is there any way to pass the username and password through command line
my Step definition looks like this

When(/^I login $/, async () => {
await login.waitForElementVisible('@form')
login.setValue('@username', 'username')
login.setValue('@password', 'password')
login.click('@login')
})

You can pass these as enviornment variables

globals: {
'username': process.env.USERNAME,
'password': process.env.PASSWORD
},
ive written the code in nightwatch.config but doesnt seem to work

Hi,
I am using nightwatch for test automation. with the comments from @MateuszJeziorski on jan 8 2016, I am able to provide the data from command line. Is there a way to provide a set of data in the command line, so that the test can take it one by one to run the tests?

Any pointers with respect to this, can be helpful!

Managed to figure out how to do a API call to get cookies in order to set cookies before globals are set:

It's still a little rough around the edges but it works at least, hope someone else can save themselves a couple of days:

```const chromedriver = require('chromedriver');
let request = require("request-promise");

function setAPI(self) {
request.post({
uri: 'https:///login',
method: "POST",
rejectUnauthorized: false,
json: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
form: {
email: '', password: ''
},
}, function (error) {
if (error) {
console.log(error);
}
})
.then(function(response) {
self.output.body = response;
return self.output.body;
});
}

let self = module.exports = {
output: {
body: 'yo'
},
tokens: {
csrf_token:' ',
jwt: '',
},
before : (browser, done) => {
self.output.body = setAPI(self);
chromedriver.start();
done();
},
after: (done) => {
self.tokens.csrf_token = self.output.body.response.csrf_token;
self.tokens.jwt = self.output.body.response.jwt;
chromedriver.stop();
done();
},
};

@nsberrow Hey, cool work with the latest post. You think we can consume this having the cookie reused to bypass succeeding login for multiple script execution?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lgaticaq picture lgaticaq  ·  3Comments

Zechtitus picture Zechtitus  ·  4Comments

jvlaar picture jvlaar  ·  4Comments

sgleonardoopitz picture sgleonardoopitz  ·  3Comments

davidlinse picture davidlinse  ·  4Comments