163 lines
6.1 KiB
JavaScript
163 lines
6.1 KiB
JavaScript
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 { parse, compileScript, compileTemplate, compileStyle } = require('vue/compiler-sfc')
|
|
const esbuild = createRequire(require.resolve('vite'))('esbuild')
|
|
const privacyModule = { exports: {} }
|
|
vm.runInNewContext(
|
|
esbuild.transformSync(
|
|
fs.readFileSync(path.join(__dirname, '../src/utils/healthPrivacy.ts'), 'utf8'),
|
|
{
|
|
loader: 'ts',
|
|
format: 'cjs'
|
|
}
|
|
).code,
|
|
{ module: privacyModule, exports: privacyModule.exports }
|
|
)
|
|
|
|
const componentPath = path.join(__dirname, '../src/views/health/identity/CollectionHealthSteps.vue')
|
|
const { descriptor, errors } = parse(fs.readFileSync(componentPath, 'utf8'), {
|
|
filename: componentPath
|
|
})
|
|
const script = compileScript(descriptor, { id: 'collection-health-tests' })
|
|
const compiled = esbuild.transformSync(script.content, { loader: 'ts', format: 'cjs' }).code
|
|
|
|
function fixture(data = {}, readOnly = false) {
|
|
const module = { exports: {} }
|
|
vm.runInNewContext(compiled, {
|
|
module,
|
|
exports: module.exports,
|
|
require: (id) => {
|
|
if (id === 'vue') return vue
|
|
if (id === '@/utils/healthPrivacy') return privacyModule.exports
|
|
throw new Error(`Unexpected import: ${id}`)
|
|
}
|
|
})
|
|
const props = vue.reactive({ activeStep: 5, readOnly, data })
|
|
const component = module.exports.default.setup(props, { expose: () => {} })
|
|
return { props, component }
|
|
}
|
|
|
|
test('health steps compile as child form fields and use persistent, animated sections', () => {
|
|
assert.deepEqual(errors, [])
|
|
const template = compileTemplate({
|
|
source: descriptor.template.content,
|
|
filename: componentPath,
|
|
id: 'collection-health-tests',
|
|
compilerOptions: { bindingMetadata: script.bindings }
|
|
})
|
|
assert.deepEqual(template.errors, [])
|
|
const css = compileStyle({
|
|
source: descriptor.styles[0].content,
|
|
filename: componentPath,
|
|
id: 'collection-health-tests',
|
|
scoped: true,
|
|
preprocessLang: 'scss'
|
|
})
|
|
assert.deepEqual(css.errors, [])
|
|
assert.doesNotMatch(descriptor.template.content, /<el-form\s/)
|
|
for (const step of [3, 4, 5]) {
|
|
assert.match(descriptor.template.content, new RegExp(`v-show="activeStep === ${step}"`))
|
|
}
|
|
assert.equal(descriptor.template.content.match(/<Transition name="collection-step">/g).length, 3)
|
|
})
|
|
|
|
test('self care and no disability clear hidden details without changing the active step', () => {
|
|
const f = fixture({
|
|
careLevel: 2,
|
|
disabled: true,
|
|
disabilityType: 'physical',
|
|
disabilityReason: '原因'
|
|
})
|
|
f.component.changeCareLevel(1)
|
|
assert.equal(f.props.data.careLevel, 1)
|
|
assert.equal(f.props.data.disabled, false)
|
|
assert.equal(f.props.data.disabilityType, null)
|
|
assert.equal(f.props.data.disabilityReason, null)
|
|
assert.equal(f.props.activeStep, 5)
|
|
Object.assign(f.props.data, {
|
|
careLevel: 3,
|
|
disabled: true,
|
|
disabilityType: 'visual',
|
|
disabilityReason: '原因'
|
|
})
|
|
f.component.changeDisabled(false)
|
|
assert.equal(f.props.data.disabled, false)
|
|
assert.equal(f.props.data.disabilityType, null)
|
|
assert.equal(f.props.data.disabilityReason, null)
|
|
})
|
|
|
|
test('disease selection preserves existing details, removes deselected entries and deduplicates codes', () => {
|
|
const f = fixture({
|
|
chronicDiseaseStatus: 1,
|
|
chronicDiseases: [
|
|
{ code: 'diabetes', diagnosedDate: '2020-01-01', treatmentStatus: 2, currentDisease: false },
|
|
{ code: 'other', otherName: '原名称' }
|
|
]
|
|
})
|
|
const original = f.props.data.chronicDiseases[0]
|
|
f.component.changeDiseases(['diabetes', 'uncertain', 'diabetes'])
|
|
assert.equal(f.props.data.chronicDiseases.length, 2)
|
|
assert.equal(f.props.data.chronicDiseases[0], original)
|
|
assert.equal(f.props.data.chronicDiseases[0].currentDisease, false)
|
|
assert.equal(f.props.data.chronicDiseases[0].diagnosedDate, '2020-01-01')
|
|
assert.equal(f.props.data.chronicDiseases[1].code, 'uncertain')
|
|
f.component.removeDisease('diabetes')
|
|
assert.deepEqual(Array.from(f.component.selectedDiseaseCodes.value), ['uncertain'])
|
|
})
|
|
|
|
test('no, unsure and declined chronic answers clear details, while yes accepts an empty list', () => {
|
|
const f = fixture()
|
|
for (const status of [2, 3, 4]) {
|
|
f.props.data.chronicDiseases = [{ code: 'hypertension' }]
|
|
f.component.changeChronicStatus(status)
|
|
assert.equal(f.props.data.chronicDiseaseStatus, status)
|
|
assert.equal(f.props.data.chronicDiseases.length, 0)
|
|
}
|
|
f.component.changeChronicStatus(1)
|
|
assert.equal(f.props.data.chronicDiseases.length, 0)
|
|
})
|
|
|
|
test('loading legacy data and invoking read-only handlers leave values intact, including zero and false', () => {
|
|
const data = {
|
|
incomeRange: 0,
|
|
careLevel: 1,
|
|
disabled: true,
|
|
disabilityType: 'physical',
|
|
disabilityReason: '旧数据',
|
|
chronicDiseaseStatus: 2,
|
|
chronicDiseases: [{ code: 'diabetes', currentDisease: false }]
|
|
}
|
|
const before = JSON.stringify(data)
|
|
const editable = fixture(data)
|
|
assert.equal(JSON.stringify(editable.props.data), before)
|
|
const f = fixture(data, true)
|
|
f.component.changeCareLevel(1)
|
|
f.component.changeDisabled(false)
|
|
f.component.changeChronicStatus(3)
|
|
f.component.changeDiseases([])
|
|
f.component.removeDisease('diabetes')
|
|
assert.equal(JSON.stringify(f.props.data), before)
|
|
})
|
|
|
|
test('diagnosis picker accepts today and earlier dates and disables future dates', () => {
|
|
const f = fixture()
|
|
const tomorrow = new Date()
|
|
tomorrow.setDate(tomorrow.getDate() + 1)
|
|
tomorrow.setHours(0, 0, 0, 0)
|
|
assert.equal(f.component.disabledFutureDate(new Date('2020-01-01')), false)
|
|
assert.equal(f.component.disabledFutureDate(new Date()), false)
|
|
assert.equal(f.component.disabledFutureDate(tomorrow), true)
|
|
})
|
|
|
|
test('read-only insurance display masks the number without rewriting the archived value', () => {
|
|
const f = fixture({ medicalInsuranceNumber: '123456789012' }, true)
|
|
assert.equal(f.component.maskHealthInsurance(f.props.data.medicalInsuranceNumber), '********9012')
|
|
assert.equal(f.props.data.medicalInsuranceNumber, '123456789012')
|
|
assert.notEqual(f.component.maskHealthInsurance('123'), '123')
|
|
})
|