Skip to content

Commit

Permalink
feat(overmind): statemachines updated api
Browse files Browse the repository at this point in the history
  • Loading branch information
christianalfoni committed Jan 23, 2021
1 parent f879801 commit 364f93e
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 49 deletions.
151 changes: 131 additions & 20 deletions packages/node_modules/overmind/src/statemachine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ describe('Statemachine', () => {

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

type States = {
type States = {
state: 'FOO'
string: string
} | {
state: 'BAR'
number: number
}

const state = statemachine<States>({
FOO: ['BAR'],
BAR: ['FOO']
}, {
state: 'FOO'
state: 'FOO',
string: 'hey'
})

const config = {
state,
}
Expand All @@ -27,6 +31,7 @@ describe('Statemachine', () => {

expect(overmind.state.state).toBe('FOO')
})

test('should transition state', () => {
type States = {
state: 'FOO'
Expand All @@ -38,10 +43,10 @@ describe('Statemachine', () => {
FOO: ['BAR'],
BAR: ['FOO']
}, {
state: 'FOO'
state: 'FOO',
})
const transition: Action = ({ state }) => {
state.transition('BAR')
state.transition('BAR', {})
}

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

const overmind = createOvermindMock(config)


overmind.actions.transition()
expect(overmind.state.state).toBe('BAR')
})

test('should ignore transition to invalid state', () => {

type States = {
Expand All @@ -72,7 +80,7 @@ describe('Statemachine', () => {
state: 'FOO'
})
const transition: Action = ({ state }) => {
state.transition('BAR')
state.transition('BAR', {})
}

const config = {
Expand All @@ -88,6 +96,7 @@ describe('Statemachine', () => {
overmind.actions.transition()
expect(overmind.state.state).toBe('FOO')
})

test('should run entry and exit transition', async () => {
expect.assertions(3)
type States = {
Expand All @@ -103,12 +112,13 @@ describe('Statemachine', () => {
state: 'FOO'
})

const transition: Action = ({ state }) => {
if (state.transition('BAR')) {
expect(state.state).toBe('BAR')
state.transition('FOO')
expect(state.state).toBe('FOO')
}
const transition: Action = async ({ state }) => {
state.transition('BAR', {}, (barState) => {
expect(barState.state).toBe('BAR')
state.transition('FOO', {}, (fooState) => {
expect(fooState.state).toBe('FOO')
})
})
}

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

const overmind = createOvermindMock(config)

await overmind.actions.transition()
expect(overmind.state.state).toBe('FOO')
})

test('should flush changes to transitions', () => {
expect.assertions(1)

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

const transition: Action = ({ state }) => {
state.transition('BAR')
state.transition('BAR', {})
}

const config = {
Expand All @@ -159,7 +171,7 @@ describe('Statemachine', () => {
})
overmind.actions.transition()
})

test('should error when mutating async in transitions', async () => {
expect.assertions(1)

Expand All @@ -176,10 +188,10 @@ describe('Statemachine', () => {
state: 'FOO'
})
const transition: Action = async ({ state }) => {
if (state.transition('BAR')) {
await state.transition('BAR', {}, async () => {
await Promise.resolve()
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(true)
}
})
}

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

return overmind.actions.transition()
})

test('should enable mutations after new async matching or transition', async () => {
expect.assertions(3)

Expand All @@ -211,19 +224,18 @@ describe('Statemachine', () => {
state: 'FOO',
})
const transition: Action = async ({ state }) => {
if (state.transition('BAR')) {
await state.transition('BAR', {}, async () => {
await Promise.resolve()
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(true)
if (state.matches('BAR')) {
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(false)
await Promise.resolve()
if (state.transition('FOO')) {
state.transition('FOO', {}, () => {
expect(state[PROXY_TREE].master.mutationTree.isBlocking).toBe(false)
}
})
}
}
})
}



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

return overmind.actions.transition()
})

test('should make copy of statemachine during tests', () => {

type States = {
Expand Down Expand Up @@ -282,4 +295,102 @@ describe('Statemachine', () => {

expect(overmind2.state.obj.foo).toBe('bar')
})
test('should have base state', () => {

type States = {
state: 'FOO'
} | {
state: 'BAR'
}

type Base = {
obj: {
foo: string
}
}

const state = statemachine<States, Base>({
FOO: ['BAR'],
BAR: ['FOO']
}, {
state: 'FOO',
}, {
obj: {
foo: 'bar'
}
})

const config = {
state,
actions: {
changeFoo({ state }) {
state.obj.foo = 'bar2'
}
}
}

const overmind = createOvermindMock(config)

// @ts-ignore
overmind.actions.changeFoo()
expect(overmind.state.obj.foo).toBe('bar2')


const overmind2 = createOvermindMock(config)

expect(overmind2.state.obj.foo).toBe('bar')
})
test('should delete existing state and merge in new state, keep base', () => {

type States = {
state: 'FOO'
foo: string
} | {
state: 'BAR'
bar: number
}

type Base = {
baz: boolean
}

const state = statemachine<States, Base>({
FOO: ['BAR'],
BAR: ['FOO']
}, {
state: 'FOO',
foo: 'bar'
}, {
baz: true
})

const transition: Action = async ({ state }) => {
await state.transition('BAR', {
bar: 123,
}, async (barState) => {
expect(barState.bar).toBe(123)
await Promise.resolve()
await state.transition('FOO', {
foo: '123'
}, async (fooState) => {
expect(fooState.foo).toBe('123')
await Promise.resolve()
})
})

}

const config = {
state,
actions: {
transition
}
}

interface Action extends IAction<typeof config, void, Promise<void>> {}

const overmind = createOvermindMock(config)

overmind.actions.transition()
})
})
Loading

0 comments on commit 364f93e

Please sign in to comment.