mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
Introduce a closed-catalog URL builder that delegates to existing list/detail href helpers, with role-based guards for leader lockdown and unrestricted-only assessor routes. Register the tool in the AI chat and teach the system prompt when to offer markdown links after resolving entity ids/slugs. Closes #383
124 lines
3.9 KiB
TypeScript
124 lines
3.9 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import { campaignConceptHref } from '@/lib/campaignIntelligenceConcepts'
|
|
import { CAMPAIGN_HOME, CAMPAIGN_PROFILE_HOME, LEADER_CONTACTS_HOME } from '@/lib/campaignPaths'
|
|
import type { CampaignUser } from '@/payload-types'
|
|
import {
|
|
buildCampaignNavigationLink,
|
|
buildCampaignNavigationLinks,
|
|
} from '@/utilities/ai/campaignNavigationUrls'
|
|
import { buildMunicipalityListHref } from '@/utilities/municipality/municipalityListUrl'
|
|
|
|
const coordinator = { role: 'coordinator' } as CampaignUser
|
|
const advisor = { role: 'advisor' } as CampaignUser
|
|
const leader = { role: 'leader' } as CampaignUser
|
|
|
|
describe('campaignNavigationUrls', () => {
|
|
it('builds home and detail paths for staff', () => {
|
|
const home = buildCampaignNavigationLink(coordinator.role, { destination: 'home' })
|
|
expect(home).toEqual({ ok: true, path: CAMPAIGN_HOME, label: 'Início' })
|
|
|
|
const municipality = buildCampaignNavigationLink(coordinator.role, {
|
|
destination: 'municipality',
|
|
slug: 'ilheus',
|
|
label: 'Ilhéus',
|
|
})
|
|
expect(municipality).toEqual({
|
|
ok: true,
|
|
path: '/campanha/municipios/ilheus',
|
|
label: 'Ilhéus',
|
|
})
|
|
})
|
|
|
|
it('rejects invalid municipality slugs', () => {
|
|
const outcome = buildCampaignNavigationLink(coordinator.role, {
|
|
destination: 'municipality',
|
|
slug: 'slug-inventado',
|
|
})
|
|
expect(outcome.ok).toBe(false)
|
|
if (!outcome.ok) {
|
|
expect(outcome.error).toMatch(/Slug de município inválido/)
|
|
}
|
|
})
|
|
|
|
it('delegates municipality list filters to buildMunicipalityListHref', () => {
|
|
const outcome = buildCampaignNavigationLink(coordinator.role, {
|
|
destination: 'municipalityList',
|
|
coverage: 'sem_assessor',
|
|
priority: 'alta',
|
|
advisors: [42],
|
|
})
|
|
expect(outcome.ok).toBe(true)
|
|
if (outcome.ok) {
|
|
expect(outcome.path).toBe(
|
|
buildMunicipalityListHref(
|
|
{ page: 1, coverage: 'sem_assessor', priority: 'alta', advisors: [42] },
|
|
1,
|
|
),
|
|
)
|
|
}
|
|
})
|
|
|
|
it('blocks staff destinations for leaders', () => {
|
|
const outcome = buildCampaignNavigationLink(leader.role, {
|
|
destination: 'municipality',
|
|
slug: 'ilheus',
|
|
})
|
|
expect(outcome.ok).toBe(false)
|
|
if (!outcome.ok) {
|
|
expect(outcome.alternatives).toEqual([
|
|
CAMPAIGN_HOME,
|
|
LEADER_CONTACTS_HOME,
|
|
CAMPAIGN_PROFILE_HOME,
|
|
])
|
|
}
|
|
})
|
|
|
|
it('allows leader-safe destinations', () => {
|
|
const contacts = buildCampaignNavigationLink(leader.role, { destination: 'leaderContacts' })
|
|
expect(contacts).toEqual({
|
|
ok: true,
|
|
path: LEADER_CONTACTS_HOME,
|
|
label: 'Meus contatos',
|
|
})
|
|
|
|
const profile = buildCampaignNavigationLink(leader.role, { destination: 'perfil' })
|
|
expect(profile).toEqual({ ok: true, path: CAMPAIGN_PROFILE_HOME, label: 'Perfil' })
|
|
})
|
|
|
|
it('blocks assessor area for advisors', () => {
|
|
const outcome = buildCampaignNavigationLink(advisor.role, {
|
|
destination: 'advisor',
|
|
id: 1,
|
|
})
|
|
expect(outcome.ok).toBe(false)
|
|
if (!outcome.ok) {
|
|
expect(outcome.error).toMatch(/assessores/)
|
|
}
|
|
})
|
|
|
|
it('builds concept glossary links with anchors', () => {
|
|
const outcome = buildCampaignNavigationLink(coordinator.role, {
|
|
destination: 'conceitos',
|
|
conceptId: 'captura',
|
|
label: 'Captura',
|
|
})
|
|
expect(outcome).toEqual({
|
|
ok: true,
|
|
path: campaignConceptHref('captura'),
|
|
label: 'Captura',
|
|
})
|
|
})
|
|
|
|
it('returns partial success in batch mode', () => {
|
|
const result = buildCampaignNavigationLinks(coordinator.role, [
|
|
{ destination: 'home', label: 'Início' },
|
|
{ destination: 'municipality', slug: 'slug-invalido' },
|
|
])
|
|
expect(result.links).toEqual([{ path: CAMPAIGN_HOME, label: 'Início' }])
|
|
expect(result.errors).toHaveLength(1)
|
|
expect(result.errors?.[0]?.index).toBe(1)
|
|
})
|
|
})
|