'use strict'; const { test, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const { RELEASES_PER_PAGE, fetchReleases } = require('../releases'); const realFetch = globalThis.fetch; afterEach(() => { globalThis.fetch = realFetch; }); function mockResponse(items) { return { ok: true, text: async () => JSON.stringify(items) }; } test('fetchReleases 逐頁讀取直到不足一頁', async () => { const fullPage = Array.from({ length: RELEASES_PER_PAGE }, (_, i) => ({ id: i })); const lastPage = [{ id: 100 }, { id: 101 }]; const requested = []; globalThis.fetch = async (url) => { const page = Number(new URL(url).searchParams.get('page')); requested.push(page); return mockResponse(page === 1 ? fullPage : lastPage); }; const releases = await fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases'); assert.equal(releases.length, RELEASES_PER_PAGE + lastPage.length); assert.deepEqual(requested, [1, 2]); }); test('fetchReleases 在空陣列頁面停止', async () => { globalThis.fetch = async () => mockResponse([]); const releases = await fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases'); assert.deepEqual(releases, []); }); test('fetchReleases 帶上授權標頭', async () => { let seenHeaders; globalThis.fetch = async (_url, opts) => { seenHeaders = opts.headers; return mockResponse([]); }; await fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases', { token: 'secret' }); assert.equal(seenHeaders.Authorization, 'token secret'); }); test('fetchReleases 在 HTTP 錯誤時丟出例外', async () => { globalThis.fetch = async () => ({ ok: false, status: 500 }); await assert.rejects( () => fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases'), /release API 請求失敗/, ); }); test('fetchReleases 在回傳非陣列時丟出例外', async () => { globalThis.fetch = async () => mockResponse({ message: 'not an array' }); await assert.rejects( () => fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases'), /回傳非陣列資料/, ); }); test('fetchReleases 在 null 回應時視為無更多資料', async () => { globalThis.fetch = async () => ({ ok: true, text: async () => 'null' }); const releases = await fetchReleases('https://gitea.example.com/api/v1/repos/o/r/releases'); assert.deepEqual(releases, []); });