diff --git a/tests/e2e/campaignMunicipalities.e2e.spec.ts b/tests/e2e/campaignMunicipalities.e2e.spec.ts index f7e3d7ad..f254582f 100644 --- a/tests/e2e/campaignMunicipalities.e2e.spec.ts +++ b/tests/e2e/campaignMunicipalities.e2e.spec.ts @@ -513,6 +513,13 @@ test.describe('Municípios — FAB overlay polish (B126)', () => { const actionsRegion = overlay.getByLabel('Ações rápidas') await expect(actionsRegion.locator('ul[data-layout="grid-3"]')).toBeVisible() + for (const label of staffActionLabels) { + await expect( + actionsRegion + .getByRole('link', { name: label, exact: true }) + .or(actionsRegion.getByRole('button', { name: label, exact: true })), + ).toBeVisible() + } const boxes = await collectActionBoundingBoxes(actionsRegion, staffActionLabels) assertThreeColumnActionGrid(groupActionsByRow(boxes), 2) diff --git a/tests/e2e/helpers/actionGridGeometry.ts b/tests/e2e/helpers/actionGridGeometry.ts index fc0adfc8..673c5a02 100644 --- a/tests/e2e/helpers/actionGridGeometry.ts +++ b/tests/e2e/helpers/actionGridGeometry.ts @@ -2,6 +2,7 @@ import type { Locator } from '@playwright/test' import { expect } from '@playwright/test' const ROW_Y_TOLERANCE_PX = 12 +const COLUMN_X_TOLERANCE_PX = 24 export type ActionBoundingBox = { label: string @@ -54,11 +55,47 @@ export function groupActionsByRow( return rows } +function clusterActionsByColumn( + boxes: readonly ActionBoundingBox[], + tolerancePx = COLUMN_X_TOLERANCE_PX, +): ActionBoundingBox[][] { + const sorted = [...boxes].sort((left, right) => left.x - right.x) + const columns: ActionBoundingBox[][] = [] + + for (const box of sorted) { + const column = columns.find((entry) => Math.abs(entry[0]!.x - box.x) <= tolerancePx) + if (column) { + column.push(box) + } else { + columns.push([box]) + } + } + + for (const column of columns) { + column.sort((left, right) => left.y - right.y) + } + + return columns.sort((left, right) => left[0]!.x - right[0]!.x) +} + /** Asserts a 3-column grid with `expectedRowCount` rows (staff = 2 rows of 3). */ export function assertThreeColumnActionGrid( - rows: readonly ActionBoundingBox[][], + boxes: readonly ActionBoundingBox[], expectedRowCount: number, ) { + expect(boxes).toHaveLength(expectedRowCount * 3) + + const columns = clusterActionsByColumn(boxes) + expect(columns).toHaveLength(3) + for (const column of columns) { + expect(column).toHaveLength(expectedRowCount) + } + + const medianHeight = [...boxes].map((box) => box.height).sort((left, right) => left - right)[ + Math.floor(boxes.length / 2) + ]! + const rowTolerance = Math.max(ROW_Y_TOLERANCE_PX, medianHeight * 0.35) + const rows = groupActionsByRow(boxes, rowTolerance) expect(rows).toHaveLength(expectedRowCount) for (const row of rows) {