From 62a7dab8a7a5d91050d7777cd53c61f6cc4c9a8f Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Tue, 25 Aug 2026 14:03:28 -0300 Subject: [PATCH] =?UTF-8?q?test(ops96-audit):=20extrair=20helpers=20puros?= =?UTF-8?q?=20de=20identidade=20(telefone/schema/migra=C3=A7=C3=A3o)=20do?= =?UTF-8?q?=20campaignAuth=20int=E2=86=92unit=20=E2=80=94=20RBAC=20intacto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/int/campaignAuth.int.spec.ts | 70 ------------------ tests/unit/campaignAuthIdentity.unit.spec.ts | 77 ++++++++++++++++++++ 2 files changed, 77 insertions(+), 70 deletions(-) create mode 100644 tests/unit/campaignAuthIdentity.unit.spec.ts diff --git a/tests/int/campaignAuth.int.spec.ts b/tests/int/campaignAuth.int.spec.ts index 8148efbf..b099c822 100644 --- a/tests/int/campaignAuth.int.spec.ts +++ b/tests/int/campaignAuth.int.spec.ts @@ -1,14 +1,11 @@ // @vitest-environment node -import { readFileSync } from 'node:fs' - import type { Payload, PayloadRequest, RequiredDataFromCollectionSlug } from 'payload' import { assert, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import { assignMunicipalityAdvisorsRecord } from '@/app/(campaign)/campanha/actions/municipality' import { CampaignUser as CampaignUserCollection } from '@/collections/CampaignUser' import { CAMPAIGN_SESSION_TTL_LONG } from '@/lib/campaignSessionTtl' -import { buildWhatsAppUrl, normalizeBrazilianPhone, sanitizeBrazilianPhoneInput } from '@/lib/phone' import { campaignLoginSchema } from '@/lib/schemas/campaign-login' import type { CampaignUser } from '@/payload-types' import config from '@/payload.config' @@ -438,19 +435,6 @@ describe('campaign authentication foundation', () => { }, ) - it('guards migration rollback when phone-only accounts exist', () => { - const migration = readFileSync( - new URL( - '../../src/migrations/20260718_010733_consolidate_campaign_schema.ts', - import.meta.url, - ), - 'utf8', - ) - - expect(migration).toContain('IF EXISTS (SELECT 1 FROM "campaign_user")') - expect(migration).toContain('RAISE EXCEPTION') - }) - it('returns only municipalities administered by an advisor', async () => { const advisor = await campaignFixtures().createCampaignUser('advisor') const assignedMunicipality = await campaignFixtures().getMunicipality() @@ -547,58 +531,4 @@ describe('campaign authentication foundation', () => { }), ) }) - - it.each([ - ['(71) 99999-1234', '71999991234'], - ['+55 71 99999-1234', '71999991234'], - ['55 71 99999-1234', '71999991234'], - ])('normalizes Brazilian mobile phone %s', (input, expected) => { - expect(normalizeBrazilianPhone(input)).toBe(expected) - }) - - it.each(['7199991234', '55719999912345', 'invalid'])( - 'rejects invalid Brazilian mobile phone %s', - (input) => { - expect(normalizeBrazilianPhone(input)).toBeNull() - }, - ) - - it.each([ - ['+55 (71) 99999-1234', '71999991234'], - ['55 71 99999 1234', '71999991234'], - ['71999991234', '71999991234'], - ['55999991234', '55999991234'], - ])( - 'sanitizes pasted or typed Brazilian phone %s without corrupting DDD 55', - (input, expected) => { - expect(sanitizeBrazilianPhoneInput(input)).toBe(expected) - }, - ) - - it('builds a wa.me URL from the canonical phone', () => { - expect(buildWhatsAppUrl('(71) 99999-1234', 'Olá, Solla!')).toBe( - 'https://wa.me/5571999991234?text=Ol%C3%A1%2C+Solla%21', - ) - }) - - it('validates a single email-or-phone login field', () => { - expect( - campaignLoginSchema.parse({ - identifier: ' pessoa@example.com ', - password: 'secret', - }), - ).toEqual({ - identifier: 'pessoa@example.com', - password: 'secret', - }) - expect( - campaignLoginSchema.parse({ - identifier: '+55 (71) 99999-1234', - password: 'secret', - }), - ).toEqual({ - identifier: '71999991234', - password: 'secret', - }) - }) }) diff --git a/tests/unit/campaignAuthIdentity.unit.spec.ts b/tests/unit/campaignAuthIdentity.unit.spec.ts new file mode 100644 index 00000000..6c38c0e6 --- /dev/null +++ b/tests/unit/campaignAuthIdentity.unit.spec.ts @@ -0,0 +1,77 @@ +// @vitest-environment node + +import { readFileSync } from 'node:fs' + +import { describe, expect, it } from 'vitest' + +import { buildWhatsAppUrl, normalizeBrazilianPhone, sanitizeBrazilianPhoneInput } from '@/lib/phone' +import { campaignLoginSchema } from '@/lib/schemas/campaign-login' + +describe('campaign auth identity helpers', () => { + it('guards migration rollback when phone-only accounts exist', () => { + const migration = readFileSync( + new URL( + '../../src/migrations/20260718_010733_consolidate_campaign_schema.ts', + import.meta.url, + ), + 'utf8', + ) + + expect(migration).toContain('IF EXISTS (SELECT 1 FROM "campaign_user")') + expect(migration).toContain('RAISE EXCEPTION') + }) + + it.each([ + ['(71) 99999-1234', '71999991234'], + ['+55 71 99999-1234', '71999991234'], + ['55 71 99999-1234', '71999991234'], + ])('normalizes Brazilian mobile phone %s', (input, expected) => { + expect(normalizeBrazilianPhone(input)).toBe(expected) + }) + + it.each(['7199991234', '55719999912345', 'invalid'])( + 'rejects invalid Brazilian mobile phone %s', + (input) => { + expect(normalizeBrazilianPhone(input)).toBeNull() + }, + ) + + it.each([ + ['+55 (71) 99999-1234', '71999991234'], + ['55 71 99999 1234', '71999991234'], + ['71999991234', '71999991234'], + ['55999991234', '55999991234'], + ])( + 'sanitizes pasted or typed Brazilian phone %s without corrupting DDD 55', + (input, expected) => { + expect(sanitizeBrazilianPhoneInput(input)).toBe(expected) + }, + ) + + it('builds a wa.me URL from the canonical phone', () => { + expect(buildWhatsAppUrl('(71) 99999-1234', 'Olá, Solla!')).toBe( + 'https://wa.me/5571999991234?text=Ol%C3%A1%2C+Solla%21', + ) + }) + + it('validates a single email-or-phone login field', () => { + expect( + campaignLoginSchema.parse({ + identifier: ' pessoa@example.com ', + password: 'secret', + }), + ).toEqual({ + identifier: 'pessoa@example.com', + password: 'secret', + }) + expect( + campaignLoginSchema.parse({ + identifier: '+55 (71) 99999-1234', + password: 'secret', + }), + ).toEqual({ + identifier: '71999991234', + password: 'secret', + }) + }) +})