Skip to content

Commit

Permalink
Merge branch 'feature-vuex-testing'
Browse files Browse the repository at this point in the history
  • Loading branch information
Filip committed Apr 19, 2020
2 parents 32d8bce + 53b21ba commit 688d497
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 24 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ jest tests/unit/Home.spec.js
- button can be disable or enabled
- can add meeting to store
- message is showed after button click and hide on @hideMessage event
5. Actions
- doReservation commits to mutation
6. Mutations
- addMeeting push item to state.meetingList
7. Getters
- getTodayMeetings returns meetings from today


## Covered topics and good practices in this repo:
Expand All @@ -96,12 +102,28 @@ jest tests/unit/Home.spec.js
- Factory functions
- Emitt events testing
- async testing syntax
- Testing vuex actions, mutations and getters
- Both side component testing
- Snapshot testing
- Acceptance testing and snapthot-diff checking

## Other topics which are not ready yet:
1. Testing vuex store actions and mutations
## Extra topic, not recommended in big stores:
- Testing Vuex store instance

## What about Vuex modules?
It's the same approach as importing actions from single module Vuex store. You are just importing actions from store module and i.e. testing in separate file for each store module

```
storeModuleA.js
storeModuleB.js
```

```
storeModuleAActions.spec.js
storeModuleAGetters.spec.js
storeModuleBActions.spec.js
...
```

## Found a bug or repo needs update? - contribute

Expand Down
45 changes: 35 additions & 10 deletions done/src/store/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
meetingList: []
export const state = {
meetingList: []
}

export const mutations = {
addMeeting (state, data) {
state.meetingList.push(data)
}
}

export const actions = {
doReservation ({ commit }, data) {
commit('addMeeting', data)
},
mutations: {
addMeeting (state, data) {
state.meetingList.push(data)
async fakeApiAction ({ commit }, data) {
try {
await axios.post('http://localhost:5679/fake/confirmMeeting', data)
commit('fakeCommit', true)
}
},
actions: {
doReservation ({ commit }, data) {
commit('addMeeting', data)
catch (error) {
commit('fakeCommit', false)
}
}
}

// Just for test case purposes
export const getters = {
getTodayMeetings ( state ) {
const today = new Date().toJSON().slice(0, 10)
return state.meetingList.filter(meeting => meeting.date === today)
}
}

export default new Vuex.Store({
state,
mutations,
actions,
getters
})
45 changes: 45 additions & 0 deletions done/tests/unit/actions.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { actions } from '@/store'
import axios from 'axios'
import flushPromises from 'flush-promises'

jest.mock('axios')

describe('actions - store', () => {
beforeEach(() => {
axios.post.mockClear()
})

it('doReservation commits to mutation', () => {
const context = {
commit: jest.fn()
}
const testItem = { 'test': true }

actions.doReservation(context, testItem)

expect(context.commit).toHaveBeenCalledWith('addMeeting', testItem)
})

it('fakeApiAction makes commit based on API response', async () => {
const context = {
commit: jest.fn()
}
const testItem = { 'test': true }

actions.fakeApiAction(context, testItem)

await flushPromises()

expect(axios.post).toHaveBeenCalledWith('http://localhost:5679/fake/confirmMeeting', testItem)
expect(axios.post).toHaveBeenCalledTimes(1)
expect(context.commit).toHaveBeenCalledWith('fakeCommit', true)

axios.post.mockImplementationOnce(() => {
throw 'error'
})
actions.fakeApiAction(context)

expect(axios.post).toHaveBeenCalledTimes(2)
expect(context.commit).toHaveBeenCalledWith('fakeCommit', false)
})
})
39 changes: 39 additions & 0 deletions done/tests/unit/getters.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { getters } from '@/store'
import { advanceTo, clear } from 'jest-date-mock'

describe('getters - store', () => {
beforeEach(() => {
advanceTo(new Date('2020-03-27T00:00:05Z'))
})

it('getTodayMeetings returns meetings from today', () => {
const state = {
meetingList: [
{
'date': '2020-03-27',
'who': 'Example Person1'
},
{
'date': '2020-03-27',
'who': 'Example Person2'
},
{
'date': '2020-04-11',
'who': 'Test meeting'
},
{
'date': '2020-02-10',
'who': 'guess who'
}
]
}

const result = getters.getTodayMeetings(state)

expect(result).toHaveLength(2)
})

afterEach(() => {
clear()
})
})
18 changes: 18 additions & 0 deletions done/tests/unit/mutations.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { mutations } from '@/store'

describe('mutations - store', () => {
it('addMeeting push item to state.meetingList', () => {
const newElement = {
'date': '2020-03-27',
'who': 'Example Person1'
}
const state = {
meetingList: []
}

mutations.addMeeting(state, newElement)

expect(state.meetingList).toStrictEqual([newElement])
expect(state.meetingList).toHaveLength(1)
})
})
99 changes: 99 additions & 0 deletions done/tests/unit/vuex-store-instance.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import axios from 'axios'
import flushPromises from 'flush-promises'

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

jest.mock('axios')

describe('vuex store instance', () => {
let store
let storeConfig

beforeEach(() => {
storeConfig = {
state: { meetingList: [] },
mutations: {
addMeeting (state, data) {
state.meetingList.push(data)
},
fakeCommit () {
return true
}
},
actions: {
doReservation ({ commit }, data) {
commit('addMeeting', data)
},
async fakeApiAction ({ commit }, data) {
try {
await axios.post('http://localhost:5679/fake/confirmMeeting', data)
commit('fakeCommit', true)
}
catch (error) {
commit('fakeCommit', false)
}
}
},
getters: {
getTodayMeetings ( state ) {
const today = '2020-01-01'
return state.meetingList.filter(meeting => meeting.date === today)
}
}
}

store = new Vuex.Store(storeConfig)

axios.post.mockClear()
})

it('commit addMeeting updates state of meetingList', () => {
const testElement = { 'test': true }

store.commit('addMeeting', testElement)

expect(store.state.meetingList).toStrictEqual([testElement])

store.commit('addMeeting', testElement)

expect(store.state.meetingList).toStrictEqual([testElement, testElement])
})

it('dispatching fakeApiAction doing mocked request', async () => {
const testItem = { 'test': true }

store.dispatch('fakeApiAction', testItem)

await flushPromises()

expect(axios.post).toHaveBeenCalledWith('http://localhost:5679/fake/confirmMeeting', testItem)
expect(axios.post).toHaveBeenCalledTimes(1)

axios.post.mockImplementationOnce(() => {
throw 'error'
})
store.dispatch('fakeApiAction', testItem)

expect(axios.post).toHaveBeenCalledTimes(2)
})

it('dispatching doReservation with today meeting updates getter getTodayMeetings', () => {
const testItem = { 'date': '2020-01-01' }

store.dispatch('doReservation', testItem)

expect(store.state.meetingList).toHaveLength(1)
expect(store.getters.getTodayMeetings).toHaveLength(1)
expect(store.getters.getTodayMeetings).toEqual([testItem])

store.dispatch('doReservation', testItem)
store.dispatch('doReservation', { 'date': '2000-01-01' })

expect(store.state.meetingList).toHaveLength(3)
expect(store.getters.getTodayMeetings).toHaveLength(2)
expect(store.getters.getTodayMeetings).toEqual([ testItem, testItem ])
})
})
7 changes: 2 additions & 5 deletions practices/tests/unit/AddMeeting.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { mount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import snapshotDiff from 'snapshot-diff'
import axios from 'axios'
import { advanceTo, clear } from 'jest-date-mock'
// Check for more: https://github.com/kentor/flush-promises
// or if you don't want to add external lib: https://github.com/kentor/flush-promises/blob/master/index.js
import flushPromises from 'flush-promises'
import AddMeeting from '@/views/AddMeeting.vue'

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

// Check for more: https://jestjs.io/docs/en/mock-functions.html
// Alternative for mocking requests: https://github.com/ctimmerm/axios-mock-adapter
jest.mock('axios')
Expand Down
1 change: 0 additions & 1 deletion practices/tests/unit/Checkbox.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { mount } from '@vue/test-utils'
import Checkbox from '@/components/Checkbox.vue'

describe('Checkbox.vue', () => {
Expand Down
5 changes: 0 additions & 5 deletions practices/tests/unit/Home.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { mount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import HomePage from '@/views/Home.vue'

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

describe('Home page', () => {
// it('meeting list contains elements from store', () => {
// })
Expand Down
1 change: 0 additions & 1 deletion practices/tests/unit/Message.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { mount } from '@vue/test-utils'
import Message from '@/components/Message.vue'

// Check for more: https://jestjs.io/docs/en/timer-mocks
Expand Down
9 changes: 9 additions & 0 deletions practices/tests/unit/actions.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { actions } from '@/store'

describe('actions - store', () => {
// it('doReservation commits to mutation', () => {
// })

// it('fakeApiAction makes commit based on API response', async () => {
// })
})
15 changes: 15 additions & 0 deletions practices/tests/unit/getters.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { getters } from '@/store'
import { advanceTo, clear } from 'jest-date-mock'

describe('getters - store', () => {
beforeEach(() => {
advanceTo(new Date('2020-03-27T00:00:05Z'))
})

// it('getTodayMeetings returns meetings from today', () => {
// })

afterEach(() => {
clear()
})
})
6 changes: 6 additions & 0 deletions practices/tests/unit/mutations.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { mutations } from '@/store'

describe('mutations - store', () => {
// it('addMeeting push item to state.meetingList', () => {
// })
})

0 comments on commit 688d497

Please sign in to comment.