Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'[vuex] must call Vue.use(Vuex) before creating a store instance' when changing tests order in src/tests/vuex.js #245

Closed
adragich opened this issue Jul 28, 2021 · 3 comments

Comments

@adragich
Copy link

adragich commented Jul 28, 2021

Vue-testing-library Vuex unit test (src/tests/vuex.js) fails if you change tests order or remove ones with renderVuexTestComponent function. It's not a bug of library, but you should refactor your tests as you share these examples in official docs.

To Reproduce Steps to reproduce the behavior:

Run test. Move 'can render with an instantiated Vuex store' test to top or remove test cases with renderVuexTestComponent function. Test fails.

Expected behavior

Test passes.

Screenshot 2021-07-28 at 13 25 35

Related information:

  • @testing-library/vue version: 0.0.0-semantically-released
  • Vue version: ^2.6.12
  • node version: v12.13.1
  • npm (or yarn) version: yarn@1.22.10

Relevant code or config (if any)

import '@testing-library/jest-dom'
import {render, fireEvent} from '@testing-library/vue'
import Vuex from 'vuex'

import VuexTest from './components/Store/VuexTest'
import {store} from './components/Store/store'

// A common testing pattern is to create a custom renderer for a specific test
// file. This way, common operations such as registering a Vuex store can be
// abstracted out while avoiding sharing mutable state.
//
// Tests should be completely isolated from one another.
// Read this for additional context: https://kentcdodds.com/blog/test-isolation-with-react
function renderVuexTestComponent(customStore) {
  // Render the component and merge the original store and the custom one
  // provided as a parameter. This way, we can alter some behaviors of the
  // initial implementation.
  return render(VuexTest, {store: {...store, ...customStore}})
}

test('can render with an instantiated Vuex store', async () => {
  const {getByTestId, getByText} = render(VuexTest, {
    store: new Vuex.Store({
      state: {count: 3},
      mutations: {
        increment(state) {
          state.count++
        },
        decrement(state) {
          state.count--
        },
      },
      actions: {
        increment(context) {
          context.commit('increment')
        },
        decrement(context) {
          context.commit('decrement')
        },
      },
    }),
  })

  await fireEvent.click(getByText('+'))
  expect(getByTestId('count-value')).toHaveTextContent('4')

  await fireEvent.click(getByText('-'))
  expect(getByTestId('count-value')).toHaveTextContent('3')
})

test('can render with vuex with defaults', async () => {
  const {getByTestId, getByText} = renderVuexTestComponent()
  await fireEvent.click(getByText('+'))

  expect(getByTestId('count-value')).toHaveTextContent('1')
})

test('can render with vuex with custom initial state', async () => {
  const {getByTestId, getByText} = renderVuexTestComponent({
    state: {count: 3},
  })
  await fireEvent.click(getByText('-'))

  expect(getByTestId('count-value')).toHaveTextContent('2')
})

test('can render with vuex with custom store', async () => {
  // This is a silly store that can never be changed.
  // eslint-disable-next-line no-shadow
  const store = {
    state: {count: 1000},
    actions: {
      increment: () => jest.fn(),
      decrement: () => jest.fn(),
    },
  }

  // Notice how here we are not using the helper method, because there's no
  // need to do that.
  const {getByTestId, getByText} = render(VuexTest, {store})

  await fireEvent.click(getByText('+'))
  expect(getByTestId('count-value')).toHaveTextContent('1000')

  await fireEvent.click(getByText('-'))
  expect(getByTestId('count-value')).toHaveTextContent('1000')
})

Additional context

I think you should discourage using instantiated store or show that initializing vuex on global Vue is okay (vuex does it anyways https://github.com/vuejs/vuex/blob/dev/src/store.js#L542).

@adragich adragich added the bug Something isn't working label Jul 28, 2021
@afontcu afontcu removed the bug Something isn't working label Jul 28, 2021
@adragich adragich changed the title Vuex '[vuex] must call Vue.use(Vuex) before creating a store instance' when changing tests order in src/tests/vuex.js Jul 28, 2021
@afontcu
Copy link
Member

afontcu commented Aug 1, 2021

Hi! Thank you for the detailed report.

Supporting instantiated Vuex stores was introduced last month in #232. Maybe @blimmer can shed some light on how they are avoiding this error? I have never used this option so I haven't encountered it myself.

@blimmer
Copy link
Contributor

blimmer commented Aug 1, 2021

Hey @adragich and @afontcu!

@adragich is correct that, if you're creating an instantiated store, you'll need to call Vue.use(Vuex) somewhere in your code. For my purposes, using jest, I do this once on the global Vue instance in a setupFilesAfterEnv script.

To make this a bit clearer in the tests, I created #247 which explicitly calls .use() on the global Vue object, and also adds a code comment about this behavior. I wasn't sure where I'd add to the documentation, but am happy to make updates if either of you has suggestions. My current thought is that the Vuex error message is pretty good at describing what you need to do to resolve the problem.

@afontcu
Copy link
Member

afontcu commented Aug 1, 2021

Fixed in #247. Thank you both!

@afontcu afontcu closed this as completed Aug 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants