title: How exactly do before and beforeEach work in Cypress?
body: <p>I think I am missing something about the way the before and beforeEach functions work in Cypress. I have a spec file that loads data from a fixture in the before method. Some of that data is used in the before function, and then again in the beforeEach function, as well as in the actual tests. The spec file contains 2 tests. The first test executes as expected. The second fails because the beforeEach says that one of the values from the fixture is undefined. </p>
  
  <p>My expectation is that if I load data from a fixture in the before method it should be available for all tests in the spec file. </p>
  
  <p>When executing the 'Check the state of the button bar' test the window.console.log(this.user_data) in the beforeEach function outputs the user_data as expected. </p>
  
  <p>When executing the 'Submit form' test the window.console.log(this.user_data) in the beforeEach function outputs undefined and the test stops. </p>
  
  <p>What am I missing here?</p>
  
  <pre><code>describe('Customer Profile', () =&gt; {
  
      before(function () {
          window.console.log('Enter the before function')
          // Load the fixture data. Its asynchronous so if we want to use it right here and now
          // we have to put the things that use inside a callback to be executed after the data
          // loaded. 
          cy.fixture('user').as('user_data').then(function (){
              window.console.log('Fixture has loaded the user data')
              cy.visit('/LaunchPad/login')
              // Fill out the login form
              cy.get('input[name="username"]').type(this.user_data.username)
              cy.get('input[name="password"]').type(this.user_data.password)
              cy.get('button[type="submit"]').click()
          })
      })
  
      beforeEach(function(){
          window.console.log('Enter the beforeEach function')
          window.console.log(this.user_data)
          // Preserve the cookies for all tests in this suite
          Cypress.Cookies.preserveOnce('SESSION')
          // Open the profile view
          cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
      })
  
      it('Check the state of the button bar', function(){
          window.console.log('Running test of button bar')
          cy.get('section.content-header &gt; h1').contains('Company Profile Details')
          // Check the state of the action bar and its buttons
          cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save')
              .should('have.attr', 'for', 'submit-form')
              .should('have.attr', 'tabindex', '0')
  
          cy.get('section.action-bar').get('#resetButton').contains('Reset')
              .should('have.attr', 'type', 'reset')
              .should('have.attr', 'value', 'Reset')
              .should('have.class', 'btn btn-sm btn-default')
  
          cy.get('section.action-bar').get('a.btn.btn-sm.btn-default').contains('Cancel')
              .should('have.attr', 'href', '/Manager/'+this.user_data.org+'/')
  
          cy.get('section.action-bar').get('a').contains('Delete').should('not.exist')
  
      })
  
      // This form has no required fields and no validation. So just pick a value or two
      // submit the form and verify the banner is correct
      it('Submit form', function(){
          window.console.log('Running the submit form test')
          cy.fixture('company_profile').as('company_profile')
          cy.get('#companyProfileDto.name').type(this.company_profile.name)
      })
  
  
  })
  </code></pre>
  
  <p><strong>UPDATE</strong>
  After doing some more reading based on what Carlos Alfredo responded with I came up this. 
  1. I still have to visit the login page. We use csrf and OATH and trying to get working example is just taking too much time. 
  2. I have to use whitelisting for the session cookie because preserveOnce does not work at all. </p>
  
  <p>Here are the files I have now. It visits the login page once and gets the session cookies setup. The two tests proceed as expected. </p>
  
  <p>support/index.js</p>
  
  <pre><code>before(function(){
      cy.login('bob', 'password')
      cy.fixture('user').as('user_data')
      cy.fixture('company_profile').as('company_profile')
  })
  
  beforeEach(function(){
      window.console.log('Enter the global beforeEach function')
      // Load the fixture data
  
  })
  </code></pre>
  
  <p>support/commands.js</p>
  
  <pre><code>/*
      We visit the login form despite what the best practise recommendation is because
      we have OAUTH redirects and a CSRF token to deal with. Since the majority of the
      examples and working use cases provided dont deal with those scenarios this is 
      the best I can do at the moment. 
  */
  Cypress.Commands.add('login', (username, password, options = {}) =&gt; {
      cy.visit('/LaunchPad/login')
      // Fill out the login form
      cy.get('input[name="username"]').type(username)
      cy.get('input[name="password"]').type(password)
      cy.get('button[type="submit"]').click()
  })
  /*
      We are white listing the cookie because Cypress.Cookies.preserveOnce('SESSION') 
      does not work. https://github.com/cypress-io/cypress/issues/2952
  
      Because we are forcing Cypress to not clear the cookies, you will have to close
      the test window after the suite is completed other wise the Vision360 apps will
      think your session is alive.
  */
  Cypress.Cookies.defaults({
      whitelist: 'SESSION'
  })
  </code></pre>
  
  <p>integration/customer_profile/customer_profile_spec.js</p>
  
  <pre><code>describe('Customer Profile', () =&gt; {
  
      it('Check the state of the button bar', function(){
          window.console.log('Running test of button bar')
  
          cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
  
          cy.get('section.content-header &gt; h1').contains('Company Profile Details')
          // Check the state of the action bar and its buttons
          cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save')
              .should('have.attr', 'for', 'submit-form')
              .should('have.attr', 'tabindex', '0')
  
          cy.get('section.action-bar').get('#resetButton').contains('Reset')
              .should('have.attr', 'type', 'reset')
              .should('have.attr', 'value', 'Reset')
              .should('have.class', 'btn btn-sm btn-default')
  
          cy.get('section.action-bar').get('a.btn.btn-sm.btn-default').contains('Cancel')
              .should('have.attr', 'href', '/Manager/'+this.user_data.org+'/')
  
          cy.get('section.action-bar').get('a').contains('Delete').should('not.exist')
  
      })
  
      // This form has no required fields and no validation. So just pick a value or two
      // submit the form and verify the banner is correct
      it('Submit form', function(){
          window.console.log('Running the submit form test')
          cy.visit('/Manager/'+this.user_data.org+'/config/company-profile')
  
          // Fill and submit the form
          cy.get('input#companyProfileDto\\.name').clear().type(this.company_profile.name)
          cy.get('section.action-bar').get('label.btn.btn-sm.btn-primary').contains('Save').click()
  
          // Check the response
          cy.get('.callout-success').contains('Your changes are saved.')
          cy.get('input#companyProfileDto\\.name').should('have.value', this.company_profile.name)
      })
  
  })
  </code></pre>