mirror of
https://github.com/insistence/RuoYi-Vue3-FastAPI.git
synced 2026-10-15 05:19:14 +00:00
* feat: 支持 v2 插件、原生扩展与签名发布 * fix: 修复测试 * feat: 增强宿主 SDK、运行观测与制品维护能力 * feat: 增强文件传输、配置观测与本地开发能力 * feat: 支持 SSE 实时事件流并完善开发脚手架 * feat: 完善长连接鉴权复核与关闭回收 * feat: 增强生命周期与任务关闭可靠性 * feat: 收紧健康检查契约并补齐前端与真实网络验收 * feat: 增加SDK溯源与离线更新工具并验证跨版本兼容 * feat: 增加持久化业务示例与受控 Python 交付 * feat: 增加统一运行诊断与多worker状态观测 * feat: 增加固定目标发布等待与自动验收 * fix: 修复多环境插件部署前缀与代理配置不一致 * fix: 修复测试
80 lines
2.4 KiB
JavaScript
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')
|