skip to Main Content

I try to get text of <span> in below HTML:

<td data-v-c0a5153a="" style="min-width: 300px; width: 300px;">
<span><!---->
    <span class="v-tooltip v-tooltip--bottom"></span>
    <span aria-haspopup="true" aria-expanded="false">
        <a class="downloaded--text">Apple</a>
        <!---->
    </span>
</span>
<span>
    <span>,</span>
    <span class="v-tooltip v-tooltip--bottom">
        <!---->
    </span>
    <span aria-haspopup="true" aria-expanded="false">
        <a class="downloaded--text">Water mellon</a>
        <!---->
    </span>
</span>
<!---->

Here is my code:

cy.get('#freeg-list-table-report')
            .find('tbody tr').eq(0).find('td').eq(5)
            .find('span').invoke('text')
            .then(text => {  
                cy.log(text)
            })

Log display:

Apple Apple

Water mellon Water mellon

Why is it duplicated? What should I do to get:

Apple

Water mellon

—- Update —-

I got an array from

listA = ["Apple", "Water mellon"]

Here my code:

    const listA = []
    cy.get('#freeg-list-table-report')
        .find('tbody tr').eq(0).find('td').eq(5)
        .find('span')
        .find('a')
        .each(a => {
            const text = a.text()
            listA.push(text)
            cy.log(text);
        })
    cy.log(listA)
    cy.log(listA[0])

But the issue occurs when I try cy.log(listA[0]) => result: null

2

Answers


  1. This Cypress code logs the text of the tags in the format you requested:

    cy.get('span a.downloaded--text').each(($el) => {
      const text = $el.text().trim()
      cy.log(text)
    })
    

    cy.get() selects all the elements with the class downloaded--text inside <span> tags. Then the .each() method iterates over each element, and .text() get the text content.

    Inside the .each() function, we format the text by trimming any extra whitespace, and then log it using the cy.log() command. This will output the text to the Cypress test runner console in the format you requested.

    Also, I used the .each() method instead of .invoke('text') so I could log the text separately for each element, rather than combining them in a single string.

    Login or Signup to reply.
  2. It happens because you have two layered <span> and each one contributes the innerText it sees.

    By way of debugging, if you run this

    cy.get('span')
      .then($els => {
        const debug = [...$els].map((el, index) => {
          return `${el.tagName} #${index}: ${el.innerText}`
        })
        console.log(debug)
      })
    

    you see the result is

    [
      'SPAN #0: Apple ', 
      'SPAN #1: ', 
      'SPAN #2: Apple ', 
      'SPAN #3: , Water mellon', 
      'SPAN #4: ,', 
      'SPAN #5: ', 
      'SPAN #6: Water mellon'
    ]
    

    That’s because invoke('text') returns the text from the current element and all descendent elements.

    So the SPAN #0 gives you Apple even though it’s not directly having that text, because it’s child <span> has it.


    If you change the element to <a> you get the correct result

    cy.get('#freeg-list-table-report')
      .find('tbody tr').eq(0).find('td').eq(5)
      .find('a').invoke('text')
      .then(text => {  
         cy.log(text)           // log: Apple Water mellon
      })
    

    If you must use .find('span') for some reason, the .invoke('text') needs to be changed

    cy.get('#freeg-list-table-report')
      .find('tbody tr').eq(0).find('td').eq(5)
      .find('span')
      .then($els => $els.clone().children().remove().end().text() ) // self explanatory 
      .then(text => {  
         cy.log(text)           // log: Apple Water mellon
      })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search