mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
Dois bugs do C142 que o e2e full do verify do deploy pegou (o PR rodou só o blast radius): - requireCampaignPageActor gate 'writable' checava advisorEditingAccess(user)==='none', que retorna 'none' para QUALQUER papel não-advisor — barrava coordinator/candidate de páginas de escrita (municipios/[slug]/editar redirecionava o coordinator pro detalhe). - CampaignQuickActionsFab não renderizava data-slot='campaign-quick-actions-fab', o locator do e2e campaignPermissionProfile. Regressões pino: campaignPageActorGate.unit.spec.ts (5 casos) + assert de data-slot no spec do FAB. Verificado: tsc/lint/format/cycles, unit 2435, int 819, e2e local dos specs afetados (os 3 casos que falhavam no deploy passam).
81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
redirect: vi.fn(),
|
|
getCampaignUser: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('next/navigation', () => ({
|
|
redirect: mocks.redirect,
|
|
}))
|
|
|
|
vi.mock('@/utilities/campaignAuth', () => ({
|
|
getCampaignUser: mocks.getCampaignUser,
|
|
}))
|
|
|
|
vi.mock('@/utilities/access/shared', () => ({
|
|
advisorEditingAccess: (user: { role: string; visibility?: string; editing?: string }) => {
|
|
if (user.role !== 'advisor') return 'none'
|
|
if (user.editing === 'somente_leitura') return 'none'
|
|
return 'carteira'
|
|
},
|
|
}))
|
|
|
|
import { requireCampaignPageActor } from '@/utilities/campaignPageActor'
|
|
|
|
type Actor = {
|
|
role: 'coordinator' | 'candidate' | 'advisor' | 'leader'
|
|
visibility?: 'carteira' | 'tudo'
|
|
editing?: 'carteira' | 'tudo' | 'somente_leitura'
|
|
email: string
|
|
}
|
|
|
|
const actor = (
|
|
role: Actor['role'],
|
|
profile?: { visibility?: Actor['visibility']; editing?: Actor['editing'] },
|
|
): Actor => ({
|
|
role,
|
|
email: `${role}@example.com`,
|
|
...profile,
|
|
})
|
|
|
|
describe('requireCampaignPageActor — gate: writable (C142)', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('lets a coordinator through the writable gate (C142 regression: advisorEditingAccess returns "none" for non-advisors)', async () => {
|
|
mocks.getCampaignUser.mockResolvedValue(actor('coordinator'))
|
|
const user = await requireCampaignPageActor({ gate: 'writable' })
|
|
expect(user.role).toBe('coordinator')
|
|
expect(mocks.redirect).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('lets a candidate through the writable gate', async () => {
|
|
mocks.getCampaignUser.mockResolvedValue(actor('candidate'))
|
|
const user = await requireCampaignPageActor({ gate: 'writable' })
|
|
expect(user.role).toBe('candidate')
|
|
expect(mocks.redirect).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('redirects an advisor with Edição somente_leitura away from write pages', async () => {
|
|
mocks.getCampaignUser.mockResolvedValue(actor('advisor', { editing: 'somente_leitura' }))
|
|
await requireCampaignPageActor({ gate: 'writable', redirectTo: '/campanha' })
|
|
expect(mocks.redirect).toHaveBeenCalledWith('/campanha')
|
|
})
|
|
|
|
it('lets an advisor with carteira editing through the writable gate', async () => {
|
|
mocks.getCampaignUser.mockResolvedValue(actor('advisor', { editing: 'carteira' }))
|
|
const user = await requireCampaignPageActor({ gate: 'writable' })
|
|
expect(user.role).toBe('advisor')
|
|
expect(mocks.redirect).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('blocks a leader (non-staff) on the writable gate', async () => {
|
|
mocks.getCampaignUser.mockResolvedValue(actor('leader'))
|
|
await requireCampaignPageActor({ gate: 'writable' })
|
|
expect(mocks.redirect).toHaveBeenCalled()
|
|
})
|
|
})
|