I'm trying to iterate over a list (<UL>) to see whether or not a specific string exists within the <li> list item elements. If the string (Lemon in this example) does not exist then I want to perform an action to add the element. Otherwise, if the string does exist then I just want to do nothing and continue on.
Sample html:
<ul id=theTree>
<li>Apple</li>
<li>Pear</li>
<li>Orange</li>
</ul>
I have tried:
let found = false
cy.get('#theTree').find('li').each( ($node, i, $list) => {
if ($node.textContent.includes("Lemon")) {
found = true
}
})
// At this point after each <li> has been iterated over, will 'found' be true or false?
if (!found) {
// Add "Lemon" to the list here if it was not found in the <ul> list...
} else {
// Do nothing. Lemon already exists in the list.
}
The if condition "$node.textContent" is returning undefined and not returning the text content from the list elements. Therefore, the .includes() function throws an error.
Also, I have feeling the asynchronous callback function from .each() needs a Promise or some other means of saving the "found = true" state, such that, the second if block can correctly determine whether or not "Lemon" was found in the list iteration.
Any help is very much appreciated.
CodePudding user response:
You have to check the result after the each
command will be executed.
For instance, you can use then
command as follows:
let found = false
cy.get('#theTree').find('li').each( ($node, i, $list) => {
if ($node.textContent.includes("Lemon")) {
found = true
}
}).then(() => {
// this callback will be executed after 'each' command so we know the result at this point.
if (!found) {
// Add "Lemon" to the list here if it was not found in the <ul> list...
} else {
// Do nothing. Lemon already exists in the list.
}
})
CodePudding user response:
Perhaps iterating with .each()
is not the easiest way to do this.
Using .then()
allows you to pass the found
value down the chain. You could also add an alias if you want to use it later in the test.
Setting a variable external to the command chain is called a "backflip" and can cause problems depending on the test structure.
cy.get('#theTree').find('li')
.then($els => {
const texts = [...$els].map(el => el.innerText) // extract texts
const found = texts.includes('Lemon')
return found
})
.then(found => {
if (!found) {
...
})
With an alias
cy.get('#theTree').find('li')
.then($els => {
const texts = [...$els].map(el => el.innerText) // extract texts
const found = texts.includes('Lemon')
return found
})
.as('found')
// later
cy.get('@found').then(found => {
if (!found) {
...
})