-
-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for async deciders in the decider specification, fix typo
- Loading branch information
1 parent
acc73ab
commit caba9e5
Showing
2 changed files
with
380 additions
and
85 deletions.
There are no files selected for viewing
231 changes: 231 additions & 0 deletions
231
src/packages/emmett/src/testing/deciderSpecification.async.unit.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import { describe, it } from 'node:test'; | ||
import { IllegalStateError, ValidationError } from '../errors'; | ||
import { AssertionError, assertTrue } from '../testing/assertions'; | ||
import { type Command, type Event } from '../typing'; | ||
import { DeciderSpecification } from './deciderSpecification'; | ||
|
||
type DoSomething = Command<'Do', { something: string }>; | ||
type SomethingHappened = Event<'Did', { something: string }>; | ||
type Entity = { something: string }; | ||
|
||
const decide = async ( | ||
{ data: { something } }: DoSomething, | ||
_entity: Entity, | ||
): Promise<SomethingHappened | [] | [SomethingHappened]> => { | ||
const event: SomethingHappened = { type: 'Did', data: { something } }; | ||
|
||
if (something === 'Ignore!') return []; | ||
if (something === 'Array!') return [event]; | ||
if (something !== 'Yes!') throw new IllegalStateError('Nope!'); | ||
|
||
return Promise.resolve(event); | ||
}; | ||
|
||
const initialState = (): Entity => ({ something: 'Meh' }); | ||
|
||
const evolve = (_entity: Entity, _event: SomethingHappened): Entity => ({ | ||
something: 'Nothing', | ||
}); | ||
|
||
const given = DeciderSpecification.for({ | ||
decide: decide, | ||
evolve, | ||
initialState: initialState, | ||
}); | ||
|
||
void describe('AsyncDeciderSpecification', () => { | ||
void describe('then', () => { | ||
void it('then fails if returns event, but assertion has an empty array', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Yes!', | ||
}, | ||
}) | ||
.then([]); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message === | ||
`Arrays lengths don't match:\nExpected: 1\nActual: 0`, | ||
); | ||
} | ||
}); | ||
}); | ||
|
||
void describe('thenNothingHappened', () => { | ||
void it('thenNothingHappened succeeds if returns empty array', async () => { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Ignore!', | ||
}, | ||
}) | ||
.thenNothingHappened(); | ||
}); | ||
|
||
void it('thenNothingHappened fails if returns event', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Yes!', | ||
}, | ||
}) | ||
.thenNothingHappened(); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message === | ||
`Array is not empty [{"type":"Did","data":{"something":"Yes!"}}]:\nExpected: 1\nActual: 0`, | ||
); | ||
} | ||
}); | ||
|
||
void it('thenNothingHappened fails if returns array of events', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Array!', | ||
}, | ||
}) | ||
.thenNothingHappened(); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message === | ||
`Array is not empty [{"type":"Did","data":{"something":"Array!"}}]:\nExpected: 1\nActual: 0`, | ||
); | ||
} | ||
}); | ||
}); | ||
|
||
void describe('thenThrows', () => { | ||
void it('check error was thrown', async () => { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(); | ||
}); | ||
|
||
void it('checks error condition', async () => { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows((error) => error.message === 'Nope!'); | ||
}); | ||
|
||
void it('checks error type', async () => { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(IllegalStateError); | ||
}); | ||
|
||
void it('checks error type and condition', async () => { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(IllegalStateError, (error) => error.message === 'Nope!'); | ||
}); | ||
|
||
void it('fails if no error was thrown', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Yes!', | ||
}, | ||
}) | ||
.thenThrows(); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message === 'Handler did not fail as expected', | ||
); | ||
} | ||
}); | ||
|
||
void it('fails if wrong error type', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(ValidationError); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message.startsWith( | ||
'Caught error is not an instance of the expected type:', | ||
), | ||
); | ||
} | ||
}); | ||
|
||
void it('fails if wrong error type and correct condition', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(ValidationError, (error) => error.message === 'Nope!'); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message.startsWith( | ||
'Caught error is not an instance of the expected type:', | ||
), | ||
); | ||
} | ||
}); | ||
|
||
void it('fails if correct error type but wrong correct condition', async () => { | ||
try { | ||
await given([]) | ||
.when({ | ||
type: 'Do', | ||
data: { | ||
something: 'Nope!', | ||
}, | ||
}) | ||
.thenThrows(IllegalStateError, (error) => error.message !== 'Nope!'); | ||
} catch (error) { | ||
assertTrue( | ||
error instanceof AssertionError && | ||
error.message === | ||
`Error didn't match the error condition: Error: Nope!`, | ||
); | ||
} | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.