nyl-auster
7/16/2017 - 8:33 AM

How to unit test a Vue.js / Nuxt.js component that uses <nuxt-link> and store

How to unit test a Vue.js / Nuxt.js component that uses <nuxt-link> and store

// Minimal Webpack config to supply to units tests.
// This is not actually used by Nuxt but instead mirrors
// the resolve and loader rules.

const resolve = require('path').resolve;
// resolve to absolute path where "npm test" is running from
const root = resolve('.')

module.exports = {
  resolve: {
    modules: [root + '/node_modules'],
    extensions: ['.js', '.vue'],
    alias: {
      '~': root,
      'static': root + '/static', // use in template with <img src="~static/nuxt.png" />
      '~static': root + '/static',
      'assets': root + '/assets', // use in template with <img src="~static/nuxt.png" />
      '~assets': root + '/assets',
      '~plugins': root + '/plugins',
      '~store': root + '/.nuxt/store',
      '~router': root + '/.nuxt/router',
      '~pages': root + '/pages',
      '~components': root + '/components',
      '~lib': root + '/lib',
    }
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
      }
    ]
  }
};
<template>
  <div class="container">
    <nav class="nav">
      <div class="nav-left">
        <span class="nav-item">
          UMAMI food magazine <br />
          <AppVersion />
        </span>
      </div>
  
      <!-- This "nav-toggle" hamburger menu is only visible on mobile -->
      <!-- You need JavaScript to toggle the "is-active" class on "nav-menu" -->
      <span class="nav-toggle" @click="setMenuMobileIsOpened">
        <span></span>
        <span></span>
        <span></span>
      </span>
  
      <!-- This "nav-menu" is hidden on mobile -->
      <!-- Add the modifier "is-active" to display it on mobile -->
      <div class="nav-right nav-menu" :class="{'is-active': this.$store.state.menuMobileIsOpened}">
        <nuxt-link to="/" class="nav-item"> Home </nuxt-link>
        <nuxt-link to="/recipes" class="nav-item"> Recipes </nuxt-link>
        <!--<nuxt-link @click.native="displayMobileMenu = false" to="/magazine" class="nav-item"> Magazine </nuxt-link>-->
      </div>
  
    </nav>
  </div>
</template>

<script>
import AppVersion from '~/components/AppVersion'
export default {
  components: { AppVersion },
  methods: {
    setMenuMobileIsOpened() {
      this.$store.commit('setMenuMobileIsOpened', !this.$store.state.menuMobileIsOpened)
    }
  }
}
</script>

<style scoped>
.nuxt-link-exact-active {
  color:#363636;
}
</style>
import Vue from 'vue'
import AppNavigation from '~/components/AppNavigation'

// Mock our router, store and nuxt-link
import Vuex from 'vuex'
import storeCreate from '~/store'
import VueRouter from 'vue-router'
import NuxtLink from '~/.nuxt/components/nuxt-link'
Vue.use(VueRouter)
Vue.use(Vuex)

/**
 * An example unit test
 */
describe('AppNavigation.vue', () => {

  let vm = null

  beforeEach(() => {
    // Inject manually Nuxt-link to avoid an error message
    AppNavigation.components.NuxtLink = NuxtLink
    const Constructor = Vue.extend(AppNavigation)
    vm = new Constructor({ router:  new VueRouter() })
    vm.$store = storeCreate()
    vm.$mount()
  })

  it('Mobile menu should have a is-active class when $store.state.menuMobileIsOpened == true', () => {
    expect(vm.$el.querySelector('.nav-right').className.trim()).toBe('nav-right nav-menu')
    vm.setMenuMobileIsOpened()
    // we should now have an active class on next DOM update
    vm.$nextTick(() => {
      expect(vm.$el.querySelector('.nav-right').className.trim()).toBe('nav-right nav-menu is-active')
    }) 
    
  })

})