teqo-backup/tests/int/municipalityMapData.int.spec.ts
Francisco Ignácio Fontoura Solla 2c30944593 B8+: escala das malhas em unidades reais, contrato do map key e degradacao
F1 — a tolerancia de simplificacao e os digitos de quantizacao viraram
politica em unidades de solo em scripts/lib/topology.mjs, consumida pelos
dois scripts de geometria. Os quantis 0.35 copiados cortavam as 19 ZE de
Salvador a ~0.6 m2 e os 417 municipios a ~1.78 km2; com tolerancia
absoluta e a grade de ~103 m do estado, a malha das zonas caiu de 480 para
30.2 pontos/feature. bahia-municipalities segue byte-identico e o tripwire
de bytes deu lugar a pontos/feature.

F2 — featureMapKey passou a ser asserido sobre features reais das tres
malhas comprometidas (417 codarea, 27 code, 19 slug), e o comentario de
MAP_KEY_PROPERTIES agora diz o que o codigo faz: as propriedades sao
mutuamente exclusivas, nao ordenadas por especificidade.

F3 — a malha das zonas e um detalhe sobre o mapa, nao o mapa: se o chunk
falha, Salvador cai no poligono municipal que ja esta desenhado embaixo e
o resto da Bahia continua funcionando, com o motivo logado. A ressalva de
aproximacao saiu do gate de comparacao e passou a depender de
bundle.hasZoneMunicipalities, derivado no servidor de municipality.kind.

F4 — orfaos deletados: os dois acessores sem chamador, isZoneMapKey (o
servidor ja sabe a regra), o wrapper simplifyTopology e o helper
polygonCount com um branch inalcancavel. MunicipalityMapNavigation
colapsou em string | undefined e MunicipalitiesByMapKey em
Record<string, string>.
2026-07-27 01:59:36 -03:00

97 lines
4 KiB
TypeScript

// @vitest-environment node
import type { Payload } from 'payload'
import { getPayload } from 'payload'
import { beforeAll, describe, expect, it } from 'vitest'
import { municipalityCatalog } from '@/lib/municipalityCatalog'
import config from '@/payload.config'
import { loadMunicipalityMapBundle } from '@/utilities/municipalityMapData'
import { installCampaignFixtures } from '../helpers/campaignFixtures'
const zoneMunicipalities = municipalityCatalog.filter((entry) => entry.kind === 'zona')
const ZONE_MUNICIPALITY_COUNT = zoneMunicipalities.length
const ZONE_MUNICIPALITY_SLUGS = new Set(zoneMunicipalities.map((entry) => entry.slug))
const ZONE_MUNICIPALITY_CODES = new Set(zoneMunicipalities.map((entry) => entry.ibgeCode))
let payload: Payload
const campaignFixtures = installCampaignFixtures({
getPayload: () => payload,
setPayload: (nextPayload) => {
payload = nextPayload
},
})
describe('loadMunicipalityMapBundle — list URL filters', () => {
beforeAll(async () => {
payload = await getPayload({ config: await config })
})
it('paints each zone under its own map key, never pooled under the city code', async () => {
const coordinator = await campaignFixtures().createCampaignUser('coordinator')
const bundle = await loadMunicipalityMapBundle(payload, coordinator, { kind: 'zona' })
expect(bundle).not.toBeNull()
expect(bundle!.zoneBreakdown).toHaveLength(ZONE_MUNICIPALITY_COUNT)
expect(bundle!.hasZoneMunicipalities).toBe(true)
const mapKeys = Object.keys(bundle!.valuesByYear['2022'] ?? {})
expect(mapKeys.length).toBeGreaterThan(0)
for (const key of mapKeys) {
expect(ZONE_MUNICIPALITY_SLUGS.has(key), key).toBe(true)
expect(ZONE_MUNICIPALITY_CODES.has(key), key).toBe(false)
}
expect(Object.keys(bundle!.municipalitiesByMapKey).sort()).toEqual([...mapKeys].sort())
// The zones share the city's TSE rank — the artifact ranks by codarea only.
const ranks = bundle!.competitiveRankByYear['2022'] ?? {}
const positions = new Set(mapKeys.map((key) => ranks[key]?.rank))
expect(positions.size).toBe(1)
})
it('returns null when the filtered municipality set is empty', async () => {
const coordinator = await campaignFixtures().createCampaignUser('coordinator')
const bundle = await loadMunicipalityMapBundle(payload, coordinator, { q: 'zzznomatch' })
expect(bundle).toBeNull()
})
it('keeps advisor access and applies URL filters on top', async () => {
const fixtures = campaignFixtures()
const advisor = await fixtures.createCampaignUser('advisor')
const administered = await fixtures.getMunicipality()
await fixtures.assignMunicipalityAdvisors(administered.id, [advisor.id])
const included = await loadMunicipalityMapBundle(payload, advisor, { q: administered.name })
expect(included).not.toBeNull()
expect(included!.zoneBreakdown.some((row) => row.slug === administered.slug)).toBe(
administered.kind === 'zona',
)
// The map's provenance caveat follows the actor's scope, not the list below it.
expect(included!.hasZoneMunicipalities).toBe(administered.kind === 'zona')
expect(Object.keys(included!.valuesByYear['2022'] ?? {})).toEqual([
administered.kind === 'zona' ? administered.slug : administered.ibgeCode,
])
const excluded =
administered.kind === 'zona'
? await loadMunicipalityMapBundle(payload, advisor, { kind: 'municipio' })
: await loadMunicipalityMapBundle(payload, advisor, { kind: 'zona' })
expect(excluded).toBeNull()
})
it('includes validVotesByYear for TSE years and reuses 2022 for 2026', async () => {
const coordinator = await campaignFixtures().createCampaignUser('coordinator')
const bundle = await loadMunicipalityMapBundle(payload, coordinator, {})
expect(bundle).not.toBeNull()
expect(bundle!.validVotesByYear['2014']).toBeDefined()
expect(bundle!.validVotesByYear['2018']).toBeDefined()
expect(bundle!.validVotesByYear['2022']).toBeDefined()
expect(bundle!.validVotesByYear['2026']).toBe(bundle!.validVotesByYear['2022'])
})
})