-
Notifications
You must be signed in to change notification settings - Fork 0
/
store.tests.ts
179 lines (150 loc) · 4.81 KB
/
store.tests.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import { describe, it, expect } from '../utils/test'
import { MissingActionError } from './store.errors'
import Store from './store'
describe('GIVEN: a generic store', () => {
describe('WHEN: it is in the initial state', () => {
const counterInitialState = 0
const counterStore = new Store(
{ n: counterInitialState },
{
actions: {
increment: state => state.n++,
},
}
)
it('THEN: its values should be the initial ones', () => {
// arrange
const expected = 0
// assert
expect(counterStore.state.n).toEqual(expected)
})
it('AND: its history should be empty', () => {
expect(counterStore.history).toBeEmpty()
})
})
describe('WHEN: it is in whichever state', () => {
const counterStore = new Store(
{ n: 288 },
{
actions: {
increment: state => state.n++,
},
}
)
it('THEN: its values can be modified dispatching actions', () => {
// arrange
const expected = 290
// act
counterStore.dispatch('increment')
counterStore.dispatch('increment')
// assert
expect(counterStore.state.n).toEqual(expected)
})
it('AND: its history is modified accordingly', () => {
// arrange
const expected = ['increment', 'increment']
// assert
expected.every(expectedAction =>
expect(counterStore.history).toContain(expectedAction)
)
expect(counterStore.history.length).toEqual(2)
})
it('AND: it throws a MissingActionError when dispatching non existing actions', () => {
// act
try {
counterStore.dispatch('this should blow up')
} catch (error) {
expect(error instanceof MissingActionError).toBeTruthy()
}
// assert
expect(counterStore.history).toNotContain('this should blow up')
})
})
})
describe('GIVEN: a store with the observer pattern', () => {
const broadcastStore = new Store(
{},
{
actions: {
broadcastMessage: (state, ..._messages) => state,
},
}
)
let counter = 0
const adderWorker = (actionName: string, message: string) => {
if (message === 'addOne') counter++
}
const resetStore = () => {
broadcastStore.listeners = []
broadcastStore.history = []
}
describe('WHEN: there are no listeners', () => {
resetStore()
it('THEN: the listeners list is empty', () => {
// assert
expect(broadcastStore.listeners).toBeEmpty()
expect(broadcastStore.history).toBeEmpty()
expect(counter).toEqual(0)
})
})
describe('WHEN: there are no listeners AND we dispatch an action', () => {
resetStore()
it('THEN: the action is added, but no listener acts', () => {
// act
broadcastStore.dispatch('broadcastMessage', 'addOne')
// assert
expect(broadcastStore.listeners).toBeEmpty()
expect(broadcastStore.history).toContain('broadcastMessage')
expect(broadcastStore.history.length).toEqual(1)
expect(counter).toEqual(0)
})
})
describe('WHEN: there is a listener AND we dispatch an action', () => {
it('THEN: if the action matches what a listener expects, that listener acts', () => {
// assert
resetStore()
expect(broadcastStore.listeners).toBeEmpty()
expect(broadcastStore.history).toBeEmpty()
// act
broadcastStore.subscribe(adderWorker)
broadcastStore.dispatch('broadcastMessage', 'addOne')
// assert
expect(broadcastStore.listeners.length).toEqual(1)
expect(broadcastStore.history.length).toEqual(1)
expect(counter).toEqual(1)
})
it('THEN: if the action does not match what a listener expects, no listener acts', () => {
// arrange
resetStore()
counter = 0
broadcastStore.subscribe(adderWorker)
// assert
expect(broadcastStore.listeners.length).toEqual(1)
expect(broadcastStore.history).toBeEmpty()
// act
broadcastStore.dispatch('broadcastMessage', 'noListener')
// assert
expect(broadcastStore.listeners.length).toEqual(1)
expect(broadcastStore.history.length).toEqual(1)
expect(counter).toEqual(0)
})
})
describe('WHEN: there is a listener AND we unsubscribe it before dispatching its matching action', () => {
it('THEN: there are no listeners that can act', () => {
// arrange
resetStore()
counter = 0
broadcastStore.subscribe(adderWorker)
// assert
expect(broadcastStore.listeners.length).toEqual(1)
expect(broadcastStore.history).toBeEmpty()
// act
broadcastStore.unsubscribe(adderWorker)
broadcastStore.dispatch('broadcastMessage', 'addOne')
// assert
expect(broadcastStore.listeners).toBeEmpty()
expect(broadcastStore.history.length).toEqual(1)
expect(counter).toEqual(0)
})
})
})