新增含空白/星號/冒號等非法字元,以及單段超過長度上限的拒絕測試。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
129 lines
4.0 KiB
JavaScript
129 lines
4.0 KiB
JavaScript
'use strict';
|
||
|
||
const test = require('node:test');
|
||
const assert = require('node:assert/strict');
|
||
|
||
const {
|
||
isUnset,
|
||
requireEnv,
|
||
normalizeBetaFlag,
|
||
loadConfig,
|
||
} = require('../config');
|
||
|
||
test('isUnset 對 undefined/null/空字串/字面 "null" 視為未設定', () => {
|
||
assert.equal(isUnset(undefined), true);
|
||
assert.equal(isUnset(null), true);
|
||
assert.equal(isUnset(''), true);
|
||
assert.equal(isUnset('null'), true);
|
||
});
|
||
|
||
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');
|
||
});
|
||
|
||
test('normalizeBetaFlag 僅 "true" 視為啟用', () => {
|
||
assert.equal(normalizeBetaFlag('true'), true);
|
||
assert.equal(normalizeBetaFlag('false'), false);
|
||
assert.equal(normalizeBetaFlag(undefined), false);
|
||
assert.equal(normalizeBetaFlag('TRUE'), false);
|
||
});
|
||
|
||
test('loadConfig 解析完整設定', () => {
|
||
const config = loadConfig({
|
||
GITEA_SERVER_URL: 'https://gitea.example.com',
|
||
GITEA_REPOSITORY: 'owner/repo',
|
||
GITEA_TOKEN: 'secret',
|
||
IS_BETA: 'true',
|
||
});
|
||
|
||
assert.deepEqual(config, {
|
||
serverUrl: 'https://gitea.example.com',
|
||
repository: 'owner/repo',
|
||
token: 'secret',
|
||
isBeta: true,
|
||
});
|
||
});
|
||
|
||
test('loadConfig 缺少 token 視為匿名(null)', () => {
|
||
const config = loadConfig({
|
||
GITEA_SERVER_URL: 'https://gitea.example.com',
|
||
GITEA_REPOSITORY: 'owner/repo',
|
||
GITEA_TOKEN: 'null',
|
||
});
|
||
|
||
assert.equal(config.token, null);
|
||
assert.equal(config.isBeta, false);
|
||
});
|
||
|
||
test('loadConfig 缺少必填項目時拋錯', () => {
|
||
assert.throws(() => loadConfig({ GITEA_REPOSITORY: 'owner/repo' }), /GITEA_SERVER_URL 未設定/);
|
||
});
|
||
|
||
test('loadConfig 於 GITEA_SERVER_URL 非合法 URL 時拋錯', () => {
|
||
assert.throws(() => loadConfig({
|
||
GITEA_SERVER_URL: 'not-a-url',
|
||
GITEA_REPOSITORY: 'owner/repo',
|
||
}), /GITEA_SERVER_URL 格式錯誤/);
|
||
});
|
||
|
||
test('loadConfig 於 GITEA_SERVER_URL 使用非 http(s) 協定時拋錯', () => {
|
||
assert.throws(() => loadConfig({
|
||
GITEA_SERVER_URL: 'ftp://gitea.example.com',
|
||
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 於 GITEA_REPOSITORY 邊界格式(空段/缺斜線/多段)皆拋錯', () => {
|
||
for (const repo of ['noslash', 'owner/', '/repo', 'a/b/c', 'owner//repo']) {
|
||
assert.throws(() => loadConfig({
|
||
GITEA_SERVER_URL: 'https://gitea.example.com',
|
||
GITEA_REPOSITORY: repo,
|
||
}), /GITEA_REPOSITORY 格式錯誤/, `應拒絕:${repo}`);
|
||
}
|
||
});
|
||
|
||
test('loadConfig 於 GITEA_REPOSITORY 含非法字元或超長段時拋錯', () => {
|
||
const bad = [
|
||
'ow ner/repo',
|
||
'owner/re*po',
|
||
'owner/re:po',
|
||
`${'a'.repeat(101)}/repo`,
|
||
];
|
||
for (const repo of bad) {
|
||
assert.throws(() => loadConfig({
|
||
GITEA_SERVER_URL: 'https://gitea.example.com',
|
||
GITEA_REPOSITORY: repo,
|
||
}), /GITEA_REPOSITORY 格式錯誤/, `應拒絕:${repo}`);
|
||
}
|
||
});
|
||
|
||
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');
|
||
});
|