Files
RuoYi-Vue3-FastAPI/ruoyi-fastapi-frontend/tests/plugins/pluginRuntimeMetrics.test.js
T
insistence 4bd83bc7cd feat: 支持 v2 插件、独立前端和签名制品发布 (#130)
* feat: 支持 v2 插件、原生扩展与签名发布

* fix: 修复测试

* feat: 增强宿主 SDK、运行观测与制品维护能力

* feat: 增强文件传输、配置观测与本地开发能力

* feat: 支持 SSE 实时事件流并完善开发脚手架

* feat: 完善长连接鉴权复核与关闭回收

* feat: 增强生命周期与任务关闭可靠性

* feat: 收紧健康检查契约并补齐前端与真实网络验收

* feat: 增加SDK溯源与离线更新工具并验证跨版本兼容

* feat: 增加持久化业务示例与受控 Python 交付

* feat: 增加统一运行诊断与多worker状态观测

* feat: 增加固定目标发布等待与自动验收

* fix: 修复多环境插件部署前缀与代理配置不一致

* fix: 修复测试
2026-10-09 23:49:45 +08:00

80 lines
2.4 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { compileScript, parse } from '@vue/compiler-sfc'
import { computed, effectScope, nextTick, reactive, ref, watch } from 'vue'
// 执行组件的真实监听与请求逻辑,只替换网络边界和卸载钩子。
const source = readFileSync(
new URL('../../src/views/system/plugin/components/PluginRuntimeMetrics.vue', import.meta.url),
'utf8'
)
const { descriptor } = parse(source)
const compiled = compileScript(descriptor, { id: 'plugin-runtime-metrics-test' })
const script = compiled.scriptSetupAst
.filter((statement) => statement.type !== 'ImportDeclaration')
.map((statement) => descriptor.scriptSetup.content.slice(statement.start, statement.end))
.join('\n')
const setup = new Function(
'computed',
'ref',
'watch',
'onBeforeUnmount',
'defineProps',
'getPluginRuntimeMetrics',
`${script}\nreturn { data, loading, error, refresh }`
)
const props = reactive({ pluginId: 'first_plugin' })
const requests = []
let unmount
const scope = effectScope()
const state = scope.run(() =>
setup(
computed,
ref,
watch,
(callback) => {
unmount = callback
},
() => props,
(pluginId, signal) =>
new Promise((resolve, reject) => {
requests.push({ pluginId, signal, resolve, reject })
})
)
)
assert.equal(state.loading.value, true)
assert.equal(requests[0].pluginId, 'first_plugin')
props.pluginId = 'second_plugin'
await nextTick()
assert.equal(requests[0].signal.aborted, true)
requests[1].resolve({ data: { series: [{ version: 'second' }] } })
await nextTick()
requests[0].resolve({ data: { series: [{ version: 'stale' }] } })
await nextTick()
assert.equal(
state.data.value.series[0].version,
'second',
'late response must not replace the selected plugin'
)
assert.equal(state.loading.value, false)
const failed = state.refresh()
requests[2].reject(new Error('network unavailable'))
await failed
assert.match(state.error.value, /查询失败/)
assert.equal(state.loading.value, false)
const retry = state.refresh()
assert.equal(state.error.value, '')
requests[3].resolve({ data: { supported: false, series: [] } })
await retry
assert.equal(state.data.value.supported, false)
const closing = state.refresh()
unmount()
scope.stop()
assert.equal(requests[4].signal.aborted, true)
requests[4].reject(new Error('cancelled'))
await closing
assert.equal(state.error.value, '', 'closing the dialog must not report a failed query')