feat(family): 表单校验抽纯函数并补单测
This commit is contained in:
parent
9d1ea0abbc
commit
95a67ae412
|
|
@ -6,6 +6,7 @@ import { addCared, type EmergencyContact } from '@/api/family'
|
||||||
import { MAX_EMERGENCY_CONTACTS, MAX_FAMILY_NAME_LEN } from '@/constants/family'
|
import { MAX_EMERGENCY_CONTACTS, MAX_FAMILY_NAME_LEN } from '@/constants/family'
|
||||||
import { navigateBack } from '@/utils/navigation'
|
import { navigateBack } from '@/utils/navigation'
|
||||||
import { showToast } from '@/utils/toast'
|
import { showToast } from '@/utils/toast'
|
||||||
|
import { validateContactForm } from './validate'
|
||||||
import styles from './add.module.scss'
|
import styles from './add.module.scss'
|
||||||
|
|
||||||
const emptyContact = (): EmergencyContact => ({
|
const emptyContact = (): EmergencyContact => ({
|
||||||
|
|
@ -35,14 +36,9 @@ export default function ContactAdd() {
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if (submitting) return
|
if (submitting) return
|
||||||
if (!name.trim() || !idNumber.trim() || !address.trim()) {
|
const result = validateContactForm({ name, idNumber, address, contacts })
|
||||||
showToast('请填写完整')
|
if (!result.ok) {
|
||||||
return
|
showToast(result.error)
|
||||||
}
|
|
||||||
// 跳过完全未填的联系人卡,只提交有内容的
|
|
||||||
const filled = contacts.filter((c) => c.name.trim() || c.phone.trim())
|
|
||||||
if (filled.some((c) => !c.name.trim() || !c.phone.trim())) {
|
|
||||||
showToast('请完整填写联系人')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +49,7 @@ export default function ContactAdd() {
|
||||||
name: name.trim(),
|
name: name.trim(),
|
||||||
idNumber: idNumber.trim(),
|
idNumber: idNumber.trim(),
|
||||||
address: address.trim(),
|
address: address.trim(),
|
||||||
contacts: filled
|
contacts: result.contacts
|
||||||
})
|
})
|
||||||
showToast('添加成功')
|
showToast('添加成功')
|
||||||
setTimeout(() => navigateBack(), 500)
|
setTimeout(() => navigateBack(), 500)
|
||||||
|
|
@ -74,7 +70,7 @@ export default function ContactAdd() {
|
||||||
<Input
|
<Input
|
||||||
className={styles.input}
|
className={styles.input}
|
||||||
placeholder="请输入最多 10 个字"
|
placeholder="请输入最多 10 个字"
|
||||||
maxLength={MAX_FAMILY_NAME_LEN}
|
maxlength={MAX_FAMILY_NAME_LEN}
|
||||||
value={name}
|
value={name}
|
||||||
onInput={(e) => setName(e.detail.value)}
|
onInput={(e) => setName(e.detail.value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import type { EmergencyContact } from '@/api/family'
|
||||||
|
|
||||||
|
export interface ContactFormInput {
|
||||||
|
name: string
|
||||||
|
idNumber: string
|
||||||
|
address: string
|
||||||
|
contacts: EmergencyContact[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ValidateResult =
|
||||||
|
| { ok: true; contacts: EmergencyContact[] }
|
||||||
|
| { ok: false; error: string }
|
||||||
|
|
||||||
|
// 必填项齐全且联系人卡要么空白(忽略)要么填全,才允许提交
|
||||||
|
export function validateContactForm(input: ContactFormInput): ValidateResult {
|
||||||
|
if (!input.name.trim() || !input.idNumber.trim() || !input.address.trim()) {
|
||||||
|
return { ok: false, error: '请填写完整' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const filled = input.contacts.filter((c) => c.name.trim() || c.phone.trim())
|
||||||
|
if (filled.some((c) => !c.name.trim() || !c.phone.trim())) {
|
||||||
|
return { ok: false, error: '请完整填写联系人' }
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ok: true, contacts: filled }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { validateContactForm, type ContactFormInput } from '@/pages/family/contact/validate'
|
||||||
|
import type { EmergencyContact } from '@/api/family'
|
||||||
|
|
||||||
|
const contact = (over: Partial<EmergencyContact> = {}): EmergencyContact => ({
|
||||||
|
id: 'c1',
|
||||||
|
name: '',
|
||||||
|
phone: '',
|
||||||
|
relation: '',
|
||||||
|
...over
|
||||||
|
})
|
||||||
|
|
||||||
|
const form = (over: Partial<ContactFormInput> = {}): ContactFormInput => ({
|
||||||
|
name: '王奶奶',
|
||||||
|
idNumber: '440301194001010000',
|
||||||
|
address: '深圳市南山区',
|
||||||
|
contacts: [],
|
||||||
|
...over
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('添加关爱对象表单校验', () => {
|
||||||
|
it('必填齐全返回 ok', () => {
|
||||||
|
const result = validateContactForm(form())
|
||||||
|
expect(result.ok).toBe(true)
|
||||||
|
if (result.ok) expect(result.contacts).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('任一必填缺失/空白报 请填写完整', () => {
|
||||||
|
const r1 = validateContactForm(form({ name: '' }))
|
||||||
|
const r2 = validateContactForm(form({ idNumber: ' ' }))
|
||||||
|
const r3 = validateContactForm(form({ address: '' }))
|
||||||
|
expect(!r1.ok && r1.error).toBe('请填写完整')
|
||||||
|
expect(!r2.ok && r2.error).toBe('请填写完整')
|
||||||
|
expect(!r3.ok && r3.error).toBe('请填写完整')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('空白联系人卡被过滤,不阻断提交', () => {
|
||||||
|
const result = validateContactForm(form({ contacts: [contact()] }))
|
||||||
|
expect(result.ok).toBe(true)
|
||||||
|
if (result.ok) expect(result.contacts).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('联系人只填了姓名或电话时报 请完整填写联系人', () => {
|
||||||
|
const r1 = validateContactForm(form({ contacts: [contact({ name: '张女士' })] }))
|
||||||
|
const r2 = validateContactForm(form({ contacts: [contact({ phone: '13800138000' })] }))
|
||||||
|
expect(!r1.ok && r1.error).toBe('请完整填写联系人')
|
||||||
|
expect(!r2.ok && r2.error).toBe('请完整填写联系人')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('姓名电话齐全的联系人保留在结果中', () => {
|
||||||
|
const c = contact({ id: 'c9', name: '张女士', phone: '13800138000', relation: '配偶' })
|
||||||
|
const result = validateContactForm(form({ contacts: [c] }))
|
||||||
|
expect(result.ok).toBe(true)
|
||||||
|
if (result.ok) expect(result.contacts).toEqual([c])
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Reference in New Issue