Conditional Summary
How do you test an UI element without controlling its precise state? For example, imagine the page loading a details element. Sometimes the details element is initially opened, sometimes it is closed.
📺 Watch this recipe explained in the video Conditional Details.
<div id="app"></div>
const app = document.getElementById('app')
// extra detail: the details element itself is delayed
setTimeout(() => {
if (Math.random() < 0.5) {
// the details are closed
app.innerHTML = `
<details>
<summary>Details</summary>
</details>
`
} else {
// the details are opened
app.innerHTML = `
<details open>
<summary>Details</summary>
<div data-cy="details">
Something small enough to escape casual notice.
</div>
</details>
`
}
// remove the details element
const details = document.querySelector('details')
details.addEventListener('toggle', () => {
if (details.open) {
details.innerHTML = `
<summary>Details</summary>
<div data-cy="details">
Something small enough to escape casual notice.
</div>
`
} else {
details.innerHTML = `
<summary>Details</summary>
`
}
})
}, 1000)
details {
border: 1px solid #aaaaaa;
border-radius: 4px;
padding: 0.5em 0.5em 0;
}
summary {
font-weight: bold;
margin: -0.5em -0.5em 0;
padding: 0.5em;
}
details[open] {
padding: 0.5em;
}
details[open] summary {
border-bottom: 1px solid #aaaaaa;
margin-bottom: 0.5em;
}
How do we confirm that the <details>
element shows the expected text when opened? The element itself should be present, and we can find out its state from its attribute open
.
cy.get('details')
.should('be.visible')
// we can determine the opened state by looking at its attribute
// if it present, its value will be "open"
.invoke('attr', 'open')
.then(Boolean)
.then((open) => {
// conditional testing depending on the element's initial state
if (open) {
cy.log('**Details are shown**')
cy.get('[data-cy="details"]').should('be.visible')
// click on the details element to close it
// and confirm the detail element is gone
cy.get('details').click()
cy.get('[data-cy="details"]').should('not.exist')
} else {
cy.log('**Details are hidden**')
cy.get('[data-cy="details"]').should('not.exist')
// click on the details element to see text
cy.get('details').click()
cy.get('[data-cy="details"]').should('be.visible')
}
})