Files
hermes-desktop/tests/client/model-selector-provider-sync.test.ts
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

52 lines
2.3 KiB
TypeScript

import { readFileSync } from 'fs'
import { describe, expect, it } from 'vitest'
const readClientFile = (path: string) => readFileSync(`packages/client/src/${path}`, 'utf8')
// 从 `computed(` 的左括号开始做括号配平,精确切出这个表达式的范围。
// 用空行切分不行:箭头函数写成单行后,紧邻的下一个顶层声明只隔一个空行。
function balancedBlock(source: string, header: string): string {
const start = source.indexOf(header)
expect(start, `${header} not found`).toBeGreaterThan(-1)
let depth = 0
for (let i = start + header.length - 1; i < source.length; i += 1) {
if (source[i] === '(') depth += 1
if (source[i] === ')') {
depth -= 1
if (depth === 0) return source.slice(start, i + 1)
}
}
return source.slice(start)
}
// known-issues #1: `providerOptions` 的 computed getter 内部给 customProvider
// 赋值。用户手动挑好的 provider 会被下一次 getter 重算无声改回去,表现为
// 「自己跳」。修法是把同步移进 watch,让 getter 恢复成纯读。
describe('ModelSelector provider selection', () => {
it('keeps the providerOptions getter free of side effects', () => {
const source = readClientFile('components/layout/ModelSelector.vue')
const block = balancedBlock(source, 'const providerOptions = computed(')
expect(block).not.toContain('customProvider.value =')
})
it('syncs customProvider from the store through a watch', () => {
const source = readClientFile('components/layout/ModelSelector.vue')
const block = balancedBlock(source, 'watch(')
// 同步点必须挂在 selectedProvider 上,而不是挂在 providerOptions 上 ——
// 后者等于把同一个副作用换个地方写一遍。
expect(block.slice(0, 200)).toContain('appStore.selectedProvider')
expect(block).toContain('customProvider.value =')
})
it('still initialises the provider when the picker opens', () => {
// watch 是懒的:不会在初始渲染时触发。openModal 的这一次赋值是首帧
// 唯一来源,不能跟着一起去掉。
const source = readClientFile('components/layout/ModelSelector.vue')
expect(source).toMatch(/function openModal\(\)[\s\S]*?customProvider\.value = appStore\.selectedProvider/)
})
})