在自定义的Jasmine Matcher中解决并拒绝了承诺

ale*_*cxe 12 javascript selenium promise jasmine protractor

故事:

我们开发了一个定制的茉莉花匹配器,可以做两件事:

  • 鼠标悬停在给定元素上
  • 检查是否显示了带有所需文本的工具提示

执行:

toHaveTooltip: function() {
    return {
        compare: function(elm, expectedTooltip) {
            var tooltipPage = requirePO("tooltip");

            browser.actions().mouseMove(elm).perform();
            browser.wait(EC.visibilityOf(tooltipPage.tooltip), 5000, "Tooltip is still not visible.");

            return {
                pass: tooltipPage.tooltip.getText().then(function(actualTooltip) {
                    return jasmine.matchersUtil.equals(actualTooltip, expectedTooltip);
                }),
                message: "Element does not have the tooltip '" + expectedTooltip + "'."
            };
        }
    };
},
Run Code Online (Sandbox Code Playgroud)

其中tooltipPage是一个单独定义的页面对象:

var Tooltip = function () {
    this.tooltip = element(by.css(".tooltip"));
};

module.exports = new Tooltip();
Run Code Online (Sandbox Code Playgroud)

使用对我们来说非常方便,真正有助于遵循DRY原则,保持我们的测试代码库清洁和可读:

expect(page.fromDateInput).toHaveTooltip("After");
Run Code Online (Sandbox Code Playgroud)

问题和问题:

现在,我要做的是让匹配器分别处理2个用例:

  • 完全没有显示鼠标上的工具提示(基本上,被browser.wait()拒绝的承诺)
  • 有一个工具提示,但不是所需的工具提示

如何改进匹配器以分别处理这两个问题并报告不同的错误?

我尝试过的:

toHaveTooltip: function() {
    return {
        compare: function(elm, expectedTooltip) {
            var tooltipPage = requirePO("tooltip");

            browser.actions().mouseMove(elm).perform();

            return browser.wait(EC.visibilityOf(tooltipPage.tooltip), 5000, "Tooltip is still not visible.").then(function () {
                return {
                    pass: tooltipPage.tooltip.getText().then(function(actualTooltip) {
                        return jasmine.matchersUtil.equals(actualTooltip, expectedTooltip);
                    }),
                    message: "Element does not have the tooltip '" + expectedTooltip + "'."
                };
            }, function () {
                return {
                    pass: false,
                    message: "No tooltip shown on mouse over the element"
                }
            });
        }
    };
},
Run Code Online (Sandbox Code Playgroud)

在这里,我试图browser.wait()明确地解决并分别处理"成功"和"错误"案件.这导致了Jasmine Spec超时和控制台上的巨大"红色"文本:

Expected ({ ptor_: ({ setFileDetector: Function, ...
5 minutes scrolling here
... InnerHtml: Function, getId: Function, getRawId: Function }) to have tooltip 'After'.
Run Code Online (Sandbox Code Playgroud)

我担心我无法从"比较"功能返回一个承诺.

Gir*_*tur 4

根据jasminewd2 (Jasmine-to-WebDriverJS 的适配器。由 Protractor 使用) 代码-

期望解决了对实际值和期望值以及pass对象属性给出的任何承诺result

因此,如果确实存在需要在自定义匹配器/期望中解析的异步函数或承诺,那么需要将其包装到值,result.pass以便量角器等待承诺被解析。

在该问题中,jasmine spec timeout遇到错误是因为 Protractor 无法理解在执行该特定操作之前需要解决一个 Promise。为了解决这个问题,要么直接在expect语句中传递async函数,要么将其传递给对象pass的值result。这是它的代码 -

toHaveTooltip: function() {
  return {
      compare: function(elm, expectedTooltip) {
          var tooltipPage = requirePO("tooltip");

          browser.actions().mouseMove(elm).perform();

              return {
                  pass: browser.wait(EC.visibilityOf(tooltipPage.tooltip), 5000, "Tooltip is still not visible.").then(function () {
                            tooltipPage.tooltip.getText().then(function(actualTooltip) {
                                return jasmine.matchersUtil.equals(actualTooltip, expectedTooltip);
                            }),
                        }, function () {
                            return false;
                        }),
                  message: "Error Occured"
              }
      }
  };
},
Run Code Online (Sandbox Code Playgroud)

然而,上述代码的问题是无法制作自定义错误消息。为了解决这个问题,我能找到的最好方法是result显式返回该对象,以便可以根据需要为其分配错误消息。这是一个例子 -

var result = {};
result.pass = browser.wait(EC.visibilityOf(tooltipPage.tooltip), 5000, "Tooltip is still not visible.").then(function () {
                  tooltipPage.tooltip.getText().then(function(actualTooltip) {
                      result.message = "Element does not have the tooltip '" + expectedTooltip + "'.";
                      return jasmine.matchersUtil.equals(actualTooltip, expectedTooltip);
                  }),
              }, function () {
                  result.message = "No tooltip shown on mouse over the element";
                  return false;
              });
return result;
Run Code Online (Sandbox Code Playgroud)

注意:message如果对象中没有属性result,则量角器将尝试自行创建通用错误消息,并且它将包含承诺对象(以 - 开头的冗长消息{ ptor_: ... },如问题所示。

希望能帮助到你。