如何在赛普拉斯中定义自定义断言运算符?
How can I define a custom assertion operator in Cypress?
在 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 开箱即用。功能请求是 Provide a "Cypress" way to access textContent (and/or innerText) - .text() command (#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' 也满足如果您寻找 'apple' 的要求,如果这不是问题,您可以使用 contains()
。Commands.js 看起来像这样:
Cypress.Commands.add('haveText', function (text) {
cy.get('.cell')
.should('contains', text)
})
但可能更符合您要求的是将 contains()
与正则表达式结合使用。您不需要 commands.js 中的任何脚本,但只需在测试脚本中就可以使用:
cy.contains(/^\s*Hello\s*$/))
\s*
是匹配任意空白字符零次或多次。
^
是从文本开头开始匹配
$
是在文末结束匹配。
正则表达式不能在 should()
中使用,很遗憾。
终于找到方法了。虽然 Cypress 没有提供这样的功能,但是由于 Cypress 使用 Chai,我们可以直接定义 Chai 方法。
注意:无法定义 have.text.trimmed
,因为断言方法 text
是一个 Chai 方法。而不是可链接的方法,无法在其后提供 trimmed
。
但是还有两个选择:
定义一个 Chai 方法 textTrimmed
。它允许我们使用 .should('have.textTrimmed', 'sometext')
,这是首选,因为我们可以定义自定义断言消息并且无需对 jQuery 实例进行棘手的黑客攻击。
定义一个 Chai 可链接方法 trimmed
。它允许使用 .should('have.trimmed.text', 'sometext')
,这似乎可行,但断言是由 Chai 方法 text
确定的,这可能会造成混淆。不推荐。
have.textTrimmed
这是在 TypeScript 中:
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
文件中,以确保 运行 在测试之前。
文件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
在 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 开箱即用。功能请求是 Provide a "Cypress" way to access textContent (and/or innerText) - .text() command (#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' 也满足如果您寻找 'apple' 的要求,如果这不是问题,您可以使用 contains()
。Commands.js 看起来像这样:
Cypress.Commands.add('haveText', function (text) {
cy.get('.cell')
.should('contains', text)
})
但可能更符合您要求的是将 contains()
与正则表达式结合使用。您不需要 commands.js 中的任何脚本,但只需在测试脚本中就可以使用:
cy.contains(/^\s*Hello\s*$/))
\s*
是匹配任意空白字符零次或多次。
^
是从文本开头开始匹配
$
是在文末结束匹配。
正则表达式不能在 should()
中使用,很遗憾。
终于找到方法了。虽然 Cypress 没有提供这样的功能,但是由于 Cypress 使用 Chai,我们可以直接定义 Chai 方法。
注意:无法定义 have.text.trimmed
,因为断言方法 text
是一个 Chai 方法。而不是可链接的方法,无法在其后提供 trimmed
。
但是还有两个选择:
定义一个 Chai 方法
textTrimmed
。它允许我们使用.should('have.textTrimmed', 'sometext')
,这是首选,因为我们可以定义自定义断言消息并且无需对 jQuery 实例进行棘手的黑客攻击。定义一个 Chai 可链接方法
trimmed
。它允许使用.should('have.trimmed.text', 'sometext')
,这似乎可行,但断言是由 Chai 方法text
确定的,这可能会造成混淆。不推荐。
have.textTrimmed
这是在 TypeScript 中:
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
文件中,以确保 运行 在测试之前。
文件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