civetan-dance
v0.1.0
Published
A behaviour-driven test framework for TypeScript, written in Civet
Maintainers
Readme
civetan-dance
A behaviour-driven test framework for TypeScript. Specs are written in Civet and read from conditions to expected behaviour.
[!WARNING] civetan-dance is currently a prototype. Its syntax is not yet stable and may change in backward-incompatible ways.
Requires Node.js ^22.18.0 || >=24.0.0 <26.0.0 on Linux or macOS. Windows is not
supported because the runner relies on process groups and POSIX signals.
Type checking specs requires TypeScript 5.4 or newer, the version that brought
NoInfer. Running them does not: Node.js loads the package from either module
system. The package is ESM only, so which projects can read its types depends on
that:
| The project | Reads the types under |
|---|---|
| "type": "module" | bundler, node10, node16, nodenext, node20 |
| CommonJS | nodenext on TypeScript 5.8, or node20 on 5.9 |
| CommonJS on node16 | nothing — node16 has no way to import an ESM-only package |
classic resolves no package that describes itself with exports, this one included.
Start here
1. Install and initialize
npm install -D civetan-dance
npx civetan --init--init creates the Civet settings required for should expressions and #
comments. It preserves existing settings when run again. In a workspace with no
tsconfig.json of its own, --init --globals adds the types to the nearest one
above it, which in a monorepo is the one at the root.
Recorded snapshots live beside the spec that took them, in __snapshots__, and belong
in version control. Nothing else a run writes does: the compiled specs and what -f
remembers both live under node_modules/.cache.
By default, specs import the APIs they use. To make the APIs global instead,
initialize with --globals now or rerun it later:
npx civetan --init --globalsThis also merges civetan-dance/globals into the nearest tsconfig.json
without replacing existing types or other settings.
2. Write a spec
Create spec/split.spec.civet:
import { describe, context, param, subject, should, eq } from "civetan-dance"
describe "splitting a comma-separated line", ->
line := param "a,b,c"
it := subject -> line().split ","
context "when the line contains commas", ->
it should eq ["a", "b", "c"]
context "when the line contains no commas", ->
line.is "abc"
it should eq ["abc"]The subject is the action under test. Each context supplies its conditions;
the second one overrides line while reusing the same action and expectation
style.
3. Run it
$ npx civetan spec
spec/split.spec.civet
splitting a comma-separated line
when the line contains commas
✓ should eq ["a", "b", "c"]
when the line contains no commas
✓ should eq ["abc"]
2 passed, 0 failedThe basic model
| API | Role |
|---|---|
| describe / context | Organize behaviour and conditions |
| param | Define an input that a context can override |
| given | Create a fresh prerequisite for each case |
| subject | Define the action under test |
| it should ... | Turn a matcher into a test case |
See Writing specs for the full DSL, matchers, hooks, spies, snapshots, and asynchronous prerequisites.
Loading application code
Native mode is the default and lets Node.js load erasable TypeScript directly.
If the application needs .tsx, Vite aliases, import.meta.env, CSS, assets,
or Vite plugins, run its specs through the bundled Vite adapter:
npx civetan --module-adapter vite --project <root> specSee Execution modes for the capability comparison and for using an existing TypeScript loader.
Everyday commands
npx civetan spec # run specs
npx civetan spec -w # watch files
npx civetan spec -f # rerun the last failures
npx civetan spec -u # update snapshots
npx civetan --help # show every optionSee the CLI reference for all options, reporters, timeouts, and concurrency settings.
Documentation
Examples of every built-in matcher are also available in
spec/examples/matchers.spec.civet.
