Multiple workspaces

Defining workspaces

First, I will configure Vitest to have two workspaces.
In vitest.config.ts, I will define a test.workspace property and assign an empty array as a value to it:
import { defineConfig } from 'vitest/config'

export default defineConfig({
	test: {
		workspace: [],
	},
})
Each entry in the test.workspace array will represent a standalone workspace (or project) that Vitest can run. Projects can have their own configurations, environments, and file patterns to know about the relevant test files.
For example, let's define a workspace configuration for unit tests:
import { defineConfig, configDefaults } from 'vitest/config'

export default defineConfig({
	test: {
		workspace: [
			{
				test: {
					name: 'unit',
					environment: 'node',
					globals: true,
					include: ['**/*.test.ts'],
					exclude: [...configDefaults.exclude, '**/*.edge.test.ts'],
				},
			},
		],
	},
})
Here, I am declaring the following:
  • The name of this workspace will be 'unit';
  • It will use node as the test environment;
  • It will have functions like test() and expect() available globally (globals: true);
  • It will only apply to the test files matching the **/*.test.ts pattern;
  • And, finally, it will exclude both the default patterns in Vitest (...configDefaults.exclude) and the edge test cases (**/*.edge.test.ts).
You may notice that this test object looks really similar to the root-level test you can define in vitest.config.ts. That's because it is! Vitest allows you to define an entire test configuration nested under your workspace.
Similarly, I will add a workspace for edge tests:
import { defineConfig, configDefaults } from 'vitest/config'

export default defineConfig({
	test: {
		workspace: [
			{
				test: {
					name: 'unit',
					environment: 'node',
					globals: true,
					include: ['**/*.test.ts'],
					exclude: [...configDefaults.exclude, '**/*.edge.test.ts'],
				},
			},
			{
				test: {
					name: 'edge',
					globals: true,
					environment: 'edge-runtime',
					include: ['**/*.edge.test.ts'],
				},
			},
		],
	},
})
One notable exception here is that I am using edge-runtime as the test environment for my edge tests. This will tap into the edge-runtime package we've installed earlier to give a proper test environment for our tests.
With Vitest configured, it is time to add some tests!

Unit tests

I will head to src/slugify.test.ts and write a simple unit test for the slugify() utility function:
import { slugify } from './slugify'

test('returns a slugified string', () => {
	expect(slugify('hello world')).toBe('hello-world')
})

Edge tests

Now, the test setup for src/api/handler.edge.test.ts will be slightly different.
I will start from importing the EdgeRuntime class from the edge-runtime package:
import { EdgeRuntime } from 'edge-runtime'
Then, let's get the request handler I need to test from ./handler:
import { EdgeRuntime } from 'edge-runtime'
import initialCode from './handler?raw'
πŸ¦‰ Notice that I am using a ?raw import modified so that initialCode is a string content of the module and not its exports. You will see why in a moment.
And now, I will declare the actual edge runtime that will evaluate and run my handler:
import { EdgeRuntime } from 'edge-runtime'
import initialCode from './handler?raw'

const runtime = new EdgeRuntime({
	initialCode,
})
While the edge-runtime test environment ensures that the correct global APIs are available in the test's context (like window or fetch), the EdgeRuntime instance creates an actual controlled runtime that will behave according to my handler (e.g. handle requests).
What remains is a test case where I will fetch some resource and assert that its response equals to that specified in ./handler:
import { EdgeRuntime } from 'edge-runtime'
import initialCode from './handler?raw'

const runtime = new EdgeRuntime({
	initialCode,
})

test('returns the user by id', async () => {
	const response = await runtime.dispatchFetch(
		'https://example.com/users/abc-123',
	)

	await expect(response.json()).resolves.toEqual({
		id: 'abc-123',
		name: 'John Maverick',
	})
})

Running tests

I can run all my tests at once using a single vitest command (or npm test already defined in the project's scripts):
npm test

 βœ“  unit  src/slugify.test.ts (1 test) 1ms
 βœ“  edge  src/api/handler.edge.test.ts (1 test) 3ms

 Test Files  2 passed (2)
      Tests  2 passed (2)
   Start at  11:17:31
   Duration  221ms (transform 31ms, setup 0ms, collect 30ms, tests 5ms, environment 16ms, prepare 73ms)
Notice how Vitest prints the workspace name (unit and edge) next to the respective test files. This lets you know which workspace is handling that file.
But I can also run individual workspaces by providing the --project option to the Vitest CLI and giving it the name of the workspace I want to run:
npm test -- --project=edge

 βœ“  edge  src/api/handler.edge.test.ts (1 test) 4ms
   βœ“ returns the user by id 3ms

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  11:18:55
   Duration  224ms (transform 17ms, setup 0ms, collect 19ms, tests 4ms, environment 16ms, prepare 32ms)
Providing --project=edge will run only those tests that match the include pattern of the 'edge' workspace in vitest.config.ts.

Please set the playground first

Loading "Multiple workspaces"
Loading "Multiple workspaces"
Login to get access to the exclusive discord channel.
  • πŸ§ͺVitest Patterns
    Testing
    Binalfew πŸš€ 🌌 ⚑:
    Hi <@283714112452821002> Working on your amazing Advanced Vitest Patterns. I was wondering if you ha...
    8 Β· a day ago
  • general
    Modals / Dialogs
    Lucas Wargha πŸš€ 🌌:
    It seems like modals and dialogs are becoming a hot topic on my team lately. I haven’t found a solid...
    • βœ…1
    3 Β· 3 months ago
  • general
    Welcome to EpicWeb.dev! Say Hello πŸ‘‹
    Kent C. Dodds β—† πŸš€πŸ†πŸŒŒβš‘:
    This is the first post of many hopefully!
    • 18
    86 Β· 2 years ago
  • general
    epic stack website initial load at home page is unstyled (sometimes)
    osmancakir πŸš€ 🌌:
    Sometimes (especially when it is loaded first time on a new browser etc.) I see this unstyled versio...
    • βœ…1
    10 Β· 6 months ago
  • general
    Resource / Api endpoints on epic stack / RR7
    Lucas Wargha πŸš€ 🌌:
    Hi everyone! Quick question for those using the Epic Stack: How are you handling resource routes ...
    • βœ…1
    2 Β· 5 months ago
  • general
    Epic stack using tanstack form
    Lucas Wargha πŸš€ 🌌:
    https://github.com/epicweb-dev/epic-stack/compare/epicweb-dev:main...wargha:feature/tanstack-form-ex...
    • βœ…1
    3 Β· 5 months ago
  • general
    Init command outdated on the EpicWeb website
    Virgile πŸ† 🌌:
    Hi everyone. I've initialized a new epic-stack project yesterday. Following instructions from http...
    • βœ…1
    3 Β· 6 months ago
  • general
    Mark as complete, resets the first time you click it.
    Daniel V.C πŸš€ 🌌:
    Not sure if anyone else has had this issue, as i've not seen anyone else talk about it, but I find ...
    • βœ…1
    8 Β· 6 months ago
  • πŸ’Ύdata
    general
    πŸ“forms
    πŸ”­foundations
    double underscore?
    trendaaang 🌌:
    What with the `__note-editor.tsx`? I don't see that in the Remix docs and I don't remember Kent talk...
    • βœ…1
    2 Β· a year ago
  • general
    Keeping Epic Stack Projects Free on Fly – Any Tips?
    Lucas Wargha πŸš€ 🌌:
    I’ve been experimenting with the Epic Stack and deploying some dummy projects on Fly. I noticed that...
    • βœ…1
    0 Β· 6 months ago
  • πŸ’Ύdata
    general
    πŸ“forms
    πŸ”­foundations
    Creating Notes
    Scott 🌌 πŸ†:
    Does anybody know in what workshop we create notes? I would like to see the routing structure. So fa...
    • βœ…1
    2 Β· 8 months ago
  • πŸ”­foundations
    πŸ’Ύdata
    general
    πŸ“forms
    πŸ”auth
    Thank you for the inspiration
    Binalfew πŸš€ 🌌 ⚑:
    <@105755735731781632> I wanted to thank you for the incredible knowledge I gained from your Epic Web...
    • ❀️1
    1 Β· 9 months ago
  • general
    npm install everytime I setup a new playground
    Duki 🌌:
    Is it normal that I have to run `npm install` in my playground directory, everytime I setup the play...
    • βœ…1
    2 Β· a year ago
  • general
    Migration to Vite: Server-only module referenced by client
    Fabian 🌌:
    Hi, I'm working on migrating to Vite following the remix docs (https://remix.run/docs/en/main/guides...
    • βœ…1
    1 Β· a year ago
  • general
    Remix Vite Plugin
    Binalfew πŸš€ 🌌 ⚑:
    <@105755735731781632> Now that remix officially supports vite (though not stable) what does it mean...
    • βœ…1
    3 Β· 2 years ago
  • general
    πŸ”­foundations
    Solutions video on localhost:5639 ?
    quang πŸš€ 🌌:
    Hi, so I'm having a hard time navigating (hopefully will be better with time) The nav on epicweb.de...
    • βœ…1
    9 Β· 2 years ago
  • general
    Epicshop is now social and mobile friendly!
    Kent C. Dodds β—† πŸš€πŸ†πŸŒŒβš‘:
    I'm excited to announce that now the Epic Web workshops are mobile friendly! https://foundations.ep...
    • πŸŽ‰2
    0 Β· a year ago