testing-server-moduleslisted
Install: claude install-skill voidcorp-core/void-harness
# testing-server-modules
`server-only` and `client-only` are import-time tripwires: they exist to **throw** the moment a server module is pulled into a client bundle (or vice-versa). That is exactly what you want at build time — and exactly what breaks Vitest, which runs neither in an RSC server graph nor in a browser. Importing any module whose chain reaches `server-only` crashes the test run with a cryptic `"This module cannot be imported from a Client Component module"` before a single assertion runs.
**Attribution**: see `.source`.
---
## The fix — alias the tripwire to an empty stub in the Vitest config
The tripwire's only job is to throw outside its runtime. Tests are outside its runtime by design, so the correct test-time substitute is an **empty module** — not a mock, not a partial.
```ts
// vitest.base.ts (shared config in the monorepo — extend it per package)
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
alias: {
'server-only': new URL('./test/stubs/empty.ts', import.meta.url).pathname,
'client-only': new URL('./test/stubs/empty.ts', import.meta.url).pathname,
},
},
});
```
```ts
// test/stubs/empty.ts
export {}; // server-only / client-only export nothing; their side effect is the throw.
```
A single shared stub serves both. In a monorepo, put the alias in the `vitest.base` config every package extends, so no package re-discovers the gotcha (composes with `harness-monorepo:turbo-pipeline-tuning`