First public release

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-28 14:56:12 -04:00
co-authored by Claude Opus 5.5
commit 7646fe162d
14 changed files with 2253 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
import { describe, expect, it } from 'vitest'
import { overall, validateReport } from '@extant2000/evidence-record'
import {
ContractDriftError,
fieldReport,
coverageReport,
formatFields,
formatCoverage,
assertFields,
assertShape,
coverage,
expectFields,
type Parser,
} from '../src/index.js'
/** Minimal zod-shaped parser so the library stays dependency-free. */
function requireKeys(keys: string[]): Parser<Record<string, unknown>> {
return {
safeParse(data: unknown) {
if (data == null || typeof data !== 'object' || Array.isArray(data)) {
return { success: false as const, error: { issues: [{ path: [], message: 'expected an object' }] } }
}
const obj = data as Record<string, unknown>
const issues = keys.filter(k => !(k in obj)).map(k => ({ path: [k], message: 'required' }))
return issues.length
? { success: false as const, error: { issues } }
: { success: true as const, data: obj }
},
}
}
describe('assertShape', () => {
it('returns the parsed data when the shape holds', () => {
expect(assertShape(requireKeys(['id']), { id: 1 }, 'GET /x')).toEqual({ id: 1 })
})
it('throws naming the context and the offending path', () => {
try {
assertShape(requireKeys(['id', 'name']), { id: 1 }, 'GET /missions')
expect.unreachable('should have thrown')
} catch (e) {
expect(e).toBeInstanceOf(ContractDriftError)
const err = e as ContractDriftError
expect(err.context).toBe('GET /missions')
expect(err.message).toContain('name: required')
}
})
it('catches null where a list was expected — the empty-table failure', () => {
expect(() => assertShape(requireKeys([]), null, 'GET /rows')).toThrow(ContractDriftError)
})
it('is NOT a framework HTTP error', () => {
// A framework-specific HTTP error would tie the library to one framework.
try {
assertShape(requireKeys(['a']), {}, 'ctx')
} catch (e) {
expect(e).toBeInstanceOf(Error)
expect((e as { statusCode?: number }).statusCode).toBeUndefined()
}
})
})
describe('expectFields — the silently-ignored request parameter', () => {
// The motivating case: Stripe ignores an unknown `expand` path
// rather than rejecting it, so a stale expand returns a VALID invoice that
// simply lacks the field. A response-shape validator passes this.
const basilInvoice = {
id: 'in_1',
latest_invoice: { id: 'inv_1', confirmation_secret: { client_secret: 'cs_x' } },
}
const preBasilInvoice = {
id: 'in_1',
latest_invoice: { id: 'inv_1', payment_intent: { client_secret: 'pi_x' } },
}
it('detects the field that was requested but never came back', () => {
const r = expectFields(basilInvoice, ['latest_invoice.payment_intent'])
expect(r.ok).toBe(false)
expect(r.missing).toEqual(['latest_invoice.payment_intent'])
})
it('passes when the requested field is present', () => {
expect(expectFields(preBasilInvoice, ['latest_invoice.payment_intent']).ok).toBe(true)
})
it('a schema validator would NOT catch this — the object is valid', () => {
// Both shapes are perfectly well-formed invoices. Only asking "did what I
// requested come back" distinguishes them.
expect(assertShape(requireKeys(['id', 'latest_invoice']), basilInvoice, 'stripe')).toBeTruthy()
expect(expectFields(basilInvoice, ['latest_invoice.payment_intent']).ok).toBe(false)
})
it('handles a missing intermediate segment without throwing', () => {
expect(expectFields({}, ['a.b.c']).missing).toEqual(['a.b.c'])
})
it('treats an explicit null as PRESENT — absent and null are different', () => {
// null means the provider answered "no value"; undefined means it never
// acknowledged the request. Conflating them hides the bug this catches.
expect(expectFields({ a: null }, ['a']).ok).toBe(true)
})
it('reports partial results, not just a boolean', () => {
const r = expectFields(basilInvoice, [
'latest_invoice.confirmation_secret',
'latest_invoice.payment_intent',
])
expect(r.present).toEqual(['latest_invoice.confirmation_secret'])
expect(r.missing).toEqual(['latest_invoice.payment_intent'])
})
})
describe('assertFields', () => {
it('surfaces the why-note so the failure explains itself', () => {
try {
assertFields({}, [{ path: 'latest_invoice.payment_intent', why: 'needed to mount Elements' }], 'stripe.subscriptions.create')
expect.unreachable('should have thrown')
} catch (e) {
expect((e as ContractDriftError).message).toContain('needed to mount Elements')
}
})
it('does not throw when everything requested came back', () => {
expect(() => assertFields({ a: 1 }, ['a'], 'ctx')).not.toThrow()
})
})
describe('coverage', () => {
it('reports which items are uncovered, not just a percentage', () => {
const r = coverage(['a', 'b', 'c', 'd'], ['a', 'b'], 75)
expect(r.pct).toBe(50)
expect(r.uncovered).toEqual(['c', 'd'])
expect(r.belowFloor).toBe(true)
})
it('passes at exactly the floor', () => {
expect(coverage(['a', 'b'], ['a'], 50).belowFloor).toBe(false)
})
it('an empty surface is 0%, never a flattering 100', () => {
// Nothing to check is not full coverage.
const r = coverage([], [], 0)
expect(r.pct).toBe(0)
expect(r.covered).toBe(0)
})
it('ignores checked items that are not part of the surface', () => {
expect(coverage(['a'], ['a', 'ghost'], 100).pct).toBe(100)
})
})
describe('report — schema pass and assertion fail are different verdicts', () => {
it('keeps a valid-object pass separate from a missing-field failure', () => {
// The Basil failure: a perfectly valid invoice missing the field that
// was asked for. One verdict cannot carry both facts.
const r = expectFields({ id: 'in_1', latest_invoice: {} }, [
{ path: 'latest_invoice.confirmation_secret', why: 'Elements cannot mount without it' },
'id',
])
expect(r.ok).toBe(false)
const rep = fieldReport(r, { context: 'stripe.subscriptions.create', expectations: [
{ path: 'latest_invoice.confirmation_secret', why: 'Elements cannot mount without it' },
] })
expect(overall(rep)).toBe('fail')
const text = formatFields(r, {
context: 'stripe.subscriptions.create',
expectations: [{ path: 'latest_invoice.confirmation_secret', why: 'Elements cannot mount without it' }],
evidence: 'full',
})
expect(text).toContain('latest_invoice.confirmation_secret')
expect(text).toContain('Elements cannot mount without it')
expect(text).toContain('stripe.subscriptions.create')
})
it('treats an empty surface as not-assessed, not as 0% coverage', () => {
const rep = coverageReport(coverage([], []))
expect(overall(rep)).toBe('not-assessed')
expect(formatCoverage(coverage([], []))).toContain('This is not 0% coverage')
})
it('names the uncovered endpoints, not just the percentage', () => {
const c = coverage(['/a', '/b', '/c'], ['/a'], 80)
const text = formatCoverage(c, 80)
expect(text).toContain('/b')
expect(text).toContain('/c')
expect(text).toContain('Below the ratchet floor')
})
it('every conclusion carries a citation', () => {
const r = expectFields({ id: 'x' }, ['id', 'missing_one'])
expect(validateReport(fieldReport(r))).toEqual([])
expect(validateReport(coverageReport(coverage(['/a'], ['/a'])))).toEqual([])
})
})
describe('Parser accepts a Zod 4 schema', () => {
it('accepts PropertyKey paths, including symbols', () => {
// Zod 4 types issue paths as PropertyKey[]. Narrowing to string|number
// made a Zod 4 schema unassignable, and where typecheck gates the
// pipeline that mismatch blocks a deploy.
const sym = Symbol('secret')
const schema = {
safeParse: () => ({
success: false as const,
error: { issues: [{ path: ['a', 1, sym], message: 'bad' }] },
}),
}
expect(() => assertShape(schema, {}, 'ctx')).toThrow(ContractDriftError)
try {
assertShape(schema, {}, 'ctx')
} catch (e) {
// `.join()` alone throws on a symbol; this must render, not crash.
expect((e as ContractDriftError).message).toContain('Symbol(secret)')
expect((e as ContractDriftError).message).toContain('a.1.')
}
})
it('still renders a plain string path unchanged', () => {
const schema = {
safeParse: () => ({
success: false as const,
error: { issues: [{ path: ['latest_invoice', 'id'], message: 'required' }] },
}),
}
try {
assertShape(schema, {}, 'ctx')
} catch (e) {
expect((e as ContractDriftError).message).toContain('latest_invoice.id: required')
}
})
})