mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:05:19 +00:00
Fase 2 do plano aprovado. Três módulos em src/utilities/contacts/:
- contactListUrl: contrato de params (q|gender|state|city|ausencia|vinculo|sort|dir|page),
canonicalize, hrefs de sort e where de fonte com 'phones.value' like (ILIKE verificado
no Postgres local).
- contactListData: loader com UM find em contact (user threadado, overrideAccess false),
vínculos (liderancas/dobradinhas/assessores/equipe) como facets sobre o conjunto
legível, filtro/sort/paginação em memória, nulos no fim (precedente B15).
- contactNameInvariant: lock contact-name:{normalized} + prefilter ILIKE + veredito
exato em memória; mensagem de conflito pt-BR.
38 testes unit novos; format + tsc limpos.
493 lines
21 KiB
TypeScript
493 lines
21 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
|
||
import { resolveActivityQuickActions } from '@/lib/activityQuickActions'
|
||
import { CAMPAIGN_WIZARD_ACTION_SLUGS } from '@/lib/campaignActionRoutes'
|
||
import { advisorQuickCreateHref } from '@/lib/campaignAdvisorQuickActions'
|
||
import { UNCOVERED_MUNICIPALITIES_LIST_HREF, homeActionsForRole } from '@/lib/campaignHomeActions'
|
||
import { CAMPAIGN_CONCEPTS_PATH } from '@/lib/campaignIntelligenceConcepts'
|
||
import { CAMPAIGN_PROFILE_HOME } from '@/lib/campaignPaths'
|
||
import {
|
||
CAMPAIGN_DEMANDS_CREATE_HREF,
|
||
demandCreateHref,
|
||
isDemandDetailPath,
|
||
isDemandsListPath,
|
||
resolveDemandDetailQuickActions,
|
||
resolveDemandsListQuickActions,
|
||
} from '@/lib/campaignQuickActionDemands'
|
||
import {
|
||
matchesDobradinhasQuickActionSurface,
|
||
parseStateDeputyDetailSlug,
|
||
resolveDobradinhasQuickActions,
|
||
} from '@/lib/campaignQuickActionDobradinhas'
|
||
import {
|
||
isCampaignActionsPath,
|
||
isCampaignHomePath,
|
||
isContactsPath,
|
||
isLeaderContactsPath,
|
||
shouldMountQuickActionsFab,
|
||
} from '@/lib/campaignQuickActionMount'
|
||
import {
|
||
ACTIVITY_DETAIL_ROOT_PATH,
|
||
ACTIVITY_LIST_PATH,
|
||
ACTIVITY_TOUR_COMPOSER_PATH,
|
||
ORGANIZATIONS_LIST_PATH,
|
||
ORGANIZATION_NEW_PATH,
|
||
isActivityTourComposerPath,
|
||
isListPath,
|
||
normalizePathname,
|
||
parseActivityQuickActionSurface,
|
||
parseOrganizationQuickActionSurface,
|
||
} from '@/lib/campaignQuickActionPaths'
|
||
import { resolveQuickActionsForPath } from '@/lib/campaignQuickActionRegistry'
|
||
import { resolveOrganizationQuickActions } from '@/lib/organizationQuickActions'
|
||
import { SUPPORTER_CREATE_HREF, SUPPORTER_IMPORT_HREF } from '@/lib/supporterQuickActions'
|
||
|
||
describe('campaignQuickActionMount', () => {
|
||
it('treats Início as exact match only', () => {
|
||
expect(isCampaignHomePath('/campanha')).toBe(true)
|
||
expect(isCampaignHomePath('/campanha/')).toBe(true)
|
||
expect(isCampaignHomePath('/campanha/municipios')).toBe(false)
|
||
})
|
||
|
||
it('matches action wizard subtree', () => {
|
||
expect(isCampaignActionsPath('/campanha/acoes')).toBe(true)
|
||
expect(isCampaignActionsPath('/campanha/acoes/atualizar-votos')).toBe(true)
|
||
expect(isCampaignActionsPath('/campanha/municipios')).toBe(false)
|
||
})
|
||
|
||
it('matches leader contacts subtree (C139 — moved to meus-contatos)', () => {
|
||
expect(isLeaderContactsPath('/campanha/meus-contatos')).toBe(true)
|
||
expect(isLeaderContactsPath('/campanha/meus-contatos/novo')).toBe(true)
|
||
expect(isLeaderContactsPath('/campanha/contatos')).toBe(false)
|
||
expect(isLeaderContactsPath('/campanha')).toBe(false)
|
||
})
|
||
|
||
it('matches the staff contacts page (C139)', () => {
|
||
expect(isContactsPath('/campanha/contatos')).toBe(true)
|
||
expect(isContactsPath('/campanha/contatos/')).toBe(true)
|
||
expect(isContactsPath('/campanha/meus-contatos')).toBe(false)
|
||
expect(isContactsPath('/campanha')).toBe(false)
|
||
})
|
||
|
||
it('mounts for staff outside Início, acoes and the contacts page', () => {
|
||
expect(shouldMountQuickActionsFab('/campanha/municipios', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/territorios', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/demandas', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/demandas/foo', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/apoiadores', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/apoiadores/42', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha', 'coordinator')).toBe(false)
|
||
expect(shouldMountQuickActionsFab('/campanha/acoes/registrar-atualizacao', 'advisor')).toBe(
|
||
false,
|
||
)
|
||
expect(shouldMountQuickActionsFab('/campanha/contatos', 'coordinator')).toBe(false)
|
||
expect(shouldMountQuickActionsFab('/campanha/contatos', 'advisor')).toBe(false)
|
||
})
|
||
|
||
it('mounts for leader only on contacts', () => {
|
||
expect(shouldMountQuickActionsFab('/campanha/meus-contatos', 'leader')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/municipios', 'leader')).toBe(false)
|
||
expect(shouldMountQuickActionsFab('/campanha/apoiadores', 'leader')).toBe(false)
|
||
expect(shouldMountQuickActionsFab('/campanha/contatos', 'leader')).toBe(false)
|
||
})
|
||
|
||
it('skips the E13 tour composer (B84)', () => {
|
||
expect(isActivityTourComposerPath(ACTIVITY_TOUR_COMPOSER_PATH)).toBe(true)
|
||
expect(shouldMountQuickActionsFab(ACTIVITY_TOUR_COMPOSER_PATH, 'coordinator')).toBe(false)
|
||
})
|
||
|
||
it('mounts assessores only for unrestricted roles (B87)', () => {
|
||
expect(shouldMountQuickActionsFab('/campanha/assessores', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/assessores/12', 'candidate')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/assessores', 'advisor')).toBe(false)
|
||
expect(shouldMountQuickActionsFab('/campanha/assessores/12', 'advisor')).toBe(false)
|
||
})
|
||
|
||
it('mounts on dobradinhas for staff (B83)', () => {
|
||
expect(shouldMountQuickActionsFab('/campanha/dobradinhas', 'coordinator')).toBe(true)
|
||
expect(shouldMountQuickActionsFab('/campanha/dobradinhas/foo', 'advisor')).toBe(true)
|
||
})
|
||
|
||
it('omits FAB on perfil for leader (B90)', () => {
|
||
expect(shouldMountQuickActionsFab(CAMPAIGN_PROFILE_HOME, 'leader')).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionPaths (activities)', () => {
|
||
it('parses list and detail surfaces', () => {
|
||
expect(parseActivityQuickActionSurface(ACTIVITY_LIST_PATH)).toEqual({ kind: 'list' })
|
||
expect(parseActivityQuickActionSurface(`${ACTIVITY_LIST_PATH}/`)).toEqual({ kind: 'list' })
|
||
expect(parseActivityQuickActionSurface(ACTIVITY_DETAIL_ROOT_PATH)).toEqual({ kind: 'list' })
|
||
expect(
|
||
parseActivityQuickActionSurface(`${ACTIVITY_DETAIL_ROOT_PATH}/caminhada-centro`),
|
||
).toEqual({
|
||
kind: 'detail',
|
||
activitySlug: 'caminhada-centro',
|
||
})
|
||
})
|
||
|
||
it('ignores nova, giros and nested edit routes', () => {
|
||
expect(parseActivityQuickActionSurface('/campanha/atividades/nova')).toBeNull()
|
||
expect(parseActivityQuickActionSurface(ACTIVITY_TOUR_COMPOSER_PATH)).toBeNull()
|
||
expect(parseActivityQuickActionSurface('/campanha/atividades/foo/editar')).toBeNull()
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionPaths (shared list helpers, C86+)', () => {
|
||
it('matches exactly with an optional trailing slash', () => {
|
||
expect(isListPath('/campanha/demandas', '/campanha/demandas')).toBe(true)
|
||
expect(isListPath('/campanha/demandas/', '/campanha/demandas')).toBe(true)
|
||
})
|
||
|
||
it('rejects siblings and descendants', () => {
|
||
expect(isListPath('/campanha/demandas/nova', '/campanha/demandas')).toBe(false)
|
||
expect(isListPath('/campanha/demandas/pedido-cairu', '/campanha/demandas')).toBe(false)
|
||
expect(isListPath('/campanha/municipios', '/campanha/demandas')).toBe(false)
|
||
})
|
||
|
||
it('normalizes a single trailing slash while preserving /', () => {
|
||
expect(normalizePathname('/campanha/')).toBe('/campanha')
|
||
expect(normalizePathname('/campanha')).toBe('/campanha')
|
||
expect(normalizePathname('/')).toBe('/')
|
||
expect(normalizePathname('/campanha/apoiadores/')).toBe('/campanha/apoiadores')
|
||
expect(normalizePathname('/campanha//')).toBe('/campanha/')
|
||
})
|
||
|
||
it('pins the degenerate inputs the inline matchers used to handle', () => {
|
||
expect(isListPath('/campanha/demandas//', '/campanha/demandas')).toBe(false)
|
||
expect(isListPath('', '/campanha/demandas')).toBe(false)
|
||
expect(isListPath('/', '/')).toBe(true)
|
||
})
|
||
})
|
||
|
||
describe('organizationQuickActions (B88)', () => {
|
||
it('parses list and detail surfaces', () => {
|
||
expect(parseOrganizationQuickActionSurface(ORGANIZATIONS_LIST_PATH)).toEqual({ kind: 'list' })
|
||
expect(parseOrganizationQuickActionSurface(`${ORGANIZATIONS_LIST_PATH}/`)).toEqual({
|
||
kind: 'list',
|
||
})
|
||
expect(parseOrganizationQuickActionSurface('/campanha/organizacoes/sindmed')).toEqual({
|
||
kind: 'detail',
|
||
organizationSlug: 'sindmed',
|
||
})
|
||
})
|
||
|
||
it('ignores nova and nested routes', () => {
|
||
expect(parseOrganizationQuickActionSurface(ORGANIZATION_NEW_PATH)).toBeNull()
|
||
expect(parseOrganizationQuickActionSurface('/campanha/organizacoes/foo/editar')).toBeNull()
|
||
})
|
||
|
||
it('lists new-organization on the catalog page', () => {
|
||
const actions = resolveOrganizationQuickActions({ kind: 'list' }, 'coordinator', {})
|
||
expect(actions.map((action) => action.id)).toEqual(['new-organization'])
|
||
expect(actions[0]?.href).toBe(ORGANIZATION_NEW_PATH)
|
||
})
|
||
|
||
it('returns empty detail catalog without leadership filter URL', () => {
|
||
expect(
|
||
resolveOrganizationQuickActions(
|
||
{ kind: 'detail', organizationSlug: 'sindmed' },
|
||
'coordinator',
|
||
{ organizationSlug: 'sindmed' },
|
||
),
|
||
).toEqual([])
|
||
})
|
||
|
||
it('returns empty catalog for leader lockdown', () => {
|
||
expect(resolveOrganizationQuickActions({ kind: 'list' }, 'leader', {})).toEqual([])
|
||
})
|
||
})
|
||
|
||
describe('activityQuickActions (B84)', () => {
|
||
it('lists vertical verbs on the activity list', () => {
|
||
const actions = resolveActivityQuickActions({ kind: 'list' }, 'coordinator', {})
|
||
// C123 — "Nova atividade" opens the agenda overlay via the page-bridged
|
||
// context; without a bridge the entry is omitted (never a dead /nova href).
|
||
expect(actions.map((action) => action.id)).toEqual(['plan-tour'])
|
||
expect(actions[0]?.href).toBe(ACTIVITY_TOUR_COMPOSER_PATH)
|
||
})
|
||
|
||
it('bridges "Nova atividade" to the overlay when the context is registered', () => {
|
||
const openActivityCreate = () => undefined
|
||
const actions = resolveActivityQuickActions({ kind: 'list' }, 'coordinator', {
|
||
openActivityCreate,
|
||
})
|
||
expect(actions.map((action) => action.id)).toEqual(['new-activity', 'plan-tour'])
|
||
expect(actions[0]?.href).toBeUndefined()
|
||
expect(actions[0]?.onAction).toBe(openActivityCreate)
|
||
})
|
||
|
||
it('prefills wizards and detail shortcuts on activity detail', () => {
|
||
const actions = resolveActivityQuickActions(
|
||
{ kind: 'detail', activitySlug: 'comicio-feira' },
|
||
'coordinator',
|
||
{ activitySlug: 'comicio-feira', municipalitySlug: 'feira-de-santana' },
|
||
)
|
||
|
||
expect(actions.some((action) => action.id === 'update-votes')).toBe(true)
|
||
expect(
|
||
actions
|
||
.find((action) => action.id === 'update-votes')
|
||
?.href?.includes('municipio=feira-de-santana'),
|
||
).toBe(true)
|
||
// C123 — "Editar" is bridged by the detail page; without the bridge it is
|
||
// omitted, never a dead /editar href.
|
||
expect(actions.find((action) => action.id === 'edit-activity')).toBeUndefined()
|
||
expect(actions.find((action) => action.id === 'activity-tasks')?.href).toBe(
|
||
'/campanha/atividades/comicio-feira?tab=tasks',
|
||
)
|
||
})
|
||
|
||
it('bridges "Editar" to the overlay when the context is registered', () => {
|
||
const openActivityEdit = () => undefined
|
||
const actions = resolveActivityQuickActions(
|
||
{ kind: 'detail', activitySlug: 'panfletagem' },
|
||
'advisor',
|
||
{ activitySlug: 'panfletagem', openActivityEdit },
|
||
)
|
||
expect(actions.find((action) => action.id === 'edit-activity')?.href).toBeUndefined()
|
||
expect(actions.find((action) => action.id === 'edit-activity')?.onAction).toBe(openActivityEdit)
|
||
})
|
||
|
||
it('omits wizard prefills without municipality context', () => {
|
||
const actions = resolveActivityQuickActions(
|
||
{ kind: 'detail', activitySlug: 'panfletagem' },
|
||
'advisor',
|
||
{ activitySlug: 'panfletagem' },
|
||
)
|
||
|
||
expect(actions.some((action) => action.id === 'register-demand')).toBe(false)
|
||
expect(actions.map((action) => action.id)).toEqual(['activity-tasks', 'activity-updates'])
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionDobradinhas (B83)', () => {
|
||
const staffActionIds = homeActionsForRole('coordinator').map((action) => action.id)
|
||
|
||
it('recognizes list, create and detail surfaces', () => {
|
||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas')).toBe(true)
|
||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas/nova')).toBe(true)
|
||
expect(matchesDobradinhasQuickActionSurface('/campanha/dobradinhas/eduardo-alves')).toBe(true)
|
||
expect(matchesDobradinhasQuickActionSurface('/campanha/municipios')).toBe(false)
|
||
})
|
||
|
||
it('parses detail slug and rejects nova', () => {
|
||
expect(parseStateDeputyDetailSlug('/campanha/dobradinhas/eduardo-alves')).toBe('eduardo-alves')
|
||
expect(parseStateDeputyDetailSlug('/campanha/dobradinhas/nova')).toBeUndefined()
|
||
})
|
||
|
||
it('returns list catalog with Nova dobradinha plus staff Início actions without prefill', () => {
|
||
const actions = resolveDobradinhasQuickActions('/campanha/dobradinhas', 'coordinator')
|
||
expect(actions.map((action) => action.id)).toEqual(['new-state-deputy', ...staffActionIds])
|
||
expect(actions[0]?.href).toBe('/campanha/dobradinhas/nova')
|
||
expect(actions.find((action) => action.id === 'update-votes')?.href).toBe(
|
||
'/campanha/acoes/atualizar-votos?from=%2Fcampanha%2Fdobradinhas',
|
||
)
|
||
expect(actions.find((action) => action.id === 'uncovered-municipalities')?.href).toBe(
|
||
UNCOVERED_MUNICIPALITIES_LIST_HREF,
|
||
)
|
||
})
|
||
|
||
it('returns staff actions without Nova on detail and create', () => {
|
||
for (const pathname of ['/campanha/dobradinhas/eduardo-alves', '/campanha/dobradinhas/nova']) {
|
||
const actions = resolveDobradinhasQuickActions(pathname, 'advisor')
|
||
expect(actions.map((action) => action.id)).toEqual(staffActionIds)
|
||
expect(actions.some((action) => action.id === 'new-state-deputy')).toBe(false)
|
||
}
|
||
})
|
||
|
||
it('returns empty for leader lockdown', () => {
|
||
expect(resolveDobradinhasQuickActions('/campanha/dobradinhas', 'leader')).toEqual([])
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionRegistry', () => {
|
||
const staffActionIds = homeActionsForRole('coordinator').map((action) => action.id)
|
||
|
||
it('delegates organization routes to the B88 catalog', () => {
|
||
const actions = resolveQuickActionsForPath(ORGANIZATIONS_LIST_PATH, 'coordinator', {})
|
||
expect(actions.map((action) => action.id)).toEqual(['new-organization'])
|
||
expect(actions[0]?.href).toBe(ORGANIZATION_NEW_PATH)
|
||
})
|
||
|
||
it('returns empty organization detail catalog in the registry', () => {
|
||
expect(
|
||
resolveQuickActionsForPath('/campanha/organizacoes/sindmed', 'advisor', {
|
||
organizationSlug: 'sindmed',
|
||
}),
|
||
).toEqual([])
|
||
})
|
||
|
||
it('returns leadership list catalog on /liderancas (B82)', () => {
|
||
const actions = resolveQuickActionsForPath('/campanha/liderancas', 'coordinator', {})
|
||
expect(actions).toHaveLength(1)
|
||
expect(actions[0]?.id).toBe('update-leadership')
|
||
})
|
||
|
||
it('returns empty catalog for unregistered paths', () => {
|
||
expect(resolveQuickActionsForPath('/campanha/lugar-inexistente', 'coordinator', {})).toEqual([])
|
||
})
|
||
|
||
it('returns empty catalog on conceitos and perfil for staff (B90)', () => {
|
||
expect(resolveQuickActionsForPath(CAMPAIGN_CONCEPTS_PATH, 'coordinator', {})).toEqual([])
|
||
expect(resolveQuickActionsForPath(CAMPAIGN_PROFILE_HOME, 'candidate', {})).toEqual([])
|
||
})
|
||
|
||
it('delegates municipality list and detail catalogs (B80)', () => {
|
||
const list = resolveQuickActionsForPath('/campanha/municipios', 'coordinator', {})
|
||
expect(list).toHaveLength(6)
|
||
|
||
const detail = resolveQuickActionsForPath('/campanha/municipios/foo', 'coordinator', {
|
||
municipalitySlug: 'foo',
|
||
})
|
||
expect(detail).toHaveLength(5)
|
||
expect(detail.find((action) => action.id === 'update-votes')?.href).toBe(
|
||
'/campanha/acoes/atualizar-votos?municipio=foo&from=%2Fcampanha%2Fmunicipios%2Ffoo',
|
||
)
|
||
})
|
||
|
||
it('delegates activity routes to the B84 catalog', () => {
|
||
// C123 — "Nova atividade" only appears once the agenda bridge registers.
|
||
expect(
|
||
resolveQuickActionsForPath(ACTIVITY_LIST_PATH, 'coordinator', {}).map((action) => action.id),
|
||
).toEqual(['plan-tour'])
|
||
const actions = resolveQuickActionsForPath(ACTIVITY_LIST_PATH, 'coordinator', {
|
||
openActivityCreate: () => undefined,
|
||
})
|
||
expect(actions.map((action) => action.id)).toEqual(['new-activity', 'plan-tour'])
|
||
})
|
||
|
||
it('delegates dobradinhas paths to the B83 catalog', () => {
|
||
const actions = resolveQuickActionsForPath('/campanha/dobradinhas', 'coordinator', {})
|
||
expect(actions.some((action) => action.id === 'new-state-deputy')).toBe(true)
|
||
})
|
||
|
||
it('builds wizard hrefs with municipality slug from context', () => {
|
||
const actions = resolveQuickActionsForPath(
|
||
'/campanha/atividades/evento-zona-1',
|
||
'coordinator',
|
||
{
|
||
municipalitySlug: 'salvador-ze-01',
|
||
},
|
||
)
|
||
const registerUpdate = actions.find((action) => action.id === 'register-update')
|
||
expect(registerUpdate?.href).toBe(
|
||
`/campanha/acoes/${CAMPAIGN_WIZARD_ACTION_SLUGS['register-update']}?municipio=salvador-ze-01&from=%2Fcampanha%2Fatividades%2Fevento-zona-1`,
|
||
)
|
||
})
|
||
|
||
it('returns staff Início catalog on territorios without municipality prefill (B81)', () => {
|
||
const actions = resolveQuickActionsForPath('/campanha/territorios', 'coordinator', {})
|
||
expect(actions.map((action) => action.id)).toEqual(staffActionIds)
|
||
expect(actions.find((action) => action.id === 'update-votes')?.href).toBe(
|
||
'/campanha/acoes/atualizar-votos?from=%2Fcampanha%2Fterritorios',
|
||
)
|
||
expect(actions.find((action) => action.id === 'uncovered-municipalities')?.href).toBe(
|
||
UNCOVERED_MUNICIPALITIES_LIST_HREF,
|
||
)
|
||
for (const action of actions) {
|
||
expect(action.href).not.toContain('municipio=')
|
||
}
|
||
})
|
||
|
||
it('returns empty catalog on territorios for leader lockdown', () => {
|
||
expect(resolveQuickActionsForPath('/campanha/territorios', 'leader', {})).toEqual([])
|
||
})
|
||
|
||
it('returns single register-demand launcher on demandas list (B85)', () => {
|
||
const actions = resolveQuickActionsForPath('/campanha/demandas', 'coordinator', {})
|
||
expect(actions.map((action) => action.id)).toEqual(['register-demand'])
|
||
expect(actions[0]?.href).toBe(CAMPAIGN_DEMANDS_CREATE_HREF)
|
||
expect(actions[0]?.href).not.toContain('municipio=')
|
||
})
|
||
|
||
it('returns A1–A5 prefilled on demand detail when municipality context is set (B85)', () => {
|
||
const actions = resolveQuickActionsForPath('/campanha/demandas/pedido-cairu', 'coordinator', {
|
||
municipalitySlug: 'cairu',
|
||
municipalityId: 42,
|
||
demandSlug: 'pedido-cairu',
|
||
})
|
||
expect(actions.map((action) => action.id)).toEqual([
|
||
'update-votes',
|
||
'register-update',
|
||
'change-trend',
|
||
'update-leadership',
|
||
'register-demand',
|
||
])
|
||
expect(actions.find((action) => action.id === 'update-votes')?.href).toBe(
|
||
'/campanha/acoes/atualizar-votos?municipio=cairu&from=%2Fcampanha%2Fdemandas%2Fpedido-cairu',
|
||
)
|
||
expect(actions.find((action) => action.id === 'register-demand')?.href).toBe(
|
||
demandCreateHref(42),
|
||
)
|
||
expect(actions.some((action) => action.id === 'uncovered-municipalities')).toBe(false)
|
||
})
|
||
|
||
it('returns empty catalog on demand detail without municipality context', () => {
|
||
expect(
|
||
resolveQuickActionsForPath('/campanha/demandas/pedido-cairu', 'coordinator', {}),
|
||
).toEqual([])
|
||
})
|
||
|
||
it('delegates assessores list and detail catalogs (B87)', () => {
|
||
const list = resolveQuickActionsForPath('/campanha/assessores', 'coordinator', {})
|
||
expect(list.map((action) => action.id)).toEqual(['new-advisor'])
|
||
expect(list[0]?.href).toBe(advisorQuickCreateHref)
|
||
|
||
const detail = resolveQuickActionsForPath('/campanha/assessores/9', 'candidate', {})
|
||
expect(detail.map((action) => action.id)).toEqual(['new-advisor'])
|
||
expect(detail[0]?.href).toBe(advisorQuickCreateHref)
|
||
})
|
||
|
||
it('returns empty catalog on assessores for advisor lockdown', () => {
|
||
expect(resolveQuickActionsForPath('/campanha/assessores', 'advisor', {})).toEqual([])
|
||
})
|
||
|
||
it('delegates apoiadores list and detail catalogs (B86)', () => {
|
||
const list = resolveQuickActionsForPath('/campanha/apoiadores', 'coordinator', {})
|
||
expect(list.map((action) => action.id)).toEqual(['register-supporter', 'import-supporters'])
|
||
expect(list[0]?.href).toBe(SUPPORTER_CREATE_HREF)
|
||
expect(list[1]?.href).toBe(SUPPORTER_IMPORT_HREF)
|
||
|
||
const advisorList = resolveQuickActionsForPath('/campanha/apoiadores', 'advisor', {})
|
||
expect(advisorList.map((action) => action.id)).toEqual(['register-supporter'])
|
||
|
||
const detail = resolveQuickActionsForPath('/campanha/apoiadores/9', 'candidate', {})
|
||
expect(detail.map((action) => action.id)).toEqual(['register-supporter'])
|
||
|
||
const listTrailingSlash = resolveQuickActionsForPath('/campanha/apoiadores/', 'advisor', {})
|
||
expect(listTrailingSlash.map((action) => action.id)).toEqual(['register-supporter'])
|
||
|
||
const detailTrailingSlash = resolveQuickActionsForPath(
|
||
'/campanha/apoiadores/9/',
|
||
'candidate',
|
||
{},
|
||
)
|
||
expect(detailTrailingSlash.map((action) => action.id)).toEqual(['register-supporter'])
|
||
|
||
expect(resolveQuickActionsForPath('/campanha/apoiadores', 'leader', {})).toEqual([])
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionDemands paths', () => {
|
||
it('matches list and detail paths but not nova', () => {
|
||
expect(isDemandsListPath('/campanha/demandas')).toBe(true)
|
||
expect(isDemandsListPath('/campanha/demandas/')).toBe(true)
|
||
expect(isDemandDetailPath('/campanha/demandas/pedido-cairu')).toBe(true)
|
||
expect(isDemandDetailPath('/campanha/demandas/nova')).toBe(false)
|
||
expect(isDemandDetailPath('/campanha/demandas')).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('campaignQuickActionDemands resolvers', () => {
|
||
it('returns empty catalog for leader lockdown', () => {
|
||
expect(resolveDemandsListQuickActions('leader')).toEqual([])
|
||
expect(
|
||
resolveDemandDetailQuickActions(
|
||
'leader',
|
||
{ municipalitySlug: 'cairu', municipalityId: 1 },
|
||
'/campanha/demandas/foo',
|
||
),
|
||
).toEqual([])
|
||
})
|
||
})
|