Salvador era um polígono só carregando os votos da cidade inteira, então o coroplético não conseguia responder "qual pedaço de Salvador está fraco / é meu". As 19 ZE ganham polígono próprio, dissolvido da malha de bairros do IBGE (Censo 2022) pela lista de circunscrição da RA 02/2017 do TRE-BA, e o mapa passa a pintar por map key (slug para as zonas, ibgeCode para o resto) em vez de codarea. O polígono municipal de Salvador continua desenhado por baixo, sem dado e sem interação, para não abrir buraco no contorno do estado. Aproximação declarada na copy e no cabeçalho do script: o TRE publica a circunscrição como lista de bairros, então o bairro é o átomo geométrico — Periperi, que a resolução corta na Rua das Pedrinhas, vai inteiro para a ZE 17. competitiveRank segue por cidade (o artefato TSE só tem federalRankByIbgeCode). Sem migration, sem collection, sem action, sem Consent.
63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
import { expect, test } from './fixtures/campaignE2EFixtures.js'
|
|
|
|
/**
|
|
* B8 F2 — Salvador used to be one polygon carrying the whole city's votes, so
|
|
* the choropleth could not answer "which piece of Salvador is weak / is mine".
|
|
* This pins the two halves of that fix: the zone mesh is drawn (one path per
|
|
* ZE, the city's own polygon left underneath as a non-interactive base) and a
|
|
* zone is addressable on its own — the readout names it and opens it.
|
|
*/
|
|
test('the dashboard map paints Salvador zone by zone and opens one', async ({ campaign, page }) => {
|
|
const { fixtures } = campaign
|
|
const password = fixtures.value('senha')
|
|
const coordinator = await campaign.payload.create({
|
|
collection: 'campaignUser',
|
|
data: {
|
|
name: fixtures.value('Coordenadora Mapa'),
|
|
email: `${fixtures.value('map-coordinator')}@example.com`,
|
|
password,
|
|
role: 'coordinator',
|
|
},
|
|
depth: 0,
|
|
})
|
|
|
|
await campaign.login(page, coordinator.email!, password)
|
|
|
|
await expect(page.getByRole('heading', { name: 'Mapa dos Municípios' })).toBeVisible({
|
|
timeout: 60_000,
|
|
})
|
|
await page.waitForSelector('path.leaflet-interactive', { timeout: 60_000 })
|
|
|
|
// 417 municípios + 19 Salvador zones; Salvador's own polygon is the one path
|
|
// that stays out of the pointer's way.
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
page.evaluate(() => {
|
|
const paths = Array.from(document.querySelectorAll('.leaflet-overlay-pane path'))
|
|
return {
|
|
total: paths.length,
|
|
interactive: paths.filter((path) => path.classList.contains('leaflet-interactive'))
|
|
.length,
|
|
}
|
|
}),
|
|
{ timeout: 30_000 },
|
|
)
|
|
.toEqual({ total: 436, interactive: 435 })
|
|
|
|
// Insertion order is z-order, so the zone mesh is the tail of the pane.
|
|
await page.evaluate(() => {
|
|
const paths = Array.from(document.querySelectorAll('.leaflet-overlay-pane path'))
|
|
paths.at(-1)?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }))
|
|
})
|
|
|
|
const readout = page.locator('div[aria-live="polite"]').first()
|
|
await expect(readout).toContainText(/Salvador — ZE \d+/)
|
|
|
|
await readout.getByRole('link', { name: 'Abrir município' }).click()
|
|
// The slug is the assertion: the detail page's own <h1> reads the municipality
|
|
// ROW, which other specs rename, while the polygon's name comes from the
|
|
// static catalog.
|
|
await expect(page).toHaveURL(/\/campanha\/municipios\/salvador-ze-\d+$/)
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible()
|
|
})
|