From 40e7ecea3373043a5a462e6aec6ddb38f8e149d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Ign=C3=A1cio=20Fontoura=20Solla?= Date: Thu, 30 Jul 2026 05:35:25 -0300 Subject: [PATCH] =?UTF-8?q?test:=20fix=20pre-existing=20unit=20drift=20?= =?UTF-8?q?=E2=80=94=20wrap=20Tooltip-needing=20renders=20in=20TooltipProv?= =?UTF-8?q?ider=20(944/944=20green)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unit/campaignCellEditOverlay.unit.spec.ts | 18 ++++++++----- tests/unit/campaignComponents.unit.spec.ts | 26 ++++++++++++++----- tests/unit/campaignTable.unit.spec.ts | 14 +++++++--- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/tests/unit/campaignCellEditOverlay.unit.spec.ts b/tests/unit/campaignCellEditOverlay.unit.spec.ts index 7b5af741..b9455b4c 100644 --- a/tests/unit/campaignCellEditOverlay.unit.spec.ts +++ b/tests/unit/campaignCellEditOverlay.unit.spec.ts @@ -9,6 +9,7 @@ import { MunicipalityListSignalControl } from '@/components/campaign/municipalit import { MunicipalityListTrendControl } from '@/components/campaign/municipality/MunicipalityListTrendControl' import type { CampaignCellEditOverlayVariant } from '@/components/campaign/shared/CampaignCellEditOverlay' import { MunicipalityPortfolioCell } from '@/components/campaign/shared/MunicipalityPortfolioCell' +import { TooltipProvider } from '@/components/ui/tooltip' import { toVoteEstimateScenarioViewModel } from '@/lib/voteEstimate' /** @@ -141,11 +142,16 @@ afterAll(() => { Reflect.deleteProperty(Element.prototype, 'scrollIntoView') }) +// The Popover variant wraps its trigger in `CampaignHoverTooltip` (Radix), +// which refuses to render outside a provider; production mounts it in the +// `(app)` layout. +const renderWithTooltip = (ui: ReactElement) => render(createElement(TooltipProvider, null, ui)) + describe('campaign cell edit overlay', () => { it.each(overlayCases)( 'opens $name in a Drawer that names the município on touch', async ({ triggerLabel, drawerTitle, footerLabel, element }) => { - render(element('sheet')) + renderWithTooltip(element('sheet')) fireEvent.click(screen.getByRole('button', { name: triggerLabel })) @@ -176,7 +182,7 @@ describe('campaign cell edit overlay', () => { it.each(overlayCases)( 'keeps $name in a Popover on the desktop table', async ({ triggerLabel, element }) => { - render(element('popover')) + renderWithTooltip(element('popover')) const trigger = screen.getByRole('button', { name: triggerLabel }) expect(trigger.getAttribute('aria-haspopup')).toBe('dialog') @@ -207,7 +213,7 @@ describe('campaign cell edit overlay', () => { * "Salvando…", which cannot happen before one. */ it('does not mount the live region until the overlay has been opened once', () => { - render( + renderWithTooltip( createElement(MunicipalityListTrendControl, { municipalityID: 1, municipalityName: MUNICIPALITY_NAME, @@ -237,7 +243,7 @@ describe('campaign cell edit overlay', () => { ) vi.stubGlobal('fetch', fetchMock) - render( + renderWithTooltip( createElement(MunicipalityListTrendControl, { municipalityID: 1, municipalityName: MUNICIPALITY_NAME, @@ -273,7 +279,7 @@ describe('campaign cell edit overlay', () => { it('submits the signal form from a button rendered in the sheet footer', async () => { const formAction = vi.fn(async () => ({})) - render( + renderWithTooltip( // `createElement`'s typing puts a required `children` in props, so the // rest-argument form this rule prefers does not type-check here. // eslint-disable-next-line react/no-children-prop @@ -317,7 +323,7 @@ describe('campaign cell edit overlay', () => { * edited. */ it('opens the município portfolio in a Drawer focused on its title', async () => { - render( + renderWithTooltip( createElement(MunicipalityPortfolioCell, { ownerId: 1, ownerName: 'Maria Souza', diff --git a/tests/unit/campaignComponents.unit.spec.ts b/tests/unit/campaignComponents.unit.spec.ts index e89a0f37..ce2ea586 100644 --- a/tests/unit/campaignComponents.unit.spec.ts +++ b/tests/unit/campaignComponents.unit.spec.ts @@ -16,6 +16,7 @@ import { CampaignScopeBadge } from '@/components/campaign/shared/CampaignScopeBa import { Progress } from '@/components/ui/Progress' import { Toggle } from '@/components/ui/Toggle' import { ToggleGroup, ToggleGroupItem } from '@/components/ui/ToggleGroup' +import { TooltipProvider } from '@/components/ui/tooltip' import type { CampaignColumnVisibility } from '@/lib/campaignColumnVisibility' import { toVoteEstimateScenarioViewModel } from '@/lib/voteEstimate' import type { CampaignFormActionState } from '@/utilities/campaignFormActionError' @@ -63,8 +64,19 @@ const mockAppRouter = stub[0]['valu prefetch: () => Promise.resolve(), }) +// Cells render `CampaignHoverTooltip` (Radix), which refuses to render outside +// a provider; production mounts it in the `(app)` layout. +const renderWithTooltip = (element: React.ReactElement) => + renderToStaticMarkup(createElement(TooltipProvider, null, element)) + const renderWithAppRouter = (element: React.ReactElement) => - renderToStaticMarkup(createElement(AppRouterContext.Provider, { value: mockAppRouter }, element)) + renderToStaticMarkup( + createElement( + AppRouterContext.Provider, + { value: mockAppRouter }, + createElement(TooltipProvider, null, element), + ), + ) describe('campaign visual foundation', () => { it('exposes the current progress value to assistive technology', () => { @@ -579,7 +591,7 @@ describe('campaign visual foundation', () => { goalCoverageByScenario: createEmptyGoalCoverageByScenario(), } - const withAdvisors = renderToStaticMarkup( + const withAdvisors = renderWithTooltip( createElement(MunicipalityList, { municipalities: [{ ...baseMunicipality, advisorIDs: [7] }], advisorNamesById: new Map([[7, { id: 7, name: 'Ana Bastos', phone: null }]]), @@ -591,7 +603,7 @@ describe('campaign visual foundation', () => { HEADER_TOOLTIP_COUNT + 1, ) - const withoutAdvisors = renderToStaticMarkup( + const withoutAdvisors = renderWithTooltip( createElement(MunicipalityList, { municipalities: [{ ...baseMunicipality, advisorIDs: [] }], advisorNamesById: new Map(), @@ -606,7 +618,7 @@ describe('campaign visual foundation', () => { }) it("wraps the coordinator's advisor Popover trigger in a tooltip, never doubling the affordance", () => { - const withAdvisors = renderToStaticMarkup( + const withAdvisors = renderWithTooltip( createElement(MunicipalityListAdvisorsControl, { municipalityID: 1, municipalityName: 'Feira de Santana', @@ -624,7 +636,7 @@ describe('campaign visual foundation', () => { // stays intact and functional. expect(withAdvisors).toContain('aria-haspopup="dialog"') - const withoutAdvisors = renderToStaticMarkup( + const withoutAdvisors = renderWithTooltip( createElement(MunicipalityListAdvisorsControl, { municipalityID: 1, municipalityName: 'Feira de Santana', @@ -641,7 +653,7 @@ describe('campaign visual foundation', () => { }) it('shows the trend justification on hover only when one was recorded', () => { - const withNote = renderToStaticMarkup( + const withNote = renderWithTooltip( createElement(MunicipalityListTrendControl, { municipalityID: 1, municipalityName: 'Feira de Santana', @@ -657,7 +669,7 @@ describe('campaign visual foundation', () => { expect(withNote).toContain('aria-haspopup="dialog"') expect(withNote).not.toContain('Salvar') - const withoutNote = renderToStaticMarkup( + const withoutNote = renderWithTooltip( createElement(MunicipalityListTrendControl, { municipalityID: 1, municipalityName: 'Feira de Santana', diff --git a/tests/unit/campaignTable.unit.spec.ts b/tests/unit/campaignTable.unit.spec.ts index 7e3571a9..8bff9767 100644 --- a/tests/unit/campaignTable.unit.spec.ts +++ b/tests/unit/campaignTable.unit.spec.ts @@ -3,6 +3,7 @@ import { renderToStaticMarkup } from 'react-dom/server' import { describe, expect, it } from 'vitest' import { CampaignTable, CampaignTableHead } from '@/components/campaign/shared/CampaignTable' +import { TooltipProvider } from '@/components/ui/tooltip' type Row = { id: number; name: string; note: string | null } @@ -11,8 +12,13 @@ const rows: Row[] = [ { id: 2, name: 'Itaberaba', note: null }, ] +// Cells/heads render `CampaignHoverTooltip` (Radix), which refuses to render +// outside a provider; production mounts it in the `(app)` layout. +const withTooltipProvider = (element: ReturnType) => + renderToStaticMarkup(createElement(TooltipProvider, null, element)) + const renderTable = (cellTooltip?: (row: Row) => string | null) => - renderToStaticMarkup( + withTooltipProvider( createElement(CampaignTable, { columns: [ { @@ -40,7 +46,7 @@ describe('CampaignTable head', () => { }) it('lets a column own its header when it needs more than its name', () => { - const html = renderToStaticMarkup( + const html = withTooltipProvider( createElement(CampaignTable, { columns: [ { @@ -101,7 +107,7 @@ describe('CampaignTable cellTooltip', () => { */ describe('CampaignTableHead description', () => { it('renders unchanged when no description is declared', () => { - const html = renderToStaticMarkup(createElement(CampaignTableHead, {}, 'Território')) + const html = withTooltipProvider(createElement(CampaignTableHead, {}, 'Território')) expect(html).toContain('Território') expect(html).not.toContain('data-slot="tooltip-trigger"') @@ -109,7 +115,7 @@ describe('CampaignTableHead description', () => { }) it('wraps the label in exactly one tooltip trigger when description is declared', () => { - const html = renderToStaticMarkup( + const html = withTooltipProvider( createElement( CampaignTableHead, { description: 'Território de Identidade a que o município pertence.' },