Files
nexusAI/docs/reference/testing.md
T
2026-08-23 23:27:53 -07:00

2.9 KiB

Testing

NexusAI has a lightweight regression suite built on Node's built-in test runner (node:test) and assertions (node:assert) — no external test dependencies. It runs offline on any node in the homelab.

npm test          # = node --test  (discovers test/*.test.js at the repo root)

What's covered

File Subject Imports the real…
test/fusion.test.js RRF ranking math fuseEpisodeResults (orchestration)
test/fts-query.test.js Keyword tokenizer + FTS5 matching buildFtsQuery (memory-service)
test/llamacpp-stream.test.js SSE stream reassembly across chunks completeStream (inference)
test/summarization.test.js Summarization decision logic maybeSummarize (orchestration)
test/entity-extraction.test.js Greeting + regurgitation guards mentionedIn, isIgnoredName (memory-service)
test/schema.test.js Fresh-DB schema completeness schema.js string (memory-service)
test/trivial-turn.test.js Greeting/trivial-turn detection isTrivialTurn (shared)
test/migrations.test.js Migration version-stepping migrate (memory-service)

Tests import the real functions rather than reimplementing logic — the functions are exported for this purpose. External calls (Ollama, Qdrant, the memory service) are mocked via global.fetch; SQLite-backed tests use the built-in node:sqlite module against a throwaway in-memory database.

node:sqlite and skips

test/schema.test.js and three cases in test/fts-query.test.js need node:sqlite, which requires Node ≥ 22.5. On older Node they skip themselves cleanly (guarded by { skip: !DatabaseSync }) rather than failing, so the suite stays green everywhere — but those checks only verify anything on a node new enough to run them. A dev machine on current Node is the source of truth for the schema and FTS matching tests.

node:sqlite is still marked experimental, so runs print a one-line ExperimentalWarning. It's harmless; node --test --no-warnings suppresses it.

Adding tests

Keep the pattern: export the real function, import it, mock I/O at the boundary (global.fetch) or use node:sqlite for DB behaviour. Prefer testing pure logic (ranking, tokenizing, version-stepping, decision branches) over wiring. Several of these tests were written after a bug slipped through — each new class of mistake is worth a case so it can't recur silently.

When a mocked service call changes shape (e.g. the utilityInference refactor moving summarization from Ollama's /api/generate to the inference service's /utility/complete), the mock URL router must move with it — an "unexpected fetch" throw in these tests usually means the code under test evolved, not broke. Runner-contract tests (migrations) inject stub no-op migration arrays rather than letting the real SQL-bearing migrations hit the minimal fake db.