Vue.js w vuex:未执行的模拟操作

时间:2017-11-09 17:18:24

标签: unit-testing vue.js vuex

我正在尝试在logout vue-router链接上触发click事件时测试以下App.vue组件...

App.vue

    <template>
      <div id="app">
         <header id="header">
            <nav>
               <ul class="navigation">
                  <li id="home"><router-link :to="{ name: 'home' }">Home</router-link></li>
                  <li id="login" v-if="!isAuthenticated"><router-link :to="{ name: 'login' }">Login</router-link></li>
                 <li id="shoppinglists" v-if="isAuthenticated"><router-link :to="{ name: 'shoppinglists' }" >Shopping Lists</router-link></li>
                 <li id="logout" v-if="isAuthenticated"><a href="#" @click.prevent="logout()" class="nav-link">Logout</a></li>
              </ul>
            </nav>
          </header><!-- /#header -->
          <section id="page">
            <router-view></router-view>
          </section><!-- /#page -->
      </div>
    </template>

    <script>
    import store from '@/vuex/store'
    import router from '@/router/index'
    import { mapGetters } from 'vuex'
    export default {
      name: 'app',
      computed: {
        ...mapGetters({ isAuthenticated: 'isAuthenticated' })
      },
      methods: {
        logout () {
          this. $store.dispatch('logout')
          .then(() => {
            window.localStorage.removeItem('vue-authenticate.vueauth_token')
            this/$router.push({ name: 'home' })
          })
        }
      },
      store,
      router
    }
    </script>

要测试注销点击,我将isAuthenticated状态预设为true,这样就会显示注销路由器链接并触发其上的点击事件。

 LOG: 'navigation: ', <ul class="navigation"><li id="home">
  <a href="/" class="router-link-active">Home</a></li> <!----> 
  <li id="shoppinglists"><a href="/shoppinglists" class="">Shopping Lists</a>
  </li> <li id="logout"><a href="#" class="nav-link">Logout</a></li></ul>

我希望已经调用了动作注销..但它不是......为什么?

App.spec.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import VueRouter from 'vue-router'

    import App from '@/App'

    import router from '@/router/index'

    import { mount } from 'avoriaz'
    import sinon from 'sinon'

    Vue.use(Vuex)
    Vue.use(VueRouter)

    describe('App.vue', () => {
      let actions
      let getters
      let store

      beforeEach(() => {
        getters = {
          isAuthenticated: (state) => {
            return state.isAuthenticated
          }
        }
        actions = {
          logout: sinon.stub().returns(Promise.resolve(true))
        }
        store = new Vuex.Store({
          getters,
          actions,
          state: {
            isAuthenticated: true,
            currentUserId: ''
          }
        })
        router
      })

      it('calls logout method', () => {
        const wrapper = mount(App, { router, store })
        console.log('navigation: ', wrapper.find('ul.navigation')[0].element)
        const logoutLink = wrapper.find('#logout a')[0]
        logoutLink.trigger('click')
        expect(actions.logout.calledOnce).to.equal(true)
      })
    })

vuex / actions.js

 import { IS_AUTHENTICATED, CURRENT_USER_ID } from './mutation_types'
 import getters from './getters'

 export default {

   logout: ({commit}) => {
     commit(IS_AUTHENTICATED, { isAuthenticated: false })
     commit(CURRENT_USER_ID, { currentUserId: '' })
     return true
   }
 }

vuex / mutations.js

 import * as types from './mutation_types'
 import getters from './getters'

 export default {
   [types.IS_AUTHENTICATED]  (state, payload) {
     state.isAuthenticated = payload.isAuthenticated
    },
   [types.CURRENT_USER_ID]  (state, payload) {
     state.currentUserId = payload.currentUserId
   }
 }

vuex / getters.js

 export default {
   isAuthenticated: (state) => {
     return state.isAuthenticated
   }
 }

1 个答案:

答案 0 :(得分:0)

最后,我找到了一种方法来测试它:

    import Vue from 'vue'
    import Vuex from 'vuex'
    import VueRouter from 'vue-router'

    import App from '@/App'

    import router from '@/router/index'

    import { mount } from 'avoriaz'
    import sinon from 'sinon'

    Vue.use(Vuex)
    Vue.use(VueRouter)

    describe('App.vue', () => {
      let actions
      let getters
      let store
      let sandbox
      let routerPush

      beforeEach(() => {
        sandbox = sinon.sandbox.create()
        getters = {
          isAuthenticated: (state) => {
            return state.isAuthenticated
          }
        }
        actions = {
          logout: sandbox.stub().returns(Promise.resolve(true))
        }
        store = new Vuex.Store({
          getters,
          state: {
            isAuthenticated: true,
            currentUserId: ''
          },
          actions
        })
        router
      })
      afterEach(() => {
        sandbox.restore()
      })

      it('calls logout method', (done) => {
        const wrapper = mount(App, { store, router })
        routerPush = sandbox.spy(wrapper.vm.$router, 'push')
        const logoutLink = wrapper.find('#logout a')[0]
        logoutLink.trigger('click')
        wrapper.vm.$nextTick(() => {
          expect(actions.logout.calledOnce).to.equal(true)
          actions.logout().then(() => {
            expect(routerPush).to.have.been.calledWith('/home')
          })
          done()
        })
      })
    })