danielroe / typed-vuex

đŸĻ A typed store accessor for vanilla Vuex.
https://typed-vuex.roe.dev
MIT License
353 stars 27 forks source link

docs: Testing store using just accessor in a Nuxt project #243

Open silmood opened 3 years ago

silmood commented 3 years ago

📚 Is your documentation request related to a problem? Please describe. I think it's a good idea to add some reference of how to write tests using the accessor. I had a few troubles setting up some unit tests. Check *additional context for the details.

🔍 Where should you find it? A new page for Testing or just adding some tests to the current example projects

ℹī¸ Additional context

This came up when i was trying to write some tests for actions and mutations without mounting a vue component or using @vue/test-utils. This way my tests will be focused on the operation of the store. The project I'm working on uses Nuxt and jest. In order to illustrate this case, here is a simplified version of the store structure and the actions and mutations:

Structure

- store
  - index.ts
  - submodule.ts
import * as submodule from './submodule'

export type RootState = {
   // Some state
}

export const state = (): RootState => ({
  // Default state
})

export const mutations = mutationTree(state, {
  // Some mutations
})

export const actions = actionTree(
  { state, mutations },
  {
    async initializeStore({ commit }): Promise<void> {
      // Some commits
      this.app.$accessor.submodule.initializeSubmodule()
    }
  }
)

export const AccessorType = getAccessorType({
  state,
  mutations,
  actions,
  modules: {
    submodule
  }
})

submodule.ts

export type SubmoduleState = {
   // Some state
}

export const state = (): SubmoduleState => ({
  // Default state
})

export const mutations = mutationTree(state, {
  // Some mutations
})

export const actions = actionTree(
  { state, mutations },
  {
    async initializeSubmodule({ commit }): Promise<void> {
      // Some commits
    }
  }
)

In order to test these files i decided to setup the store as if I weren't using Nuxt (like the setup described in the docs)

import * as submodule from '../submodule'
import { state, mutations, actions } from '../index'

const pattern = {
  state,
  mutations,
  actions,
  modules: {
    submodule
  }
}

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

const store = new Vuex.Store(pattern)
const accessor = useAccessor(store, pattern)

describe('RootStore', () => {
  describe('when initialize store', () => {

    beforeAll(async () => {
      await accessor.initializeStore()
    })

    it('should setup general configuration', () => {
      // Some assertions
    })
  })
})

The problem with this configuration is that NuxtAppOptions will be undefined so when you try to reference another module within an action there will be an exception like this one: TypeError: Cannot read property '$accessor' of undefined . So in this example, the problem is in this line:

// TypeError: Cannot read property '$accessor' of undefined
this.app.$accessor.submodule.initializeSubmodule()

After a quick research it seems you need to mock Nuxt global plugins as it's described here. However I think that's just too much for this case. My solution was simply mock the NuxtAppOptions and assign it the to the store:

const store = new Vuex.Store(pattern) as any
const accessor = useAccessor(store, pattern)

// Trick to use accessor within actions
store.app = {
  $accessor: accessor
}

Maybe it isn't the best solution but it works perfectly for this scenario. I hope this can be helpful.

jeanlucmongrain commented 3 years ago

Nice, an other interesting, but quickly dead project.

An other case of single-maintainer that don't want to collaborate with community contributions (ignored pull requests) and issues.

danielroe commented 3 years ago

Nice, an other interesting, but quickly dead project.

An other case of single-maintainer that don't want to collaborate with community contributions (ignored pull requests) and issues.

@bclermont I'm sorry you feel that way. I'm deleting your other duplicate comments as I'm not sure they add anything.

PRs are welcome, and never ignored â™Ĩī¸