以惯用方式组织javascript webdriver promise代码

Organise javascript webdriver promises code idiomatically

本文关键字:webdriver promise 代码 javascript 方式组      更新时间:2023-09-26

我通过量角器使用webdriver断言html表中特定行的内容。我有以下代码可以正常工作,但看起来很糟糕。我想要有关如何更好地用承诺习惯性地组织此代码的建议;特别是,我想更明显地说明此代码有 3 个部分:

  1. 查找页面上带有 td 的行,其中包含指定matchText
  2. 检查是否只有一行匹配,并使用有用的调试信息处理错误情况
  3. 检查此匹配行中 tds 的文本内容是否符合预期

有没有办法我可以更好地组织它以使其更具可读性,也许通过链接承诺或其他东西?

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

是的,您可以将 promise 回调从非抛出案例解包到链式版本:

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

如何使用 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);
});
最后,

我从@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函数足够通用,可以在其他地方使用