solidjs/solid
Testing
Active contributors: Ryan Carniato, Damian Tarnawski, Joe Pea
Solid has four kinds of tests:
- Behavioural tests with Vitest, exercising the reactive runtime in jsdom (
packages/solid/test/*.spec.ts(x),packages/solid/web/test/*.spec.tsx,packages/solid/store/test/*.spec.ts). - Type tests that compile against
tsc --project tsconfig.test.json(packages/solid/test/*.type-tests.ts). - Integration tests that spawn Node and probe every published entry point (
packages/test-integration/test-imports.mjs). - Benchmarks for the runtime (
packages/solid/test/component.bench.ts,packages/solid/bench/).
Behavioural tests with Vitest
Configuration lives in packages/solid/vite.config.mjs:
test: {
environment: "jsdom",
transformMode: { web: [/\.[jt]sx?$/] },
deps: { registerNodeLoader: true },
threads: false,
isolate: false,
globals: true
}threads: false and isolate: false keep all tests in a single worker so the reactive global state can be reset between tests cleanly. Coverage is via @vitest/coverage-v8 with v8's coverage instrumentation.
The Vite config aliases:
| Alias | Resolved to |
|---|---|
solid-js |
packages/solid/src |
solid-js/web |
packages/solid/web/src |
solid-js/jsx-runtime |
packages/solid/src/jsx |
rxcore |
packages/solid/web/src/core |
This is the magic that lets tests run against the source tree without a build step.
Writing a new test
packages/solid/test/signals.spec.ts is the model. Tests use Solid's own createRoot to scope reactive state:
test('createSignal', () => {
createRoot(() => {
const [value, setValue] = createSignal(1);
expect(value()).toBe(1);
setValue(2);
expect(value()).toBe(2);
});
});Always wrap test bodies in createRoot (or render for component tests) — otherwise reactive primitives created during the test will leak owners across the suite.
For DOM-rendering tests, packages/solid/web/test/suspense.spec.tsx shows the pattern: import render from solid-js/web, render into a fresh document.createElement('div'), and assert against the DOM.
Running a single suite
cd packages/solid
pnpm vitest run signals.spec.ts # one file
pnpm vitest run -t "createSignal" # by test name
pnpm vitest # watch mode (not the default in CI)Type tests
The test-types script (packages/solid/package.json) runs tsc --project tsconfig.test.json against the *.type-tests.ts files. These are the surface-area regression tests:
| File | Covers |
|---|---|
packages/solid/test/signals.type-tests.ts (1,129 lines) |
The full type contract of createSignal, Setter<T>, createMemo, createEffect, Signal<T>, etc. |
packages/solid/test/component.type-tests.ts |
Component<P>, ParentComponent<P>, FlowComponent<P, C>, mergeProps, splitProps. |
packages/solid/test/resource.type-tests.ts |
createResource, Resource<T>, ResourceFetcher, ResourceSource. |
Type tests run as part of pnpm test. They do not assert at runtime — instead they rely on // @ts-expect-error annotations and shape-equality checks via helper types. If you change a public type in packages/solid/src/reactive/signal.ts, update the corresponding type tests in the same PR.
Integration / import tests
packages/test-integration/test-imports.mjs is a Node script that imports every published entry of solid-js (root, /web, /store, /web/storage, /h, /html, /universal, plus the dev variants), checks that the expected named exports exist, and exits non-zero if any are missing. This catches regressions in packages/solid/package.json's exports map and in the Rollup build.
Run it with:
pnpm --filter test-integration testIt depends on a successful pnpm build because it imports from dist/.
Benchmarks
packages/solid/test/component.bench.ts— Vitestbenchblocks for component creation cost, mergeProps, etc. Run withpnpm vitest bench.packages/solid/bench/— older standalone benchmarks (kairo, rval-mod, etc.) that compare Solid's reactive runtime against other libraries. Run withpnpm --filter solid-js bench.
These are not part of CI. Maintainers use them locally to validate performance-sensitive changes.
Coverage
pnpm coverageRuns vitest run --coverage per package. Output goes to packages/solid/coverage/. The .github/workflows/main-ci.yml job uploads the lcov.info to Coveralls (badge in README.md).
Common pitfalls
- Forgetting
createRoot. Tests that allocate signals/effects without a root will leak owners and break later tests because ofisolate: false. - Asserting after a microtask. Some primitives (e.g.
createEffect, resources) defer execution. Useawait Promise.resolve()or, for transitions,await transition.done. - Touching the DOM in a non-DOM test.
packages/solid/test/runs in jsdom but does not importsolid-js/webfor most signal tests. Add the.tsxextension and importrenderonly when you need a renderer. - Type-test drift. Changing a generic in
signal.tswithout updatingsignals.type-tests.tsleaves a hole. The CItest-typesstep catches most cases but a few// @ts-expect-errorlines may need re-balancing.
For the wider tooling story (Rollup, Babel, Turborepo, Prettier), see Tooling.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.