import test from 'node:test'; import assert from 'node:assert/strict'; import { SignalSnapshotRepository } from '../server/domains/shared/persistence/SignalSnapshotRepository.js'; import { MockDatabaseConnection } from './helpers/mockDb.js'; import type { DatabaseConnection } from '../server/domains/shared/db/index.js'; import type { ScoreResult } from '../server/domains/shared/types/index.js'; const passResult: ScoreResult = { label: '🟢 BUY (High Conviction)', tier: 'PASS', score: 9, scoreSummary: 'Score: 9', audit: { passedGates: true, breakdown: { roe: 3 }, coverage: { active: 6, total: 11 } }, }; const rejectResult: ScoreResult = { label: '🔴 REJECT', tier: 'REJECT', score: null, scoreSummary: 'Gate failed: P/E 40 > 15', audit: { passedGates: false, failures: ['P/E 40 > 15'] }, }; function repo(): SignalSnapshotRepository { return new SignalSnapshotRepository( new MockDatabaseConnection() as unknown as DatabaseConnection, ); } test('SignalSnapshotRepository', async (t) => { await t.test('record() builds a valid UPSERT (16 params, no throw)', () => { // QueryBuilder validates placeholder count — a param mismatch throws here. assert.doesNotThrow(() => repo().record({ ticker: 'aapl', assetType: 'STOCK', price: 189.5, signal: '✅ Strong Buy', fundamental: passResult, inflated: passResult, rateRegime: 'NORMAL', }), ); }); await t.test('record() tolerates gate-failed results (null score)', () => { assert.doesNotThrow(() => repo().record({ ticker: 'XYZ', assetType: 'STOCK', price: null, signal: '❌ Avoid', fundamental: rejectResult, inflated: rejectResult, }), ); }); await t.test('recordBatch() returns count written', () => { const n = repo().recordBatch([ { ticker: 'AAPL', assetType: 'STOCK', price: 189.5, signal: '✅ Strong Buy', fundamental: passResult, inflated: passResult, }, { ticker: 'MSFT', assetType: 'STOCK', price: 425.3, signal: '🔄 Neutral', fundamental: passResult, inflated: passResult, }, ]); assert.equal(n, 2); }); await t.test('read methods build valid queries', () => { const r = repo(); assert.deepEqual(r.history('aapl'), []); assert.deepEqual(r.byDate('2026-06-09'), []); assert.deepEqual(r.latestBefore('2026-06-09'), []); }); });