How to use Cypress fixture data outside of a promise's then() block

Viewed 6697

I'm testing Cypress and I have this code for a custom Cypress command:

Cypress.Commands.add('login', (user, password) => {
  if (!user || !password) {
    user = 'user@test.com.br';
    password = '123321';
  }

  cy.visit('');
  cy.contains('Entrar').click();
  cy.get('input[name=_username]')
    .type(user);
  cy.get('input[name=_password]')
    .type(password);
  cy.get('.btn').click();
});

If you call cy.login() without any arguments, user and password are assigned within the if block. Otherwise, it uses the passed parameter values.

I tried to add fixtures here, and came up with this code:

Cypress.Commands.add('login', (user, password) => {

  if (!user || !password) {

    cy.fixture('users').then((json) => {
      var user, password;

      user = json[0].email;
      password = json[0].password;

      login2(user,password);
    });

  } else {

    login2(user, password);

  }

  function login2(user, password) {

    cy.visit('');
    cy.contains('Entrar').click();
    cy.get('input[name=_username]')
      .type(user);
    cy.get('input[name=_password]')
      .type(password);
    cy.get('.btn').click();

  }
});

When I set user = json[0].email, it has the value just inside the .then, so I created the function login to fix that.

I imagine there is a better way to do this. Any ideas?

1 Answers

Cypress documentation provides guidance for working with Return Values. Most notably, it advises the following:

Return Values

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

The documentation then goes on to explain the use of Closures, and nesting commands inside of the .then() block. Taking advantage of this approach in cypress/support/commands.js, you might simplify your code like this:

Cypress.Commands.add("login", (user, pw) => {
  let username;
  let password;

  cy.fixture('default-user') // <-- fixture in a separate file, default-user.js
    .then((defaultUser) => {
      username = user || defaultUser.username;
      password = pw || defaultUser.password;

      cy.get('input[name=_username]').type(username);
      cy.get('input[name=_password]').type(password);

      cy.get('.btn').click();
    });
});

For reference, default-user.js looks like this:

{
  username: 'user@test.com.br',
  password: '123321'
}

successful test run image

The Cypress documentation on Aliases and Sharing Context are helpful for understanding the nuances for referencing values in different Cypress contexts and use cases.

Related