KDavid
KDavid

Reputation: 21

cy.visit() does not recognize a URL being passed in as an argument

This is my first time using Cypress (and first SO post) and I keep running into an error. First, here is my code:

describe('Add new user to existing clinic team', () => {

    const serverId = 'e6ar8r9c';
      const testEmail = '[email protected]'
      let confirmationLink

      it('signs in as admin', () => {
    cy.visit('******')
    cy.get('#user_email').type('*******')
    cy.get('#user_password').type('******')
    cy.get('.button').click()
  
    // show teams roster
    cy.get('.hide-for-large > a > .fas').click()          
    cy.get('.vertical > :nth-child(1) > #programs-menu-btn > .fas').click()
    
    // click into the clinic team
    cy.get('table tbody > tr').contains('clinic team test apr 28#4').click()

    // click into the user roster for the clinic team
    cy.get('ul#program-team-tabs > li#team-icon-li').click()

    // enter user email to be added
    cy.get('#email').type(testEmail)
    cy.get('button.non-button').click()

    // get email
    cy.mailosaurGetMessage(serverId, {
      sentTo: testEmail
    }).then(email => {
      expect(email.subject).to.equal('Existing user invitation instructions');
      cy.log(email.subject)
      cy.log(email.html.links[0].href)
      confirmationLink = email.html.links[0].href
    })
  
    // follow email link
    cy.visit(confirmationLink)    
  })
})

When it logs the email link to the console, it logs the full URL of the link. However, it prints this error: "cy.visit() must be called with a url or an options object containing a url as its 1st argument" as if confirmationLink doesn't contain a URL, which, according to the console log, it does. Why is it not recognizing the URL?

Upvotes: 2

Views: 920

Answers (3)

Raju
Raju

Reputation: 2509

Because of how the commands are queued in cypress, cy.visit(confirmationLink) gets into the queue even before then block of cy.mailosaurGetMessage is executed and a value is assigned to confirmationLink. So, confirmationLink will be Undefined when it is actually used by your cy.visit() command.

This can be fixed by moving your cy.visit() into the then block. Your code will look as below.

describe('Add new user to existing clinic team', () => {
  const serverId = 'e6ar8r9c';
  const testEmail = '[email protected]';

  it('signs in as admin', () => {
    cy.visit('******');
    cy.get('#user_email').type('*******');
    cy.get('#user_password').type('******');
    cy.get('.button').click();

    // show teams roster
    cy.get('.hide-for-large > a > .fas').click();
    cy.get('.vertical > :nth-child(1) > #programs-menu-btn > .fas').click();

    // click into the clinic team
    cy.get('table tbody > tr').contains('clinic team test apr 28#4').click();

    // click into the user roster for the clinic team
    cy.get('ul#program-team-tabs > li#team-icon-li').click();

    // enter user email to be added
    cy.get('#email').type(testEmail);
    cy.get('button.non-button').click();

    // get email
    cy.mailosaurGetMessage(serverId, {
      sentTo: testEmail,
    }).then((email) => {
      expect(email.subject).to.equal('Existing user invitation instructions');
      cy.visit(email.html.links[0].href);
    });
  });
});

Upvotes: 1

Lisa La
Lisa La

Reputation: 55

Cypress provides alias's to capture values from higher up the test.

For example,

cy.mailosaurGetMessage(serverId, {
  sentTo: testEmail
})
.then(email => {
  expect(email.subject).to.equal('Existing user invitation instructions');
  cy.log(email.subject)
  cy.log(email.html.links[0].href)
  return email.html.links[0].href
})
.as('confirmationLink')

cy.get('@confirmationLink')
  .then((confirmationLink ) => {
    cy.visit(confirmationLink)    
  })

Upvotes: 1

Fody
Fody

Reputation: 32044

Short answer, wrap the visit in a .then():

// get email
cy.mailosaurGetMessage(serverId, {
  sentTo: testEmail
}).then(email => {
  expect(email.subject).to.equal('Existing user invitation instructions');
  cy.log(email.subject)
  cy.log(email.html.links[0].href)
  confirmationLink = email.html.links[0].href
}).then(() => {
  // follow email link
  cy.visit(confirmationLink)    
})

Reason is, Cypress scans the test for commands, adds them to the command queue then runs the queue.

So the value of confirmationLink used when cy.vist(confirmationLink) is added to the queue is the value at the beginning of the test.

Using a .then() around any command defers adding to the queue until all preceding commands have run.

A better pattern is to pass the confirmationLink down the chain

 // get email
cy.mailosaurGetMessage(serverId, {
  sentTo: testEmail
}).then(email => {
  expect(email.subject).to.equal('Existing user invitation instructions');
  cy.log(email.subject)
  cy.log(email.html.links[0].href)
  confirmationLink = email.html.links[0].href

  return confirmationLink;  // pass to next command

}).then((confirmationLink ) => {
  // follow email link
  cy.visit(confirmationLink)    
})

Upvotes: 1

Related Questions