win
win

Reputation: 139

Protractor error --- TypeError: Cannot read property 'click' of undefined

I am new to protractor testing of angularjs. Basically I want to check a checkbox if it is unchecked. With the following code I get the error as in title "TypeError: Cannot read property 'click' of undefined"

var PageObject = function () {
    this.hidePanelHeaderCb = element(by.id("hidePanelHeader"));

    this.checkHidePanelHeaderCb = function() {
        this.hidePanelHeaderCb.isSelected().then(function (selected) {
          if(selected !== true) {
                (this.hidePanelHeaderCb).click();
          }
        });
    };
};
module.exports = PageObject;

the webpage snippet which I got with right click -> inspect is:

<span id="hidePanelHeader" ng-class="{'icon-CheckBoxSelected': panelProperties.hidePanelHeader, 'icon-CheckBoxUnselected': !panelProperties.hidePanelHeader}" ng-click="switchHidePanelHeader()" role="button" tabindex="0" class="icon-CheckBoxSelected" style=""></span>

I tried using isChecked() and it gives a different error.

I called using panelPropertiesPageObject.checkHidePanelHeaderCb();

All the other functions using this manner of code are working fine. Its the checkbox code that I added which is not working. So using "document" instead of "this" is probably not the reason.

Upvotes: 2

Views: 8562

Answers (3)

craig
craig

Reputation: 5016

Using ES2015 (ES6):

If you are using ES2015 (ES6), this could be fixed with:

var PageObject = function () {
  this.hidePanelHeaderCb = element(by.id("hidePanelHeader"));

  this.checkHidePanelHeaderCb = () => {
    this.hidePanelHeaderCb.isSelected().then(selected => {
      if(!selected) {
        this.hidePanelHeaderCb.click();
      }
    });
  };
};
module.exports = PageObject;

I would suggest reading fat arrow syntax and lexical scoping.

Upvotes: 0

win
win

Reputation: 139

Following works using closure for obviating the issue caused by the promise:

this.checkHidePanelHeaderCb = function() {
    var that = this;
    this.hidePanelHeaderCb.isSelected().then(function(selected) {
      if(selected !== true) {
            that.hidePanelHeaderCb.click();
      }
    });
};

Upvotes: 0

Konstantin A. Magg
Konstantin A. Magg

Reputation: 1118

Be careful with JavaScript scopes. In functions, this refers to the function object. So with every this.hidePanelHeaderCb statement in a function, you add a property to this object.

Instead you can store the element promise in a variable and work with it.

Please try this:

var PageObject = function () {

    this.checkHidePanelHeaderCb = function() {
        var hidePanelHeader = element(by.id("hidePanelHeader"));
        hidePanelHeader.isSelected().then(function (selected) {
            if(selected !== true) {
                hidePanelHeader.click();
            }
        });
    };

};

module.exports = PageObject;

This is all I can tell you about the syntax. More is hard to add without HTML and more JS context.


Edit: The example above uses three hidePanelHeaderCb properties on different objects:

var PageObject = function () {
    // #1 PageObject.hidePanelHeaderCb (defined here)
    this.hidePanelHeaderCb = element(by.id("hidePanelHeader"));

    // PageObject.checkHidePanelHeaderCb (defined here)
    this.checkHidePanelHeaderCb = function() {
        // #2 PageObject.checkHidePanelHeaderCb.hidePanelHeaderCb (undefined)
        this.hidePanelHeaderCb.isSelected().then(function (selected) {
          if(selected !== true) {
                // #3 anonymousThenCallback.hidePanelHeaderCb (also undefined)
                (this.hidePanelHeaderCb).click();
          }
        });
    };
};
module.exports = PageObject;

Upvotes: 3

Related Questions