After this lesson, you will be able to: Test functions and modules with Vitest or Jest, mock modules and network calls, and use snapshot testing where it actually helps.
Now the hands-on JavaScript/TypeScript layer. Vitest and Jest have nearly identical APIs, so learning one transfers to the other. This lesson covers writing real tests, mocking modules and fetch, and the right (narrow) use for snapshot tests.
Vitest is the modern Vite-native runner; the API matches Jest's describe/it/expect.
// package.json{ "scripts": { "test": "vitest", "test:ci": "vitest run --coverage" } }// src/discount.tsexport function applyDiscount(price: number, code: string): number {if (code === 'HALF') return price / 2;if (code === 'TENOFF') return Math.max(0, price - 10);return price;}// src/discount.test.tsimport { describe, it, expect } from 'vitest';import { applyDiscount } from './discount';describe('applyDiscount', () => {it('halves the price for HALF', () => {expect(applyDiscount(40, 'HALF')).toBe(20);});it('never goes below zero', () => {expect(applyDiscount(5, 'TENOFF')).toBe(0);});it('ignores unknown codes', () => {expect(applyDiscount(40, 'NOPE')).toBe(40);});});
Mock at the boundary: the module you import or the global fetch. Keep your own logic real.
import { describe, it, expect, vi, beforeEach } from 'vitest';import { getWeatherSummary } from './weather';// Mock the whole module:vi.mock('./emailClient', () => ({sendEmail: vi.fn().mockResolvedValue({ ok: true }),}));beforeEach(() => vi.restoreAllMocks());it('summarizes the API response', async () => {// Stub global fetch so no real network call happens:vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ok: true,json: async () => ({ tempC: 21, condition: 'Clear' }),}));const summary = await getWeatherSummary('London');expect(summary).toBe('London: 21C, Clear');expect(fetch).toHaveBeenCalledOnce();});
A snapshot test serializes a value (often rendered UI) and saves it; future runs compare against the saved snapshot. It is handy for catching unintended changes to complex output, like a rendered component's structure. The trap: huge snapshots that nobody reads, so reviewers rubber-stamp updates and the test guards nothing. Keep snapshots small and intentional, and review every snapshot change like real code. For most logic, explicit assertions beat a snapshot.
Pick the best answer.
Sign in and purchase access to unlock this lesson.