mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
- Consent.beforeDelete bloqueia delete com referências (APIError 409 composto
por coleção), fim do 23502 cru no admin (contagens com overrideAccess).
- submitWhatsapp/submitPetitionSignature delegam o ciclo de transação ao dono
withPayloadTransaction (rollback no commit-falho, AggregateError, after-commit),
preservando os contratos { ok: true } / { ok: true, signatureNumber }.
- contactStateSchema exportado + contactCitySchema/contactCityFieldSchema
consolidados; as 4 fichas usam os exports únicos (fim das cópias inline do
predicate value in CitiesByState). withMutableConsentFixture purga consent
via raw SQL para bypassar o hook no harness de teste.
Co-Authored-By: opencode <noreply@opencode.ai>
146 lines
4.7 KiB
TypeScript
146 lines
4.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { BRAZILIAN_PHONE_DUPLICATE_MESSAGE } from '@/lib/phone'
|
|
import {
|
|
contactCitySchema,
|
|
contactCreateSchema,
|
|
contactFieldUpdateSchema,
|
|
contactStateSchema,
|
|
} from '@/lib/schemas/contact'
|
|
|
|
describe('contactCreateSchema (C139)', () => {
|
|
it('accepts a full valid ficha', () => {
|
|
const result = contactCreateSchema.safeParse({
|
|
name: 'Maria Silva',
|
|
email: 'maria@example.com',
|
|
phones: ['71999990000'],
|
|
gender: 'feminino',
|
|
state: 'BA',
|
|
city: 'Salvador',
|
|
postalCode: '40000000',
|
|
})
|
|
expect(result.success).toBe(true)
|
|
})
|
|
|
|
it('accepts the minimal ficha (name + state)', () => {
|
|
const result = contactCreateSchema.safeParse({ name: 'Ana Souza', state: 'BA' })
|
|
expect(result.success).toBe(true)
|
|
})
|
|
|
|
it('rejects a missing state', () => {
|
|
const result = contactCreateSchema.safeParse({ name: 'Ana Souza' })
|
|
expect(result.success).toBe(false)
|
|
if (!result.success)
|
|
expect(result.error.issues.some((issue) => issue.path[0] === 'state')).toBe(true)
|
|
})
|
|
|
|
it('rejects an unknown gender', () => {
|
|
expect(
|
|
contactCreateSchema.safeParse({ name: 'Ana Souza', state: 'BA', gender: 'x' }).success,
|
|
).toBe(false)
|
|
})
|
|
|
|
it('rejects a single-word name', () => {
|
|
expect(contactCreateSchema.safeParse({ name: 'Ana', state: 'BA' }).success).toBe(false)
|
|
})
|
|
|
|
it('rejects duplicated phones within the same ficha (C112)', () => {
|
|
const result = contactCreateSchema.safeParse({
|
|
name: 'Ana Souza',
|
|
state: 'BA',
|
|
phones: ['71999990000', '71999990000'],
|
|
})
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(
|
|
result.error.issues.some((issue) => issue.message === BRAZILIAN_PHONE_DUPLICATE_MESSAGE),
|
|
).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('accepts an empty phone list', () => {
|
|
expect(
|
|
contactCreateSchema.safeParse({ name: 'Ana Souza', state: 'BA', phones: [] }).success,
|
|
).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('contactFieldUpdateSchema — C139 variants', () => {
|
|
it('accepts the city variant', () => {
|
|
expect(
|
|
contactFieldUpdateSchema.safeParse({ id: 5, field: 'city', city: 'Camaçari' }).success,
|
|
).toBe(true)
|
|
expect(contactFieldUpdateSchema.safeParse({ id: 5, field: 'city', city: 'C' }).success).toBe(
|
|
false,
|
|
)
|
|
})
|
|
|
|
it('transforms an empty postalCode to undefined (clear semantics)', () => {
|
|
const result = contactFieldUpdateSchema.safeParse({
|
|
id: 5,
|
|
field: 'postalCode',
|
|
postalCode: '',
|
|
})
|
|
expect(result.success).toBe(true)
|
|
if (result.success) {
|
|
const data = result.data as { field: string; postalCode?: string }
|
|
expect(data.postalCode).toBeUndefined()
|
|
}
|
|
})
|
|
|
|
it('accepts an 8-digit postalCode and rejects a malformed one', () => {
|
|
expect(
|
|
contactFieldUpdateSchema.safeParse({ id: 5, field: 'postalCode', postalCode: '42800000' })
|
|
.success,
|
|
).toBe(true)
|
|
expect(
|
|
contactFieldUpdateSchema.safeParse({ id: 5, field: 'postalCode', postalCode: 'abc' }).success,
|
|
).toBe(false)
|
|
})
|
|
|
|
it('keeps the legacy variants working', () => {
|
|
expect(
|
|
contactFieldUpdateSchema.safeParse({ id: 5, field: 'name', name: 'Ana Souza' }).success,
|
|
).toBe(true)
|
|
expect(
|
|
contactFieldUpdateSchema.safeParse({ id: 5, field: 'phones', phones: ['71999990000'] })
|
|
.success,
|
|
).toBe(true)
|
|
})
|
|
|
|
it('collapses an empty city to undefined in the create ficha (C139 DRY)', () => {
|
|
const result = contactCreateSchema.safeParse({ name: 'Ana Souza', state: 'BA', city: '' })
|
|
expect(result.success).toBe(true)
|
|
if (result.success) {
|
|
expect((result.data as { city?: string }).city).toBeUndefined()
|
|
}
|
|
})
|
|
|
|
it('reports the long-city message on the field-update city variant', () => {
|
|
const result = contactFieldUpdateSchema.safeParse({
|
|
id: 5,
|
|
field: 'city',
|
|
city: 'a'.repeat(101),
|
|
})
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(result.error.issues.some((issue) => issue.message === 'Cidade muito longa')).toBe(true)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('contactStateSchema / contactCitySchema (S9+ DRY consolidation)', () => {
|
|
it('contactStateSchema accepts a known UF and rejects an unknown one', () => {
|
|
expect(contactStateSchema.safeParse('BA').success).toBe(true)
|
|
expect(contactStateSchema.safeParse('XX').success).toBe(false)
|
|
})
|
|
|
|
it('contactCitySchema reports the long-city message at the max boundary', () => {
|
|
expect(contactCitySchema.safeParse('Camaçari').success).toBe(true)
|
|
const result = contactCitySchema.safeParse('a'.repeat(101))
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(result.error.issues.some((issue) => issue.message === 'Cidade muito longa')).toBe(true)
|
|
}
|
|
})
|
|
})
|