0

I've created a variables.json that host static settings for different environments.

What I would like to do in my test.js file is specify which site I'll be using with the variables I've defined in my variables.json file.

I wrote a series of NPM scripts to help, what I thought would, specify either the local or production objects from the variables.json.

Here is my variables.json:

{
  "local": {
    "domainLogin": "https://admin.local.us/en-US/signin",
    "domainDash": "https://admin.local.us/en-US/trunk-slug/branch-slug/dashboard"
  },
  "production": {
    "domainLogin": "http://admin.production.io/en-US/signin",
    "domainDash": "http://admin.production.io/en-US/trunk-slug/branch-slug/dashboard"
  }
}

Here is my test.js script:

var driver = require('selenium-webdriver');
var chai = require('chai');
var expect = chai.expect;

var config = require('../../../../../variables');

chai.use(require('chai-as-promised'));

describe('Admin Tests - User Alice', function() {
  var domainVar = process.env.envVar;
  var domain = config.domainVar.domainLogin;
  var dashboard = config.domainVar.domainDash;

  before(function() {
    this.timeout(50000);
    this.driver = new driver.Builder().withCapabilities(driver.Capabilities.firefox()).build();
    this.driver.get(domain);

    return this.driver.sleep(250);
  });

  after(function() {
    return this.driver.quit();
  });

  describe('would like to', function() {
    it('verify they are on login screen', function() {
      this.driver.sleep(250);

      var formButton = this.driver.findElement({
        css: 'button[type="submit"]'
      });

      return expect(this.driver.getCurrentUrl()).to.eventually.equal(domain);
    });
  });

  describe('login with their credentials', function() {
    beforeEach(function() {
      this.driver.sleep(500);

      this.driver.findElement({
        css: 'input[name="email"]'
      }).sendKeys('[email protected]');

      this.driver.findElement({
        css: 'input[name="password"]'
      }).sendKeys('example');

      var formButton = this.driver.findElement({
        css: 'button[type="submit"]'
      });

      this.driver.actions()
        .mouseMove(formButton)
        .click()
        .perform();

      this.driver.sleep(250);
    });

    it('verify they are in admin dashboard', function() {
      this.driver.sleep(500);
      return expect(this.driver.getCurrentUrl()).to.eventually.equal(dashboard);
    });
  });
});

Here are the NPM scripts I use:

{
  "scripts": {
    "env-local": "env envVar='local'",
    "env-prod": "env envVar='production'",
    "el-2378-p:spec": "npm run env-local mocha test/spec/admin/dashboard/alice/test.js -- --reporter spec --slow 0",
    "test": "mocha"
  }
}

Here is the error I get when I run the test:

var domain = config.domainVar.domainLogin;
                               ^

TypeError: Cannot read property 'domainLogin' of undefined
    at Suite.<anonymous> (/test.js:11:32)
    at context.describe.context.context (/node_modules/mocha/lib/interfaces/bdd.js:47:10)
    at Object.<anonymous> (/test.js:9:1)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at /node_modules/mocha/lib/mocha.js:216:27
    at Array.forEach (native)
    at Mocha.loadFiles (/node_modules/mocha/lib/mocha.js:213:14)
    at Mocha.run (/node_modules/mocha/lib/mocha.js:453:10)
    at Object.<anonymous> (/node_modules/mocha/bin/_mocha:393:18)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:138:18)
    at node.js:974:3

Oddly enough if I change the lines in my test.js script from:

  var domainVar = process.env.envVar;
  var domain = config.domainVar.domainLogin;
  var dashboard = config.domainVar.domainDash;

to:

  var domainVar = process.env.envVar;
  var domain = config.local.domainLogin;
  var dashboard = config.local.domainDash;

It will work, but it makes my domainVar useless. What I'm trying to do is specify which variables I want to use in my NPM scripts. If I have to specify between local and production I'll need multiple versions of the same script and the test.js file wouldn't be loosely coupled as I'd like it to be.

When I console.log(domainVar) in my test.js file I do get the output:

local

Which makes me suspect that while I can output a string with an node_env variable my test.js file does not recognize it as a valid property to append with?

If this is true why is this happening? When I make the variable domainVar wouldn't it simply replace the text that it is representing (local)? Why is

config.local.domainLogin not equivalent to config.domainVar.domainLogin

Is there a better way to verify environment variables than what I've done in the above?

2
  • Why not use something like the node-config module? I understand that you're asking one question and I'm replying with another, but there are modules that address many of these things already. Commented Dec 14, 2015 at 19:23
  • @MatthewBakaitis I didn't know about that module. I think I was asking my question incorrectly and while searching for solutions I was stuck on an incorrect path. Commented Dec 14, 2015 at 20:06

1 Answer 1

2

It's quite hard to understand what you mean, or what you're trying to do, but I'll take a stab...

I suspect you think that by doing

var domainVar = process.env.envVar;
var domain = config.domainVar.domainLogin;
var dashboard = config.domainVar.domainDash;

And assuming domainVar equals "local", you'd get the equivalent of

var domain = config.local.domainLogin;
var dashboard = config.local.domainDash;

But this is not at all how this works.

The fact that a variable exists with a specific identifier doesn't "override" usage of that name (identifier...) in other places. If you want to use the value of a variable to access the property of an object, use the square bracket notation:

var domainVar = process.env.envVar;
var domain = config[domainVar].domainLogin;
var dashboard = config[domainVar].domainDash;
Sign up to request clarification or add additional context in comments.

2 Comments

This solution works, thank you. To make sure I understand correctly. We are using the bracket notation since the variables.json has objects that need to be accessed and we need to use the correct syntax to access the object properties? Why wouldn't using dot notation access the object properties?
@azemPC - actually it doesn't seem like you understand this topic at all, and respectfully I'd advise you to learn JavaScript from the ground up using a reputable source of information as this is a fundamental structure of the language that you don't understand. It would do you good to spend that time

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.