mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
- Contact.phone (text único) → phones (array field Payload, subcampo value): fonte única; principal = phones[0]; beforeValidate normaliza, filtra vazios, rejeita inválido e duplicado DENTRO da ficha (C111 entre fichas preservado) - migration add_contact_phones_array: backfill phone → phones[0] (gen_random_uuid) antes do drop da coluna + índice em value (hand-edit documentado; snapshot .json gerado mantém as colunas C99/C100 já existentes) - primaryPhoneOf / phoneValuesOf / reorderWithPrimaryPhone em src/lib/phone.ts (ordem = prioridade; inline edit = seta o principal preservando o resto) - findOrCreateContactByPhone aceita phones[] (dedupe pelo primário; reuse faz append dos faltantes; locks em todos os números digitados) - sync conta→ficha (CampaignUser): phone da conta faz APPEND quando a ficha não tem (nunca reordena nem remove); tombstone LGPD substitui TODOS os telefones - convite redemption: telefone digitado vira principal, demais preservados - import CSV: preview sinaliza compartilhado também por número secundário; bulk insere contact_phones (JOIN nas leituras, uuid no insert) - busca por telefone (apoiadores, pickers, combobox) casa qualquer número - UI: PhonesFieldEditor compartilhado (repetível mascarado, remover, ↑/↓, modo inline com Salvar) nas 5 superfícies — liderança (form/ficha/lista), apoiador (form/ficha), dobradinha (ficha), assessor (ficha), wizard - UI pública (petição/WhatsApp) intocada: zod e forms ficam com phone; as ações mapeiam phone → phones[0] - testes: spec novo campaignMultiPhones (aceite completo), specs C111/C99 atualizados, e2e wizard/apoiador ajustados
77 lines
2 KiB
TypeScript
77 lines
2 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
resolveBahiaMunicipality,
|
|
supporterCreateSchema,
|
|
supporterImportConfirmSchema,
|
|
supporterVoteIntentionSchema,
|
|
} from '@/lib/schemas/supporter'
|
|
|
|
describe('supporter schemas', () => {
|
|
it('normalizes phones and optional BA municipality', () => {
|
|
const parsed = supporterCreateSchema.parse({
|
|
name: 'Maria da Silva',
|
|
phones: ['+55 (71) 98888-7777'],
|
|
city: 'salvador',
|
|
consentAccepted: true,
|
|
})
|
|
|
|
expect(parsed.phones).toEqual(['71988887777'])
|
|
expect(parsed.city).toBe('Salvador')
|
|
expect(resolveBahiaMunicipality('feira de santana')).toBe('Feira de Santana')
|
|
expect(resolveBahiaMunicipality('Nowhere')).toBeNull()
|
|
})
|
|
|
|
it('requires highlighted consent when vote intention is set on create', () => {
|
|
expect(
|
|
supporterCreateSchema.safeParse({
|
|
name: 'Maria Silva',
|
|
phones: ['71988887777'],
|
|
voteIntention: 'certo',
|
|
consentAccepted: true,
|
|
}).success,
|
|
).toBe(false)
|
|
|
|
expect(
|
|
supporterCreateSchema.safeParse({
|
|
name: 'Maria Silva',
|
|
phones: ['71988887777'],
|
|
voteIntention: 'certo',
|
|
consentAccepted: true,
|
|
voteIntentionConsentAccepted: true,
|
|
}).success,
|
|
).toBe(true)
|
|
})
|
|
|
|
it('requires operator attestation and a token for import confirm', () => {
|
|
expect(
|
|
supporterImportConfirmSchema.safeParse({
|
|
importToken: 'token',
|
|
}).success,
|
|
).toBe(false)
|
|
|
|
expect(
|
|
supporterImportConfirmSchema.safeParse({
|
|
operatorAttested: true,
|
|
}).success,
|
|
).toBe(false)
|
|
|
|
expect(
|
|
supporterImportConfirmSchema.parse({
|
|
operatorAttested: true,
|
|
importToken: 'batch.123.sig',
|
|
}).importToken,
|
|
).toBe('batch.123.sig')
|
|
})
|
|
|
|
it('requires vote intention consent acceptance', () => {
|
|
expect(
|
|
supporterVoteIntentionSchema.safeParse({
|
|
id: 1,
|
|
voteIntention: 'indeciso',
|
|
}).success,
|
|
).toBe(false)
|
|
})
|
|
})
|