Major Changes
-
#3036 Thanks @mattpocock, @davidkpiano! - Substantially simplified how paths and plans work in
TestModel
. ChangedgetShortestPlans
andgetSimplePlans
togetShortestPaths
andgetSimplePaths
. These functions now return an array of paths, instead of an array of plans which contain paths.Also added
getPaths
, which defaults togetShortestPaths
. This can be passed apathGenerator
to customize how paths are generated.
-
#3036 Thanks @mattpocock! - Moved event cases out of
events
, and into their own attribute calledeventCases
:const model = createTestModel(machine, { eventCases: { CHOOSE_CURRENCY: [ { currency: 'GBP' }, { currency: 'USD' } ] } }); model.getPaths().forEach((path) => { it(path.description, async () => { await path.test({ events: { CHOOSE_CURRENCY: ({ event }) => { console.log(event.currency); } } }); }); });
eventCases
will also now always produce a new path, instead of only creating a path for the first case which matches.
- #3036 Thanks @davidkpiano! - Removed
.testCoverage()
, and instead madegetPlans
,getShortestPlans
andgetSimplePlans
cover all states and transitions enabled by event cases by default.
-
#3036 Thanks @davidkpiano! - Added validation on
createTestModel
to ensure that you don't include invalid machine configuration in your test machine. Invalid machine configs includeinvoke
,after
, and any actions with adelay
.Added
createTestMachine
, which provides a slimmed-down API for creating machines which removes these types from the config type signature.
-
#3036 Thanks @davidkpiano! -
getShortestPaths()
andgetPaths()
will now traverse all transitions by default, not just all events.Take this machine:
const machine = createTestMachine({ initial: 'toggledOn', states: { toggledOn: { on: { TOGGLE: 'toggledOff' } }, toggledOff: { on: { TOGGLE: 'toggledOn' } } } });
In
@xstate/test
version 0.x, this would run this path by default:toggledOn -> TOGGLE -> toggledOff
This is because it satisfies two conditions:
- Covers all states
- Covers all events
But this a complete test - it doesn't test if going from
toggledOff
totoggledOn
works.Now, we seek to cover all transitions by default. So the path would be:
toggledOn -> TOGGLE -> toggledOff -> TOGGLE -> toggledOn
-
#3036 Thanks @mattpocock, @davidkpiano! - Moved
events
fromcreateTestModel
topath.test
.Old:
const model = createTestModel(machine, { events: {} });
New:
const paths = model.getPaths().forEach((path) => { path.test({ events: {} }); });
This allows for easier usage of per-test mocks and per-test context.
-
#3036 Thanks @mattpocock, @davidkpiano! - Added
states
topath.test()
:const paths = model.getPaths().forEach((path) => { path.test({ states: { myState: () => {}, 'myState.deep': () => {} } }); });
This allows you to define your tests outside of your machine, keeping the machine itself easy to read.
Minor Changes
- #3036 Thanks @mattpocock, @davidkpiano! - Added
path.testSync(...)
to allow for testing paths in sync-only environments, such as Cypress.