In Cypress test, I often need to check if the text in an DOM element is equal some expected test. But since there might be some whitespaces around the text, I can't simply write:
cy.get('.cell')
.should('have.text', 'Hello')
Instead, I have to write:
cy.get('.cell')
.then($cell => $cell.text().trim())
.should('eq', 'Hello')
I want to define a custom assertion operator like have.text.trimmed
, allow me to use it like this:
cy.get('.cell')
.should('have.text.trimmed', 'Hello');
But I can't find any document in official site about it. Would someone share some example?
Finally, I find the way to do it. Although Cypress doesn't provide such a feature, but since Cypress uses Chai, we can just define Chai methods.
Note: it's not possible to define have.text.trimmed
, since assertion method text
is a Chai method. rather than a chainable method, there is no way to provide a trimmed
after it.
But there are still two options:
Define a Chai method textTrimmed
. It allows us using .should('have.textTrimmed', 'sometext')
, which is preferred since we can define a custom assertion message and no tricky hacking on jQuery instances.
Define a Chai chainable method trimmed
. It allows using .should('have.trimmed.text', 'sometext')
, which seems to work, but the assertion is determined by the Chai method text
, which may be confusion. It is not recommended.
have.textTrimmed
This is in 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
);
});
Put the code in cypress/support/index.js
file to make sure running it before tests.
You may want to see the complete demo here: 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()
}
});
})
As I said, it's not recommended because of the tricky hack and unclear assertion message.
You can also see the complete demo here: https://github.com/freewind-demos/typescript-cypress-custom-operator-have-trimmed-text-demo/blob/master/cypress/support/index.ts
Currently it is not possible out of the box for Cypress. The feature request is Provide a "Cypress" way to access textContent (and/or innerText) - .text() command (#630).
But you can work around it by adding custom commands to support/commands.js and use those commands in your testscript. You will end up with this in commands.js:
Cypress.Commands.add('haveText', function (text) {
cy.get('.cell')
.then($cell => $cell.text().trim())
.should('eq', text)
})
In the test script you will end up with:
cy.haveText('Hello')
Instead of using the trim()
in command.js you could also use contains()
, this does a partial match so whitespaces are no problem (note that 'apple pie' also meets the requirements if you look for 'apple', if that is not a problem you can use contains()
. Commands.js would look like this:
Cypress.Commands.add('haveText', function (text) {
cy.get('.cell')
.should('contains', text)
})
But what probably meets your requirements even more is using contains()
in combination with a regular expression. You don't need any scripts in commands.js, but just in the test script you can use this:
cy.contains(/^\s*Hello\s*$/))
The \s*
is to match any whitespace character zero or more times.
The ^
is to start matching at the beginning of the text
The $
is to end matching at the end of the text.
The regular expression can't be used within a should()
, sadly enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With