Check out a free preview of the full State Machines in JavaScript with XState course:
The "XState FSM, Testing XState & immer" Lesson is part of the full, State Machines in JavaScript with XState course featured in this preview video. Here's what you'd learn in this lesson:

David explains that XState with finite state machine Finite State Machine or FSM has no hierarchy, which allows the package to be small, introduces testing with XState, and recommends the use of the immer library. The immer library allows developers to update a state by mutating a proxy of the state.

Get Unlimited Access Now

Transcript from the "XState FSM, Testing XState & immer" Lesson

[00:00:00]
>> Other examples that I want to talk about as well. There's different packages for XState. We talked about xstate/react and xstate/vue. If you want a very small version of XState, less than 2 kilobytes, then there's xstate/fsm. So in the first half of this workshop, we talked about flat finite state machines.

[00:00:22] So that's state machines without nesting, without hierarchy or any of that. And for a lot of use cases, that works pretty well. But we saw that with combinatorial explosion, you do need those nested and those orthogonal states in order to organize and maintain your states in a much better way.

[00:00:42] And so the xstate/fsm package provides a very, very similar setup to what XState provides you, with one difference, no hierarchy. And that's what allows this package to be really small. Additionally, there is the xstate/test package. And so this package is really useful for testing, and not just testing your state machines, but testing any app at all.

[00:01:11] It utilizes something that's called model-based testing in which there's an article here and a talk here that I really recommend you watch. Because model-based testing is another one of those techniques which is not talked about too much nowadays, but it is a really powerful technique. In essence, a model-based test is a test that's, well, based on the model.

[00:01:33] You create the model of your application which is saying that this application behaves in this way. We have one state where the user could do this, or the user could do something else. And depending on what the user does, you go to different states. And when you define your model in that way, you could use that model to test your application by adding test inside the state definition.

[00:02:01] So you could have a meta, test, and, for example, over here, we're waiting for the input to be checked. So what xstate/test is going to do is it's going to essentially write all of your end-to-end tests for you. You specify what the states are, what the transitions are, what those events mean.

[00:02:20] So for example, if I have a button click event, I want to map that to directly clicking a button. And if I'm in a state, I want to assert that I am actually in that state. What XState is going to do then is it's going to trace all the paths from the initial state to every other state and make sure that all those paths are traversable.

[00:02:41] And if it's not, xstate/test is going to tell you exactly where it failed. So model-based testing is a very powerful technique for auto-generating tests instead of handwriting tests. So there's a really good post on model-based testing if you're interested by Sauce Labs. So model-based testing. And it talks about, it's this one, the challenges and benefits of model-based testing.

[00:03:09] So if you're interested, I really recommend you check that out. So another interesting addition to XState recently is xstate/immer. So the more you work with XState, the more you find that things start making sense. You start thinking in terms of models, and in terms of events, and state transitions.

[00:03:36] And it's really useful, but you also find yourself maybe being a little bit frustrated with how you assign and update states. And that's where xstate/immer comes into play. If you haven't heard of immer, immer is a really, really useful library by Michel Weststrate, where immer allows you to basically take your state, mutate it.

[00:03:58] And it's not really mutating, it's mutating a proxy of the state. And whatever mutations you make, it's going to apply those immutably to the original state. And so we could do the same thing in XState. So by using immer in XState, now your assignments look very mutable. But behind the scenes, for example, ctx.count++, behind the scenes, these are immutable updates.

[00:04:27] And so this is really useful if you want to describe logic safely and state updates in a safer way. But just making sure that you are immutable all the way through. So I highly recommend you check out xstate/immer. It's a really useful library and I've been using it to help with XState work as well.

[00:04:50] So Matt asks in the chat, if you use xstate/fsm and after integrating, you feel like you need full exit. Is it a matter of switching packages? Yes, so if you have xstate/fsm, you could use the exact same machine that you create in xstate/fsm with normal XState. So upgrading is seamless.

[00:05:13] All you do is you get rid of this @ sign, you get rid of FSM, and everything is going to work exactly the same.