Provide tenant-scoped leader options for the Web protocol form, exclude ordinary members and retain historical names only for display. Default only to a leader of the selected region and prevent delayed requests from replacing manual choices. Refs #1. Add backend option isolation and Web cascade regression coverage.
167 lines
5.9 KiB
TypeScript
167 lines
5.9 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import ts from 'typescript'
|
|
|
|
const source = readFileSync(
|
|
new URL('../views/cell-storage/protocol/ProtocolFormDialog.vue', import.meta.url),
|
|
'utf8'
|
|
)
|
|
function method(name: string) {
|
|
const asyncStart = source.indexOf(` async function ${name}(`)
|
|
const start = asyncStart >= 0 ? asyncStart : source.indexOf(` function ${name}(`)
|
|
const end = source.indexOf('\n }', start) + 4
|
|
return source.slice(start, end)
|
|
}
|
|
function harness() {
|
|
const requests: Array<{ resolve: (value: any) => void; reject: (error: Error) => void }> = []
|
|
const hospitals: Array<{ resolve: () => void }> = []
|
|
const refs = {
|
|
managerLoading: { value: false },
|
|
managerUserOptions: { value: [] as any[] },
|
|
managerSnapshot: { value: null as any },
|
|
regionManagerUserId: { value: null as string | null },
|
|
formData: { regionId: 'a', regionManagerUserId: '' }
|
|
}
|
|
const deps = {
|
|
...refs,
|
|
linkedRegionMode: { value: false },
|
|
regionOptions: { value: [] },
|
|
hospitalOptions: { value: [] },
|
|
fetchRegionsByStaffUser: async () => ({ list: [{ id: 'b', regionName: 'B区' }] }),
|
|
loadHospitalsByRegion: () => new Promise<void>((resolve) => hospitals.push({ resolve })),
|
|
fetchProtocolRegionManagers: () =>
|
|
new Promise((resolve, reject) => requests.push({ resolve, reject })),
|
|
fetchUserList: async () => ({ list: [{ id: 'member', nickName: '普通员工' }] }),
|
|
fetchRegionStaffList: async () => ({
|
|
list: [{ userId: 'member', nickName: '普通员工', isLeader: false }]
|
|
}),
|
|
makeManagerUserStub: (id: string, nickName: string) => ({ id, nickName }),
|
|
ElMessage: { error: () => {} }
|
|
}
|
|
const code = ts.transpileModule(
|
|
`let managerSearchVersion = 0; let managerDefaultVersion = 0;
|
|
${method('remoteSearchManagerUsers')}
|
|
${method('applyDefaultRegionManager')}
|
|
${method('onManagerUserChange')}
|
|
${method('applyRegionsForSalesUser')}
|
|
return { search: remoteSearchManagerUsers, apply: applyDefaultRegionManager, select: onManagerUserChange, applySales: applyRegionsForSalesUser }`,
|
|
{ compilerOptions: { target: ts.ScriptTarget.ES2022 } }
|
|
).outputText
|
|
return {
|
|
...refs,
|
|
requests,
|
|
hospitals,
|
|
...new Function(...Object.keys(deps), code)(...Object.values(deps))
|
|
}
|
|
}
|
|
const leaders = [
|
|
{ id: 'head-a', nickName: 'A负责人', regionIds: ['a'] },
|
|
{ id: 'head-b', nickName: 'B负责人', regionIds: ['b'] }
|
|
]
|
|
|
|
test('manager search uses all region leaders without appending historical ordinary users', async () => {
|
|
const h = harness()
|
|
h.regionManagerUserId.value = 'member'
|
|
h.managerSnapshot.value = { id: 'member', nickName: '历史人员' }
|
|
const pending = h.search('')
|
|
h.requests[0]?.resolve({ list: leaders })
|
|
await pending
|
|
assert.deepEqual(
|
|
h.managerUserOptions.value.map((u: any) => u.id),
|
|
['head-a', 'head-b']
|
|
)
|
|
assert.equal(h.managerSnapshot.value.nickName, '历史人员')
|
|
})
|
|
|
|
test('a region without a leader stays empty instead of defaulting to an ordinary member', async () => {
|
|
const h = harness()
|
|
const pending = h.apply('a')
|
|
h.requests[0]?.resolve({ list: [leaders[1]] })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, '')
|
|
assert.equal(h.regionManagerUserId.value, null)
|
|
})
|
|
|
|
test('default manager belongs to selected region while candidates include all leaders', async () => {
|
|
const h = harness()
|
|
const pending = h.apply('a')
|
|
h.requests[0]?.resolve({ list: leaders })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, 'head-a')
|
|
assert.deepEqual(
|
|
h.managerUserOptions.value.map((u: any) => u.id),
|
|
['head-a', 'head-b']
|
|
)
|
|
})
|
|
|
|
test('clearing a region invalidates pending manager defaults', async () => {
|
|
const h = harness()
|
|
const pending = h.apply('a')
|
|
h.formData.regionId = ''
|
|
await h.apply('')
|
|
h.requests[0]?.resolve({ list: leaders })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, '')
|
|
})
|
|
|
|
test('out-of-order manager searches cannot overwrite the latest result', async () => {
|
|
const h = harness()
|
|
const first = h.search('A')
|
|
const second = h.search('B')
|
|
h.requests[1]?.resolve({ list: leaders })
|
|
await second
|
|
h.requests[0]?.resolve({ list: leaders })
|
|
await first
|
|
assert.deepEqual(
|
|
h.managerUserOptions.value.map((u: any) => u.id),
|
|
['head-b']
|
|
)
|
|
})
|
|
|
|
test('a manual selection is not overwritten by a pending default response', async () => {
|
|
const h = harness()
|
|
const pending = h.apply('a')
|
|
h.managerUserOptions.value = leaders
|
|
h.select('head-b')
|
|
h.requests[0].resolve({ list: leaders })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, 'head-b')
|
|
})
|
|
|
|
test('failed manager loading clears the old default and never falls back to ordinary users', async () => {
|
|
const h = harness()
|
|
h.formData.regionManagerUserId = 'old'
|
|
h.regionManagerUserId.value = 'old'
|
|
const pending = h.apply('a')
|
|
h.requests[0].reject(new Error('network failure'))
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, '')
|
|
assert.deepEqual(h.managerUserOptions.value, [])
|
|
})
|
|
|
|
test('a delayed default call for an old region cannot clear the current manager', async () => {
|
|
const h = harness()
|
|
h.formData.regionId = 'b'
|
|
h.formData.regionManagerUserId = 'head-b'
|
|
h.regionManagerUserId.value = 'head-b'
|
|
const pending = h.apply('a')
|
|
h.requests[0]?.resolve({ list: leaders })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, 'head-b')
|
|
assert.equal(h.regionManagerUserId.value, 'head-b')
|
|
})
|
|
|
|
test('sales-linked region loading does not overwrite a manager chosen while hospitals load', async () => {
|
|
const h = harness()
|
|
const pending = h.applySales('sales-b')
|
|
await Promise.resolve()
|
|
h.managerUserOptions.value = leaders
|
|
h.select('head-a')
|
|
h.hospitals[0].resolve()
|
|
await Promise.resolve()
|
|
h.requests[0].resolve({ list: leaders })
|
|
await pending
|
|
assert.equal(h.formData.regionManagerUserId, 'head-a')
|
|
})
|