From c83cf284970fbd27dc11953cc0249b4347362ae5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 31 Jul 2026 05:50:41 +0000 Subject: [PATCH] test(miss-52): sheet cells without the shared host fail loud MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CampaignCellEditOverlay: dev-mode console.error when a variant=sheet cell mounts without CampaignListSheetProvider (prod keeps the lazy-mount fallback for resilience; unit tests exercise it, so the invariant is development-only). - sharedSheetHostConventions.unit.spec.ts: any tsx rendering { + if (variant !== 'sheet' || sharedSheet) return + if (process.env.NODE_ENV !== 'development') return + console.error( + 'CampaignCellEditOverlay: variant="sheet" sem CampaignListSheetProvider — ' + + 'cada célula aberta mantém um Drawer próprio (miss #52). Envolva a lista no provider.', + ) + }, [variant, sharedSheet]) + /** * The region is mounted from the first open onwards and never unmounted * again — a live region has to exist BEFORE its text changes or most screen diff --git a/tests/unit/sharedSheetHostConventions.unit.spec.ts b/tests/unit/sharedSheetHostConventions.unit.spec.ts new file mode 100644 index 00000000..de42e059 --- /dev/null +++ b/tests/unit/sharedSheetHostConventions.unit.spec.ts @@ -0,0 +1,41 @@ +import { readdirSync, readFileSync } from 'node:fs' +import { relative, resolve } from 'node:path' +import { describe, expect, it } from 'vitest' + +// Miss #52 (2026-07-30): the municipalities list hydrated ~125 idle Drawer +// roots (25 rows × 5 sheet controls) and prod tripped React #130 — CSS +// `display:none` does not remove hydration cost. The fix pattern is ONE +// shared Drawer per list surface via `CampaignListSheetProvider`, with cell +// bodies portaled into it. The provider reached the municípios mobile cards +// and this pass (2026-07-31) the three chip-relation lists (lideranças, +// dobradinhas, assessores) — this guard keeps the next chip-cell table from +// mounting sheet overlays providerless. +describe('shared sheet host for chip-relation cells (miss #52)', () => { + const componentRoots = ['src/components', 'src/app'] as const + const chipCellUsage = / { + const offenders: string[] = [] + + for (const root of componentRoots) { + const files = readdirSync(resolve(process.cwd(), root), { + recursive: true, + withFileTypes: true, + }) + .filter((entry) => entry.isFile() && entry.name.endsWith('.tsx')) + .map((entry) => resolve(entry.parentPath, entry.name)) + + for (const file of files) { + const source = readFileSync(file, 'utf8') + if (!chipCellUsage.test(source)) continue + if (source.includes('CampaignListSheetProvider')) continue + offenders.push(relative(process.cwd(), file)) + } + } + + expect( + offenders, + 'chip-relation cells open sheet overlays on coarse pointers — wrap the table in CampaignListSheetProvider (one shared Drawer per list)', + ).toEqual([]) + }) +})