Files
shanxia2.0/web-admin/scripts/mobile-related-detail-route.test.ts

92 lines
4.8 KiB
TypeScript

import assert from 'node:assert/strict'
import test from 'node:test'
import { readFileSync } from 'node:fs'
import { parse } from '@vue/compiler-sfc'
import ts from 'typescript'
import * as vue from 'vue'
import { createRouter, createMemoryHistory, useRoute, useRouter } from 'vue-router'
import * as navigation from '../src/utils/mp-webview'
const flush = async () => { for (let i = 0; i < 20; i++) await Promise.resolve() }
async function mount(kind: 'contract' | 'quote', embedded = false) {
const filename = `../src/views/m/crm/${kind}/detail.vue`
const script = parse(readFileSync(new URL(filename, import.meta.url), 'utf8')).descriptor.scriptSetup!.content
const ast = ts.createSourceFile('detail.ts', script, ts.ScriptTarget.Latest, true)
const bindings: Record<string, any> = {}
for (const n of ast.statements.filter(ts.isImportDeclaration)) {
if (n.importClause?.name) bindings[n.importClause.name.text] = () => undefined
const named = n.importClause?.namedBindings
if (named && ts.isNamedImports(named)) for (const e of named.elements) bindings[e.name.text] = () => undefined
}
const router = createRouter({ history: createMemoryHistory(), routes: [
{ path: '/m/crm/contract/:id', name: 'MpCrmContractDetail', component: {} },
{ path: '/m/crm/quote/:id', name: 'MpCrmQuoteDetail', component: {} },
{ path: '/m/crm/customer/:id', name: 'MpCrmCustomerDetail', component: {} },
{ path: '/m/pl/plan/:id', name: 'MpPlanDetail', component: {} }
] })
await router.push(embedded ? '/m/pl/plan/P1' : `/m/crm/${kind}/A`)
const reads: Array<{ id: string; resolve: (value: any) => void }> = []
const props = vue.reactive({ embedded, recordId: 'E1', hideProductPrice: false })
const transport = (id: string) => new Promise((resolve) => reads.push({ id, resolve }))
Object.assign(bindings, Object.fromEntries(Object.entries(vue).filter(([k]) => /^[a-zA-Z_$][\w$]*$/.test(k) && k !== 'default')), navigation, {
useRoute, useRouter,
defineProps: () => props, withDefaults: (value: any) => value,
useUserStore: () => ({ info: {} }),
useDictStore: () => ({ dictMap: {}, getOptions: () => [], getLabel: () => '', getTagType: () => 'info' }),
getContract: transport, getQuote: transport,
fetchCategoryTree: async () => [], buildPathLabelMapFromTreeRoots: () => new Map(),
listContractApproval: async () => ({ data: [] }), listApproval: async () => ({ data: [] }),
listQuoteProduct: async () => ({ rows: [] }), enrichQuoteDetailProductMeta: async () => {},
document: { querySelector: () => null }, window: { addEventListener() {}, removeEventListener() {}, clearTimeout() {} }
})
const statements = ast.statements.filter((s) => !ts.isImportDeclaration(s))
const names = statements.flatMap((s) => ts.isFunctionDeclaration(s) ? [s.name!.text] : ts.isVariableStatement(s) ? s.declarationList.declarations.map((d) => d.name.getText(ast)) : [])
const code = ts.transpile(statements.map((n) => n.getText(ast)).join('\n'), {target:ts.ScriptTarget.ESNext})
const renderer = vue.createRenderer<any, any>({patchProp(){},insert(){},remove(){},createElement:()=>({}),createText:()=>({}),createComment:()=>({}),setText(){},setElementText(){},parentNode:()=>null,nextSibling:()=>null})
let api: any
const app = renderer.createApp({setup() {
api = new Function(...Object.keys(bindings), `${code};return {${names.join(',')}}`)(...Object.values(bindings))
return () => vue.h('div')
}})
app.use(router)
app.mount({})
api.onShellReady()
await flush()
return { api, reads, router, props, stop: () => app.unmount() }
}
for (const kind of ['contract', 'quote'] as const) for (const nextId of ['A', 'B']) {
test(`${kind}离开到客户${nextId},不请求客户ID且迟到详情无权回写`, async () => {
const h = await mount(kind)
assert.deepEqual(h.reads.map((r) => r.id), ['A'])
await h.router.push(`/m/crm/customer/${nextId}`)
await flush()
assert.deepEqual(h.reads.map((r) => r.id), ['A'], '离开watch不能发起外模块请求')
void h.api.loadDetail()
await flush()
assert.deepEqual(h.reads.map((r) => r.id), ['A'])
h.reads[0].resolve({ id: 'A', products: [], productList: [] })
await flush()
assert.equal(h.api[kind].value, null)
assert.equal(h.api.currentRecordId(), '')
await h.router.push(`/m/crm/${kind}/A`)
await flush()
assert.deepEqual(h.reads.map((r) => r.id), ['A', 'A'])
h.stop()
})
}
test('embedded合同只认recordId,宿主路径和ID变化不触发详情读取', async () => {
const h = await mount('contract', true)
await h.router.push('/m/crm/customer/B')
await flush()
assert.deepEqual(h.reads.map((r) => r.id), ['E1'])
h.props.recordId = 'E2'
await flush()
assert.deepEqual(h.reads.map((r) => r.id), ['E1', 'E2'])
h.reads[0].resolve({id:'E1'})
await flush()
assert.equal(h.api.contract.value, null)
h.stop()
})