elder-yudao-pro/yudao-ui-admin-vue3/tests/collection-draft.test.cjs

243 lines
7.8 KiB
JavaScript
Raw Permalink Normal View History

const { test } = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const vm = require('node:vm')
const { createRequire } = require('node:module')
const vue = require('vue')
const esbuild = createRequire(require.resolve('vite'))('esbuild')
const flowModule = { exports: {} }
vm.runInNewContext(
esbuild.transformSync(
fs.readFileSync(path.join(__dirname, '../src/views/health/identity/collectionFlow.ts'), 'utf8'),
{ loader: 'ts', format: 'cjs' }
).code,
{ module: flowModule, exports: flowModule.exports }
)
// 加载实际 composable,仅替换 HTTP 与组件卸载回调,无浏览器或 DOM 依赖。
function fixture(initialDraft = null) {
const calls = []
const backend = {
getCollectionDraft: async () => initialDraft,
saveCollectionDraft: async (payload) => {
calls.push(JSON.parse(JSON.stringify(payload)))
}
}
const module = { exports: {} }
const source = fs.readFileSync(
path.join(__dirname, '../src/views/health/identity/useCollectionDraft.ts'),
'utf8'
)
const code = esbuild.transformSync(source, { loader: 'ts', format: 'cjs' }).code
vm.runInNewContext(code, {
module,
exports: module.exports,
require: (id) =>
id === 'vue'
? { ...vue, onBeforeUnmount: () => {} }
: id === './collectionFlow'
? flowModule.exports
: backend,
// 测试手动触发保存,避免真实的一秒定时器影响执行和结果。
setTimeout: () => 1,
clearTimeout: () => {}
})
const data = vue.ref({
identityType: 10,
realName: '',
gender: 3,
consentConfirmed: true,
password: 'never-store-this'
})
const accountMode = vue.ref('new')
const activeStep = vue.ref(1)
const visible = vue.ref(true)
const readOnly = vue.ref(false)
const draft = module.exports.useCollectionDraft(data, accountMode, activeStep, visible, readOnly)
return { data, accountMode, activeStep, visible, readOnly, draft, calls, backend }
}
test('restores incomplete fields and step without restoring password', async () => {
const f = fixture({
currentStep: 2,
fields: { realName: '测试老人', educationLevel: null, accountMode: 'existing' }
})
await f.draft.initializeDraft()
assert.equal(f.data.value.realName, '测试老人')
assert.equal(f.activeStep.value, 2)
assert.equal(f.accountMode.value, 'existing')
assert.equal(f.data.value.password, undefined)
await f.draft.pauseDraft()
})
test('normalizes cleared options while preserving zero and false; excludes password', async () => {
const f = fixture()
await f.draft.initializeDraft()
Object.assign(f.data.value, {
maritalStatus: 0,
elderlyUniversity: false,
residenceType: '',
educationLevel: undefined
})
await f.draft.saveDraftNow()
const fields = f.calls[0].fields
assert.equal(fields.maritalStatus, 0)
assert.equal(fields.elderlyUniversity, false)
assert.equal(fields.residenceType, null)
assert.equal(fields.educationLevel, null)
assert.equal('password' in fields, false)
await f.draft.pauseDraft()
})
test('serializes saves so delayed earlier requests cannot overwrite newer input', async () => {
const f = fixture()
await f.draft.initializeDraft()
let release
f.backend.saveCollectionDraft = async (payload) => {
f.calls.push(JSON.parse(JSON.stringify(payload)))
if (f.calls.length === 1)
await new Promise((resolve) => {
release = resolve
})
}
f.data.value.realName = '较早输入'
const first = f.draft.saveDraftNow()
await Promise.resolve()
await Promise.resolve()
f.data.value.realName = '最新输入'
const second = f.draft.saveDraftNow()
assert.equal(f.calls.length, 1)
release()
await first
await second
assert.equal(f.calls[1].fields.realName, '最新输入')
await f.draft.pauseDraft()
})
test('pausing before a formal submission prevents close from recreating the old draft', async () => {
const f = fixture()
await f.draft.initializeDraft()
f.data.value.realName = '正式提交'
await f.draft.saveDraftNow()
await f.draft.pauseDraft()
f.visible.value = false
await vue.nextTick()
await Promise.resolve()
assert.equal(f.calls.length, 1)
})
test('restores seventh-step nested drafts and excludes server metadata from subsequent saves', async () => {
const f = fixture({
currentStep: 7,
fields: {
consentConfirmed: true,
chronicDiseaseStatus: 1,
chronicDiseases: [{ code: 'diabetes', currentDisease: false }],
emergencyContacts: [
{
name: '联系人',
relationship: 'child',
phone: '13900000001',
primary: true,
contactOnly: true
}
]
}
})
await f.draft.initializeDraft()
assert.equal(f.activeStep.value, 7)
assert.equal(f.data.value.chronicDiseases[0].currentDisease, false)
Object.assign(f.data.value, {
collectorId: 999,
collectionCompletedTime: 'forged',
incomeRange: 0,
disabled: false
})
await f.draft.saveDraftNow()
assert.equal(f.calls[0].currentStep, 7)
assert.equal(f.calls[0].fields.incomeRange, 0)
assert.equal(f.calls[0].fields.disabled, false)
assert.equal('collectorId' in f.calls[0].fields, false)
assert.equal('collectionCompletedTime' in f.calls[0].fields, false)
await f.draft.pauseDraft()
})
test('queued snapshots keep the original nested contacts while later edits save separately', async () => {
const f = fixture()
await f.draft.initializeDraft()
let release
f.backend.saveCollectionDraft = async (payload) => {
if (f.calls.length === 0)
await new Promise((resolve) => {
release = resolve
})
f.calls.push(JSON.parse(JSON.stringify(payload)))
}
f.data.value.emergencyContacts = [
{
name: '原联系人',
relationship: 'child',
phone: '13900000001',
primary: true,
contactOnly: true
}
]
const first = f.draft.saveDraftNow()
await Promise.resolve()
await Promise.resolve()
f.data.value.emergencyContacts[0].name = '修改联系人'
const second = f.draft.saveDraftNow()
release()
await first
await second
assert.equal(f.calls[0].fields.emergencyContacts[0].name, '原联系人')
assert.equal(f.calls[1].fields.emergencyContacts[0].name, '修改联系人')
await f.draft.pauseDraft()
})
test('unconfirmed consent limits autosave to basic identity and contact fields', async () => {
const f = fixture()
await f.draft.initializeDraft()
Object.assign(f.data.value, {
consentConfirmed: false,
realName: '基础姓名',
contactPhone: '13800000001',
idCard: 'must-not-upload',
birthDate: '1949-01-01',
chronicDiseases: [{ code: 'diabetes' }],
medicalInsuranceNumber: 'must-not-upload',
emergencyContacts: [{ name: '敏感联系人' }]
})
await f.draft.saveDraftNow()
const fields = f.calls[0].fields
assert.equal(fields.realName, '基础姓名')
assert.equal(fields.contactPhone, '13800000001')
assert.equal(fields.consentConfirmed, false)
for (const key of [
'idCard',
'birthDate',
'medicalInsuranceNumber',
'chronicDiseases',
'emergencyContacts'
])
assert.equal(key in fields, false)
await f.draft.pauseDraft()
})
test('failed draft initialization can be retried without losing current user input', async () => {
const f = fixture()
f.backend.getCollectionDraft = async () => {
throw new Error('offline')
}
await f.draft.initializeDraft()
assert.equal(f.draft.draftFailed.value, true)
f.data.value.realName = '当前输入'
f.backend.getCollectionDraft = async () => ({ currentStep: 1, fields: { realName: '较早草稿' } })
await f.draft.saveDraftNow()
assert.equal(f.calls[0].fields.realName, '当前输入')
assert.equal(f.data.value.realName, '当前输入')
assert.equal(f.draft.draftFailed.value, false)
await f.draft.pauseDraft()
})