test(B136): assert 3×2 grid by column clusters (tolerant row heights)

This commit is contained in:
Cursor Agent 2026-08-02 23:14:53 +00:00
parent 993b9af69b
commit 3ac5d303e8
No known key found for this signature in database
2 changed files with 45 additions and 1 deletions

View file

@ -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)

View file

@ -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) {