Loading
Current section: Setup 5 exercises
solution

Multiple Workspaces Solution

Set up Vitest with unit and edge workspaces, using node and edge-runtime environments, to test different layers of your app.

Loading solution

Transcript

00:00 Let's start by defining multiple projects in VTest, one for our unit tests and another for our edge function tests. To do that, head to your VTest configuration, and in this test object, add a new property called projects. Assign it an empty array as a value, for now. You might have

00:16 used a different property before here called workspace, and while it will still work in the current version of VTest, it's being deprecated, so highly recommend to use the projects property instead from now on. Luckily, the value to these properties remains the same, and you can provide a combination of different things to this array. You can provide an inline VTest configuration,

00:36 this is something that we're going to use right now, and you can also provide a path to a VTest config, maybe if it's nested somewhere like this. Alternatively, you can provide a whole pattern here. For example, if you're in a monorepo, you can specify that VTest should look up

00:50 nested VTest configurations matching this pattern. This is really handy. So, for now, let's define inline configuration for our unit tests. Provide the test key again, because we are defining our configuration from the root. Give it a distinct name, unit. Specify that we're going to use globals

01:06 here, and provide environment as node. Now, the only thing remaining is to tell VTest which files should be considered unit tests. In other words, which files should belong to this project. You can do that by providing the include property, and here you can provide file patterns to match. So,

01:22 let's say that all tests ending in .test.ts will be considered a part of our unit project. In a similar manner, let's define VTest configuration for our edge function tests. I will copy this object and give it another name, so let's call it edge. We'll still use global functions like test

01:38 and expect. The environment, though, will be different. We will use a custom environment called edge runtime that we will install in a second, and the pattern will be different as well. We will target tests ending on .edge.test.ts, and once you do, you can spot that this pattern

01:55 actually will include this one as well. So, our tests will overlap, and that's not very nice. To fix that, let's go to the unit test here, which has a more permissive pattern, and provide the exclude area explicitly, because the options you provide here in your configurations

02:09 are taken as is. You can merge them with the root level options by providing the extend property here, but you can also be explicit and have every project self-contained. So, to exclude this, we'll simply provide this edge test pattern over here, and there's just one tiny catch.

02:26 Because of this explicitness that I mentioned, VTest will not merge any of these properties with VTest defaults. So, for example, if you run unit tests right now, it may accidentally pick up tests matching this pattern from your not module directories, and that's not nice.

02:40 And to fix that problem, head to the VTest slash config import, and import config defaults object. This object contains all the default values for VTest configuration, and now you can go to this exclude pattern for unit tests, and spread the value of config default slash exclude.

02:58 So, this exclude here will contain the different exclude patterns that VTest has, for example, for not modules. And now, this concludes the definition of these two separate projects. So, to summarize quickly, what we have is, in our tests, we have projects, which is an array of different VTest projects, one for unit tests, and another for edge function tests. Now that we have

03:18 this defined, it's time for us to configure this edge runtime environment, so these edge function tests can even run. I'll open my terminal and run npm install, and install all the packages necessary for my edge function tests. Now, this completes the test setup, so it's time for us to write the

03:33 tests themselves. Let's do the unit tests first. So, in this slugify.test.ts test for the slugify function, I will create a new test case, call it returns a slugified string, and use this slugify function as I expect. So, if I provided a string with a space, for example, over here, I expect

03:51 the return result to be hello world, where the space gets replaced with a dash, which is very common when you slugify strings in JavaScript. And now to the edge function tests. So, the request handler function I have here runs in an edge runtime, and in order for me to test it reliably, I need to replicate that environment in my tests as well. That's why we installed all of those

04:10 dependencies before. I can head to the test file at handler.edge.test.ts and do a few things related to the test setup first. So, I'm going to import from edge runtime package the class called edge runtime. Then, I will create a variable called runtime that will be instantiation of this class

04:27 new edge runtime. And here, I need to provide the code to execute in this special edge runtime environment. For this, I will import my code from the function, from this handler that I want to test, and I will add ?raw, which will use the raw loader in VTest to load this module as string,

04:46 basically to load the content of that module instead of the expert that that module has. And I will name it initial code and provide here as a shorthand property like this. Now, I'll create a simple test case called returns user by id, make it a promise, and orchestrate

05:04 my test like this. So, what's happening here is I'm using this runtime object to call dispatch fetch methods, which is a special method to perform a fetch request within that edge runtime, and then I'm just getting the response back and asserting on that response, making sure that the

05:18 JSON body of this response equals to the object that I'm returning from my edge handler over here. And this concludes my edge test case, as well as my unit test cases. Let's run those projects right now through the CLI. So, we can open the terminal, and just as normal, we would run npm test,

05:35 which runs the VTest command, and you can see that it prints the results of both of these projects. First, here is the unit project with our slugify test and the edge project with our handler test. This is very handy to run all our projects at the same time, but you can also run a specific project in isolation. If you use the Vita CLI and then provide it with the option project and

05:55 specify the project name, for example, unit, this will only run the unit test, which you can see in the test report. And in the same way, you can provide a different name, for example, edge to run our edge handler tests, and here we have the results as well.