Skip to main content
浏览文档目录
第 10 章

测试

@uniflow/plugin-sdk/testing 迷你宿主

@uniflow/plugin-sdk/testing 的 createTestHost 是一个内存里的迷你宿主:你的插件代码经与应用相同的运行时与消息协议执行 (结构化复制、错误还原、调用结束后能力作废都一样),宿主一侧按应用的规则实现:参数按 schema 校验、权限裁剪、read 模式只读、 模型来源的写命令先 describe 再确认、撤销栈、日历只能改自己的事件、存储的名字规则与 64KB 上限。

TypeScript
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { createTestHost } from '@uniflow/plugin-sdk/testing'
import plugin from '../src/main'
import pluginJson from '../plugin.json'
import en from '../locales/en.json'

test('snooze 可以撤销', async () => {
  const host = createTestHost({
    pluginJson, definition: plugin, locales: { en },
    courses: [{ id: 'c1', name: 'Biology', code: 'BIO 101' }],
    assignments: [/* PluginAssignment */],
    events: [/* 用户自己的日历事件 */],
    fetch: { 'https://api.example.com/x': 'body' },      // network 权限的假下载
    openFile: () => ({ name: 'a.csv', text: 'q,a' }),    // files.open 的假对话框
    confirm: (description) => true,                     // 模型来源写命令的确认
  })
  const r = await host.run('snooze', { assignmentId: 'a1' }, { source: 'agent' })
  assert.equal(r.ok, true)
  assert.deepEqual(host.confirmations, ['把「Lab 3」隐藏到 …'])
  assert.equal((await host.undo()).ok, true)
  assert.deepEqual(host.storage(), { snoozed: {} })
})
host 上的 说明
run(action, args, { source }) source: 'ui'(默认,界面)/ 'agent'(模型:写命令先确认、agentVisible:false 的命令调不到)
undo() 撤销最近一次可撤销的写命令
storage() / deviceStorage() 存储的快照 { 集合: { id: data } }
events() 日历事件快照
confirmations / saved / panels 确认卡片文字 / files.save 写了什么 / openPanel 的参数
setLocale(lang)、t 切换语言、取文案

测什么:每个命令至少覆盖正常路径、参数错误、前置条件错误(describe 里就拒绝)、撤销;纯计算逻辑抽成纯函数单独测 (模板里的 src/sessions.ts、src/due.ts)。迷你宿主是应用的忠实缩影但不是应用本身:发布前在应用里(开发者模式)走一遍。