@recoengine/testing
v0.1.2
Published
Test harness for recoengine: fixtures, a golden runner and port contract checks — assert a port honours cancellation and both error policies in one line.
Maintainers
Readme
@recoengine/testing
Test harness for engines built on
@recoengine/core: fixtures, a golden
runner, and reusable port contracts. Framework-agnostic — works with Vitest, Jest, node
:test, or anything else.
npm i -D @recoengine/testingWhat it is
Two halves.
Fixtures — the synthetic parts every test used to hand-roll: a candidate provider, a payload-copying extractor, a fixed clock, a request builder, an engine assembler, and small helpers to read results. So a test says what it means and nothing more.
catalogueOf, itemsOf, historyOf, events, fixedClock, request, testEngine
(+ EngineSpec), payloadExtractor, profileExtractor, passthroughStrategy,
constantStrategy, throwingExtractor, rankedIds, scoreById, RecoError, TEST_LIMITS.
Contracts — reusable conformance checks. Each is an async function that throws on violation, so it's one line inside any runner and pulls in no runner as a dependency.
| Contract | Checks |
| --- | --- |
| assertHonoursCancellation | the component aborts when the signal fires (mandatory) |
| assertExtractorErrorPolicy | an extractor follows the required error policy (mandatory) |
| assertDeterministic | same input → same output |
| assertScoresWellFormed | scores are finite and in range |
| assertExplanationSums | contributions add up to the reported score |
| assertScoringStrategy / assertScoreModifier | a plugin honours its port contract |
Usage
import { test } from 'vitest'
import { testEngine, request, historyOf, events, rankedIds, assertHonoursCancellation } from '@recoengine/testing'
import { myStrategy } from '../src/my-strategy.js'
test('my strategy ranks the popular item first', async () => {
const engine = testEngine({ items: ['a', 'b', 'c'], plugins: [myStrategy()] })
const result = await engine.recommend(request({ history: historyOf(events('a', 'a', 'b')) }))
expect(rankedIds(result)).toEqual(['a', 'b', 'c'])
})
test('my strategy honours cancellation', async () => {
await assertHonoursCancellation(/* … */)
})Options types: ExtractorErrorPolicyOptions, StrategyContractOptions,
ModifierContractOptions. (Exact fixture/contract signatures are in the
source.)
Links
- Repository & full docs: https://github.com/waleron07/recommendationEngine
MIT
