import assert from 'node:assert/strict' import test from 'node:test' import { readFileSync } from 'node:fs' import { compileFunction } from 'node:vm' import { computed, reactive, ref } from './vue.mjs' const source = readFileSync(new URL('../../frontend/src/views/components/ConfigSettings/ConfigSettings.js', import.meta.url), 'utf8') const createPage = compileFunction( source.replace(/^import .*$/gm, '').replace('export function usePage', 'function usePage') + '\nreturn usePage()', ['computed', 'onMounted', 'reactive', 'ref', 'ElMessage', 'ElMessageBox', 'http', 'useGlobalStatusStore'] ) function fixture(get) { const messages = [] const page = createPage(computed, () => {}, reactive, ref, { error: message => messages.push(message) }, {}, { get }, () => ({ hasCapability: () => true })) return { page, messages } } test('旧版配置仅请求状态,不并发请求分区、备份和审计', async () => { const requests = [] const { page, messages } = fixture(async path => { requests.push(path) return { errorNo: 0, data: { available: false, unavailableReason: '在线配置管理尚未启用' } } }) await page.loadAll() assert.deepEqual(requests, ['/api/v1/config/status']) assert.equal(page.availabilityError.value, '在线配置管理尚未启用') assert.deepEqual(messages, []) assert.equal(page.loading.value, false) }) test('备份和审计失败只显示局部错误,不阻挡配置编辑区域', async () => { const { page, messages } = fixture(async path => { if (path.endsWith('/status')) return { errorNo: 0, data: { available: true } } if (path.endsWith('/base')) return { errorNo: 0, data: {} } throw new Error('配置服务暂时不可用') }) await page.loadAll() assert.equal(page.availabilityError.value, '') assert.equal(page.editorText.value, '{}') assert.equal(page.backupsError.value, '配置服务暂时不可用') assert.equal(page.auditError.value, '配置服务暂时不可用') assert.deepEqual(messages, []) await page.loadBackups() assert.deepEqual(messages, []) assert.equal(page.backupsError.value, '配置服务暂时不可用') }) test('附属模块失败清除旧数据和回滚选择,重试成功清除错误', async () => { let fail = true const { page } = fixture(async () => { if (fail) throw new Error('网络不可用') return { errorNo: 0, data: [{ generation: 2 }] } }) page.backups.value = [{ generation: 1 }] page.auditItems.value = [{ id: 'old' }] page.rollbackGeneration.value = 1 page.rollbackPreview.value = { targetGeneration: 1 } page.rollbackConfirmed.value = true await Promise.all([page.loadBackups(), page.loadAudit()]) assert.deepEqual(page.backups.value, []) assert.deepEqual(page.auditItems.value, []) assert.equal(page.rollbackGeneration.value, 0) assert.equal(page.rollbackPreview.value, null) assert.equal(page.rollbackConfirmed.value, false) fail = false await Promise.all([page.loadBackups(), page.loadAudit()]) assert.equal(page.backupsError.value, '') assert.equal(page.auditError.value, '') assert.equal(page.backups.value.length, 1) assert.equal(page.auditItems.value.length, 1) assert.equal(page.backupsLoading.value, false) assert.equal(page.auditLoading.value, false) }) test('状态请求失败后可重试恢复,不保留不可用提示', async () => { let available = false const { page } = fixture(async path => { if (!available) throw new Error('网络不可用') return { errorNo: 0, data: path.endsWith('/status') ? { available: true } : {} } }) await page.loadAll() assert.equal(page.availabilityError.value, '网络不可用') available = true await page.loadAll() assert.equal(page.availabilityError.value, '') })