Files
droid2api/tests/refresh-client.test.js
2025-12-27 15:07:54 +08:00

113 lines
2.7 KiB
JavaScript

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);
});