Skip to content

Commit 364f93e

Browse files
feat(overmind): statemachines updated api
1 parent f879801 commit 364f93e

File tree

2 files changed

+190
-49
lines changed

2 files changed

+190
-49
lines changed

packages/node_modules/overmind/src/statemachine.test.ts

Lines changed: 131 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@ describe('Statemachine', () => {
77

88
test('should set initial state', () => {
99

10-
type States = {
10+
type States = {
1111
state: 'FOO'
12+
string: string
1213
} | {
1314
state: 'BAR'
15+
number: number
1416
}
1517

1618
const state = statemachine<States>({
1719
FOO: ['BAR'],
1820
BAR: ['FOO']
1921
}, {
20-
state: 'FOO'
22+
state: 'FOO',
23+
string: 'hey'
2124
})
25+
2226
const config = {
2327
state,
2428
}
@@ -27,6 +31,7 @@ describe('Statemachine', () => {
2731

2832
expect(overmind.state.state).toBe('FOO')
2933
})
34+
3035
test('should transition state', () => {
3136
type States = {
3237
state: 'FOO'
@@ -38,10 +43,10 @@ describe('Statemachine', () => {
3843
FOO: ['BAR'],
3944
BAR: ['FOO']
4045
}, {
41-
state: 'FOO'
46+
state: 'FOO',
4247
})
4348
const transition: Action = ({ state }) => {
44-
state.transition('BAR')
49+
state.transition('BAR', {})
4550
}
4651

4752
const config = {
@@ -54,9 +59,12 @@ describe('Statemachine', () => {
5459
interface Action extends IAction<typeof config, void, void> {}
5560

5661
const overmind = createOvermindMock(config)
62+
63+
5764
overmind.actions.transition()
5865
expect(overmind.state.state).toBe('BAR')
5966
})
67+
6068
test('should ignore transition to invalid state', () => {
6169

6270
type States = {
@@ -72,7 +80,7 @@ describe('Statemachine', () => {
7280
state: 'FOO'
7381
})
7482
const transition: Action = ({ state }) => {
75-
state.transition('BAR')
83+
state.transition('BAR', {})
7684
}
7785

7886
const config = {
@@ -88,6 +96,7 @@ describe('Statemachine', () => {
8896
overmind.actions.transition()
8997
expect(overmind.state.state).toBe('FOO')
9098
})
99+
91100
test('should run entry and exit transition', async () => {
92101
expect.assertions(3)
93102
type States = {
@@ -103,12 +112,13 @@ describe('Statemachine', () => {
103112
state: 'FOO'
104113
})
105114

106-
const transition: Action = ({ state }) => {
107-
if (state.transition('BAR')) {
108-
expect(state.state).toBe('BAR')
109-
state.transition('FOO')
110-
expect(state.state).toBe('FOO')
111-
}
115+
const transition: Action = async ({ state }) => {
116+
state.transition('BAR', {}, (barState) => {
117+
expect(barState.state).toBe('BAR')
118+
state.transition('FOO', {}, (fooState) => {
119+
expect(fooState.state).toBe('FOO')
120+
})
121+
})
112122
}
113123

114124
const config = {
@@ -121,9 +131,11 @@ describe('Statemachine', () => {
121131
interface Action extends IAction<typeof config, void, void | Promise<void>> {}
122132

123133
const overmind = createOvermindMock(config)
134+
124135
await overmind.actions.transition()
125136
expect(overmind.state.state).toBe('FOO')
126137
})
138+
127139
test('should flush changes to transitions', () => {
128140
expect.assertions(1)
129141

@@ -141,7 +153,7 @@ describe('Statemachine', () => {
141153
})
142154

143155
const transition: Action = ({ state }) => {
144-
state.transition('BAR')
156+
state.transition('BAR', {})
145157
}
146158

147159
const config = {
@@ -159,7 +171,7 @@ describe('Statemachine', () => {
159171
})
160172
overmind.actions.transition()
161173
})
162-
174+
163175
test('should error when mutating async in transitions', async () => {
164176
expect.assertions(1)
165177

@@ -176,10 +188,10 @@ describe('Statemachine', () => {
176188
state: 'FOO'
177189
})
178190
const transition: Action = async ({ state }) => {
179-
if (state.transition('BAR')) {
191+
await state.transition('BAR', {}, async () => {
180192
await Promise.resolve()
181193
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(true)
182-
}
194+
})
183195
}
184196

185197
const config = {
@@ -195,6 +207,7 @@ describe('Statemachine', () => {
195207

196208
return overmind.actions.transition()
197209
})
210+
198211
test('should enable mutations after new async matching or transition', async () => {
199212
expect.assertions(3)
200213

@@ -211,19 +224,18 @@ describe('Statemachine', () => {
211224
state: 'FOO',
212225
})
213226
const transition: Action = async ({ state }) => {
214-
if (state.transition('BAR')) {
227+
await state.transition('BAR', {}, async () => {
215228
await Promise.resolve()
216229
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(true)
217230
if (state.matches('BAR')) {
218231
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(false)
219232
await Promise.resolve()
220-
if (state.transition('FOO')) {
233+
state.transition('FOO', {}, () => {
221234
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(false)
222-
}
235+
})
223236
}
224-
}
237+
})
225238
}
226-
227239

228240

229241
const config = {
@@ -239,6 +251,7 @@ describe('Statemachine', () => {
239251

240252
return overmind.actions.transition()
241253
})
254+
242255
test('should make copy of statemachine during tests', () => {
243256

244257
type States = {
@@ -282,4 +295,102 @@ describe('Statemachine', () => {
282295

283296
expect(overmind2.state.obj.foo).toBe('bar')
284297
})
298+
test('should have base state', () => {
299+
300+
type States = {
301+
state: 'FOO'
302+
} | {
303+
state: 'BAR'
304+
}
305+
306+
type Base = {
307+
obj: {
308+
foo: string
309+
}
310+
}
311+
312+
const state = statemachine<States, Base>({
313+
FOO: ['BAR'],
314+
BAR: ['FOO']
315+
}, {
316+
state: 'FOO',
317+
}, {
318+
obj: {
319+
foo: 'bar'
320+
}
321+
})
322+
323+
const config = {
324+
state,
325+
actions: {
326+
changeFoo({ state }) {
327+
state.obj.foo = 'bar2'
328+
}
329+
}
330+
}
331+
332+
const overmind = createOvermindMock(config)
333+
334+
// @ts-ignore
335+
overmind.actions.changeFoo()
336+
expect(overmind.state.obj.foo).toBe('bar2')
337+
338+
339+
const overmind2 = createOvermindMock(config)
340+
341+
expect(overmind2.state.obj.foo).toBe('bar')
342+
})
343+
test('should delete existing state and merge in new state, keep base', () => {
344+
345+
type States = {
346+
state: 'FOO'
347+
foo: string
348+
} | {
349+
state: 'BAR'
350+
bar: number
351+
}
352+
353+
type Base = {
354+
baz: boolean
355+
}
356+
357+
const state = statemachine<States, Base>({
358+
FOO: ['BAR'],
359+
BAR: ['FOO']
360+
}, {
361+
state: 'FOO',
362+
foo: 'bar'
363+
}, {
364+
baz: true
365+
})
366+
367+
const transition: Action = async ({ state }) => {
368+
await state.transition('BAR', {
369+
bar: 123,
370+
}, async (barState) => {
371+
expect(barState.bar).toBe(123)
372+
await Promise.resolve()
373+
await state.transition('FOO', {
374+
foo: '123'
375+
}, async (fooState) => {
376+
expect(fooState.foo).toBe('123')
377+
await Promise.resolve()
378+
})
379+
})
380+
381+
}
382+
383+
const config = {
384+
state,
385+
actions: {
386+
transition
387+
}
388+
}
389+
390+
interface Action extends IAction<typeof config, void, Promise<void>> {}
391+
392+
const overmind = createOvermindMock(config)
393+
394+
overmind.actions.transition()
395+
})
285396
})

0 commit comments

Comments
 (0)