后端迁移测试文件

This commit is contained in:
yml
2026-05-21 17:39:34 +08:00
parent 3a2f89e233
commit acd5c0d50e
37 changed files with 12 additions and 2 deletions
+104
View File
@@ -0,0 +1,104 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import {
formatLogEntry,
formatLogTimestamp,
normalizeLogLevel,
resolveExpiredLogFilenames,
resolveLogFilePath,
shouldWriteLog,
} from './logger.js'
test('normalizeLogLevel falls back to info for unsupported values', () => {
assert.equal(normalizeLogLevel('debug'), 'debug')
assert.equal(normalizeLogLevel('WARN'), 'warn')
assert.equal(normalizeLogLevel('verbose'), 'info')
assert.equal(normalizeLogLevel(''), 'info')
})
test('shouldWriteLog respects configured minimum log level', () => {
assert.equal(shouldWriteLog('debug', 'debug'), true)
assert.equal(shouldWriteLog('info', 'debug'), true)
assert.equal(shouldWriteLog('debug', 'info'), false)
assert.equal(shouldWriteLog('info', 'warn'), false)
assert.equal(shouldWriteLog('warn', 'warn'), true)
assert.equal(shouldWriteLog('error', 'warn'), true)
})
test('resolveLogFilePath uses daily log file names by channel', () => {
assert.match(resolveLogFilePath('app', '2026-04-14T10:00:00.000Z'), /app-2026-04-14\.log$/)
assert.match(resolveLogFilePath('webhook', '2026-04-14T10:00:00.000Z'), /webhook-2026-04-14\.log$/)
})
test('resolveExpiredLogFilenames keeps latest seven days and ignores unknown files', () => {
const expired = resolveExpiredLogFilenames([
'app-2026-04-14.log',
'app-2026-04-13.log',
'app-2026-04-08.log',
'app-2026-04-07.log',
'webhook-2026-04-06.log',
'app.log',
'webhook.log',
'random.txt',
], '2026-04-14T12:00:00.000Z', 7)
assert.deepEqual(expired, [
'app-2026-04-07.log',
'webhook-2026-04-06.log',
'app.log',
'webhook.log',
])
})
test('formatLogTimestamp renders readable local timestamp with timezone offset', () => {
const rendered = formatLogTimestamp('2026-04-14T10:36:24.974Z')
assert.match(rendered, /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [+-]\d{2}:\d{2}$/)
})
test('formatLogEntry prints readable one-line output for flat details', () => {
const text = formatLogEntry({
time: '2026-04-14T10:36:24.974Z',
level: 'info',
scope: '[http/access]',
message: 'request completed',
pid: 4671,
detail: {
requestId: 'req-123',
method: 'GET',
statusCode: 401,
},
}, { color: false })
assert.match(text, /INFO\s+\[http\/access\] request completed/)
assert.match(text, /pid=4671/)
assert.match(text, /requestId=req-123/)
assert.match(text, /method=GET/)
assert.match(text, /statusCode=401/)
assert.doesNotMatch(text, /^\{/)
})
test('formatLogEntry prints nested detail blocks without ansi colors in file mode', () => {
const text = formatLogEntry({
time: '2026-04-14T10:36:24.974Z',
level: 'warn',
scope: '[admin/auth]',
message: '后台鉴权失败',
pid: 4671,
detail: {
statusCode: 401,
errorCode: 'admin_auth_required',
error: {
message: '未登录或登录已失效',
stack: 'Error: test',
},
},
}, { color: false })
assert.match(text, /WARN\s+\[admin\/auth\] 后台鉴权失败/)
assert.match(text, /statusCode=401/)
assert.match(text, /errorCode=admin_auth_required/)
assert.match(text, /\n \{/)
assert.match(text, /未登录或登录已失效/)
assert.doesNotMatch(text, /\u001B\[/)
})