typescripttestingcypress

Repeated use of cy.wrap()


In the code below, why do I have to repeat cy.wrap(article) instead of wrapping it once and storing the wrapped result in a reusable variable as shown on line three?

verifyArticleContent(article: JQuery<HTMLElement>, expected_article: Topic) {
            // Wrapping once does not work.
            // const article2 = cy.wrap(article)

            // Title
            cy.wrap(article).find('h2 a')
                .should('have.text', expected_article.title)
                .and('have.attr', 'href', '/forum/discussion/' + expected_article.id)

            // Description
            cy.wrap(article).find('p.data-description').should('have.text', 
                expected_article.description.substring(0, 300) + ' ...')

            // Details
            cy.wrap(article).find('p.data-author-date').should('have.text',
                expected_article.user?.username + ', ' +                          // username
                Util.dateToString(expected_article.date, 'en'))                   // date
}

Further clarification and an example of how I thought it would work:

verifyArticleContent(article: JQuery<HTMLElement>, expected_article: Topic) {
            // Wrapping once does not work.
            const article2 = cy.wrap(article)

            // Title
            article2.find('h2 a')
                .should('have.text', expected_article.title)
                .and('have.attr', 'href', '/forum/discussion/' + expected_article.id)

            // STOPS WORKING HERE. If I comment out this description check, it fails on the details with the same (almost) error.
            // Description
            article2.find('p.data-description').should('have.text', 
                expected_article.description.substring(0, 300) + ' ...')

            // Details
            article2.find('p.data-author-date').should('have.text',
                expected_article.user?.username + ', ' +                          // username
                Util.dateToString(expected_article.date, 'en'))                   // date
}

picture of the error message


Solution

  • Cypress works on chained commands where the "subject" of the test is passed down through the chain.

    The strong advice given here Core concepts is not to use the assigned value of the chain, since this subject can be altered during the chain.

    You cannot assign or work with the return values of any Cypress command. Commands are enqueued and run asynchronously.

    To illustrate, here is a minimal example that does exactly what your code is doing.

    cy.visit('https://example.com');
    cy.get('body').then($body => {
    
      const body = cy.wrap($body)
    
      body.find('p a')
        .should('have.text', 'More information...')
        .and('have.attr', 'href', 'https://www.iana.org/domains/example')
        .then($subject => {
          console.log($subject[0])
        })
    
      body.find('h1')
        .should('have.text', 'Example Domain')
    })
    

    I'm creating your article: JQuery<HTMLElement> parameter by cy.get('body').then($body => and applying cy.wrap() to it the same as you have.

    After .and('have.attr', 'href', ... I added a console log to inspect the current subject.

    The console output is

    <a href="https://www.iana.org/domains/example">More information...</a>
    

    so the subject is no longer body, it is the <a> element.


    The Cypress fail message tells you exactly what's going on:

    Expected to find element: h1, but never found it. Queried from: <a>

    enter image description here