From 8b5beb511caabc13dcc2cdbc72aff69972f6b0b9 Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Mon, 10 Aug 2026 00:14:46 -0300 Subject: [PATCH] =?UTF-8?q?fix(C104):=20r=C3=B3tulo=20do=20cabe=C3=A7alho?= =?UTF-8?q?=20de=20detalhe=20all-day=20+=20e2e=20do=20slot=20com=20allDayS?= =?UTF-8?q?lot=20ativo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../campanha/(app)/atividades/[slug]/page.tsx | 6 +- tests/e2e/campaignActivity.e2e.spec.ts | 58 +++++++------------ 2 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/app/(campaign)/campanha/(app)/atividades/[slug]/page.tsx b/src/app/(campaign)/campanha/(app)/atividades/[slug]/page.tsx index 40dbbe95..8599adaf 100644 --- a/src/app/(campaign)/campanha/(app)/atividades/[slug]/page.tsx +++ b/src/app/(campaign)/campanha/(app)/atividades/[slug]/page.tsx @@ -19,7 +19,7 @@ import { Badge } from '@/components/ui/Badge' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { campaignPageMetadata } from '@/lib/campaignPageChrome' -import { formatBahiaDateTimeLabel } from '@/lib/campaignTime' +import { formatActivityWhenLabel } from '@/utilities/activityViewModels' import { getActivityDetailPageData } from '@/utilities/activityDetailPageData' import { @@ -115,7 +115,9 @@ export default async function ActivityDetailPage({ ))} - {view.startAt ? formatBahiaDateTimeLabel(view.startAt) : 'Data a definir'} + {view.startAt + ? formatActivityWhenLabel(view.startAt, { allDay: view.allDay, endAt: view.endAt }) + : 'Data a definir'}
diff --git a/tests/e2e/campaignActivity.e2e.spec.ts b/tests/e2e/campaignActivity.e2e.spec.ts index c9875a92..1ec983c7 100644 --- a/tests/e2e/campaignActivity.e2e.spec.ts +++ b/tests/e2e/campaignActivity.e2e.spec.ts @@ -181,25 +181,19 @@ test.describe('Agenda — calendário operacional', () => { await campaign.login(page, coordinator.email!, coordinator.password) await page.goto(`${campaign.baseURL}/campanha/agenda?municipality=${municipality.id}`) - const dayCell = page.getByRole('gridcell').nth(1) + const slotLocator = page.locator('[data-time="14:00:00"]:visible').last() // FullCalendar renders the time axis lazily and re-lays out on mount: the // grid first paints empty and re-renders (replacing its gridcells) when the // events land. Wait for the load to finish before interacting, or the // locator's element is replaced mid-action ("Element is not attached"). await expect(page.getByText('Carregando compromissos…')).toHaveCount(0, { timeout: 15_000 }) - const slotLocator = page.locator('[data-time="14:00:00"]:visible').last() await expect(slotLocator).toBeVisible() - await expect(dayCell).toBeVisible() - await dayCell.scrollIntoViewIfNeeded() - const slotBox = await slotLocator.boundingBox() - const dayBox = await dayCell.boundingBox() - if (!slotBox || !dayBox) throw new Error('A grade semanal não expôs o slot esperado.') - await dayCell.click({ - position: { - x: dayBox.width / 2, - y: slotBox.y - dayBox.y + slotBox.height / 2, - }, - }) + // C104 — with the all-day lane enabled, the v7 classic theme paints the + // all-day day fills over the time grid; real clicks still land on the slot + // (FullCalendar resolves by data-time), but Playwright's actionability + // check refuses them, so the click is forced on the slot lane itself. + await slotLocator.scrollIntoViewIfNeeded() + await slotLocator.click({ force: true }) // The click no longer navigates: the inline overlay opens at the slot. await expect(page).toHaveURL(new RegExp('/campanha/agenda.*')) @@ -263,21 +257,15 @@ test.describe('Agenda — calendário operacional', () => { await campaign.login(page, coordinator.email!, coordinator.password) await page.goto(`${campaign.baseURL}/campanha/agenda?municipality=${municipality.id}`) - const dayCell = page.getByRole('gridcell').nth(1) await expect(page.getByText('Carregando compromissos…')).toHaveCount(0, { timeout: 15_000 }) const slotLocator = page.locator('[data-time="14:00:00"]:visible').last() await expect(slotLocator).toBeVisible() - await expect(dayCell).toBeVisible() - await dayCell.scrollIntoViewIfNeeded() - const slotBox = await slotLocator.boundingBox() - const dayBox = await dayCell.boundingBox() - if (!slotBox || !dayBox) throw new Error('A grade semanal não expôs o slot esperado.') - await dayCell.click({ - position: { - x: dayBox.width / 2, - y: slotBox.y - dayBox.y + slotBox.height / 2, - }, - }) + // C104 — with the all-day lane enabled, the v7 classic theme paints the + // all-day day fills over the time grid; real clicks still land on the slot + // (FullCalendar resolves by data-time), but Playwright's actionability + // check refuses them, so the click is forced on the slot lane itself. + await slotLocator.scrollIntoViewIfNeeded() + await slotLocator.click({ force: true }) const startTrigger = page.getByLabel('Início *') await expect(startTrigger).toBeVisible() @@ -329,25 +317,19 @@ test.describe('Agenda — calendário operacional', () => { await campaign.login(page, coordinator.email!, coordinator.password) await page.goto(`${campaign.baseURL}/campanha/agenda?municipality=${municipality.id}`) - const dayCell = page.getByRole('gridcell').nth(1) + const slotLocator = page.locator('[data-time="14:00:00"]:visible').last() // FullCalendar renders the time axis lazily and re-lays out on mount: the // grid first paints empty and re-renders (replacing its gridcells) when the // events land. Wait for the load to finish before interacting, or the // locator's element is replaced mid-action ("Element is not attached"). await expect(page.getByText('Carregando compromissos…')).toHaveCount(0, { timeout: 15_000 }) - const slotLocator = page.locator('[data-time="14:00:00"]:visible').last() await expect(slotLocator).toBeVisible() - await expect(dayCell).toBeVisible() - await dayCell.scrollIntoViewIfNeeded() - const slotBox = await slotLocator.boundingBox() - const dayBox = await dayCell.boundingBox() - if (!slotBox || !dayBox) throw new Error('A grade semanal não expôs o slot esperado.') - await dayCell.click({ - position: { - x: dayBox.width / 2, - y: slotBox.y - dayBox.y + slotBox.height / 2, - }, - }) + // C104 — with the all-day lane enabled, the v7 classic theme paints the + // all-day day fills over the time grid; real clicks still land on the slot + // (FullCalendar resolves by data-time), but Playwright's actionability + // check refuses them, so the click is forced on the slot lane itself. + await slotLocator.scrollIntoViewIfNeeded() + await slotLocator.click({ force: true }) await expect(page.getByLabel('Título *')).toBeVisible() await page.getByLabel('Título *').fill(title)