import test from 'node:test'; import assert from 'node:assert/strict'; import { requestRefreshToken } from '../refresh-client.js'; function mockResponse({ ok, status, jsonData, textData, headers }) { const normalizedHeaders = {}; if (headers) { for (const [key, value] of Object.entries(headers)) { normalizedHeaders[key.toLowerCase()] = value; } } return { ok, status, json: async () => jsonData ?? {}, text: async () => textData ?? '', headers: { get: (name) => normalizedHeaders[name.toLowerCase()] ?? null } }; } test('refresh retries on 500 then succeeds', async () => { let calls = 0; const fetchImpl = async () => { calls += 1; if (calls === 1) { return mockResponse({ ok: false, status: 500, textData: 'boom' }); } return mockResponse({ ok: true, status: 200, jsonData: { access_token: 'access', refresh_token: 'refresh' } }); }; const data = await requestRefreshToken({ refreshUrl: 'https://example.com', refreshToken: 'refresh_token', clientId: 'client', timeoutMs: 20, maxRetries: 1, retryDelayMs: 1, fetchImpl }); assert.equal(data.access_token, 'access'); assert.equal(calls, 2); }); test('refresh does not retry on 400', async () => { let calls = 0; const fetchImpl = async () => { calls += 1; return mockResponse({ ok: false, status: 400, textData: 'bad request' }); }; await assert.rejects( () => requestRefreshToken({ refreshUrl: 'https://example.com', refreshToken: 'refresh_token', clientId: 'client', timeoutMs: 20, maxRetries: 2, retryDelayMs: 1, fetchImpl }), (err) => err?.status === 400 ); assert.equal(calls, 1); }); test('refresh retries on timeout abort', async () => { let calls = 0; const fetchImpl = async (url, options) => { calls += 1; return new Promise((resolve, reject) => { if (!options?.signal) { resolve(mockResponse({ ok: true, status: 200, jsonData: {} })); return; } if (options.signal.aborted) { const error = new Error('Aborted'); error.name = 'AbortError'; reject(error); return; } options.signal.addEventListener('abort', () => { const error = new Error('Aborted'); error.name = 'AbortError'; reject(error); }); }); }; await assert.rejects( () => requestRefreshToken({ refreshUrl: 'https://example.com', refreshToken: 'refresh_token', clientId: 'client', timeoutMs: 5, maxRetries: 1, retryDelayMs: 1, fetchImpl }), (err) => err?.name === 'AbortError' ); assert.equal(calls, 2); });