Skip to content
Advertisement

Get text from series of elements to an array using cypress JS

I’m trying to get comma separated text from series of <th> elements in a table row. I tried to use element.each() method for 3 nested loops from Cypress and it was super slow and was throwing error (cy.click() failed because this element is detached from the DOM.) sporadically in different test levels (Sometimes passed without any issue). I assume this might be due to large number of unnecessary loops to capture values with the above mentioned method.

Code

const verifyLeaderBoard = () => {
    let ClassName;
    let clickedElement;
    LeaderBoard.elementCollections('rows').each(($rowelements, indexrow, $list) => {
        cy.wrap($rowelements).invoke('attr', 'class').then((TeeTimeTableRowClass) => {
            ClassName = TeeTimeTableRowClass || 'Empty';
            cy.wait(10).then(() => {
                if ((ClassName.indexOf('accordion-toggle') !== -1)) {
                    cy.wait(5).then(() => {
                        LeaderBoard.inputFields('playerserach').focus().wait(100);
                    }).then(() => {
                        cy.wrap($rowelements).click({ force: true }).wait(1000);
                        clickedElement = $rowelements;
                    })
                } else if ((ClassName.indexOf('hidden-row-wrap') !== -1)) {
                    cy.wait(10).then(() => {
                        cy.wrap($rowelements).xpath('.//div[@class="table-responsive-xl"]//table[@class="table score-table"]//thead//tr')
                            .each(($HoleandParElement, index, $list) => {
                                cy.wrap($HoleandParElement).xpath('.//th')
                                    .each(($HoleandParElementtabledata, index, $list) => {
                                        cy.wrap($HoleandParElementtabledata).invoke('text')
                                            .then(texts => {
                                                console.log(texts)
                                            })
                                    })
                            })
                    }).then(() => {
                        cy.wrap(clickedElement).click({ force: true }).wait(100);
                    })
                }
            })
        })
    })
}

Error

enter image description here

Its working fine without the error if I just skip final element.each() as follows.

Code

const verifyLeaderBoard = () => {
    let ClassName;
    let clickedElement;
    LeaderBoard.elementCollections('rows').each(($rowelements, indexrow, $list) => {
        cy.wrap($rowelements).invoke('attr', 'class').then((TeeTimeTableRowClass) => {
            ClassName = TeeTimeTableRowClass || 'Empty';
            cy.wait(10).then(() => {
                if ((ClassName.indexOf('accordion-toggle') !== -1)) {
                    cy.wait(5).then(() => {
                        LeaderBoard.inputFields('playerserach').focus().wait(100);
                    }).then(() => {
                        cy.wrap($rowelements).click({ force: true }).wait(1000);
                        clickedElement = $rowelements;
                    })
                } else if ((ClassName.indexOf('hidden-row-wrap') !== -1)) {
                    cy.wait(10).then(() => {
                        cy.wrap($rowelements).xpath('.//div[@class="table-responsive-xl"]//table[@class="table score-table"]//thead//tr')
                            .each(($HoleandParElement, index, $list) => {
                                cy.wrap($HoleandParElement).invoke('text')
                                    .then(texts => {
                                        console.log(texts)
                                    })
                            })
                    }).then(() => {
                        cy.wrap(clickedElement).click({ force: true }).wait(100);
                    })
                }
            })
        })
    })
}

But in this case all the data in separate <th> tags are merged without a single space (Not possible to split by a string)

enter image description here

I’m searching for a solution to capture all the texts in <th> tags with a special character to divide each value.

HTML Structure

enter image description here

Advertisement

Answer

Used bellow line to collect all inner text to an array.

Cypress._.map(Cypress.$.makeArray($els), 'innerText')

Following code with the above solution was used to generate the array which contains all inner texts in <th> tags and this was must faster than using .each for the bulk of elements.

const verifyLeaderBoard = () => {
    let ClassName;
    let clickedElement;
    LeaderBoard.elementCollections('rows').each(($rowelements, indexrow, $list) => {
        cy.wrap($rowelements).invoke('attr', 'class').then((TeeTimeTableRowClass) => {
            ClassName = TeeTimeTableRowClass || 'Empty';
            cy.wait(10).then(() => {
                if ((ClassName.indexOf('accordion-toggle') !== -1)) {
                    cy.wait(5).then(() => {
                        LeaderBoard.inputFields('playerserach').focus().wait(100);
                    }).then(() => {
                        cy.wrap($rowelements).click({ force: true }).wait(1000);
                        clickedElement = $rowelements;
                    });
                } else if ((ClassName.indexOf('hidden-row-wrap') !== -1)) {
                    cy.wait(10).then(() => {
                        cy.wrap($rowelements).xpath('.//div[@class="table-responsive-xl"]//table[@class="table score-table"]//thead//tr')
                            .each(($HoleandParElement, index, $list) => {
                                cy.wrap($HoleandParElement).xpath('.//th').then(($els) => {
                                    // jQuery => Array => get "innerText" from each
                                    let elementsArray = Cypress._.map(Cypress.$.makeArray($els), 'innerText');
                                    console.log('elementsArray');
                                    console.log([...elementsArray.entries()]);
                                  });
                            });
                    }).then(() => {
                        cy.wrap(clickedElement).click({ force: true }).wait(100);
                    });
                };
            });
        });
    });
};
Advertisement