Skip to content

test(tests): shared embeddings mock, SQL insert helpers, stubFetch, vi.stubEnv (#126) - #141

Merged
devinmlowe merged 7 commits into
mainfrom
ponytail/tests
Sep 21, 2026
Merged

devinmlowe merged 7 commits into
mainfrom
ponytail/tests

Conversation

@devinmlowe

Copy link
Copy Markdown
Owner

Summary

Collapses the duplicated test scaffolding named in #126 into tests/helpers.ts and a new tests/mocks/ directory. Pure test refactor: no source change, no behaviour change, and the suite reports exactly the same count before and after (1702 tests in 133 files), three times in a row.

Closes #126

Findings done

  • Embeddings mock — tests/mocks/embeddings.ts exports deterministicVector and deterministicEmbeddings(). Eleven suites that each re-declared the 20-line hash vector inside a vi.mock factory now register vi.mock(p, async () => (await import("../mocks/embeddings.js")).deterministicEmbeddings()). Query and document embeddings of the same text share a vector (the shape forget-tool, scope-inheritance and semantic/forget already used); every converted suite passes with it. The short partial mocks (embedQuery: vi.fn() and the like, 2–8 lines each) are left as they are because several tests rely on their unset returns — so the count is 11 of the 31 sites, not all 31.
  • SQL row inserts — insertEntity, insertRelationship, insertCluster, insertBridgeScore, insertConversation, insertExchange, insertMemory in tests/helpers.ts; the copies in analyzer, bridge-persistence, naming, temporal, reflection, daemon, scheduler, validate and batch-entity-linking are gone (batch-entity-linking keeps a four-line id-deriving wrapper, validate the vec_exchanges part of its helper). insertEntity always writes the entities_fts row, as production does.
  • stubFetch — tests/mocks/llm-fetch.ts holds stubFetch, anthropicToolMock, anthropicCalls, json, urlOf once; the four *-factory suites keep a two-line wrapper naming their tool and payloads so the test bodies are untouched.
  • Env isolation — vitest.config.ts sets test.unstubEnvs: true; fourteen suites replace their save/delete/restore loops with vi.stubEnv(key, undefined) in beforeEach, and direct process.env.X = … writes inside their tests became vi.stubEnv so those are restored too. doctor.test.ts keeps its beforeAll/afterAll pair because unstubEnvs runs per test.
  • createTestMemory ×6, makeExchanges ×5, FakeWorker ×2, built-CLI guard ×5 — one copy each: createTestMemory / makeExchanges / builtCli / itBuilt in tests/helpers.ts, the behaviour-driven FakeWorker in tests/mocks/fake-worker.ts (dispatch.test expresses its per-worker replies and the "sqlite exploded" worker as behaviours).
  • cosineSimilarity / one-caller fixtures — the helper copy is deleted; collapse, consolidator and episodic/embeddings import src/_core/search/vector.ts. createTestFixture is inlined into parser.test's fixture() and createSyntheticToolCall into the two literals in store.test.

Findings skipped

None. Two counts in the issue were re-verified and differ from its text: the embeddings mock is 11 deterministic copies plus 20 short partial stubs (only the 11 are consolidated, see above), and createTestMemory had six copies (one nested in episodic/search.test.ts), not five.

Not touched on purpose: tests/interfaces/cli/transfer.test.ts (its embeddings mock copy stays; #124 owns that file) and anything under tests/interfaces/web/.

Test counts

Test files Tests
before (main 46cc854) 133 passed 1702 passed
after, run 1 (merged with origin/main) 133 passed 1702 passed
after, run 2 133 passed 1702 passed
after, run 3 133 passed 1702 passed

npm run build green. git diff --shortstat origin/main...HEAD: 56 files changed, 760 insertions(+), 1756 deletions(-).

Removed tests

None.

Extra verification

Three consecutive npm run test:run passes (above) to rule out order-dependent flakiness from the shared helpers and unstubEnvs.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso

devinmlowe and others added 7 commits September 21, 2026 00:30
…es (#126)

Eleven suites each re-declared a 20-line hash-based deterministicVector
inside a vi.mock factory for src/_core/embeddings. tests/mocks/embeddings.ts
now exports deterministicVector and deterministicEmbeddings(); each site is
a three-line vi.mock that imports it. Queries and documents of the same
text share a vector (the shape forget-tool, scope-inheritance and
semantic/forget already used), which every converted suite passes with.
The short partial mocks (embedQuery: vi.fn() and the like) are left alone:
they are a few lines each and several tests rely on their unset returns.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso
…#126)

insertEntity, insertRelationship, insertCluster, insertBridgeScore,
insertConversation, insertExchange and insertMemory now live once in
tests/helpers.ts (entities also get their entities_fts row, as production
does). The nine suites that each re-declared some of them call the shared
ones; batch-entity-linking keeps its four-line id-deriving wrapper and
validate keeps the vec_exchanges part of its helper, both delegating the
row insert. Defaults follow the reflection copy (confidence 0.8,
importance 0.7, cluster coherence 0.8); every converted suite passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso
…126)

graph/extractor-factory, semantic/extractor-factory, commitments-factory
and consolidator-factory each carried the same 60-line stubFetch (Ollama
tags/generate, OpenRouter tool call, reject the rest) plus json, urlOf,
anthropicCalls and makeAnthropicMock, differing only in the tool name and
payloads. tests/mocks/llm-fetch.ts holds them once; each suite keeps a
two-line wrapper naming its tool and payloads so the test bodies are
untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso
…ops (#126)

vitest.config.ts sets test.unstubEnvs so every variable stubbed with
vi.stubEnv is restored before the next test. Fourteen suites that saved,
deleted and restored their env keys by hand now stub each key to
undefined in beforeEach and drop the restore loop; direct process.env
writes inside their tests became vi.stubEnv calls so those are restored
too. doctor.test.ts keeps its beforeAll/afterAll pair because unstubEnvs
runs per test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso
…ilt-CLI guard (#126)

createTestMemory (six copies), makeExchanges (five) and the built-CLI
skip guard (five `const cli = fileURLToPath(...)` / `it.skipIf(!built)`
pairs) move into tests/helpers.ts as createTestMemory, makeExchanges,
builtCli and itBuilt. The two FakeWorker classes become one
behaviour-driven tests/mocks/fake-worker.ts; dispatch.test expresses its
per-worker replies and the "sqlite exploded" worker as behaviours.
tests/helpers.ts drops its cosineSimilarity copy (the three users import
src/_core/search/vector.ts) and inlines the one-caller createTestFixture
and createSyntheticToolCall into parser.test and store.test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K88GYGYEE6wuuhewcsTbso
@devinmlowe
devinmlowe merged commit 08da145 into main Sep 21, 2026
10 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ponytail] Tests: shared embeddings mock, SQL insert helpers, stubFetch, vi.stubEnv

1 participant