Search code examples
typescriptvue.jsjestjsnuxt.jsvue-test-utils

how to spy on dispatch on fetch/middleware method


I'm trying to test a simple page

<template>
  <HomeTemplate />
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  async fetch(context) { // or middleware(context)
    await context.store.dispatch('categories/index')
  }
})
</script>

I would like to spy on dispatch and know if everything went perfectly, so i triedbut first I tried to spy on just the action:

import { Wrapper, shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex, { Store } from 'vuex'
import HomePage from './index.vue'
import { CategoriesState } from '@/store/categories'

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

describe('HomePage', () => {
  type Instance = InstanceType<typeof HomePage>
  let wrapper: Wrapper<Instance>

  let store: Store<CategoriesState>

  const mockIndex: jest.Mock = jest.fn()

  beforeAll(() => {
    store = new Vuex.Store({
      modules: {
        categories: {
          namespaced: true,
          actions: { index: mockIndex }
        }
      }
    })

    wrapper = shallowMount(HomePage, {
      stubs: ['HomeTemplate'],
      localVue,
      store
    })
  })

  it('should call vuex action to fetch categories', () => {
    expect(mockIndex).toHaveBeenCalledWith('categories/index')
  })
})

considering that the fetch() or middleware() method receives the nuxt context, I tried to mock it

import { Wrapper, shallowMount } from '@vue/test-utils'
import HomePage from './index.vue'

describe('HomePage', () => {
  type Instance = InstanceType<typeof HomePage>
  let wrapper: Wrapper<Instance>

  const mockIndex: jest.Mock = jest.fn()

  beforeAll(() => {
    wrapper = shallowMount(HomePage, {
      stubs: ['HomeTemplate'],
      mocks: {
        context: {
          store: {
            dispatch: mockIndex
          }
        }
      }
    })
  })

  it('should call vuex action to fetch categories', () => {
    expect(mockIndex).toHaveBeenCalledWith('categories/index')
  })
})

but it still doesn't work, enter image description here

could someone help me make it work properly?

thank you!


Solution

  • fetch is a hook that is specific to Nuxt. @vue/test-utils is unaware of it, mockIndex isn't expected to be called in tests, unless the hook is called explicitly.

    It should be:

    const context = {
      store: {
        dispatch: mockIndex
      }
    };
    
    await HomePage.options.fetch(context);
    expect(mockIndex).toBeCalledWith(...)