如何在赛普拉斯中定义自定义断言运算符?

时间:2019-04-25 06:00:08

标签: cypress assertion

在赛普拉斯测试中,我经常需要检查DOM元素中的文本是否等于某些预期测试。但是由于文本周围可能会有一些空格,所以我不能简单地写:

cy.get('.cell')
  .should('have.text', 'Hello')

相反,我必须写:

cy.get('.cell')
  .then($cell => $cell.text().trim())
  .should('eq', 'Hello')

我想定义一个自定义断言运算符,例如have.text.trimmed,让我这样使用它:

cy.get('.cell')
  .should('have.text.trimmed', 'Hello');

但是我在官方网站上找不到任何有关它的文件,有人会分享给我一些例子吗?

2 个答案:

答案 0 :(得分:2)

最后,我找到了解决方法。尽管cypress不提供这种功能,但是由于cypress使用chai,因此我们只能定义chai方法。

注意:由于断言方法have.text.trimmed是一种chai方法,而不是可链接的方法,因此无法定义text,因此无法在其后提供trimmed

但是仍然有两个选择:

  1. 定义一个chai方法textTrimmed,允许我们使用.should('have.textTrimmed', 'sometext'),这是首选方法,因为我们可以定义自定义断言消息,并且不会对JQuery实例造成棘手的黑客攻击。

  2. 定义chai可链接方法trimmed,允许使用似乎有效的.should('have.trimmed.text', 'sometext'),但是断言由chai方法text确定,这可能会造成混淆。不推荐。

have.textTrimmed

这是打字稿:

chai.Assertion.addMethod('textTrimmed', function (expectedString: string) {
  const $element = this._obj;

  new chai.Assertion($element).to.be.exist;

  const actual = $element.text().trim();
  const expected = expectedString.trim();
  this.assert(
    actual === expected
    , 'expected #{this} to have text #{exp} after trimmed, but the text was #{act} after trimmed'
    , 'expected #{this} not to have text #{exp} after trimmed'
    , expected
    , actual
  );
});

将代码放入cypress/support/index.js中,以确保在测试之前运行该代码。

您可能想在此处查看完整的演示:https://github.com/freewind-demos/typescript-cypress-add-custom-assertion-method-textTrimmed-demo/blob/master/cypress/support/textTrimmed.ts

have.trimmed.text

chai.use((chai, utils) => {

  chai.Assertion.addChainableMethod("trimmed", () => {
  }, function () {
    const obj = utils.flag(this, 'object')

    const oldText = obj.text.bind(obj);
    obj.text = () => {
      return oldText().trim()
    }
  });
})

正如我所说,由于棘手的hack和不清楚的断言消息,因此不建议这样做。

您还可以在此处查看完整的演示:https://github.com/freewind-demos/typescript-cypress-custom-operator-have-trimmed-text-demo/blob/master/cypress/support/index.ts

答案 1 :(得分:1)

当前,柏树开箱即用。功能请求为https://github.com/cypress-io/cypress/issues/630

但是您可以通过将自定义命令添加到support / commands.js并在测试脚本中使用这些命令来解决此问题。您将在commands.js中得到的最终结果是:

Cypress.Commands.add('haveText', function (text) {
  cy.get('.cell')
  .then($cell => $cell.text().trim())
  .should('eq', text)
})

在测试脚本中,您最终会得到:

cy.haveText('Hello')

除了可以在command.js中使用trim()之外,您还可以使用contains(),因为它会部分匹配,所以空格没有问题(请注意,“ apple pie”也符合要求)对于“苹果”,如果不是问题,则可以使用contains()。Commands.js如下所示:

Cypress.Commands.add('haveText', function (text) {
  cy.get('.cell')
  .should('contains', text)
})

但是可能更符合您要求的是结合使用contains()和正则表达式。您不需要在command.js中使用任何脚本,而只需在测试脚本中使用以下脚本即可:

cy.contains(/^\s*Hello\s*$/))

\s*可以匹配任何空白字符零次或多次。 ^将在文本开头开始匹配 $将在文本结尾处结束匹配。

可悲的是,should()中不能使用正则表达式