Cypress , test-vue-utils : how to use mock an api call with an action in vue

Viewed 115

I would like to test an action , my action contains an api call

my action in vuex

File containts actions in my store ( store 'ex.js' ) exActions.js

export const exActions = {
    getExFromApi({ commit, rootGetters }, { id }) {
        getApiExById({ access_token: rootGetters.auth.token, id }).then(res => {
            commit('SET_INIT_EX', res)
            commit('SET_CURRENT_EX', res)
        }).catch(error => {
            console.warn(error)
        })
    },

File containt call api exAPi.js

export const getApiExById= (params, group) => {
    // call return promise
}

My File test

// import api
const api = require('../../../src/api/exAPi')
let store = null

describe('Unit Test', function() {
    beforeEach(() => {
        const localVue = createLocalVue()
        localVue.use(Vuex)
        store = new Vuex.Store({
            modules: {
                exStore
            }
        })
    })
    context('test : action -> getExFromApi', function() {
        it('1',  async function() {
          let rootGetters = {
                auth: {
                    token: 'aaa'
                }
            }
            let commit = cy.spy()
            // mock call api , return a promise defined
            cy.stub(api, 'getApiExById').resolved('foo')
            
            // start the method 
            await store.dispatch('getExFromApi', ({commit, rootGetters}, {id: '1'}))

            // expect 'foo' value because cy.stub api return 'foo'
            expect(commit.args).to.deep.equal([
              ['SET_INIT_EX', 'foo'],
              ['SET_CURRENT_EX', 'foo']
            ])

           cy.stub.restore()

start file with node -> ./node_modules/.bin/cypress open-ct The problem, the 'getExFromApi' start but launch the real call api and not the mock.

I do anything wrong ? thanks you for help.

1 Answers

When you import api into the test, it's not the same instance as the app is using.

const api = require('../../../src/api/exAPi')   // creates a new instance

To get the same instance, in store ex.js

import * as api from '../api/exAPi'   // import module
const {getApiExById} = api       // method for use in exActions 

if (window.Cypress) {            // are we testing?
  window.api = api               // allow test to see module instance
}

In test

cy.window().then(win => {
  // mock call api , return a promise defined
  cy.stub(win.api, 'getApiExById').resolved('foo')   // mocking the same instance
}

I'm a bit wary of the cy.window().then(, maybe this is better

// mock call api , return a promise defined
const win = cy.state('window');
cy.stub(win.api, 'getApiExById').resolved('foo')   // mocking the same instance

Importing the module in ex.js

Because you're using a named export in exApi.js but the stub is failing, I presume there's no default export, i.e the module is not exported like this

...
export default {
  getApiExById
}

If so, change the default import in ex.js to

import * as api from '../api/exAPi'   // import module
...

Ref How to stub exported function in ES6?

Related