Testing
Caution
This is the only frontend testing framework that sparks joy.
#
Why test your logics in the first place?While adding a new feature into a logic, such as "make it possible to duplicate dashboards" into
a fictional dashboardsLogic.ts
, you write a clear set of actions, listeners, reducers and so forth.
However, when you read dashboardsLogic.ts
, its code is grouped by functionality: first all actions, then all reducers.
The original intent behind each line of code is lost:
There is a lot of value in having a logic grouped by functionality. It ultimately makes it easy to add new features, as you have a clear overview of what's already there.
Yet if you're not careful, it's also easy to make mistakes. You could change an action without understanding its place in an existing feature, and break things.
That is why we write logic tests.
When building a feature, write the same story twice. Once in a test, grouping all new code together, and once more in the logic, code split up by functionality.
One side checking the other. Two factor authentication for your code.
#
Live-Replay testingTo test a logic, you dispatch some actions, and make sure they in turn change the right values and/or dispatch other actions.
You literally just write down what should happen in a chain of dispatched actions and matched values:
It doesn't matter if the actions you're matching have already been dispatched or if we need to wait for them.
.toDispatchActions
can both query a recorded history of actions, and wait for new ones to arrive.
In turn, .toMatchValues
matches values as they were after the matched action, no matter what they are now.
#
Kea-Test-Utils#
Installing- Install and configure jest
- Install
kea-test-utils
with either:yarn add --dev kea-test-utils
npm install --save-dev kea-test-utils
#
Reset the context before each testKea stores everything in a context. Call resetContext() before each test to reset Kea's brain.
#
Mount and unmount your logicRead the docs on Lifecycles and Mounting and Unmounting. Then make sure your logic is mounted before the tests run:
expectLogic()
#
The entrypoint to the Live-Replay logic testing. All of these options work:
.toDispatchActions()
#
Match dispatched actions in order. Waits up to 3s
and requires await
if any of the actions haven't already happened.
.toDispatchActionsInAnyOrder()
#
Match dispatched actions in any order. Waits up to 3s
and requires await
if any of the actions haven't already happened.
.toNotHaveDispatchedActions()
#
Make sure none of the given actions have been dispatched. Use with delay
or toFinishListeners
.
.toFinishListeners()
#
Wait for all listeners on a logic to finish.
.toFinishAllListeners()
#
Wait for all running listeners to finish.
.toMatchValues()
#
Match the store's state as it was after a matched action.
truth
and partial
#
Use the truth
and partial
helpers, or jest's expect
matchers to make matching easier:
#
Match values at the end of historyIf you use toDispatchActions([])
, we lock the history index that toMatchValues
uses to the last matched action.
This allows you to effortlessly query history, but sometimes you might want to see what are the current values. Here you have two options.
- Actually match a better action with
.toDispatchActions(['doSomethingElse'])
if applicable - Use
.clearHistory()
to reset all matched actions. See below for details.
.toMount()
#
Expect specific logics to be mounted
.printActions()
#
Show what actions have been printed now, and where the current pointer for value matching is.
.delay()
#
Wait the time in ms
.
.clearHistory()
#
Forget anything ever happened. This can be useful if you want to reset the index used for toMatchValues
after matching
with toDispatchActions
.
#
Common issues#
Adapt kea-router to run in nodejsTo run kea-router in a jest test, you need to pass it a mocked history object. Otherwise and especially when using jsdom, the URL might persist between tests.
Install the memory
package, and adapt as needed:
#
How to test Kea and React togetherIf you keep all your state in Kea, and only test your logics, you're mostly done with your frontend testing.
What's missing is making sure the right values are rendered in the right places, and the right actions get clicked when the right button is pressed.
I'm not yet ready to recommend a best practice here. However a year ago this approach got the job done.