test(calculate-version): 整併單元測試至 app/test 並移除無法執行的重複測試目錄 #7

Closed
jiantw83 wants to merge 6 commits from test/consolidate-app-test-20260626-111823 into develop
Member

變更摘要

修正 calculate-version 重複且部分無法執行的單元測試目錄(PR #5 合入後遺留)。

app/package.jsonnpm testnode --test,工作目錄為 app/)只會探索 app/test/;但 repo 根目錄另有一份 test/,其中包含 main 的整合測試(index.test.js,以依賴注入驗證成功/失敗路徑),這些測試實際上從未被執行。

內容

  • config / index / releases / version 測試收斂到 app/test/,並修正 require 路徑(../app/x../x)。
  • 保留 app/test/output.test.js
  • 移除 repo 根目錄無法被執行的重複 test/

影響

  • 不更動任何 production 程式碼,僅調整測試檔位置與 require 路徑。
  • cd app && npm test 由 30 筆增為 34 筆且全數通過(含原本未被執行的 main 整合測試)。
## 變更摘要 修正 `calculate-version` 重複且部分無法執行的單元測試目錄(PR #5 合入後遺留)。 `app/package.json` 的 `npm test`(`node --test`,工作目錄為 `app/`)只會探索 `app/test/`;但 repo 根目錄另有一份 `test/`,其中包含 `main` 的整合測試(`index.test.js`,以依賴注入驗證成功/失敗路徑),這些測試實際上從未被執行。 ## 內容 - 將 `config` / `index` / `releases` / `version` 測試收斂到 `app/test/`,並修正 `require` 路徑(`../app/x` → `../x`)。 - 保留 `app/test/output.test.js`。 - 移除 repo 根目錄無法被執行的重複 `test/`。 ## 影響 - 不更動任何 production 程式碼,僅調整測試檔位置與 `require` 路徑。 - `cd app && npm test` 由 30 筆增為 34 筆且全數通過(含原本未被執行的 `main` 整合測試)。
jiantw83 added 1 commit 2026-06-26 03:19:12 +00:00
app/package.json 的 npm test(node --test,cwd 為 app/)只會探索 app/test/,
repo 根目錄另一份 test/ 中的 main 整合測試(index.test.js)因此從未被執行。
將 config/index/releases/version 收斂至 app/test/(修正 require 路徑),
保留 output 測試,移除重複且無法執行的 repo 根 test/。現 app/test/ 共 34 筆測試皆可執行。

🤖 AI Code Review 團隊

👤 角色 🎯 面向 🧠 個性
🗡️ Assassin security 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用
🎼 Bard style 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版
🧰 Leo maintainability 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來
🔮 Mage logic 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」
🧪 Maya testing 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑
Rogue efficiency 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
gitea-actions bot reviewed 2026-06-26 03:19:49 +00:00
gitea-actions bot left a comment

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 0 筆 3 筆 1 筆 0 筆
舊問題 0 筆 3 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 14 次呼叫)

提示 token 回應 token 合計
151,229 2,108 234,822

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 0 筆 | 3 筆 | 1 筆 | 0 筆 | | 舊問題 | 0 筆 | 3 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 14 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 151,229 | 2,108 | 234,822 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
@@ -11,3 +12,3 @@
test('isUnset 對未設定值回傳 true', () => {
test('isUnset 將 undefined/空字串/null 字面值視為未設定', () => {
assert.equal(isUnset(undefined), true);

嚴重等級🟡 警告
審查員:Leo
問題:測試案例名稱與內容不符,將相反行為寫在同一個 test 中,且移除了對 null 與 "false" 的特定檢查。
建議:將斷言拆分為獨立的測試案例,並補回對 null 與字串 "false" 的邊界測試。

**嚴重等級**:🟡 警告 **審查員**:Leo **問題**:測試案例名稱與內容不符,將相反行為寫在同一個 test 中,且移除了對 null 與 "false" 的特定檢查。 **建議**:將斷言拆分為獨立的測試案例,並補回對 null 與字串 "false" 的邊界測試。
Ghost marked this conversation as resolved
@@ -27,2 +21,4 @@
assert.throws(() => requireEnv('FOO', ''), /FOO 未設定/);
assert.equal(requireEnv('FOO', 'bar'), 'bar');
});

嚴重等級🟡 警告
審查員:Leo
問題:測試案例同時包含「錯誤處理」與「成功回傳」兩種行為。測試應遵循單一職責原則,若邏輯調整導致其中一項失敗,目前寫法會使得錯誤定位變得困難。
建議:建議將 requireEnv 的拋錯測試與成功回傳測試拆分為兩個獨立的測試案例。

**嚴重等級**:🟡 警告 **審查員**:Leo **問題**:測試案例同時包含「錯誤處理」與「成功回傳」兩種行為。測試應遵循單一職責原則,若邏輯調整導致其中一項失敗,目前寫法會使得錯誤定位變得困難。 **建議**:建議將 requireEnv 的拋錯測試與成功回傳測試拆分為兩個獨立的測試案例。
Ghost marked this conversation as resolved
@@ -14,1 +8,3 @@
return { ok: true, text: async () => JSON.stringify(items) };
// 以可控的假回應替換全域 fetch,並於結束後還原
function withFetch(handler, run) {
const original = globalThis.fetch;

嚴重等級🔵 建議
審查員:Leo
問題:withFetch 為全域 fetch 的通用封裝工具,目前定義在特定測試檔案內。若後續專案中其他測試檔案也需要模擬 fetch,將導致測試工具邏輯重複分散。
建議:建議將此類通用的測試輔助函式提取至獨立的測試工具檔案(例如 app/test/test-utils.js),以提升測試程式碼的重用性與維護一致性。

**嚴重等級**:🔵 建議 **審查員**:Leo **問題**:withFetch 為全域 fetch 的通用封裝工具,目前定義在特定測試檔案內。若後續專案中其他測試檔案也需要模擬 fetch,將導致測試工具邏輯重複分散。 **建議**:建議將此類通用的測試輔助函式提取至獨立的測試工具檔案(例如 app/test/test-utils.js),以提升測試程式碼的重用性與維護一致性。
Ghost marked this conversation as resolved
@@ -16,0 +16,4 @@
const rel = (tag) => ({ tag_name: tag });
test('compareVersionArrays 逐區段比較且較短者較小', () => {
assert.ok(compareVersionArrays([1, 10], [1, 2, 3]) > 0);

嚴重等級🟡 警告
審查員:Maya
問題:新的 compareVersionArrays 測試雖增加了案例,但移除了 compareVersionArrays([2, 0, 0], [1, 9, 9]) > 0,這對 Major 版本進位的跨區段比較極為重要。
建議:建議補回對大版本變更的比較測試,確保版本排序邏輯正確。

**嚴重等級**:🟡 警告 **審查員**:Maya **問題**:新的 `compareVersionArrays` 測試雖增加了案例,但移除了 `compareVersionArrays([2, 0, 0], [1, 9, 9]) > 0`,這對 Major 版本進位的跨區段比較極為重要。 **建議**:建議補回對大版本變更的比較測試,確保版本排序邏輯正確。
Ghost marked this conversation as resolved
gitea-actions bot added 1 commit 2026-06-26 03:19:51 +00:00
admin closed this pull request 2026-06-26 05:56:42 +00:00
admin reopened this pull request 2026-06-26 05:56:44 +00:00
jiantw83 added 3 commits 2026-06-26 06:01:40 +00:00
- config 對 GITEA_REPOSITORY 加入 owner/repo 格式驗證,拒絕路徑穿越與特殊字元
- releases JSON 解析失敗時,錯誤訊息納入截斷的回傳內容片段以利除錯

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 新增 logger section/info/error 的輸出格式測試
- config 補上 GITEA_REPOSITORY 驗證測試,並拆分 isUnset/requireEnv 的正反例
- version 補回 compareVersionArrays 的 major 跨區段比較案例

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(ai-review 狀態): 更新 findings.json 與 exclusions.json
CI / AI Code Review (pull_request) Failing after 23s
dd8977ffa4
已解決 6 條(warning x6:輸入驗證、錯誤訊息、logger 測試、測試拆分與補強),1 條判定為誤報寫入 exclusions(info:withFetch 抽離屬過度設計),findings 清空。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

🤖 AI Code Review 團隊

👤 角色 🎯 面向 🧠 個性
🗡️ Assassin security 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用
🎼 Bard style 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版
🧰 Leo maintainability 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來
🔮 Mage logic 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」
🧪 Maya testing 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑
Rogue efficiency 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
gitea-actions bot reviewed 2026-06-26 06:02:02 +00:00
gitea-actions bot left a comment

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 1 筆 3 筆 2 筆 0 筆
舊問題 0 筆 0 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 14 次呼叫)

提示 token 回應 token 合計
98,941 2,296 244,028

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 1 筆 | 3 筆 | 2 筆 | 0 筆 | | 舊問題 | 0 筆 | 0 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 14 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 98,941 | 2,296 | 244,028 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
@@ -58,0 +58,4 @@
// 驗證 repository 為 owner/repo 格式(僅允許字母數字與 . _ -,且拒絕 . 與 .. 路徑穿越段)
function assertRepository(name, value) {
const parts = value.split('/');
const valid = parts.length === 2

嚴重等級🟡 警告
審查員:Maya
問題:新增的 assertRepository 函式缺乏對 owner/repo 字串長度的邊界檢查,且變數名稱 valid 過於通用,語義不夠明確。
建議:建議在 assertRepository 中加入長度限制檢查,並將 valid 更名為 isRepoFormatValid 或類似具備明確語義的命名。

**嚴重等級**:🟡 警告 **審查員**:Maya **問題**:新增的 `assertRepository` 函式缺乏對 owner/repo 字串長度的邊界檢查,且變數名稱 `valid` 過於通用,語義不夠明確。 **建議**:建議在 `assertRepository` 中加入長度限制檢查,並將 `valid` 更名為 `isRepoFormatValid` 或類似具備明確語義的命名。
@@ -65,2 +65,3 @@
} catch {
throw new Error(`release API 回傳資料無法解析 (page=${page})`);
// 附上截斷的回傳內容片段,便於除錯回傳格式異常
const snippet = text.slice(0, 200);

嚴重等級🔵 建議
審查員:Bard
問題:將截斷字串直接串接在 Error 訊息中若處理不當易造成混淆,變數名稱 snippet 語義不明確。
建議:建議在錯誤訊息中對片段內容進行適當標記,並將變數更名為 contentSnippet

**嚴重等級**:🔵 建議 **審查員**:Bard **問題**:將截斷字串直接串接在 Error 訊息中若處理不當易造成混淆,變數名稱 `snippet` 語義不明確。 **建議**:建議在錯誤訊息中對片段內容進行適當標記,並將變數更名為 `contentSnippet`。
@@ -66,1 +66,3 @@
throw new Error(`release API 回傳資料無法解析 (page=${page})`);
// 附上截斷的回傳內容片段,便於除錯回傳格式異常
const snippet = text.slice(0, 200);
throw new Error(`release API 回傳資料無法解析 (page=${page}): ${snippet}`);

嚴重等級🔴 嚴重
審查員:Maya
問題:新增的異常處理邏輯截斷了 text 為 200 字元,但在 text 為極大值或無法轉為字串時未進行防禦性檢查,且截斷點可能將多位元組字元拆分導致亂碼。
建議:請確保 text 是字串後再截斷,並使用正確處理多位元組字元的方式(如 Array.from(text).slice(0, 200).join(''))以避免亂碼。

**嚴重等級**:🔴 嚴重 **審查員**:Maya **問題**:新增的異常處理邏輯截斷了 `text` 為 200 字元,但在 `text` 為極大值或無法轉為字串時未進行防禦性檢查,且截斷點可能將多位元組字元拆分導致亂碼。 **建議**:請確保 `text` 是字串後再截斷,並使用正確處理多位元組字元的方式(如 `Array.from(text).slice(0, 200).join('')`)以避免亂碼。
@@ -68,0 +81,4 @@
assert.throws(() => loadConfig({
GITEA_SERVER_URL: 'ftp://gitea.example.com',
GITEA_REPOSITORY: 'owner/repo',
}), /必須使用 http 或 https/);

嚴重等級🟡 警告
審查員:Maya
問題:缺少針對 assertRepository 邊界條件(如空字串、異常格式)的測試。
建議:補上 assert.throws 測試案例以涵蓋上述邊界條件,確保驗證邏輯完整。

**嚴重等級**:🟡 警告 **審查員**:Maya **問題**:缺少針對 `assertRepository` 邊界條件(如空字串、異常格式)的測試。 **建議**:補上 `assert.throws` 測試案例以涵蓋上述邊界條件,確保驗證邏輯完整。
@@ -0,0 +5,4 @@
const logger = require('../logger');
// 暫時攔截 process.stdout.write,回傳期間內寫出的內容

嚴重等級🟡 警告
審查員:Leo
問題:在測試中使用 monkey-patch 直接覆蓋 process.stdout.writeprocess.stderr.write 是極度危險的模式,可能導致狀態污染;且針對 logger.error 的測試不夠全面。
建議:建議重構 logger 使其支援依賴注入;並增加針對錯誤內容包含情況及非字串參數的斷言測試。

**嚴重等級**:🟡 警告 **審查員**:Leo **問題**:在測試中使用 monkey-patch 直接覆蓋 `process.stdout.write` 或 `process.stderr.write` 是極度危險的模式,可能導致狀態污染;且針對 `logger.error` 的測試不夠全面。 **建議**:建議重構 `logger` 使其支援依賴注入;並增加針對錯誤內容包含情況及非字串參數的斷言測試。
@@ -0,0 +7,4 @@
// 暫時攔截 process.stdout.write,回傳期間內寫出的內容
function captureStdout(fn) {
const original = process.stdout.write;

嚴重等級🔵 建議
審查員:Bard
問題:測試工具函式 captureStdoutcaptureStderr 邏輯高度重複,不符合 DRY 原則。
建議:建議抽取出通用的 captureStream(stream, fn) 函式以提升可維護性。

**嚴重等級**:🔵 建議 **審查員**:Bard **問題**:測試工具函式 `captureStdout` 與 `captureStderr` 邏輯高度重複,不符合 DRY 原則。 **建議**:建議抽取出通用的 `captureStream(stream, fn)` 函式以提升可維護性。
gitea-actions bot added 1 commit 2026-06-26 06:02:03 +00:00
admin closed this pull request 2026-06-26 06:02:28 +00:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: old-docker-actions/calculate-version#7