From a9d137ac9ec053526bc7ad52442d322274517c34 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 26 Jun 2026 14:01:30 +0800 Subject: [PATCH] =?UTF-8?q?test(calculate-version):=20=E8=A3=9C=E5=BC=B7?= =?UTF-8?q?=E6=B8=AC=E8=A9=A6=E8=A6=86=E8=93=8B=E4=B8=A6=E6=8B=86=E5=88=86?= =?UTF-8?q?=E6=B7=B7=E5=90=88=E6=B8=AC=E8=A9=A6=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 logger section/info/error 的輸出格式測試 - config 補上 GITEA_REPOSITORY 驗證測試,並拆分 isUnset/requireEnv 的正反例 - version 補回 compareVersionArrays 的 major 跨區段比較案例 Co-Authored-By: Claude Opus 4.8 (1M context) --- app/test/config.test.js | 35 ++++++++++++++++++++++--- app/test/logger.test.js | 55 ++++++++++++++++++++++++++++++++++++++++ app/test/version.test.js | 1 + 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 app/test/logger.test.js diff --git a/app/test/config.test.js b/app/test/config.test.js index d67f54e..c41bed6 100644 --- a/app/test/config.test.js +++ b/app/test/config.test.js @@ -10,15 +10,25 @@ const { loadConfig, } = require('../config'); -test('isUnset 將 undefined/空字串/null 字面值視為未設定', () => { +test('isUnset 對 undefined/null/空字串/字面 "null" 視為未設定', () => { assert.equal(isUnset(undefined), true); + assert.equal(isUnset(null), true); assert.equal(isUnset(''), true); assert.equal(isUnset('null'), true); - assert.equal(isUnset('value'), false); }); -test('requireEnv 未設定時拋錯,有值時回傳原值', () => { +test('isUnset 對其他非空值視為已設定', () => { + assert.equal(isUnset('value'), false); + assert.equal(isUnset('false'), false); + assert.equal(isUnset('0'), false); +}); + +test('requireEnv 未設定時拋錯', () => { assert.throws(() => requireEnv('FOO', ''), /FOO 未設定/); + assert.throws(() => requireEnv('FOO', undefined), /FOO 未設定/); +}); + +test('requireEnv 有值時回傳原值', () => { assert.equal(requireEnv('FOO', 'bar'), 'bar'); }); @@ -73,3 +83,22 @@ test('loadConfig 於 GITEA_SERVER_URL 使用非 http(s) 協定時拋錯', () => GITEA_REPOSITORY: 'owner/repo', }), /必須使用 http 或 https/); }); + +test('loadConfig 於 GITEA_REPOSITORY 格式錯誤或含路徑穿越時拋錯', () => { + assert.throws(() => loadConfig({ + GITEA_SERVER_URL: 'https://gitea.example.com', + GITEA_REPOSITORY: '../evil', + }), /GITEA_REPOSITORY 格式錯誤/); + assert.throws(() => loadConfig({ + GITEA_SERVER_URL: 'https://gitea.example.com', + GITEA_REPOSITORY: 'owner/repo/extra', + }), /GITEA_REPOSITORY 格式錯誤/); +}); + +test('loadConfig 接受含點號的合法 owner/repo', () => { + const config = loadConfig({ + GITEA_SERVER_URL: 'https://gitea.example.com', + GITEA_REPOSITORY: 'my.org/my.repo', + }); + assert.equal(config.repository, 'my.org/my.repo'); +}); diff --git a/app/test/logger.test.js b/app/test/logger.test.js new file mode 100644 index 0000000..390b4dc --- /dev/null +++ b/app/test/logger.test.js @@ -0,0 +1,55 @@ +'use strict'; + +const test = require('node:test'); +const assert = require('node:assert/strict'); + +const logger = require('../logger'); + +// 暫時攔截 process.stdout.write,回傳期間內寫出的內容 +function captureStdout(fn) { + const original = process.stdout.write; + let out = ''; + process.stdout.write = (chunk) => { out += chunk; return true; }; + try { + fn(); + } finally { + process.stdout.write = original; + } + return out; +} + +// 暫時攔截 process.stderr.write,回傳期間內寫出的內容 +function captureStderr(fn) { + const original = process.stderr.write; + let out = ''; + process.stderr.write = (chunk) => { out += chunk; return true; }; + try { + fn(); + } finally { + process.stderr.write = original; + } + return out; +} + +test('section 以主/次分隔線包夾標題輸出至 stdout', () => { + const out = captureStdout(() => logger.section('參數檢查')); + const line = '='.repeat(50); + const subline = '-'.repeat(50); + assert.equal(out, `\n${line}\n參數檢查\n${subline}\n`); +}); + +test('info 以 [info] 前綴與換行輸出至 stdout', () => { + const out = captureStdout(() => logger.info('IS_BETA=false')); + assert.equal(out, '[info] IS_BETA=false\n'); +}); + +test('error 以 [error] 前綴與換行輸出至 stderr', () => { + const out = captureStderr(() => logger.error('GITEA_SERVER_URL 未設定')); + assert.equal(out, '[error] GITEA_SERVER_URL 未設定\n'); +}); + +test('error 僅輸出不終止行程,呼叫後仍可繼續執行', () => { + let reached = false; + captureStderr(() => { logger.error('still alive'); reached = true; }); + assert.equal(reached, true); +}); diff --git a/app/test/version.test.js b/app/test/version.test.js index f24e040..13fdc43 100644 --- a/app/test/version.test.js +++ b/app/test/version.test.js @@ -18,6 +18,7 @@ const rel = (tag) => ({ tag_name: tag }); test('compareVersionArrays 逐區段比較且較短者較小', () => { assert.ok(compareVersionArrays([1, 10], [1, 2, 3]) > 0); assert.ok(compareVersionArrays([1, 2], [1, 2, 0]) < 0); + assert.ok(compareVersionArrays([2, 0, 0], [1, 9, 9]) > 0); assert.equal(compareVersionArrays([1, 2, 3], [1, 2, 3]), 0); });