76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import { parse } from '@vue/compiler-sfc'
|
|
import ts from 'typescript'
|
|
const source = parse(
|
|
readFileSync(new URL('../src/views/m/crm/product/categories.vue', import.meta.url), 'utf8')
|
|
).descriptor.scriptSetup!.content
|
|
const ast = ts.createSourceFile('category.ts', source, ts.ScriptTarget.Latest, true)
|
|
function harness(fetchCategoryTree: (...args: any[]) => Promise<any>) {
|
|
const names = ['loadTree', 'getCategoryTreeSelect', 'openAdd', 'resetForm']
|
|
const code = ast.statements
|
|
.filter((n) => ts.isFunctionDeclaration(n) && names.includes(n.name!.text))
|
|
.map((n) => n.getText(ast))
|
|
.join('\n')
|
|
const state: Record<string, any> = {
|
|
fetchCategoryTree,
|
|
keyword: { value: ' 酸 ' },
|
|
loading: { value: false },
|
|
loadError: { value: '' },
|
|
tree: { value: [] },
|
|
expandedIds: { value: {} },
|
|
collectExpandIds: () => ({}),
|
|
categoryTreeOptions: { value: [] },
|
|
actionOpen: { value: false },
|
|
formOpen: { value: false },
|
|
formTitle: { value: '' },
|
|
formData: {},
|
|
nameError: { value: '' },
|
|
showFailToast: (message: string) => state.toasts.push(message),
|
|
toasts: []
|
|
}
|
|
const handlers = new Function(
|
|
...Object.keys(state),
|
|
'let loadSeq = 0;\n' + ts.transpile(code) + ';return {loadTree,openAdd}'
|
|
)(...Object.values(state))
|
|
return { ...state, ...handlers }
|
|
}
|
|
test('category search trims query, reports errors, and retries successfully', async () => {
|
|
let fail = true
|
|
const calls: any[] = []
|
|
const h = harness(async (params) => {
|
|
calls.push(params)
|
|
if (fail) throw new Error('网络中断')
|
|
return { data: [{ id: 'a', categoryName: '酸' }] }
|
|
})
|
|
await h.loadTree()
|
|
assert.equal(h.loadError.value, '网络中断')
|
|
assert.equal(h.loading.value, false)
|
|
fail = false
|
|
await h.loadTree()
|
|
assert.deepEqual(calls, [{ categoryName: '酸' }, { categoryName: '酸' }])
|
|
assert.equal(h.loadError.value, '')
|
|
assert.equal(h.tree.value[0].id, 'a')
|
|
})
|
|
test('an earlier category response cannot replace the latest search', async () => {
|
|
const resolve: ((value: any) => void)[] = []
|
|
const h = harness(() => new Promise((r) => resolve.push(r)))
|
|
const first = h.loadTree()
|
|
h.keyword.value = '碱'
|
|
const second = h.loadTree()
|
|
resolve[1]({ data: [{ id: 'new' }] })
|
|
await second
|
|
resolve[0]({ data: [{ id: 'old' }] })
|
|
await first
|
|
assert.equal(h.tree.value[0].id, 'new')
|
|
})
|
|
test('failed parent-option loading keeps the category form closed and explains retry', async () => {
|
|
const h = harness(async () => {
|
|
throw new Error('分类加载失败')
|
|
})
|
|
await h.openAdd()
|
|
assert.equal(h.formOpen.value, false)
|
|
assert.deepEqual(h.toasts, ['分类加载失败'])
|
|
})
|