In the Cypress documentation for Variables and Aliases it uses the dollar sign before the variables in the then-clauses. Like this:
cy.get('button').then(($btn) => { // $btn is the object that the previous // command yielded us }) But I can't figure out why.
There are many other posts simply saying a bunch of stuff about "that it's just another character" so nothing special. And also a bunch of mentions of jQuery, obviously.
I just had an example of a complex Cypress-command, that didn't work, because I didn't have the dollar sign. Here is my code:
The Command
Cypress.Commands.add( "verifyUsersAccessToArticle", ( articleFixture, userType ) => { cy.fixture( articleFixture, "utf8" ).as( 'article' ); // Intercept async-loaded content XHR cy.get( "@article" ).then( ($article) => { cy.intercept({ method: 'GET', url: '/wp-json/sn/public/v1/article/' + $article.postId, }).as('postContentFull'); }); // Log in cy.visit( Cypress.env( 'baseUrl' ) ); if( userType !== 'noUser' ){ cy.loginUser( userType ); } // Go to article cy.get( "@article" ).then( ($article) => { cy.visit( Cypress.env( 'baseUrl' ) + $article.url ); }); // Let content load cy.wait( 1000 ); if( userType !== 'noUser' ){ cy.userIsLoggedIn(); } cy.get( "@article" ).then( ($article) => { // Have access if( $article[ userType ].hasAccess ){ cy.get( '@postContentFull' ).then( ( $postContentFull ) => { expect( $postContentFull.response.statusCode ).to.equal( 200 ); cy.get( '#main .post-content' ).children().its( 'length' ).should( 'be.gte', 4 ); // 4 <p>'s cy.get('.react-pay-product-paywall').should( 'not.exist' ); }); } // Doesn't have access if( ! $article[ userType ].hasAccess ){ cy.get( '@postContentFull' ).then( ( $postContentFull ) => { expect( $postContentFull.response.statusCode ).to.equal( 402 ); cy.get( '#main .post-content' ).children().its( 'length' ).should( 'be.lte', 4 ); // 4 <p>'s cy.get('.react-pay-title').contains( $article[ userType ].paywallTitle ); cy.get('.react-pay-card-price > span').contains( $article[ userType ].paywallPrice ); }); } }); }); The Test
it( 'Verify users access to article', () => { let articles = [ 'foo-article', 'bar-article' ]; articles.forEach( (article) => { cy.verifyUsersAccessToArticle( Cypress.env( 'name' ) + '/' + article, 'subscriptionTypeZero' ); }); }); If I wrote postContentFull instead of $postContentFull, then I'm getting an error on the second run (when it runs the iteration for the bar-article):
- then function(){} TypeError Cannot read properties of undefined (reading 'statusCode') Overarching question
What does that dollar sign do?
And am I blind - or why can I not find it in the Cypress documentation?
Update 1: I might have misunderstood something
I think I have a flakey test - and have incorrectly assumed that the dollar sign was the solution. But I'm pretty sure that it's simply because the @article (that is intercepted) hasn't resolved, when the cy.get( "@article" ).then( ($article) => { is executed.
And when I added the dollar sign, the server simply returned faster.
I still would like to figure out, what the dollar sign does. :-)
21 Answer
Ditto comments above, but further info -
You should wait on the intercept, not get it.
cy.get('@postContentFull') will only work if the intercept has already intercepted.
Also, since you construct a new intercept for each article make the alias unique (otherwise you can't be sure which intercept you get).
cy.fixture( articleFixture, "utf8" ) .then(article => { // convention: no $ here, since it's not jQuery const alias = 'postContentFull' + article.postId cy.intercept('/wp-json/sn/public/v1/article/' + article.postId) .as(alias) cy.visit('/'); // visit baseUrl if(userType !== 'noUser') { cy.loginUser(userType); } cy.visit(article.url); // Cypress prepends baseUrl cy.wait('@' + alias).then(() => { if(article[userType].hasAccess) { ... } else { ... } }) }) 