1

File Structure

enter image description here

01.spec.js - - - I call helpers from the protractor specs which is fine

describe('should click on element', function () {
    var helper1 = require('../../modules/helpers/helper1.js');

    it('should click and assert...', function() {
        helper1.clickOnCircle('Accounts');
    });
});

...But to use any helper functions from another helper file...

helpers1.js - - - I have to require the helper in every function

module.exports = {
    clickOnCircle: clickOnCircle,
    clickOnBox   : clickOnBox
};

var helper2 = require('./helper2.js');   //node require doesn't hit something like this

function clickOnCircle(circleText) {
    var helper2 = require('./helper2.js');   //needed in every function
    helper2.doSomething(circleText);
}

function clickOnBox(boxText) {
    var helper2 = require('./helper2.js');   //needed in every function
    helper2.doSomething(boxText);
}

It's almost like I want the helper files to be available globally. I've messed around using configuration parameters but I still end up having to require the helper from each function.

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
luker02
  • 387
  • 2
  • 5
  • 13

3 Answers3

1

You can load other modules just once at the beginning of your module and then reference them anywhere from within that module.

This should work just fine:

// require in any other modules we need here
// modules are cached by the system
var helper2 = require('./helper2.js');

function clickOnCircle(circleText) {
    helper2.doSomething(circleText);
}

function clickOnBox(boxText) {
    helper2.doSomething(boxText);
}

module.exports = {
    clickOnCircle: clickOnCircle,
    clickOnBox   : clickOnBox
};
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    In comparison with OP's code you've moved `module.exports` to the bottom of the script (before requiring other modules). I am curious why does it make difference? Is module loader ignoring anything after `module.exports`? – Michael Radionov Jul 24 '15 at 14:26
  • It's all about the scope module.exports is a JavaScript object, so it's scoped to use only data within itself, by setting the functions inside module.exports they are scoped to that object, so a variable call outside after the object is created is irrelevant and cannot be used. By setting the variable before module.exports is created our variable can be set to the same scope as our functions on a global scope rather than inside the scope of our object. – dhershman Jul 24 '15 at 14:45
  • @michaelradionov - the order does not make a difference. I just prefer the logical order of require statements, function definitions then exports. – jfriend00 Jul 24 '15 at 21:06
0

What about using inheritance,

for example:

function shapeModel() {

    var helper = require('./helper2.js');

function clickOnCircle() {
    return helper.doSomething(circleText);
  }

  function clickOnBox() {
    return helper.doSomething(boxText);
  }

  return {
    clickOnCircle: clickOnCircle(),
    clickOnBox   : clickOnBox()
  }
}

module.exports = shapeModel

This also makes a class for you to use in the module. This places the exports at the bottom of the page allowing the helper variable to stay scoped as global instead of scoped outside your module.exports

dhershman
  • 341
  • 2
  • 12
  • I see your point but does this snippet limit me if I want to do other things within the clickOnCircle() and clickOnBox() functions besides just calling the helper function? – luker02 Jul 24 '15 at 15:43
  • It shouldn't as long as you declare them within shapeModel to declare them for the entire class. – dhershman Jul 24 '15 at 15:45
  • So if I require the file above, I would call it like... var shapemodel = require('shapemodel.js'); shapemodel.clickOnCircle(); ... but I get "undefined is not a function" ... is this how you call this function now? – luker02 Jul 30 '15 at 18:14
  • you would just do `var shapemodel = require(/location/of/jsfile/shapeModel)` then you could do shapemodel.clickOnCircle(); – dhershman Jul 30 '15 at 18:19
0

here is a brief example of how we use our helpers and page objects. We have a file called helper.js and all of our page objects are in the pages folder. We are using the require-all node module to help us include all our page objects.

// Require all application pages
global.pages = require('require-all')(__dirname + '/../pages/');
global.EC = protractor.ExpectedConditions;

// Instantiate all pages in our applications, and make them globally available to the tests

//***** User/Nav Pages *****
global.loginPage                 = new pages.Navigation.LoginHomePage();
global.instructorHomePage        = new pages.Navigation.InstructorHomePage();
global.studentHomePage           = new pages.Navigation.StudentHomePage();
global.studentAccessPage         = new pages.Misc.StudentAccessPage();
global.selfEnrollPage            = new pages.User.SelfEnrollPage();
global.instructorNavPanelPage    = new pages.Navigation.InstructorNavPanelPage();
global.studentNavPanelPage       = new pages.Navigation.StudentNavPanelPage();
global.createInstructorPage      = new pages.Admin.CreateInstructorPage();
global.addUserPage               = new pages.User.AddUserPage();

then this is a template of how we would have one of those pages

var TemplatePage = function() {   
  //***** Buttons & Links *****   
  this.link = element(by.linkText('link'));   
  this.link2 = element(by.linkText('link2'));

  //***** Input Fields *****


  //***** Drop-Downs *****


  //***** Check Boxes *****


  //***** Page Elements *****


  //***** Helpers *****

  this.clickLink = function() {
    return link.click();   };

};

module.exports = TemplatePage;
BarretV
  • 1,197
  • 7
  • 17
  • This answer definitely put us on the right track. We require all helpers from `onPrepare()` and can easily call them from different specs making our code very clean. Thanks. – luker02 Aug 10 '15 at 16:12
  • that's great news to hear. I'm glad you were able achieve your goal in making the code clean. – BarretV Aug 11 '15 at 16:38