/** * deploy-url.test.ts — 離線驗證下載源組裝(Arcrun#4:codeload → Gitea archive)。 * * 涵蓋純函式:buildArchiveUrl(URL 組裝)、buildDownloadHeaders(token → header)。 * 打真 Gitea 下載/部署是 leo 的閘,不在單元測試做。 * * 用 Node 內建 test runner(node --test,零額外依賴;Node ≥22.18 自帶 TS type-stripping)。 */ import { test } from 'node:test'; import assert from 'node:assert/strict'; import { buildArchiveUrl, buildDownloadHeaders } from '../src/lib/deploy.ts'; test('buildArchiveUrl 指向 Gitea archive API,不再是 GitHub codeload', () => { const url = buildArchiveUrl('main', 'bust123'); assert.ok(url.startsWith('https://git.uncle6.me/api/v1/repos/Leo/Arcrun/archive/main.tar.gz'), `預期 Gitea archive API,實得:${url}`); assert.ok(!/codeload|github\.com/.test(url), `不應含 GitHub 下載源:${url}`); }); test('buildArchiveUrl 帶 cache-buster query(#13 P2 stale 防護沿用)', () => { const url = buildArchiveUrl('main', 'abc def'); // 含空白 → 應被 encode assert.match(url, /[?&]_cb=abc%20def$/); }); test('buildArchiveUrl ref 進 archive 檔名(tag/branch 皆走同路徑)', () => { const url = buildArchiveUrl('v1.2.3', 'x'); assert.ok(url.includes('/archive/v1.2.3.tar.gz?'), url); }); test('buildArchiveUrl 可用 repo / base 覆蓋(fork/自架站台)', () => { const url = buildArchiveUrl('main', 'x', 'Mira/Arcrun', 'https://gitea.example.org'); assert.ok(url.startsWith('https://gitea.example.org/api/v1/repos/Mira/Arcrun/archive/main.tar.gz'), url); }); test('buildDownloadHeaders:有 token → 帶 Gitea 慣用 Authorization: token ', () => { const h = buildDownloadHeaders('secrettok'); assert.equal(h.Authorization, 'token secrettok'); assert.equal(h['Cache-Control'], 'no-cache'); assert.equal(h.Pragma, 'no-cache'); }); test('buildDownloadHeaders:無 token(public repo)→ 不帶 Authorization,仍 no-cache', () => { // 顯式傳 undefined 會觸發預設參數 giteaToken()(讀 env);要驗 public 路徑需清掉 env token。 const saved = { a: process.env.ARCRUN_GITEA_TOKEN, g: process.env.GITEA_TOKEN }; delete process.env.ARCRUN_GITEA_TOKEN; delete process.env.GITEA_TOKEN; try { const h = buildDownloadHeaders(); // 走預設 → giteaToken() → undefined assert.equal(h.Authorization, undefined); assert.equal(h['Cache-Control'], 'no-cache'); } finally { if (saved.a !== undefined) process.env.ARCRUN_GITEA_TOKEN = saved.a; if (saved.g !== undefined) process.env.GITEA_TOKEN = saved.g; } }); test('buildDownloadHeaders:ARCRUN_GITEA_TOKEN 優先於 GITEA_TOKEN(env 機制,不寫死)', () => { const saved = { a: process.env.ARCRUN_GITEA_TOKEN, g: process.env.GITEA_TOKEN }; process.env.ARCRUN_GITEA_TOKEN = 'preferred'; process.env.GITEA_TOKEN = 'fallback'; try { assert.equal(buildDownloadHeaders().Authorization, 'token preferred'); } finally { if (saved.a === undefined) delete process.env.ARCRUN_GITEA_TOKEN; else process.env.ARCRUN_GITEA_TOKEN = saved.a; if (saved.g === undefined) delete process.env.GITEA_TOKEN; else process.env.GITEA_TOKEN = saved.g; } }); test('buildDownloadHeaders:空字串 token 視為無(避免送出 "token ")', () => { const h = buildDownloadHeaders(''); assert.equal(h.Authorization, undefined); });