'use strict'; const { test, afterEach } = require('node:test'); const assert = require('node:assert/strict'); const logger = require('../logger'); const realStdout = process.stdout.write; const realStderr = process.stderr.write; afterEach(() => { process.stdout.write = realStdout; process.stderr.write = realStderr; }); // 同時攔截 stdout 與 stderr,回傳本次 run() 內各自寫出的字串 function capture(run) { const out = []; const err = []; process.stdout.write = (chunk) => { out.push(String(chunk)); return true; }; process.stderr.write = (chunk) => { err.push(String(chunk)); return true; }; try { run(); } finally { process.stdout.write = realStdout; process.stderr.write = realStderr; } return { out: out.join(''), err: err.join('') }; } const TIME = /\[\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}\]/; test('info 未帶 stage 時以 [INF][時間]: 格式輸出至 stdout', () => { const { out, err } = capture(() => logger.info('IS_BETA=false')); assert.match(out, new RegExp(`^\\[INF\\]${TIME.source}: IS_BETA=false\\n$`)); assert.equal(err, ''); }); test('info 帶 stage 時以 [階段][INF][時間]: 格式輸出至 stdout', () => { const { out, err } = capture(() => logger.info('IS_BETA=false', '參數檢查')); assert.match(out, new RegExp(`^\\[參數檢查\\]\\[INF\\]${TIME.source}: IS_BETA=false\\n$`)); assert.equal(err, ''); }); test('error 未帶 stage 時以 [ERR][時間]: 格式輸出至 stderr,且不寫入 stdout', () => { const { out, err } = capture(() => logger.error('GITEA_SERVER_URL 未設定')); assert.match(err, new RegExp(`^\\[ERR\\]${TIME.source}: GITEA_SERVER_URL 未設定\\n$`)); assert.equal(out, ''); }); test('error 帶 stage 時以 [階段][ERR][時間]: 格式輸出至 stderr', () => { const { err } = capture(() => logger.error('讀取失敗', '取得舊版本')); assert.match(err, new RegExp(`^\\[取得舊版本\\]\\[ERR\\]${TIME.source}: 讀取失敗\\n$`)); }); test('forStage 回傳的子記錄器自動帶入階段名稱', () => { const staged = logger.forStage('計算版本號'); const { out, err } = capture(() => { staged.info('NEW_VERSION=0.0.6'); staged.error('計算錯誤'); }); assert.match(out, new RegExp(`^\\[計算版本號\\]\\[INF\\]${TIME.source}: NEW_VERSION=0.0.6\\n$`)); assert.match(err, new RegExp(`^\\[計算版本號\\]\\[ERR\\]${TIME.source}: 計算錯誤\\n$`)); }); test('info/error 的時間戳為 yyyy/MM/dd HH:mm:ss 格式', () => { const { out } = capture(() => logger.info('x')); assert.match(out, TIME); });