import test from 'node:test'; import assert from 'node:assert/strict'; import { buildQuoteLifecycleStatistics, classifyQuoteLifecycleStatisticsBucket, quoteLifecycleStatisticWindow, } from '../src/core/quote-lifecycle-statistics.mjs'; test('quote lifecycle statistics classify states without upgrading submitted-only rows to success', () => { assert.equal(classifyQuoteLifecycleStatisticsBucket({ lifecycle_state: 'submitted', execution: { status: 'submitted', result_code: 'quote_response_ok' }, }), 'submitted_no_reply'); assert.equal(classifyQuoteLifecycleStatisticsBucket({ lifecycle_state: 'failed', execution: { status: 'failed', failure_category: 'quote_not_found_or_finished' }, }), 'submission_failed'); assert.equal(classifyQuoteLifecycleStatisticsBucket({ lifecycle_state: 'command_emitted', }), 'awaiting_executor'); assert.equal(classifyQuoteLifecycleStatisticsBucket({ lifecycle_state: 'completed', outcome_status: 'completed', has_settlement_evidence: true, }), 'success'); }); test('quote lifecycle statistics can aggregate retained quote subject buckets', () => { const rows = buildQuoteLifecycleStatistics({ computedAt: '2026-06-12T14:20:00.000Z', lifecycleRows: [{ quote_id: 'quote-retained-success', quote_activity_at: '2026-06-12T14:11:01.000Z', latest_stage_at: '2026-06-12T14:11:10.000Z', statistics_bucket: 'success', }], }); const allTime = rows.find((row) => row.grain === 'all_time'); const fiveMinute = rows.find((row) => ( row.grain === 'five_minute' && row.window_start === '2026-06-12T14:10:00.000Z' )); assert.equal(allTime.quote_count, 1); assert.equal(allTime.bucket_counts.success, 1); assert.equal(fiveMinute.quote_count, 1); assert.equal(fiveMinute.bucket_counts.success, 1); }); test('quote lifecycle statistics use UTC grain boundaries with Monday UTC weeks', () => { assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-12T17:34:44.123Z', 'five_minute'), { grain: 'five_minute', window_start: '2026-06-12T17:30:00.000Z', window_end: '2026-06-12T17:35:00.000Z', }); assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-14T23:59:00.000Z', 'week'), { grain: 'week', window_start: '2026-06-08T00:00:00.000Z', window_end: '2026-06-15T00:00:00.000Z', }); assert.deepEqual(quoteLifecycleStatisticWindow('2026-06-01T00:00:00.000Z', 'month'), { grain: 'month', window_start: '2026-06-01T00:00:00.000Z', window_end: '2026-07-01T00:00:00.000Z', }); }); test('quote lifecycle statistics dedupe quotes and refresh later results in the original quote window', () => { const rows = [ { quote_id: 'quote-follow', lifecycle_state: 'command_emitted', quote_activity_at: '2026-06-12T17:31:01.000Z', latest_stage_at: '2026-06-12T17:31:03.000Z', }, { quote_id: 'quote-follow', lifecycle_state: 'failed', quote_activity_at: '2026-06-12T17:31:01.000Z', latest_stage_at: '2026-06-12T17:36:10.000Z', execution: { status: 'failed', failure_category: 'quote_not_found_or_finished', }, }, ]; const statistics = buildQuoteLifecycleStatistics({ lifecycleRows: rows, computedAt: '2026-06-12T17:40:00.000Z', }); const allTime = statistics.find((row) => row.grain === 'all_time'); const fiveMinute = statistics.find((row) => ( row.grain === 'five_minute' && row.window_start === '2026-06-12T17:30:00.000Z' )); const laterFiveMinute = statistics.find((row) => ( row.grain === 'five_minute' && row.window_start === '2026-06-12T17:35:00.000Z' )); assert.equal(allTime.quote_count, 1); assert.equal(allTime.bucket_counts.submission_failed, 1); assert.equal(allTime.bucket_counts.awaiting_executor, 0); assert.equal(fiveMinute.quote_count, 1); assert.equal(fiveMinute.bucket_counts.submission_failed, 1); assert.equal(laterFiveMinute, undefined); }); test('quote lifecycle statistics preserve missing identifiers as unavailable evidence', () => { const statistics = buildQuoteLifecycleStatistics({ lifecycleRows: [{ quote_id: null, lifecycle_state: 'observed', quote_activity_at: '2026-06-12T17:31:01.000Z', }], computedAt: '2026-06-12T17:40:00.000Z', }); const allTime = statistics.find((row) => row.grain === 'all_time'); const fiveMinute = statistics.find((row) => row.grain === 'five_minute'); assert.equal(allTime.quote_count, 0); assert.equal(allTime.missing_identifier_count, 1); assert.equal(allTime.bucket_counts.unavailable, 1); assert.equal(fiveMinute.quote_count, 0); assert.equal(fiveMinute.missing_identifier_count, 1); });