🍡 mochi

SSR framework for Svelte 5 + Bun with islands-based selective hydration

On this page

Testing

Unit tests

Test pure functions, stores, and any non-server logic directly with bun test — no Mochi-specific setup:

// src/lib/slugify.test.ts
import { expect, test } from 'bun:test';
import { slugify } from './slugify';

test('lowercases and dasherizes', () => {
  expect(slugify('Hello World')).toBe('hello-world');
});
bun test

Full-app tests

A test that boots a real server with Mochi.serve() must run one file per process. Mochi.serve() allows one instance per process, so two server-booting test files in the same bun test run throw Mochi.serve() has already been called.

runTests solves this. It globs src/**/*.test.ts and runs each file in its own bun test process, parallelised across CPU cores. Add a small script:

// scripts/run-tests.ts
#!/usr/bin/env bun
import { runTests } from 'mochi-framework';

await runTests();

Point your test script at it:

// package.json
{
  "scripts": {
    "test": "bun scripts/run-tests.ts"
  }
}

Each file gets a fresh process, so every test can call Mochi.serve({ port: 0 }) without colliding:

// src/routes.test.ts
import { afterAll, beforeAll, expect, test } from 'bun:test';
import type { Server } from 'bun';
import { Mochi } from 'mochi-framework';
import { routes } from './routes';

let server: Server;

beforeAll(async () => {
  server = await Mochi.serve({ port: 0, logger: { enabled: false }, routes });
});

afterAll(() => server.stop(true));

test('GET / renders', async () => {
  const res = await fetch(`http://localhost:${server.port}/`);
  expect(res.status).toBe(200);
});

Options

runTests(options?) accepts:

  • dir — package root to scan and run tests from. Defaults to the current working directory.
  • sequential — files (relative to dir) that must run on their own, after the parallel batch, for tests that cannot share machine state:
await runTests({ sequential: ['src/liveReload.test.ts'] });

runTests reprints a recap at the end — every failed file, the failing test names, and their error output — and exits with code 1 if any file failed.

Bun workspaces: use the hoisted linker