最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Cypress Best Practice - Store and compare two values - Stack Overflow

programmeradmin0浏览0评论

I want to store a value, then perform an action and assert that the value has not changed. I do have a code that works but I would like to have input if there is a more elegant solution.

The basic idea is:

  • Get the number or results displayed ('counts'), store it in a .then() function
  • Change the use
  • Get the number of results displayed ('new_counts'), store it in a new .then function
  • Compare counts and new_counts in the 2nd .then() function
describe('Store and compare a value', () => {
    it('store and compare', () => {

        cy.login()
        cy.visit('url2')
        cy.get('.total-count-results').invoke('text')
            .then((text) => {
                const counts = text 
                cy.get('.medium.col100 > .filterwrapper > input').type('Test Dummy',{force: true})
                cy.get('.medium.col100 > .filterwrapper > input').type('{enter}')
                cy.get('.total-count-results').invoke('text')
                    .then((text) => {
                        const new_counts = text
                        expect(new_counts).to.eq(counts)
                    })
            })
    })
})

That is the best I could come up with to handle asynchronicity.

I want to store a value, then perform an action and assert that the value has not changed. I do have a code that works but I would like to have input if there is a more elegant solution.

The basic idea is:

  • Get the number or results displayed ('counts'), store it in a .then() function
  • Change the use
  • Get the number of results displayed ('new_counts'), store it in a new .then function
  • Compare counts and new_counts in the 2nd .then() function
describe('Store and compare a value', () => {
    it('store and compare', () => {

        cy.login()
        cy.visit('url2')
        cy.get('.total-count-results').invoke('text')
            .then((text) => {
                const counts = text 
                cy.get('.medium.col100 > .filterwrapper > input').type('Test Dummy',{force: true})
                cy.get('.medium.col100 > .filterwrapper > input').type('{enter}')
                cy.get('.total-count-results').invoke('text')
                    .then((text) => {
                        const new_counts = text
                        expect(new_counts).to.eq(counts)
                    })
            })
    })
})

That is the best I could come up with to handle asynchronicity.

Share Improve this question edited Sep 28, 2021 at 9:41 jonrsharpe 122k30 gold badges266 silver badges473 bronze badges asked Sep 28, 2021 at 9:33 cypher_nullcypher_null 6721 gold badge14 silver badges24 bronze badges 2
  • 1 You could simplify by actually naming the arrow function parameters what you want the variables to be called, and asserting directly rather than nesting another then, but otherwise this is what docs.cypress.io/guides/core-concepts/variables-and-aliases suggests. – jonrsharpe Commented Sep 28, 2021 at 9:42
  • Thanks. I will take a look at that part of the documentation again. Also, thanks for editing my post to match SO standards better! – cypher_null Commented Sep 28, 2021 at 10:52
Add a comment  | 

3 Answers 3

Reset to default 8

I don't think aliases are required. Here is my solution that I tested locally. I kept most of the code in Alapan Das' answer so it's easier to compare. To me, it seems more concise and easier to read without aliases.

describe('Store and compare a value', () => {
    it('store and compare', () => {  
        cy.login()
        cy.visit('url2')
        cy.get('.total-count-results').invoke('text')
            .then((previousText) => {
                cy.get('.medium.col100 > .filterwrapper > input').type('Test Dummy',{force: true})
                cy.get('.medium.col100 > .filterwrapper > input').type('{enter}')
                cy.get('.total-count-results').invoke('text').should("eq", previousText)
            })
    })
})

You can use aliases for this and do something like this:

describe('Store and compare a value', () => {
  it('store and compare', () => {
    cy.login()
    cy.visit('url2')
    cy.get('.total-count-results').invoke('text').as('counts')
    cy.get('.medium.col100 > .filterwrapper > input').type('Test Dummy', {
      force: true,
    })
    cy.get('.medium.col100 > .filterwrapper > input').type('{enter}')
    cy.get('.total-count-results').invoke('text').as('new_counts')
    cy.get('@counts').then((counts) => {
      cy.get('@new_counts').then((new_counts) => {
        expect(new_counts).to.eq(counts)
      })
    })
  })
})

A good solution for comparing values like this can be to use a closure variable, as per the example in Cypress' documentation at https://docs.cypress.io/api/commands/should#Compare-text-values-of-two-elements. In your example, something like this:

describe('Store and compare a value', () => {
    it('store and compare', () => {

        let counts // closure variable
        cy.login()
        cy.visit('url2')
        cy.get('.total-count-results').invoke('text')
            .then(text => counts = text)     // set closure variable

        cy.get('.medium.col100 > .filterwrapper > input').type('Test Dummy',{force: true})
        cy.get('.medium.col100 > .filterwrapper > input').type('{enter}')

        cy.get('.total-count-results').invoke('text')
            .then(new_counts => expect(new_counts).to.eq(counts))   // compare closure variable
            //.should("eq",counts)  // won't work: counts still undefined when run
    })
})

This is reasonably concise, and avoids having nested '.then' clauses, which can become like callback hell as complexity grows.

(See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures for background on closures: in short, "a closure gives you access to an outer function's scope from an inner function". The inner functions here are the two .then functions: they access the counts variable from the outer it function's scope.)

发布评论

评论列表(0)

  1. 暂无评论