import { test } from 'node:test'; import assert from 'node:assert/strict'; import { withCollabRetry } from '../src/lib/access.js'; const err = (status, msg = `http ${status}`) => Object.assign(new Error(msg), { status }); const noLog = () => {}; function adminStub() { const calls = []; return { calls, addCollaborator(owner, repo, username, permission) { calls.push({ owner, repo, username, permission }); return Promise.resolve(); } }; } test('403 adds collaborator (write) then retries once and succeeds', async () => { const admin = adminStub(); let attempts = 0; const out = await withCollabRetry(async () => { attempts++; if (attempts === 1) throw err(403); return 'ok'; }, { adminGitea: admin, owner: 'nirpa', repo: 'newrepo', botUsername: 'shre-reviewer', log: noLog }); assert.equal(out, 'ok'); assert.equal(attempts, 2); assert.deepEqual(admin.calls, [{ owner: 'nirpa', repo: 'newrepo', username: 'shre-reviewer', permission: 'write' }]); }); test('non-403 errors are rethrown without touching collaborators', async () => { const admin = adminStub(); await assert.rejects( () => withCollabRetry(() => Promise.reject(err(500)), { adminGitea: admin, owner: 'o', repo: 'r', botUsername: 'b', log: noLog }), /http 500/ ); assert.equal(admin.calls.length, 0); }); test('403 with no admin client rethrows the original 403', async () => { await assert.rejects( () => withCollabRetry(() => Promise.reject(err(403)), { adminGitea: null, owner: 'o', repo: 'r', botUsername: 'b', log: noLog }), (e) => e.status === 403 ); }); test('retry happens exactly once: second 403 propagates', async () => { const admin = adminStub(); let attempts = 0; await assert.rejects( () => withCollabRetry(() => { attempts++; return Promise.reject(err(403)); }, { adminGitea: admin, owner: 'o', repo: 'r', botUsername: 'b', log: noLog }), (e) => e.status === 403 ); assert.equal(attempts, 2); assert.equal(admin.calls.length, 1); }); test('addCollaborator failure propagates (no infinite loop)', async () => { const admin = { addCollaborator: () => Promise.reject(err(422, 'bad permission')) }; let attempts = 0; await assert.rejects( () => withCollabRetry(() => { attempts++; return Promise.reject(err(403)); }, { adminGitea: admin, owner: 'o', repo: 'r', botUsername: 'b', log: noLog }), /bad permission/ ); assert.equal(attempts, 1); }); test('success path never consults the admin client', async () => { const out = await withCollabRetry(() => Promise.resolve(42), { adminGitea: undefined, owner: 'o', repo: 'r', botUsername: 'b', log: noLog }); assert.equal(out, 42); });