import test from 'node:test'; import assert from 'node:assert/strict'; import { createLibraryPageReader } from '../src/services/library-pages.js'; function legacyReader(total = 474) { const calls = []; const read = async request => { calls.push(request); if (Object.hasOwn(request, 'page')) throw Object.assign(Error('old interface'), { code: 'UNKNOWN_REQUEST_FIELD' }); const offset = Number(request.cursor || 0), end = Math.min(total, offset + request.limit); return { generation: 'g1', totalMatched: total, records: Array.from({ length: end - offset }, (_, i) => ({ record_id: `jd:${offset + i}` })), nextCursor: end < total ? String(end) : null }; }; return { calls, read }; } test('新版读取器直接按页读取一次,不走游标兼容路径', async () => { const pager = createLibraryPageReader();let calls = 0; const result = await pager({ op: 'browse', page: 50, limit: 24 }, async request => { calls++;return { page: request.page, totalPages: 100 }; }, '/new'); assert.equal(calls, 1);assert.equal(result.page, 50); }); test('旧接口跨远页按100条跳读,并缓存精确范围/版本下的游标', async () => { const pager = createLibraryPageReader(), { read, calls } = legacyReader(); const request = { op: 'browse', entity: 'products', filters: { brand: 'ksf' }, quality: 'audit', generation: 'g1', page: 1, limit: 24 }; const first = await pager(request, read, '/legacy');assert.equal(first.records.length, 24); const last = await pager({ ...request, page: 999 }, read, '/legacy'); assert.equal(last.page, 20);assert.equal(last.totalPages, 20);assert.equal(last.records.length, 18); assert.equal(last.records[0].record_id, 'jd:456'); assert.ok(calls.length <= 8);assert.ok(calls.some(call => call.limit === 100)); const before = calls.length; await pager({ ...request, page: 20 }, read, '/legacy');assert.equal(calls.length, before + 1); await pager({ ...request, filters: { brand: 'tongyi' }, page: 1 }, read, '/legacy'); assert.ok(calls.at(-1).filters.brand === 'tongyi' && !calls.at(-1).cursor); }); test('旧接口空范围正确显示0页,读取失败与代际变更不转成空页', async () => { const pager = createLibraryPageReader(), empty = legacyReader(0); const request = { op: 'browse', entity: 'products', page: 5, limit: 24, generation: 'g1' }; const result = await pager(request, empty.read, '/empty'); assert.deepEqual([result.page, result.totalPages, result.records], [1, 0, []]); const reader = legacyReader();let changed = false; const read = async request => { const result = await reader.read(request);return changed ? { ...result, generation: 'g2' } : result; }; await pager({ ...request, page: 1 }, read, '/changes');changed = true; await assert.rejects(() => pager(request, read, '/changes'), { code: 'LIBRARY_VERSION_CHANGED' }); await assert.rejects(() => createLibraryPageReader()(request, async () => { throw Object.assign(Error('读取失败'), { code: 'LIBRARY_BUSY' }); }, '/busy'), { code: 'LIBRARY_BUSY' }); });