import test from 'node:test'; import assert from 'node:assert/strict'; import { extractCdrFeedList, parseCdrFeedLinkNext, resolveCdrFeedNextPage } from '../services/cdrFeedParser.js'; import { cdrDedupKey, cdrStartTime, cdrCallingNumber, } from '../services/cdrFeedParser.js'; import { filterCdrToWindow } from '../services/callReport/joinCallQuality.js'; test('extractCdrFeedList handles items array', () => { const rows = [{ id: 1 }, { id: 2 }]; assert.deepEqual(extractCdrFeedList({ items: rows }), rows); }); test('extractCdrFeedList handles numeric-keyed items object', () => { const rows = [{ id: 'a' }, { id: 'b' }]; assert.deepEqual(extractCdrFeedList({ items: { 0: rows[0], 1: rows[1] } }), rows); }); test('extractCdrFeedList handles top-level array', () => { const rows = [{ id: 1 }]; assert.deepEqual(extractCdrFeedList(rows), rows); }); test('extractCdrFeedList handles records alias', () => { const rows = [{ id: 1 }]; assert.deepEqual(extractCdrFeedList({ records: rows }), rows); }); test('cdrField reads report column labels', () => { const row = { 'Report ID': 'abc-1', 'Start time': '2026-07-23T14:00:00.000Z', 'Calling number': '+15551234567', 'Called number': '+12122194600', Duration: 42, Direction: 'Inbound', }; assert.equal(cdrStartTime(row), '2026-07-23T14:00:00.000Z'); assert.equal(cdrCallingNumber(row), '+15551234567'); assert.equal(cdrDedupKey(row), 'id:abc-1'); }); test('cdrDedupKey keeps distinct report rows', () => { const a = { 'Report ID': '1', 'Start time': '2026-07-23T14:00:00.000Z' }; const b = { 'Report ID': '2', 'Start time': '2026-07-23T15:00:00.000Z' }; assert.notEqual(cdrDedupKey(a), cdrDedupKey(b)); }); test('filterCdrToWindow keeps API rows when start time is report-labeled', () => { const window = { startTime: '2026-07-23T13:00:00.000Z', endTime: '2026-07-24T01:00:00.000Z', }; const rows = [ { 'Start time': '2026-07-23T14:00:00.000Z', 'Report ID': '1' }, { 'Start time': '2026-07-23T15:00:00.000Z', 'Report ID': '2' }, ]; assert.equal(filterCdrToWindow(rows, window).length, 2); }); test('parseCdrFeedLinkNext reads rel=next from Link header', () => { const link = '; rel="next"'; assert.equal( parseCdrFeedLinkNext(link), 'https://analytics-calling.webexapis.com/v1/cdr_feed?startTimeForNextFetch=2025-08-15T09:30:00.000Z&max=5000', ); }); test('resolveCdrFeedNextPage prefers Link header over body token', () => { const baseUrl = 'https://analytics-calling.webexapis.com/v1/cdr_feed'; const baseParams = { startTime: 'a', endTime: 'b', locations: 'Store 0782', max: 5000 }; const next = resolveCdrFeedNextPage( { next: 'cursor-token' }, { link: '; rel="next"' }, baseUrl, baseParams, ); assert.deepEqual(next, { url: 'https://example.com/page2', params: null }); }); test('resolveCdrFeedNextPage falls back to body next cursor', () => { const baseUrl = 'https://analytics-calling.webexapis.com/v1/cdr_feed'; const baseParams = { startTime: 'a', endTime: 'b', locations: 'Store 0782', max: 5000 }; const next = resolveCdrFeedNextPage({ next: 'cursor-token' }, {}, baseUrl, baseParams); assert.deepEqual(next, { url: baseUrl, params: { ...baseParams, next: 'cursor-token' }, }); });