Search code examples
javascriptangularjsseleniumprotractorend-to-end

Protractor custom locator fails to locate the element


I have added a custom data attribute to the elements i need to identify and interact using protractor. The attribute is data-test-id. I created a custom locator in the onPrepare callback in conf.js to detect the element. It is below:

onPrepare: function () {
    by.addLocator('testId', function(value, parentElement) {
      parentElement = parentElement || document;
      var nodes = parentElement.querySelectorAll('[data-test-id]');
      return Array.prototype.filter.call(nodes, function(node) {
        return (node.getAttribute('[data-test-id]') === value);
      });
    });
  }

My angular app has a h1 with the text Home inside it. I added the data-test-id attribute to it:

<h1 data-test-id="test-element">Home</h1>

Here is my Protractor test:

test.js:

describe('Navigate to the website.', function() {
    it('Should have the Heading as Home', function() {
        browser.get('http://localhost:8888/#/');
        browser.waitForAngular();

        var textValue = 'Home';
        var heading = element(by.testId('test-element'));

        expect(heading.getText()).toEqual(textValue);
    });
});

conf.js:

exports.config = {
  //directConnect: true,
  seleniumAddress: 'http://localhost:4444/wd/hub',
  // Capabilities to be passed to the webdriver instance.
  capabilities: {
    'browserName': 'chrome'
  },

  // Spec patterns are relative to the current working directly when
  // protractor is called.
  specs: ['test.js'],

  // Options to be passed to Jasmine-node.
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000
  },

  onPrepare: function () {
    by.addLocator('testId', function(value, parentElement) {
      parentElement = parentElement || document;
      var nodes = parentElement.querySelectorAll('[data-test-id]');
      return Array.prototype.filter.call(nodes, function(node) {
        return (node.getAttribute('[data-test-id]') === value);
      });
    });
  }
};

When I run the sample test, I get the following error:

1) Navigate to the website. Should have the Heading as Home
Message: NoSuchElementError: No element found using locator: by.testId("test-element")

What am I doing wrong? How can I fix this issue and get this to work?


Solution

  • When you are getting the attribute, you should ask for data-test-id instead of [data-test-id]. Looks like a copy-paste error.

    Replace:

    return (node.getAttribute('[data-test-id]') === value);
    

    with:

    return (node.getAttribute('data-test-id') === value);