Trying to access nested function, “undefined is not a function”

I'm working on some end-to-end tests using JavaScript (Protractor). I've got a PageObjects file that contains the following:

var SomeClass = function() {
    this.get = function() {
        browser.get('http://blah');
    };

    this.person = function() {
        var firstNameInput = element(by.id('firstName'));
        var lastNameInput = element(by.id('lastName'));

        this.setTitle = function(title) {
            element(by.xpath('//select[@id="title"]/option[text()="' + title +'"]')).click();
        };

        this.setFirstName = function(firstName) {
            firstNameInput.sendKeys(firstName);
        };

        this.setLastName = function(lastName) {
            lastNameInput.sendKeys(lastName);
        };
    };
};

module.exports = new SomeClass();

In my spec, I'm trying to access the nested function like this:

describe('some test', function() {
    var someClass = require('./some_class.po.js');
    var data = require('./some_class.data.json');

    it('do stuff', function() {
        someClass.get();
        someClass.person.setTitle(data.title);
        someClass.person.setFirstName(data.firstName);
        someClass.person.setLastName(data.lastName);
    });
});

When I try to run this test, the higher level someClass.get() works just fine, but when it attempts to execute someClass.person.setTitle(data.title), I get a Failed: undefined is not a function message.

Any idea what I'm doing wrong? I'm only using setters, no getters. Don't think I need to return anything.

Answers:

Answer

You need to make some changes in your code to access inner functions of person(). Added return this at the end of person(), so that the inner properties and methods of person() can be accessed from outside of the person().

See the changes highlighted in the code below.

var SomeClass = function() {
  this.get = function() {
    browser.get('http://blah');
  };

  this.person = function() {
    var firstNameInput = element(by.id('firstName'));
    var lastNameInput = element(by.id('lastName'));

    this.setTitle = function(title) {
      element(by.xpath('//select[@id="title"]/option[text()="' + title + '"]')).click();
    };

    this.setFirstName = function(firstName) {
      firstNameInput.sendKeys(firstName);
    };

    this.setLastName = function(lastName) {
      lastNameInput.sendKeys(lastName);
    };

    return this;
    // ^^^^^^^^^
  };
};

module.exports = new SomeClass();

Then, you can access setTitle as follow.

someClass.person().setTitle(data.title)
//              ^^ 

Demo

var SomeClass = function() {
  this.person = function() {
    this.setTitle = function(title) {
      document.write(title);
    };

    return this;
    // ^^^^^^^^^
  };
};

var myObj = new SomeClass();
myObj.person().setTitle('Hello World!');

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.