Non-breaking space
Dealing with
character aka Non-breaking space.
Via cy.contains
When using cy.contains command Cypress automatically converts the
entity into space character. Thus cy.contains
finds element that include
.
<div data-testid="testattr">
<div><span>GBP 0.50</span></div>
</div>
// both commands work
cy.contains('[data-testid=testattr]', 'GBP 0.50').should(
'be.visible',
)
cy.get('[data-testid=testattr]')
.filter(':contains("GBP 0.50")')
.should('have.length', 1)
Asserting text
But if the HTML contains the whitespace special character
then checking elements by text is tricky. See #9530 for example. This is because .filter uses jQuery :contains selector which uses literal text match.
<div data-testid="testattr">
<div><span>GBP 0.50</span></div>
</div>
cy.contains('[data-testid=testattr]', 'GBP 0.50').should(
'be.visible',
)
<div data-testid="testattr">
<div><span>GBP 0.50</span></div>
</div>
// we can filter by text before the
cy.get('[data-testid=testattr]')
.filter(':contains("GBP")')
.should('have.length', 1)
cy.get('[data-testid=testattr]')
// the following filter DOES NOT WORK
// .filter(':contains("GBP 0.50")')
// the following filter DOES NOT WORK
// .filter(':contains("GBP 0.50")')
// but the Unicode representation of non-breaking space character works
.filter(':contains("GBP\u00a00.50")')
.should('have.length', 1)
<div data-testid="testattr">
<div><span>GBP 0.50</span></div>
</div>
cy.get('[data-testid=testattr]')
.find('span')
.should('have.text', 'GBP\u00a00.50')
Be careful with newlines and white space
<div id="network-message">
Warning: this message has multiple spaces
and empty lines
</div>
const message = `
Warning: this message has multiple spaces
and empty lines
`
// 🚨 INCORRECT, this will fail, demo only
// the newlines and empty lanes break the comparison
cy.contains('#network-message', message)
// ✅ use "should(callback)" function to get the full text
// and compare it ourselves without whitespace removal
// as it is done by the cy.contains command
cy.get('#network-message').should($el => {
const text = $el.text()
expect(text, 'the original text').to.equal(message)
})
Even better is to use the included Chai-jQuery assertion have.text
// equivalent and and shorter Chai-jQuery assertion
cy.get('#network-message').should('have.text', message)
// if you know only part of the expected text
cy.get('#network-message').should('include.text', message)
Watch the video A Quick Should Have Text Example With Multiline Text.
cy.filter
Filtering using Just checking how .filter(:contains)
works
<ul>
<li>Home</li>
<li>Services</li>
<li>Advanced Services</li>
<li>Pricing</li>
<li>Contact</li>
</ul>
cy.get('li')
.filter(':contains("Services")')
.should('have.length', 2)