最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Looping over elements and testing them individually in protractor - Stack Overflow

programmeradmin4浏览0评论

Is there a way to implement loops so that the following code can be reduced?

    var navItems = element.all(by.repeater('item in mc.navItems'));
    expect(navItems.count()).toEqual(4);

    expect(navItems.get(0).getText()).toEqual('page1'.toUpperCase());
    navItems.get(0).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page1');

    expect(navItems.get(1).getText()).toEqual('page2'.toUpperCase());
    navItems.get(1).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page2');

    expect(navItems.get(2).getText()).toEqual('page3'.toUpperCase());
    navItems.get(2).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page3');

    expect(navItems.get(3).getText()).toEqual('page4'.toUpperCase());
    navItems.get(3).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page4');

I've tried multiple ways but they all fail because I'm not sure how to get them to wait until the promised value is returned.

Here's one way that fails:

var navItems = element.all(by.repeater('item in mc.navItems'));
for(var i = 0; i < navItems.count(); i++) {
    expect(navItems.get(i).getText()).toEqual(expectedValue[i].toUpperCase());
    navItems.get(i).click();
    expect(browser.getLocationAbsUrl()).toEqual('/' + expectedValue[i]);
}

where expectedValue = ['page1', 'page2', 'page3', 'page4'];

The problem with this is that the for loop evaluates the condition even before the promised value is returned and so the contents of the loop are never executed.

I'm sure I can use a then and attach a callback function to count() but that would only make things messy because I'd have to make navItems a global variable so that it can be accessed by the callback function and I also need to make sure that navItems is populated before the callback function is executed.

I'm aware that the expect() method takes care of promises in a nice clean way, I would like to implement something like this.

Is there a way to implement loops so that the following code can be reduced?

    var navItems = element.all(by.repeater('item in mc.navItems'));
    expect(navItems.count()).toEqual(4);

    expect(navItems.get(0).getText()).toEqual('page1'.toUpperCase());
    navItems.get(0).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page1');

    expect(navItems.get(1).getText()).toEqual('page2'.toUpperCase());
    navItems.get(1).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page2');

    expect(navItems.get(2).getText()).toEqual('page3'.toUpperCase());
    navItems.get(2).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page3');

    expect(navItems.get(3).getText()).toEqual('page4'.toUpperCase());
    navItems.get(3).click();
    expect(browser.getLocationAbsUrl()).toEqual('/page4');

I've tried multiple ways but they all fail because I'm not sure how to get them to wait until the promised value is returned.

Here's one way that fails:

var navItems = element.all(by.repeater('item in mc.navItems'));
for(var i = 0; i < navItems.count(); i++) {
    expect(navItems.get(i).getText()).toEqual(expectedValue[i].toUpperCase());
    navItems.get(i).click();
    expect(browser.getLocationAbsUrl()).toEqual('/' + expectedValue[i]);
}

where expectedValue = ['page1', 'page2', 'page3', 'page4'];

The problem with this is that the for loop evaluates the condition even before the promised value is returned and so the contents of the loop are never executed.

I'm sure I can use a then and attach a callback function to count() but that would only make things messy because I'd have to make navItems a global variable so that it can be accessed by the callback function and I also need to make sure that navItems is populated before the callback function is executed.

I'm aware that the expect() method takes care of promises in a nice clean way, I would like to implement something like this.

Share Improve this question asked Jul 22, 2015 at 10:46 Karthik BalakrishnanKarthik Balakrishnan 4,3936 gold badges40 silver badges69 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 4

I'm using protractor with cucumber and what I do is something like this

element.all(by.repeater('item in mc.navItems')).then(function (elements) {
  navItems = elements
  var expectations = []
  for (var i = 0; i < navItems.count(); i++) {
    expect(navItems.get(i).getText()).toEqual(expectedValue[i].toUpperCase());
    navItems.get(i).click();
    expectations.push(expect(browser.getLocationAbsUrl()).toEqual('/' + expectedValue[i]));
  }
  Q.all(expectations).should.notify(callback)
})

so the test will wait for all expectations to execute before notifying callback

I don't know if the each() method was available at the time this question was asked, but these days I'm pretty sure each() is the best approach.

In the stated context, the answer would look something like:

var navItems = element.all(by.repeater('item in mc.navItems'));

navItems.each((element, index) => {
  expect(element.getText()).toEqual(('page'+index).toUpperCase());
  element.click();
  expect(browser.getLocationAbsUrl()).toEqual('/page'+index);
});

Much better than calling out each element individually!

I think the problem that you have is not with the delay in return of promise but with closure. Take a look here-Using protractor with loops You can also use a recursion loop with if instead of using for as it is simpler-

function loop(i){
     if(i>=navItems.count())
              {
                return null;
              }
              else
              {
                expect(navItems.get(i).getText()).toEqual(expectedValue[i].toUpperCase());
        navItems.get(i).click();
        expectations.push(expect(browser.getLocationAbsUrl()).toEqual('/' + expectedValue[i]));
                })
            return loop(i+1)
          }
        }return loop(navItems.count()); 

Step 1 : first get the list of elements

let listOfElements = element.all(by.repeater('item in mc.navItems'));    

Step 2: Iterate the element using below line

listOfElements.each(function (element, index) {
                    element.getText().then(function (text) {
                        console.log(index, text);
                    });
                });
发布评论

评论列表(0)

  1. 暂无评论