用idiomatically组织javascript webdriver promises代码

时间:2015-03-10 19:05:42

标签: javascript angularjs webdriver promise protractor

我通过量角器使用webdriver从html表中声明特定行的内容。我有以下代码,它可以正常工作,但看起来很糟糕。我想知道如何用promises来更好地组织这段代码;特别是,我想让这个代码有3个部分更明显:

  1. 在页面上找到包含指定matchText的td的行
  2. 检查只有一行匹配,并使用有用的调试信息处理错误案例
  3. 检查此匹配行中tds的文本内容是否符合预期
  4. 我是否有办法更好地组织这个以使其更具可读性,可能是通过链接承诺或其他东西?

    browser.findElements(by.xpath("//td[text() = '" + matchText + "']/..")).then(function(trs) {
      if (trs.length == 0) {
        throw 'Unable to find td element equal to ' + matchText
      } else if (trs.size > 1) {
        protractor.promise.all(trs.map(function(tr){return tr.getInnerHtml()})).then(function(trsInnerHtml) {
          throw 'Matched multiple td elements for ' + matchText + ':' + trsInnerHtml;
        })
      } else {
        trs[0].findElements(by.tagName('td')).then(function(tds) {
          protractor.promise.all(tds.map(function(td) {return td.getText()})).then(function(tdContent){
            expect(tdContent).toEqual(expectedContent);
          })
        });
      }
    });
    

3 个答案:

答案 0 :(得分:2)

如何使用elementelement.all()并让expect()解决我们的承诺,并从引入便捷的toBeArrayOfSize()匹配器的jasmine-matchers包中获得一些帮助:

element.all(by.xpath("//td[text() = '" + matchText + "']/..")).then(function(trs) {
    expect(trs).toBeArrayOfSize(1);

    expect(trs[0].element(by.tagName('td')).getText()).toEqual(expectedContent);
});

答案 1 :(得分:2)

是的,你可以unwrap the promise callbacks从非投掷案例到链式版本:

browser.findElements(by.xpath("//td[text()='" + matchText + "']/..")).then(function(trs) {
  if (trs.length == 0) {
    throw 'Unable to find td element equal to ' + matchText
  } else if (trs.size > 1) {
    return protractor.promise.all(trs.map(function(tr) {
      return tr.getInnerHtml()
    })).then(function(trsInnerHtml) {
      throw 'Matched multiple td elements for ' + matchText + ':' + trsInnerHtml;
    });
  } else {
    return trs[0].findElements(by.tagName('td'));
  }
}).then(function(tds) {
  return protractor.promise.all(tds.map(function(td) {return td.getText()}));
}).then(function(tdContent){
  expect(tdContent).toEqual(expectedContent);
});

答案 2 :(得分:1)

最后我从@Bergi和@alexce的元素api中获取了链接承诺(感谢两者!)并提出了这个:

it('Matches tds', function() {
  browser.get('index.html');      
  var textToMatch = 'TDs';
  expect(
    element.all(trsContainingTd(textToMatch)).then(extractTds)
  ).toEqual(
    [['Expected', 'TDs', 'content']]
  );
});

function trsContainingTd(matchText) {
  return by.xpath("//td[text() = '" + matchText + "']/..");
}

function extractTds(trs) {
  return protractor.promise.all(trs.map(function(tr) {
    return tr.all(by.tagName('td')).getText();
  }));
}

这对我的眼睛有一些好处:

  1. 这是一个单一的期望
  2. 如果有比预期更多/更少的匹配行,它将打印出有用的调试
  3. trsContainingTdextractTds函数通常足以在别处使用