2
votes

Thanks for taking a look.

I'm trying to run automated tests on my Vuex-backed application and am having trouble diagnosing why committing a mutation in a Mocha testfile results in a warning from Vuex saying that I'm directly modifying the state, even though it's modified within a mutation. I use Vuex to keep track of the global state and render certain elements based on the global state (e.g. show buttonA if state.status === 'INITIAL', show buttonB if state.status === 'LOADING').

For example, I have a central store with: state = { status: 'INITIAL' };

Then I have a corresponding mutation:

'LOADING': (state) => {
    state.status = 'LOADING';
},

Then if I commit changes normally through a component or through a store action it works fine: this.$store.commit('INITIAL');

However, if I try to establish the same Vuex store and commit the same changes in a Mocha test file, it gives the error:

'[Vue warn]: Error in callback for watcher "function () { return this._data.$$state; }": "Error: [vuex] Do not mutate vuex store state outside mutation handlers."

The mutation occurs correctly and the tests pass smoothly, but it gives me this warning at the point when the mutation sets: state.status = 'LOADING';

I have tried moving sending the commit request to within an action, but that did not resolve the issue. I've tried changing where the store/Vue are declared, but that did not resolve the issue. I've tried setting strict: false for the store, but that didn't resolve the issue nor even hide it.

I don't feel like I'm doing something that abnormal in wanting to test commits as such, but I may be totally off-base. Please let me know if I need to provide more information, the error dump, or an example repo.

Thanks! Keith

1

1 Answers

1
votes

I found that somewhere else in my code, I was creating a global Vuex store. I was later instantiating another store in my test code. The test code works, but the "official" instantiation of the Vuex store is noticing that objects are changing outside of its control (because a second Vuex store is modifying it).

For more context, I have a module, counter.js:

const store = {
  count: 0
}
const mutations = {
  increment(state) {
    state.count++;
  }
}
export default {
  store,
  mutations
}

In my store.js file I have

import counter from './store/modules/counter'
...
const store = new Vuex({
  modules: {
    counter
  }
})

And in my test.spec.js file I have

import counter from './store/modules/counter'
...
describe('something', () => {
  it('does something', () => {
    let store = new Vuex({
      modules: {
        counter
      }
    })
    store.commit('increment')
  })
})

When Vuex creates a store, it doesn't make a copy of the store and mutations objects, it just takes hold of the references passed to it, setting up appropriate checks and other hooks. This happens twice (or more) when running tests and causes the errors to be thrown – albeit in a different scope, thus why Mocha doesn't mark it as a failed test.