mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:35:20 +00:00
- helpers puros movidos utilities->lib: slug, phone, wordStartFilter, voteEstimate (9 inversoes lib->utilities zeradas) - chaves de consent em src/lib/campaignConsentKeys.ts (client-safe); campaignInvite/campaignConsent re-exportam; onda0ConsentTexts referencia as constantes - 'server-only' em 21 loaders Payload/cache (CLI segue com --conditions=react-server) - ciclo de tipos supporterListFilters <-> supporterUi quebrado (SupporterListFilterInput estrutural; sqlFilters idem) - votePledgeData dividido: votePledgeViews (puro, client-safe) + votePledgeData (loaders, server-only) - padrao contract-module - predicados de role client-safe em src/lib/campaignRoles.ts; access/shared deriva deles (fonte unica); nav.ts para de importar o barrel campaignAccess (casts 'as CampaignUser' eliminados)
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const phoneMocks = vi.hoisted(() => ({
|
|
normalizeBrazilianPhone: vi.fn<(value: string) => string | null>(),
|
|
}))
|
|
|
|
vi.mock('@/lib/phone', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('@/lib/phone')>()
|
|
phoneMocks.normalizeBrazilianPhone.mockImplementation(actual.normalizeBrazilianPhone)
|
|
|
|
return {
|
|
...actual,
|
|
normalizeBrazilianPhone: phoneMocks.normalizeBrazilianPhone,
|
|
}
|
|
})
|
|
|
|
import { Contact } from '@/collections/Contact'
|
|
import { leadershipCreateSchema } from '@/lib/schemas/leadership'
|
|
|
|
import { stub } from '../helpers/stub'
|
|
|
|
const contactPhoneHook = Contact.hooks?.beforeValidate?.[0]
|
|
|
|
type ContactPhoneHookArgs = Parameters<NonNullable<typeof contactPhoneHook>>[0]
|
|
|
|
const runContactPhoneHook = async (phone: string) => {
|
|
if (typeof contactPhoneHook !== 'function') {
|
|
throw new Error('Expected Contact.beforeValidate phone hook.')
|
|
}
|
|
|
|
const data = { phone }
|
|
await contactPhoneHook(stub<ContactPhoneHookArgs>({ data }))
|
|
return data.phone
|
|
}
|
|
|
|
describe('Contact phone normalization boundary', () => {
|
|
beforeEach(() => {
|
|
phoneMocks.normalizeBrazilianPhone.mockClear()
|
|
})
|
|
|
|
it('normalizes once before leadership dedupe and skips canonical Contact input', async () => {
|
|
const parsed = leadershipCreateSchema.parse({
|
|
municipalities: [1],
|
|
name: 'Liderança normalizada',
|
|
phone: '+55 (71) 99999-1234',
|
|
})
|
|
|
|
expect(parsed.phone).toBe('71999991234')
|
|
expect(await runContactPhoneHook(parsed.phone)).toBe('71999991234')
|
|
expect(phoneMocks.normalizeBrazilianPhone).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('normalizes a formatted phone sent directly to the Contact API boundary', async () => {
|
|
expect(await runContactPhoneHook('+55 (71) 99999-1234')).toBe('71999991234')
|
|
expect(phoneMocks.normalizeBrazilianPhone).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('rejects an invalid canonical-length direct API phone without re-normalizing it', async () => {
|
|
await expect(runContactPhoneHook('00000000000')).rejects.toThrow('Celular brasileiro inválido.')
|
|
expect(phoneMocks.normalizeBrazilianPhone).not.toHaveBeenCalled()
|
|
})
|
|
})
|