Skip to main content

Testing — Part 2: Setting Up Vitest in a Monorepo

Ticket: SCRUM-125 | Status: Approved ✅

What This Task Was About

The VocabPal project is a monorepo with three workspaces: shared/ (pure TypeScript services), web/ (React app), and extension/ (Chrome extension). The goal of this ticket was to install Vitest and configure it properly for each workspace, so each package can run its own tests independently.

Acceptance criteria:

  • Vitest installed
  • A vitest.config.ts created for each workspace
  • Each workspace's package.json has a working test script

What I Did

Installed Vitest at the root and created a vitest.config.ts for each workspace. Initial config looked like this across all three:

// shared/vitest.config.ts (also used for web/ and extension/ — this was wrong)
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'node',
},
});

I also needed to add test scripts to each workspace's package.json.


Mistakes and Fixes

Issue 1: Wrong test environment for web/ and extension/

I set environment: 'node' for all three workspaces. That's correct for shared/ — it's pure TypeScript with no DOM. But web/ and extension/ are React apps. Running React component tests in a node environment means there's no document, no window, no DOM at all — tests would crash immediately.

Fix: Use environment: 'jsdom' for web/ and extension/. jsdom is a browser-like environment that simulates the DOM inside Node.js, which is what React Testing Library requires.

// web/vitest.config.ts and extension/vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'jsdom', // ← not 'node'
},
});
// shared/vitest.config.ts — node is correct here
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'node',
},
});

Issue 2: Workspace test scripts not updated

The package.json files in each workspace still had the placeholder:

"test": "echo Error: no test specified && exit 1"

I added the vitest.config.ts files but forgot to actually wire up the test commands.

Fix: Update the test script in each workspace's package.json:

"scripts": {
"test": "vitest",
"test:watch": "vitest --watch"
}

This matters because in a monorepo you often want to run tests for just one package (e.g. cd shared && npm test). If the workspace script is still a placeholder, that won't work.


Key Takeaways

  • node environment = no DOM. Use it for pure TypeScript/Node.js code.
  • jsdom environment = simulated browser DOM. Required for React component tests.
  • Each workspace in a monorepo should have its own vitest.config.ts and its own test script.
  • globals: true means describe, it, expect are available globally in every test file — no imports needed.

Code Review Feedback

Katie Nguyen (2026-03-02):

[Code Review - Changes Needed] SCRUM-125: Set up Vitest in monorepo

Good start — Vitest is installed and configs are in place. Two things to fix:

Issue 1: Wrong test environment for web and extension

All three vitest.config.ts files use environment: 'node'. That is correct for shared/ (pure TypeScript, no DOM). But web/ and extension/ are React apps — they render components, interact with the DOM, handle click events. Running those tests in a node environment means no document, no window, no DOM at all — your tests would crash immediately.

Fix: change environment to 'jsdom' in web/vitest.config.ts and extension/vitest.config.ts.

export default defineConfig({
test: {
globals: true,
environment: 'jsdom', // <-- change this
},
});

Issue 2: Workspace test scripts not updated

The shared/, web/, and extension/ package.json files still have the placeholder: "test": "echo Error: no test specified && exit 1". Fix:

"scripts": {
"test": "vitest",
"test:watch": "vitest --watch"
}

Please fix both issues and move the ticket back to In Review when done.


Katie Nguyen (2026-03-02):

[Code Review Feedback] SCRUM-125: Set up Vitest in monorepo — APPROVED ✅

All fixes confirmed: web/ and extension/ now use environment: 'jsdom', shared/ stays node, and all three workspace test scripts run vitest. Good work.