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

admin2025-04-17  0

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.

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.

Share Improve this question edited Jan 8, 2017 at 13:54 win asked Jan 8, 2017 at 12:27 winwin 1394 silver badges17 bronze badges 6
  • It seems like You are not getting the DOM element correctly. Try find element by document.getElementById("hidePanelHeader") – Sandeep Sharma Commented Jan 8, 2017 at 12:32
  • @SandeepSharma The click is quite deep, it's more like Konstantin's answer, that the this context is no longer the one he expects – Icepickle Commented Jan 8, 2017 at 12:34
  • Yes, here this is also binded to calling context :- not binded to outer global this.. – Sandeep Sharma Commented Jan 8, 2017 at 12:40
  • @divya, as your question is very protractor-specific, probably you want to mention protractor in the title. At least for me this would be helpful. – Konstantin A. Magg Commented Jan 8, 2017 at 12:53
  • Thanks Sandeep, Ice, Konstantin for your replies. I modified the title and the code snippet to accurately show whats in the program. 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. – win Commented Jan 8, 2017 at 13:44
 |  Show 1 more ment

3 Answers 3

Reset to default 3

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;

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();
      }
    });
};

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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1744885507a272510.html

最新回复(0)