Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement login command and access vuex store

I have a login process where after sending a request to the server and getting a response, I do this:

 this.$auth.setToken(response.data.token);
 this.$store.dispatch("setLoggedUser", {
     username: this.form.username
 });

Now I'd like to emulate this behavior when testing with cypress, so i don't need to actually login each time I run a test.

So I've created a command:

Cypress.Commands.add("login", () => {
  cy
    .request({
      method: "POST",
      url: "http://localhost:8081/api/v1/login",
      body: {},
      headers: {
        Authorization: "Basic " + btoa("administrator:12345678")
      }
    })
    .then(resp => {
      window.localStorage.setItem("aq-username", "administrator");
    });

});

But I don't know how to emulate the "setLoggedUser" actions, any idea?

like image 978
Tomer Avatar asked Jul 01 '18 10:07

Tomer


2 Answers

In your app code where you create the vuex store, you can conditionally expose it to Cypress:

const store = new Vuex.Store({...})

// Cypress automatically sets window.Cypress by default
if (window.Cypress) {
  window.__store__ = store
}

then in your Cypress test code:

cy.visit()
// wait for the store to initialize
cy.window().should('have.property', '__store__')

cy.window().then( win => {
  win.__store__.dispatch('myaction')
})

You can add that as another custom command, but ensure you have visited your app first since that vuex store won't exist otherwise.

like image 55
bkucera Avatar answered Nov 02 '22 17:11

bkucera


  • Step 1: Inside main.js provide the store to Cypress:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

if (window.Cypress) {
  // Add `store` to the window object only when testing with Cypress
  window.store = store
}
  • Step 2: Inside cypress/support/commands.js add a new command:
Cypress.Commands.add('login', function() {
  cy.visit('/login') // Load the app in order `cy.window` to work
  cy.window().then(window => { // .then() to make cypress wait until window is available
    cy.wrap(window.store).as('store') // alias the store (can be accessed like this.store)
    cy.request({
      method: 'POST',
      url: 'https://my-app/api/auth/login',
      body: {
        email: '[email protected]',
        password: 'passowrd'
      }
    }).then(res => {
      // You can access store here
      console.log(this.store)
    })
  })
})
  • Step 4: Inside cypress/integration create a new test
describe('Test', () => {
  beforeEach(function() {
    cy.login() // we run our custom command
  })

  it('passes', function() { // pass function to keep 'this' context
    cy.visit('/')
    // we have access to this.store in our test
    cy.wrap(this.store.state.user).should('be.an', 'object')
  })
})
like image 41
Roland Avatar answered Nov 02 '22 18:11

Roland