1. Subcategoría en modal descarte (catálogo completo + select) 2. Apartado sin monto mínimo (eliminada validación de 0,000) 3. PDF solo con propuesta elegida (no las 4) 4. Co-acreditado: checkbox 'no tiene' valida sin campos obligatorios 5. Documentos apartado: previsualizar + descargar (endpoint + frontend) 6. Oportunidades: sin duplicados, orden Confirmar→Afluencia→Cotizar→Aparto(verde)→Descartar
211 lines
6.7 KiB
TypeScript
211 lines
6.7 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import {
|
|
datosGeneralesSchema,
|
|
coacreditadoSchema,
|
|
referenciasSchema,
|
|
REGEX_CURP,
|
|
REGEX_RFC,
|
|
} from './schemas'
|
|
import type { DatosGenerales } from '../types'
|
|
|
|
// Datos válidos base con el fixture del cliente del PDF de referencia
|
|
const generalesValidos: DatosGenerales = {
|
|
campaniaVenta: '',
|
|
fecha: '2026-07-19',
|
|
nombreCompleto: 'PASCUAL MARTIN TELLEZ CHIGUINDO',
|
|
nacionalidad: 'MEXICANA',
|
|
nivelEstudios: 'MAESTRIA',
|
|
curp: 'TECP891124HBCLHS07',
|
|
rfc: 'TECP8911246B4',
|
|
nss: '',
|
|
delegacionMunicipio: 'TIJUANA',
|
|
direccion: 'RIO EUFRATES EDIF 1 7145 203',
|
|
codigoPostal: '22223',
|
|
antiguedadDomicilio: '2',
|
|
fechaNacimiento: '1989-11-24',
|
|
lugarNacimiento: 'TIJUANA',
|
|
estadoCivil: 'SOLTERO',
|
|
regimenBienes: '',
|
|
peso: '87',
|
|
estatura: '1.78',
|
|
email: 'dantemartinchi@gmail.com',
|
|
telCasa: '',
|
|
celular: '6646935924',
|
|
viviendaAnios: '2',
|
|
tipoVivienda: 'PROPIA',
|
|
tipoCompra: 'VIVIR_AHI',
|
|
actividadOcupacion: 'AGENTE DEL MINISTERIO PUBLICO FEDERAL',
|
|
usuarioEnkontrol: '',
|
|
}
|
|
|
|
describe('regex de identificadores', () => {
|
|
it('acepta CURP válida', () => {
|
|
expect(REGEX_CURP.test('TECP891124HBCLHS07')).toBe(true)
|
|
})
|
|
|
|
it('rechaza CURP inválida', () => {
|
|
expect(REGEX_CURP.test('TECP891124HBCLHS0')).toBe(false) // corta
|
|
expect(REGEX_CURP.test('tecp891124hbclhs07')).toBe(false) // minúsculas
|
|
expect(REGEX_CURP.test('TECP89112XHBCLHS07')).toBe(false) // fecha inválida
|
|
})
|
|
|
|
it('acepta RFC válido', () => {
|
|
expect(REGEX_RFC.test('TECP8911246B4')).toBe(true)
|
|
})
|
|
|
|
it('rechaza RFC inválido', () => {
|
|
expect(REGEX_RFC.test('TECP8911246B')).toBe(false) // corto
|
|
expect(REGEX_RFC.test('TECP891124!B4')).toBe(false)
|
|
expect(REGEX_RFC.test('tecp8911246b4')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('datosGeneralesSchema', () => {
|
|
it('acepta los datos del fixture', () => {
|
|
expect(datosGeneralesSchema.safeParse(generalesValidos).success).toBe(true)
|
|
})
|
|
|
|
it('rechaza CURP inválida', () => {
|
|
const r = datosGeneralesSchema.safeParse({ ...generalesValidos, curp: 'XXXX000000XXXXXXX0' })
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('rechaza RFC inválido', () => {
|
|
const r = datosGeneralesSchema.safeParse({ ...generalesValidos, rfc: '123' })
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('rechaza email inválido', () => {
|
|
const r = datosGeneralesSchema.safeParse({ ...generalesValidos, email: 'no-es-correo' })
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('rechaza código postal que no tenga 5 dígitos', () => {
|
|
const r = datosGeneralesSchema.safeParse({ ...generalesValidos, codigoPostal: '2223' })
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('exige régimen de bienes solo cuando el estado civil es CASADO', () => {
|
|
const casado = datosGeneralesSchema.safeParse({ ...generalesValidos, estadoCivil: 'CASADO' })
|
|
expect(casado.success).toBe(false)
|
|
const casadoConRegimen = datosGeneralesSchema.safeParse({
|
|
...generalesValidos,
|
|
estadoCivil: 'CASADO',
|
|
regimenBienes: 'SEPARACION_BIENES',
|
|
})
|
|
expect(casadoConRegimen.success).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('coacreditadoSchema', () => {
|
|
const base = {
|
|
generales: { ...generalesValidos, nombreCompleto: '', curp: '', rfc: '', email: '', fechaNacimiento: '', celular: '' },
|
|
empleo: {
|
|
tipoEmpleo: '' as const,
|
|
tipoEconomia: '' as const,
|
|
compania: '',
|
|
antiguedadAnios: '',
|
|
antiguedadMeses: '',
|
|
direccion: '',
|
|
colonia: '',
|
|
numero: '',
|
|
codigoPostal: '',
|
|
puesto: '',
|
|
telefono: '',
|
|
ext: '',
|
|
delegacion: '',
|
|
},
|
|
economicos: {
|
|
ingresosMensuales: 0,
|
|
otrosIngresos: 0,
|
|
gastosLuz: 0,
|
|
gastosOtros: 0,
|
|
dependientes: { personas: '', parentesco: '', edad: '' },
|
|
},
|
|
}
|
|
|
|
it('no exige datos del co-acreditado cuando el toggle está apagado', () => {
|
|
const r = coacreditadoSchema.safeParse({ ...base, tieneCoacreditado: false })
|
|
expect(r.success).toBe(true)
|
|
})
|
|
|
|
it('acepta datos ocultos a medias cuando el toggle está apagado', () => {
|
|
const conBasura = {
|
|
...base,
|
|
tieneCoacreditado: false as const,
|
|
generales: { ...base.generales, fecha: '', email: 'no-es-correo', codigoPostal: 'abc' },
|
|
}
|
|
const r = coacreditadoSchema.safeParse(conBasura)
|
|
expect(r.success).toBe(true)
|
|
})
|
|
|
|
it('exige el nombre del co-acreditado cuando el toggle está activo', () => {
|
|
const r = coacreditadoSchema.safeParse({ ...base, tieneCoacreditado: true })
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('acepta co-acreditado con nombre cuando el toggle está activo', () => {
|
|
const r = coacreditadoSchema.safeParse({
|
|
...base,
|
|
tieneCoacreditado: true,
|
|
generales: { ...base.generales, nombreCompleto: 'MARIA LOPEZ PEREZ' },
|
|
})
|
|
expect(r.success).toBe(true)
|
|
})
|
|
|
|
it('no exige usuarioEnkontrol del co-acreditado (no se captura en el bloque compacto)', () => {
|
|
const sinUsuarioEnkontrol = JSON.parse(
|
|
JSON.stringify({
|
|
...base,
|
|
tieneCoacreditado: true,
|
|
generales: { ...base.generales, nombreCompleto: 'MARIA LOPEZ PEREZ' },
|
|
}),
|
|
) as typeof base & { tieneCoacreditado: true }
|
|
delete (sinUsuarioEnkontrol.generales as Record<string, unknown>).usuarioEnkontrol
|
|
const r = coacreditadoSchema.safeParse(sinUsuarioEnkontrol)
|
|
expect(r.success).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('referenciasSchema', () => {
|
|
const vacia = { nombre: '', telefono: '', parentesco: '', direccion: '' }
|
|
|
|
it('rechaza cuando ninguna referencia tiene nombre y teléfono', () => {
|
|
const r = referenciasSchema.safeParse([vacia, vacia, vacia, vacia])
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('rechaza referencia con nombre pero sin teléfono', () => {
|
|
const r = referenciasSchema.safeParse([
|
|
{ ...vacia, nombre: 'JOSE ARNOLDO MENDOZA' },
|
|
vacia,
|
|
vacia,
|
|
vacia,
|
|
])
|
|
expect(r.success).toBe(false)
|
|
})
|
|
|
|
it('acepta con al menos 1 referencia válida', () => {
|
|
const r = referenciasSchema.safeParse([
|
|
{ nombre: 'JOSE ARNOLDO MENDOZA', telefono: '6641887799', parentesco: 'AMIGO', direccion: 'ALTAMIRA' },
|
|
vacia,
|
|
vacia,
|
|
vacia,
|
|
])
|
|
expect(r.success).toBe(true)
|
|
})
|
|
|
|
it('acepta un solo bloque de referencia (arreglo dinámico, ya no exige 4)', () => {
|
|
const r = referenciasSchema.safeParse([
|
|
{ nombre: 'JOSE ARNOLDO MENDOZA', telefono: '6641887799', parentesco: 'AMIGO', direccion: 'ALTAMIRA' },
|
|
])
|
|
expect(r.success).toBe(true)
|
|
})
|
|
|
|
it('rechaza más de 4 referencias', () => {
|
|
const valida = { nombre: 'JOSE ARNOLDO MENDOZA', telefono: '6641887799', parentesco: '', direccion: '' }
|
|
const r = referenciasSchema.safeParse([valida, valida, valida, valida, valida])
|
|
expect(r.success).toBe(false)
|
|
})
|
|
})
|