Testing vuex

A297a5edc76d3041eb63ef6b7b4eba42?s=47 Jakub
October 15, 2016

Testing vuex

Testing a real world applcation build with vue.js and vuex.
Examples how to test vuex getters, mutations and actions

Presentation Repo on GitHub: https://github.com/apertureless/presentation-vuex-testing

Example Project on GitHub: https://github.com/apertureless/vuex-notes-app

A297a5edc76d3041eb63ef6b7b4eba42?s=128

Jakub

October 15, 2016
Tweet

Transcript

  1. Welcome to Testing Vuex

  2. Requirements · Basic Javascript knowledge · Basic understanding on how

    Vue.js works · Basic Javascript Testing knowledge
  3. What we will learn

  4. · What is Vuex · How does Vuex work ·

    Testing Vuex getters · Testing Vuex mutation · Testing Vuex actions · In a real world example.
  5. But wait...

  6. What is ... Vuex ? !

  7. Vuex is a state management pattern & framework. Inspired by

    facebooks flux pattern and redux implementation of it.
  8. What is a "State Management Pattern" and why do we

    need it?
  9. Simple Vue App new Vue({ // state data () {

    return { count: 0 } }, // view template: ` <div>{{ count }}</div> `, // actions methods: { increment () { this.count++ } } })
  10. Simple one-way data flow

  11. But ... A complex application have different components, with child

    components and looks more like this.
  12. Flux Pattern for the rescue

  13. None
  14. We need this for Vue.js!

  15. None
  16. And this is. Vuex

  17. Our Test Application https://github.com/apertureless/vuex-notes- app

  18. Testing getters

  19. // getters.js export const activeNote = state => state.activeNote

  20. // getters.spec.js describe('getters', () => { // Mock state const

    state = { notes: [ { text: 'Mock', favorite: false }, { text: 'Mock2', favorite: true }, { text: 'Mock3', favorite: false }, ], activeNote: {} } it('notes', () => { // Get results with mocked state const result = getters.notes(state) // Assign results with state expect(result).to.deep.equal(state.notes) }) })
  21. Testing mutations

  22. // mutations.js export const mutations = { addNote (state) {

    const newNote = { text: 'Neue Notiz', favorite: false } state.notes.push(newNote) state.activeNote = newNote }, ... }
  23. // mutations.spec.js import { mutations } from '../../vuex/mutations' // destructure

    assign mutations const { addNote, editNote, deleteNote } = mutations describe('mutations', () => { it('addNote', () => { // mock state const state = { notes: [] } // apply mutation addNote(state) // assert result expect(state.notes).to.be.an('array') expect(state.notes[0].text).to.equal('Neue Notiz') }) })
  24. Testing Actions // actions.js export const addNote = ({ commit

    }) => commit('addNote') export const editNote = ({ commit }, e) => commit('editNote', e.target.value) export const deleteNote = ({ commit }) => commit('deleteNote')
  25. We need a helper function

  26. const testAction = (action, args, state, expectedMutations, done) => {

    let count = 0 // Mock Commit const commit = (type, payload) => { const mutation = expectedMutations[0] expect(mutation.type).to.equal(type) if (payload) { expect(mutation.payload).to.deep.equal(payload) } count ++ if (count >= expectedMutations.length) { done() } } // call the action with mocked store and arguments action({ commit, state }, ...args) // check if no mutations should have been dispatched if (expectedMutations.length === 0) { expect(count).to.equal(0) done() } }
  27. helper.js · Mocks a vuex commit · Checks the expected

    mutation type with the dispatched · Checks payload
  28. // actions.spec.js describe('actions', () => { it('addNote', (done) => {

    const state = store.state testAction(actions.addNote, [], state, [ { type: 'addNote' } ], done) }) ....
  29. Advanced Action Testing

  30. Actions can be tricky, if you interact with external APIs

    / Services.
  31. So we need to mock the endpoints.

  32. Example action // actions.js import shop from '../api/shop' export const

    getAllProducts = ({ dispatch }) => { dispatch('REQUEST_PRODUCTS') shop.getProducts(products => { dispatch('RECEIVE_PRODUCTS', products) }) }
  33. Testing action with inject loader // use require syntax for

    inline loaders. // with inject-loader, this returns a module factory // that allows us to inject mocked dependencies. const actionsInjector = require('inject!./actions') // create the module with our mocks const actions = actionsInjector({ '../api/shop': { getProducts (cb) { setTimeout(() => { cb([ /* mocked response */ ]) }, 100) } } })
  34. Testing it describe('actions', () => { it('getAllProducts', done => {

    testAction(actions.getAllProducts, [], {}, [ { type: 'REQUEST_PRODUCTS' }, { type: 'RECEIVE_PRODUCTS', payload: { /* mocked response */ } } ], done) }) })