如何在Cypress中定义自定义断言操作符?

2022-08-06 00:00:00 javascript assertion cypress chai

在Cypress测试中,我经常需要检查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');

但我在官方网站上找不到任何关于它的文档。谁能分享一些例子?


解决方案

最终,我找到了做这件事的方法。虽然Cypress没有提供这样的功能,但是由于Cypress使用Chai,所以我们只能定义Chai方法。

注意:不可能定义have.text.trimmed,因为断言方法text是Chai方法。除了可链接的方法之外,无法在它之后提供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()
    }
  });
})

正如我所说,不建议这样做,因为黑客很棘手,断言消息不明确。

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

相关文章