Search code examples
javascriptangularjsselenium-webdriverprotractorangularjs-e2e

Is it possible to use a for loop for DRY protractor test? *var coming up undefined*


Goal: I want to make make a loop over an it block that tests if an element text matches.

Error: Error: No element found using locator: by.cssContainingText(".submenu li a", "undefined")

Question: How do I write a for loop to test multiple list items'? Moreover, How do i make var title visible to the inner it block

For this example: I have 2 test that I want to DRY up via a loop this next test example is just psuedocode doesn't work working test below.

var config = require('../../protractor.conf.js').config;

describe('this Homepage Body Tests', function(){

  browser.driver.get(config.homepageUrl);

  describe('sub navigation functionality', function () {
    //creates teh array of strings for this sample
    var title = ['find a store', 'clinic'];


    for(var i = 0; i < title.length; i++){

      it("should open find a" + title[i] + "page", function(){

        browser.driver.sleep(2000);
        browser.ignoreSynchronization = true;
        var link = element(by.cssContainingText('.submenu li a', title[i]));
        expect(link.getText()).toEqual(title[i]);


      });
    };
 });

});

HTML:

  <div class="submenu">
    <ul>
        <li><a >find a store</a>
        </li>
        <li><a>clinic</a>
        </li>

    </ul>
  </div>

Working Tests example:

it("should open find a store page", function(){

  browser.driver.sleep(2000);
  browser.ignoreSynchronization = true;

  var title = 'find a store';
  var link = element(by.cssContainingText('.submenu li a', title));


  expect(link.getText()).toEqual(title);


});

it("should open find a clinic page", function(){

  browser.driver.sleep(2000);
  browser.ignoreSynchronization = true;

  var title = 'clinic';

  var link = element(by.cssContainingText('.submenu li a', title));


  expect(link.getText()).toEqual(title);


});

Update:

it("should open find a store page", function(){

      browser.driver.sleep(2000);
      browser.ignoreSynchronization = true;

      var string = 'find a store';
      var main = '.main';
      var link = element(by.cssContainingText('.submenu li a', string));


      expect(link.getText()).toEqual(string);
      //I WANT OT CLICK ON THAT TOO!
      link.click().then(function() {

        browser.driver.sleep(3000);
        var title = element(by.cssContainingText(main, string));
        expect(title.getText()).toBe(string);
      });

    });

Solution

  • This is where element.all() + map() would help:

    var titles = element.all(by.css('.submenu li a')).map(function (elm) {
        return elm.getText();
    });
    
    expect(titles).toBeArrayOfStrings();
    expect(titles).toEqual(['find a store', 'clinic']);
    

    FYI, here is the relevant feature request:

    Also see: