Smail/test/frontend/logs.test.mjs
smail b77b272a5e
Some checks are pending
Security Checks / security (push) Waiting to run
保存日志权限分页与归档并发修正,继续运行验收
2026-09-08 22:44:21 +08:00

88 lines
3.5 KiB
JavaScript

import assert from 'node:assert/strict'
import test from 'node:test'
import { readFileSync } from 'node:fs'
import { compileFunction } from 'node:vm'
import { createRequire } from 'node:module'
import { computed, ref } from './vue.mjs'
const root = new URL('../../frontend/src/views/components/LogSettings/', import.meta.url)
const read = name => readFileSync(new URL(name, root), 'utf8')
const create = compileFunction(
read('LogSettings.js').replace(/^import .*$/gm, '').replace('export function', 'function') + '\nreturn useLogs()',
['computed', 'onBeforeUnmount', 'onMounted', 'ref', 'watch', 'http']
)
function fixture(get) {
let dispose
const page = create(computed, callback => { dispose = callback }, () => {}, ref, () => {}, { get })
return { page, dispose: () => dispose() }
}
test('日志页面模板和样式能编译,详情不使用原始 HTML 渲染', () => {
const require = createRequire(new URL('../../frontend/package.json', import.meta.url))
const { parse, compileScript, compileStyle } = require('@vue/compiler-sfc')
const { descriptor, errors } = parse(read('LogSettings.vue'))
assert.deepEqual(errors, [])
assert.doesNotThrow(() => compileScript(descriptor, { id: 'logs', inlineTemplate: true }))
assert.deepEqual(compileStyle({ source: read('LogSettings.css'), id: 'logs', scoped: true }).errors, [])
assert.doesNotMatch(read('LogSettings.vue'), /v-html/)
})
test('日志查询传递时间与操作者筛选,并将业务失败显示为错误', async () => {
const requests = []
const { page } = fixture(async (_, options) => {
requests.push(options.params)
return requests.length === 1
? { errorNo: 0, data: { items: [{ id: 'safe' }], hasMore: false } }
: { errorNo: 500, errorMsg: '日志暂不可用' }
})
page.actorId.value = ' 42 '
page.dateRange.value = ['2026-09-01T00:00:00Z', '2026-09-08T00:00:00Z']
await page.search()
assert.equal(requests[0].actorId, '42')
assert.equal(requests[0].from, '2026-09-01T00:00:00.000Z')
assert.equal(page.items.value.length, 1)
await page.search()
assert.equal(page.error.value, '日志暂不可用')
assert.equal(page.items.value.length, 0)
assert.equal(page.displayActor({ actorId: '0' }), '系统')
})
test('压缩日志短页正确返回上一页,文件过期后重置偏移', async () => {
let filename = 'runtime-2026-08-15.log.gz'
const offsets = []
const { page } = fixture(async (_, { params }) => {
if (!params.file) return { errorNo: 0, data: { files: [{ name: filename, compressed: true }] } }
offsets.push(params.offset)
return { errorNo: 0, data: { lines: Array(params.offset === 0 ? 8 : 12).fill('日志'), hasMore: true } }
})
page.category.value = 'runtime'
await page.search()
await page.next()
await page.next()
await page.previous()
assert.deepEqual(offsets, [0, 8, 20, 8])
filename = 'runtime-2026-08-16.log.gz'
await page.next()
assert.equal(page.offset.value, 0)
assert.equal(offsets.at(-1), 0)
})
test('慢响应及卸载后的响应不得覆盖最新日志', async () => {
let complete
let count = 0
const { page, dispose } = fixture(async () => {
if (++count === 1) return new Promise(resolve => { complete = resolve })
return { errorNo: 0, data: { items: [{ id: 'new' }] } }
})
const first = page.search()
await page.search()
complete({ errorNo: 0, data: { items: [{ id: 'old' }] } })
await first
assert.equal(page.items.value[0].id, 'new')
const last = page.search()
dispose()
await last
assert.equal(page.items.value[0].id, 'new')
})