2

I have a namespaced Vuex store in my Vue 2.6 app one module of which is like this:

 //books.js

 export default {
  state: {
    books: null
  },
  mutations: {
    SET_BOOKS(state, books) {
      state.books = books;
    },
  },
  actions: {
    setBooks: async function ({ commit }) {
      //api call
      commit('SET_BOOKS', books);
    }
  },
  namespaced: true
};

I want to test a component that calls the setBooks action. I am using mapActions to access the actions. The relevant code is:

 //Books.vue

 methods: {
    ...mapActions("books", ["setBooks"]),
    }
  },
  created: async function() {
    await this.setBooks();
  }

The problem is that my test can't find the action:

import { shallowMount } from '@vue/test-utils';
import Books from '@/views/Books';
import Vuex from 'vuex';
import flushPromises from 'flush-promises';
import { createLocalVue } from '@vue/test-utils'

const localVue = createLocalVue();
localVue.use(Vuex);

describe('Books', () => {

  let actions;
  let store;
  let wrapper;
  beforeEach(() => {
    store = new Vuex.Store({
      state: {
        books: {
          books: null
        }
      },
      actions: {
        setBooks: jest.fn()
      }
    });
    wrapper = shallowMount(Books, { store, localVue })
  });

  it("renders the books", async () => {
    await flushPromises();
    expect(actions.setBooks).toHaveBeenCalled();
  });
});

I get an error [vuex] module namespace not found in mapActions(): books/

if I try to namespace the actions code in the my test to:

actions: {
    books: {
        setBooks: jest.fn()
    }
}

I get TypeError: Cannot read property 'setBooks' of undefined

Please help, thank you!

r_zelazny
  • 517
  • 3
  • 19

1 Answers1

1

The docs for vue-test-utils include an example of testing with modules.

Change your beforeEach:

beforeEach(() => {
  actions = { setBooks: jest.fn() }
  store = new Vuex.Store({
    modules: {
      books: {
        state: { books: null },
        actions
      }
    }
  })
...
})

Your test calls actions.setBooks, but in your original code actions was simply declared, but not used in the creation of your store.

  • thanks, I was importing that from another file but I changed the post to make it more clear. – r_zelazny Jun 15 '20 at 19:23
  • Updated my answer. Create the actions object before your create the mock store. Your original code declared an actions object with the let keyword, but it remains undefined. – hey_its_jimmy Jun 15 '20 at 19:38
  • I still get the `[vuex] module namespace not found in mapActions(): setting/` which makes sense since nowhere does the actions object specifiy the namespace....thanks for your help though....one related question is in the test if I do `expect(actions.books.setBooks).toHaveBeenCalled();` -- namespace the actions object, but this gives a different error ` [vuex] actions should be function or object with "handler" function but "actions.setting" is {}.` – r_zelazny Jun 15 '20 at 19:57
  • Updated my answer. Wrap with modules: {...} when creating the vuex store – hey_its_jimmy Jun 15 '20 at 20:13
  • that makes perfect sense...(hopefully) final question: how do I reference the function in my test? when I do `expect(books.actions.setBooks).toHaveBeenCalled()` I get `books is not defined`; when I try `expect(actions.setBooks).toHaveBeenCalled()` I get ` [vuex] module namespace not found in mapActions(): books/` – r_zelazny Jun 15 '20 at 20:31
  • 1
    I figured it out: just needed to add `namespaced: true` to `books` module. thanks for your help! – r_zelazny Jun 15 '20 at 20:53