import { test } from 'node:test' import assert from 'node:assert/strict' import { backoffDelay, transientReason } from '../src/retry.mjs' test('transientReason matches connection resets and network errors', () => { assert.ok(transientReason('Error: Connection reset by server')) assert.ok(transientReason('read ECONNRESET')) assert.ok(transientReason('socket hang up')) assert.ok(transientReason('fetch failed')) assert.ok(transientReason('HTTP status 503 Service Unavailable')) assert.ok(transientReason('429 Too Many Requests')) assert.ok(transientReason('The request timed out')) }) test('transientReason ignores ordinary failures', () => { assert.equal(transientReason('goal file not found'), null) assert.equal(transientReason('AssertionError: expected 1 to equal 2'), null) assert.equal(transientReason(''), null) assert.equal(transientReason(undefined, null), null) }) test('transientReason scans several fields and returns the first match', () => { assert.ok(transientReason(null, 'stderr: ECONNRESET while streaming')) }) test('backoffDelay doubles and caps', () => { assert.equal(backoffDelay(1, { base: 1000, jitter: false }), 1000) assert.equal(backoffDelay(2, { base: 1000, jitter: false }), 2000) assert.equal(backoffDelay(3, { base: 1000, jitter: false }), 4000) assert.equal(backoffDelay(10, { base: 1000, max: 5000, jitter: false }), 5000) }) test('backoffDelay jitter stays within half..full', () => { assert.equal(backoffDelay(2, { base: 1000, jitter: true, random: () => 0 }), 1000) assert.equal(backoffDelay(2, { base: 1000, jitter: true, random: () => 1 }), 2000) })