Skip to content

Commit 688d497

Browse files
author
Filip
committed
Merge branch 'feature-vuex-testing'
2 parents 32d8bce + 53b21ba commit 688d497

File tree

13 files changed

+292
-24
lines changed

13 files changed

+292
-24
lines changed

README.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ jest tests/unit/Home.spec.js
8585
- button can be disable or enabled
8686
- can add meeting to store
8787
- message is showed after button click and hide on @hideMessage event
88+
5. Actions
89+
- doReservation commits to mutation
90+
6. Mutations
91+
- addMeeting push item to state.meetingList
92+
7. Getters
93+
- getTodayMeetings returns meetings from today
8894

8995

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

103-
## Other topics which are not ready yet:
104-
1. Testing vuex store actions and mutations
110+
## Extra topic, not recommended in big stores:
111+
- Testing Vuex store instance
112+
113+
## What about Vuex modules?
114+
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
115+
116+
```
117+
storeModuleA.js
118+
storeModuleB.js
119+
```
120+
121+
```
122+
storeModuleAActions.spec.js
123+
storeModuleAGetters.spec.js
124+
storeModuleBActions.spec.js
125+
...
126+
```
105127

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

done/src/store/index.js

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,45 @@
11
import Vue from 'vue'
22
import Vuex from 'vuex'
3+
import axios from 'axios'
34

45
Vue.use(Vuex)
56

6-
export default new Vuex.Store({
7-
state: {
8-
meetingList: []
7+
export const state = {
8+
meetingList: []
9+
}
10+
11+
export const mutations = {
12+
addMeeting (state, data) {
13+
state.meetingList.push(data)
14+
}
15+
}
16+
17+
export const actions = {
18+
doReservation ({ commit }, data) {
19+
commit('addMeeting', data)
920
},
10-
mutations: {
11-
addMeeting (state, data) {
12-
state.meetingList.push(data)
21+
async fakeApiAction ({ commit }, data) {
22+
try {
23+
await axios.post('http://localhost:5679/fake/confirmMeeting', data)
24+
commit('fakeCommit', true)
1325
}
14-
},
15-
actions: {
16-
doReservation ({ commit }, data) {
17-
commit('addMeeting', data)
26+
catch (error) {
27+
commit('fakeCommit', false)
1828
}
1929
}
30+
}
31+
32+
// Just for test case purposes
33+
export const getters = {
34+
getTodayMeetings ( state ) {
35+
const today = new Date().toJSON().slice(0, 10)
36+
return state.meetingList.filter(meeting => meeting.date === today)
37+
}
38+
}
39+
40+
export default new Vuex.Store({
41+
state,
42+
mutations,
43+
actions,
44+
getters
2045
})

done/tests/unit/actions.spec.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { actions } from '@/store'
2+
import axios from 'axios'
3+
import flushPromises from 'flush-promises'
4+
5+
jest.mock('axios')
6+
7+
describe('actions - store', () => {
8+
beforeEach(() => {
9+
axios.post.mockClear()
10+
})
11+
12+
it('doReservation commits to mutation', () => {
13+
const context = {
14+
commit: jest.fn()
15+
}
16+
const testItem = { 'test': true }
17+
18+
actions.doReservation(context, testItem)
19+
20+
expect(context.commit).toHaveBeenCalledWith('addMeeting', testItem)
21+
})
22+
23+
it('fakeApiAction makes commit based on API response', async () => {
24+
const context = {
25+
commit: jest.fn()
26+
}
27+
const testItem = { 'test': true }
28+
29+
actions.fakeApiAction(context, testItem)
30+
31+
await flushPromises()
32+
33+
expect(axios.post).toHaveBeenCalledWith('http://localhost:5679/fake/confirmMeeting', testItem)
34+
expect(axios.post).toHaveBeenCalledTimes(1)
35+
expect(context.commit).toHaveBeenCalledWith('fakeCommit', true)
36+
37+
axios.post.mockImplementationOnce(() => {
38+
throw 'error'
39+
})
40+
actions.fakeApiAction(context)
41+
42+
expect(axios.post).toHaveBeenCalledTimes(2)
43+
expect(context.commit).toHaveBeenCalledWith('fakeCommit', false)
44+
})
45+
})

done/tests/unit/getters.spec.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { getters } from '@/store'
2+
import { advanceTo, clear } from 'jest-date-mock'
3+
4+
describe('getters - store', () => {
5+
beforeEach(() => {
6+
advanceTo(new Date('2020-03-27T00:00:05Z'))
7+
})
8+
9+
it('getTodayMeetings returns meetings from today', () => {
10+
const state = {
11+
meetingList: [
12+
{
13+
'date': '2020-03-27',
14+
'who': 'Example Person1'
15+
},
16+
{
17+
'date': '2020-03-27',
18+
'who': 'Example Person2'
19+
},
20+
{
21+
'date': '2020-04-11',
22+
'who': 'Test meeting'
23+
},
24+
{
25+
'date': '2020-02-10',
26+
'who': 'guess who'
27+
}
28+
]
29+
}
30+
31+
const result = getters.getTodayMeetings(state)
32+
33+
expect(result).toHaveLength(2)
34+
})
35+
36+
afterEach(() => {
37+
clear()
38+
})
39+
})

done/tests/unit/mutations.spec.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { mutations } from '@/store'
2+
3+
describe('mutations - store', () => {
4+
it('addMeeting push item to state.meetingList', () => {
5+
const newElement = {
6+
'date': '2020-03-27',
7+
'who': 'Example Person1'
8+
}
9+
const state = {
10+
meetingList: []
11+
}
12+
13+
mutations.addMeeting(state, newElement)
14+
15+
expect(state.meetingList).toStrictEqual([newElement])
16+
expect(state.meetingList).toHaveLength(1)
17+
})
18+
})
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { createLocalVue } from '@vue/test-utils'
2+
import Vuex from 'vuex'
3+
import axios from 'axios'
4+
import flushPromises from 'flush-promises'
5+
6+
const localVue = createLocalVue()
7+
localVue.use(Vuex)
8+
9+
jest.mock('axios')
10+
11+
describe('vuex store instance', () => {
12+
let store
13+
let storeConfig
14+
15+
beforeEach(() => {
16+
storeConfig = {
17+
state: { meetingList: [] },
18+
mutations: {
19+
addMeeting (state, data) {
20+
state.meetingList.push(data)
21+
},
22+
fakeCommit () {
23+
return true
24+
}
25+
},
26+
actions: {
27+
doReservation ({ commit }, data) {
28+
commit('addMeeting', data)
29+
},
30+
async fakeApiAction ({ commit }, data) {
31+
try {
32+
await axios.post('http://localhost:5679/fake/confirmMeeting', data)
33+
commit('fakeCommit', true)
34+
}
35+
catch (error) {
36+
commit('fakeCommit', false)
37+
}
38+
}
39+
},
40+
getters: {
41+
getTodayMeetings ( state ) {
42+
const today = '2020-01-01'
43+
return state.meetingList.filter(meeting => meeting.date === today)
44+
}
45+
}
46+
}
47+
48+
store = new Vuex.Store(storeConfig)
49+
50+
axios.post.mockClear()
51+
})
52+
53+
it('commit addMeeting updates state of meetingList', () => {
54+
const testElement = { 'test': true }
55+
56+
store.commit('addMeeting', testElement)
57+
58+
expect(store.state.meetingList).toStrictEqual([testElement])
59+
60+
store.commit('addMeeting', testElement)
61+
62+
expect(store.state.meetingList).toStrictEqual([testElement, testElement])
63+
})
64+
65+
it('dispatching fakeApiAction doing mocked request', async () => {
66+
const testItem = { 'test': true }
67+
68+
store.dispatch('fakeApiAction', testItem)
69+
70+
await flushPromises()
71+
72+
expect(axios.post).toHaveBeenCalledWith('http://localhost:5679/fake/confirmMeeting', testItem)
73+
expect(axios.post).toHaveBeenCalledTimes(1)
74+
75+
axios.post.mockImplementationOnce(() => {
76+
throw 'error'
77+
})
78+
store.dispatch('fakeApiAction', testItem)
79+
80+
expect(axios.post).toHaveBeenCalledTimes(2)
81+
})
82+
83+
it('dispatching doReservation with today meeting updates getter getTodayMeetings', () => {
84+
const testItem = { 'date': '2020-01-01' }
85+
86+
store.dispatch('doReservation', testItem)
87+
88+
expect(store.state.meetingList).toHaveLength(1)
89+
expect(store.getters.getTodayMeetings).toHaveLength(1)
90+
expect(store.getters.getTodayMeetings).toEqual([testItem])
91+
92+
store.dispatch('doReservation', testItem)
93+
store.dispatch('doReservation', { 'date': '2000-01-01' })
94+
95+
expect(store.state.meetingList).toHaveLength(3)
96+
expect(store.getters.getTodayMeetings).toHaveLength(2)
97+
expect(store.getters.getTodayMeetings).toEqual([ testItem, testItem ])
98+
})
99+
})

practices/tests/unit/AddMeeting.spec.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import { mount, createLocalVue } from '@vue/test-utils'
2-
import Vuex from 'vuex'
1+
import snapshotDiff from 'snapshot-diff'
32
import axios from 'axios'
3+
import { advanceTo, clear } from 'jest-date-mock'
44
// Check for more: https://github.com/kentor/flush-promises
55
// or if you don't want to add external lib: https://github.com/kentor/flush-promises/blob/master/index.js
66
import flushPromises from 'flush-promises'
77
import AddMeeting from '@/views/AddMeeting.vue'
88

9-
const localVue = createLocalVue()
10-
localVue.use(Vuex)
11-
129
// Check for more: https://jestjs.io/docs/en/mock-functions.html
1310
// Alternative for mocking requests: https://github.com/ctimmerm/axios-mock-adapter
1411
jest.mock('axios')

practices/tests/unit/Checkbox.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { mount } from '@vue/test-utils'
21
import Checkbox from '@/components/Checkbox.vue'
32

43
describe('Checkbox.vue', () => {

practices/tests/unit/Home.spec.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import { mount, createLocalVue } from '@vue/test-utils'
2-
import Vuex from 'vuex'
31
import HomePage from '@/views/Home.vue'
42

5-
const localVue = createLocalVue()
6-
localVue.use(Vuex)
7-
83
describe('Home page', () => {
94
// it('meeting list contains elements from store', () => {
105
// })

practices/tests/unit/Message.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { mount } from '@vue/test-utils'
21
import Message from '@/components/Message.vue'
32

43
// Check for more: https://jestjs.io/docs/en/timer-mocks

practices/tests/unit/actions.spec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { actions } from '@/store'
2+
3+
describe('actions - store', () => {
4+
// it('doReservation commits to mutation', () => {
5+
// })
6+
7+
// it('fakeApiAction makes commit based on API response', async () => {
8+
// })
9+
})

practices/tests/unit/getters.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getters } from '@/store'
2+
import { advanceTo, clear } from 'jest-date-mock'
3+
4+
describe('getters - store', () => {
5+
beforeEach(() => {
6+
advanceTo(new Date('2020-03-27T00:00:05Z'))
7+
})
8+
9+
// it('getTodayMeetings returns meetings from today', () => {
10+
// })
11+
12+
afterEach(() => {
13+
clear()
14+
})
15+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { mutations } from '@/store'
2+
3+
describe('mutations - store', () => {
4+
// it('addMeeting push item to state.meetingList', () => {
5+
// })
6+
})

0 commit comments

Comments
 (0)