Files
cinny/src/app/utils/uploadRetry.test.ts
T

60 lines
2.1 KiB
TypeScript
Raw Normal View History

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { MatrixClient, MatrixError } from 'matrix-js-sdk';
import { uploadContent } from './matrix';
// Drives `uploadContent` with a fake client whose uploads fail per `plan`
// (one entry per attempt: an Error to reject with, or 'ok'). Back-off sleeps
// are real timers, so failures are kept to 1-2 retries per test.
const run = async (plan: Array<Error | 'ok'>, cancelAfterAttempt?: number) => {
let attempt = 0;
const controller = new AbortController();
const mx = {
uploadContent: () => {
attempt += 1;
const step = plan[attempt - 1];
if (cancelAfterAttempt === attempt) controller.abort();
return step === 'ok' ? Promise.resolve({ content_uri: 'mxc://x/y' }) : Promise.reject(step);
},
} as unknown as MatrixClient;
let outcome: { mxc?: string; error?: MatrixError } = {};
await uploadContent(mx, new Blob(['x']) as unknown as File, {
onProgress: () => undefined,
onSuccess: (mxc) => {
outcome = { mxc };
},
onError: (error) => {
outcome = { error };
},
signal: controller.signal,
});
return { attempts: attempt, ...outcome };
};
const abortError = () => new DOMException('request failed', 'AbortError');
test('a dropped connection (SDK reports it as AbortError) is retried', async () => {
const r = await run([abortError(), 'ok']);
assert.equal(r.attempts, 2);
assert.equal(r.mxc, 'mxc://x/y');
});
test('a user cancel (our signal aborted) is NOT retried even though it is also an AbortError', async () => {
const r = await run([abortError(), 'ok'], 1);
assert.equal(r.attempts, 1);
assert.equal(r.mxc, undefined);
assert.ok(r.error);
});
test('5xx is retried, 4xx fails fast', async () => {
const server = new MatrixError({ errcode: 'M_UNKNOWN', error: 'boom' }, 502);
const r = await run([server, 'ok']);
assert.equal(r.attempts, 2);
assert.equal(r.mxc, 'mxc://x/y');
const tooLarge = new MatrixError({ errcode: 'M_TOO_LARGE', error: 'big' }, 413);
const s = await run([tooLarge, 'ok']);
assert.equal(s.attempts, 1);
assert.equal(s.error?.httpStatus, 413);
});