test(release-cleanup): 補齊 cleanup/config/main 與新驗證函式測試

新增 cleanupReleases、cleanupOrphanTags 的失敗路徑與分類測試、
loadConfig 環境變數驗證測試、main 整合測試,以及 requireUrl/
requireRepository 與 content-type 檢查測試。測試共 41 項全數通過。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeffery
2026-06-26 10:55:45 +08:00
co-authored by Claude Opus 4.8
parent 154ab032bf
commit 7c225d4122
6 changed files with 295 additions and 6 deletions
+72 -1
View File
@@ -1,6 +1,6 @@
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { selectReleasesToDelete } from '../releases.js'
import { selectReleasesToDelete, cleanupReleases } from '../releases.js'
const releases = [
{ id: 1, tag_name: 'v1.0.0', created_at: '2024-01-01T00:00:00Z' },
@@ -32,3 +32,74 @@ test('selectReleasesToDelete 不改動原陣列', () => {
selectReleasesToDelete(releases, 1)
assert.deepEqual(releases, original)
})
test('selectReleasesToDelete 對無效 created_at 視為最舊,不產生 NaN 排序', () => {
const list = [
{ id: 1, tag_name: 'good', created_at: '2024-05-01T00:00:00Z' },
{ id: 2, tag_name: 'bad', created_at: 'not-a-date' },
{ id: 3, tag_name: 'empty' },
]
const toDelete = selectReleasesToDelete(list, 1)
// 最新的 good 被保留;兩筆無效日期視為最舊,落入待刪除
assert.equal(toDelete.length, 2)
assert.ok(!toDelete.some((r) => r.tag_name === 'good'))
})
// 建立可記錄刪除呼叫的假 client
function fakeClient(releases, statusFor = () => 204) {
const deleted = []
return {
deleted,
async fetchAllPages() {
return releases
},
async deleteResource(url) {
deleted.push(url)
return statusFor(url)
},
}
}
test('cleanupReleases 刪除超出保留數的舊 release', async () => {
const client = fakeClient([
{ id: 1, tag_name: 'v1', name: 'n1', created_at: '2024-01-01T00:00:00Z' },
{ id: 2, tag_name: 'v2', name: 'n2', created_at: '2024-02-01T00:00:00Z' },
{ id: 3, tag_name: 'v3', name: 'n3', created_at: '2024-03-01T00:00:00Z' },
])
await cleanupReleases(client, { releaseApiUrl: 'http://x/releases', keepCount: 1 })
// 保留最新 v3,刪除 v2 與 v1
assert.deepEqual(client.deleted, ['http://x/releases/2', 'http://x/releases/1'])
})
test('cleanupReleases 在未超過保留數時不刪除', async () => {
const client = fakeClient([
{ id: 1, tag_name: 'v1', name: 'n1', created_at: '2024-01-01T00:00:00Z' },
])
await cleanupReleases(client, { releaseApiUrl: 'http://x/releases', keepCount: 2 })
assert.equal(client.deleted.length, 0)
})
test('cleanupReleases 在 deleteResource 回傳非 204 時仍繼續處理其餘項目', async () => {
const client = fakeClient(
[
{ id: 1, tag_name: 'v1', name: 'n1', created_at: '2024-01-01T00:00:00Z' },
{ id: 2, tag_name: 'v2', name: 'n2', created_at: '2024-02-01T00:00:00Z' },
{ id: 3, tag_name: 'v3', name: 'n3', created_at: '2024-03-01T00:00:00Z' },
],
(url) => (url.endsWith('/2') ? 500 : 204), // v2 刪除失敗
)
await cleanupReleases(client, { releaseApiUrl: 'http://x/releases', keepCount: 1 })
// 即使 v2 失敗(500),v1 仍被嘗試刪除
assert.deepEqual(client.deleted, ['http://x/releases/2', 'http://x/releases/1'])
})
test('cleanupReleases 略過沒有 id 的 release', async () => {
const client = fakeClient([
{ id: 1, tag_name: 'v3', name: 'n3', created_at: '2024-03-01T00:00:00Z' },
{ id: null, tag_name: 'v1', name: 'n1', created_at: '2024-01-01T00:00:00Z' },
{ id: 2, tag_name: 'v2', name: 'n2', created_at: '2024-02-01T00:00:00Z' },
])
await cleanupReleases(client, { releaseApiUrl: 'http://x/releases', keepCount: 1 })
// 保留最新 v3;待刪除為 v2 與 (無 id 的) v1 → 無 id 者被略過
assert.deepEqual(client.deleted, ['http://x/releases/2'])
})