From ba8d8678a0c769f276598335302a8c32f3d79565 Mon Sep 17 00:00:00 2001 From: Corentin Date: Fri, 8 May 2026 00:37:39 +0200 Subject: [PATCH] test(e2e): add data-testid attributes for Playwright e2e (Patch 008 R3.1.e) Minimal testid additions to 4 renderer files so Playwright can target stable selectors: table-renderer, cell-{rowId}-{fieldName}, kanban-board, kanban-column-{label}, kanban-card-{rowId}, calendar-renderer, inline-editor-input, inline-editor-readonly. Also adds Dockerfile.e2e for the client build used in docker-compose.e2e.yml. Co-Authored-By: Claude Sonnet 4.6 --- ACADENICE_PATCHES.md | 51 +++++++++++++++++++ apps/client/Dockerfile.e2e | 44 ++++++++++++++++ .../components/inline-editor.tsx | 8 ++- .../renderers/calendar-renderer.tsx | 2 +- .../renderers/kanban-renderer.tsx | 14 +++-- .../renderers/table-renderer.tsx | 3 +- 6 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 apps/client/Dockerfile.e2e diff --git a/ACADENICE_PATCHES.md b/ACADENICE_PATCHES.md index 0cf34180..323aa6a0 100644 --- a/ACADENICE_PATCHES.md +++ b/ACADENICE_PATCHES.md @@ -632,3 +632,54 @@ En attendant, le rendu est identique fonctionnellement (HTML table + colonnes de - Decider du sort de l'EE branding ("Powered by Docmost" sur les pages partagees publiques) - Crowdin / i18n : ajouter une cle `appName` au lieu du hardcode et router via `getAppName()` - Strategie : renommer le package npm `docmost` -> `docadenice` quand on aura un build pipeline custom complet (impacte trop d'imports actuellement) + +--- + +## Patch 008 — R3.1.e : data-testid pour Playwright e2e + +**Commit** : (local-only, branche `acadenice/main`) +**Date** : 2026-05-08 +**Scope** : ajouts `data-testid` minimaux dans les renderers — aucune logique modifiee + +### Fichiers modifies + +#### `apps/client/src/features/acadenice/database-view/renderers/table-renderer.tsx` + +- `` : ajout `data-testid="table-renderer"` — permet a Playwright de cibler le renderer sans dependre de la structure CSS. +- `
` : ajout `data-testid={`cell-${row.id}-${field.name}`}` — permet de cibler une cellule specifique par row ID et nom de champ. + +#### `apps/client/src/features/acadenice/database-view/components/inline-editor.tsx` + +- Branche `!canWrite` : ajout `data-testid="inline-editor-readonly"` sur le `` — permet aux tests RBAC de verifier que l'editeur est bien en lecture seule. +- Branche `default` (`TextInput`) : ajout `data-testid="inline-editor-input"` — permet de cibler l'input dans les tests d'edition inline. + +#### `apps/client/src/features/acadenice/database-view/renderers/kanban-renderer.tsx` + +- `KanbanCard` wrapper div : ajout `data-testid={`kanban-card-${row.id}`}` — ciblage par row ID pour les tests de drag. +- `KanbanColumn` wrapper div : ajout `data-testid={`kanban-column-${column.label}`}` — ciblage par label de colonne. +- Board div (DndContext child) : ajout `data-testid="kanban-board"` — detection de la presence du kanban dans la page. + +#### `apps/client/src/features/acadenice/database-view/renderers/calendar-renderer.tsx` + +- Root div du composant : ajout `data-testid="calendar-renderer"` — detection de la presence du calendrier. + +#### `apps/client/Dockerfile.e2e` (nouveau) + +- Cree pour docker-compose.e2e.yml : build Vite du client + serve via `serve@14` sur le port 5173. +- Utilise uniquement pour les e2e — pas de changement sur le Dockerfile de production. + +### Raison des choix + +- `data-testid` sur les elements conteneurs plutot que sur les elements internes — plus stable face aux refactors de structure interne. +- Pas de `data-testid` sur les elements Mantine (Button, Select, etc.) : ces composants ont leurs propres selectors d'accessibilite (role, aria-label) que Playwright prefere nativement. +- Aucun `data-testid` ajoute dans les hooks, services, ou extension Tiptap — non necessaire pour les assertions UI e2e. + +### Tests impactes + +7 scenarios e2e dans `e2e/tests/` utilisent ces testids : +- `database-view-insert.spec.ts` : `table-renderer` +- `database-view-edit-inline.spec.ts` : `cell-{rowId}-{fieldName}`, `inline-editor-input` +- `database-view-realtime-sse.spec.ts` : `table-renderer` +- `database-view-rbac-denied.spec.ts` : `inline-editor-readonly` +- `database-view-kanban-drag.spec.ts` : `kanban-board`, `kanban-column-{label}`, `kanban-card-{rowId}` +- `database-view-calendar-reschedule.spec.ts` : `calendar-renderer` diff --git a/apps/client/Dockerfile.e2e b/apps/client/Dockerfile.e2e new file mode 100644 index 00000000..8360a543 --- /dev/null +++ b/apps/client/Dockerfile.e2e @@ -0,0 +1,44 @@ +# Dockerfile.e2e — DocAdenice client for e2e stack. +# +# Builds the Vite app and serves it via a lightweight static server. +# Used only in docker-compose.e2e.yml — not for production. + +FROM node:22-alpine AS build + +WORKDIR /app + +# Copy workspace root (monorepo — client may depend on shared packages). +COPY package*.json ./ +COPY apps/client/package*.json ./apps/client/ + +# Install deps. +RUN npm ci --workspace=apps/client 2>/dev/null || \ + (cd apps/client && npm ci) + +COPY . . + +# Build with e2e environment placeholders. +# VITE_ vars must be set at build time (Vite inlines them). +# In CI they are overridden via docker-compose env: section. +ARG VITE_APP_URL=http://localhost:3001 +ARG VITE_BRIDGE_URL=http://localhost:4001 + +ENV VITE_APP_URL=${VITE_APP_URL} +ENV VITE_BRIDGE_URL=${VITE_BRIDGE_URL} + +RUN cd apps/client && npm run build + +# --- Serve stage --- +FROM node:22-alpine AS serve + +WORKDIR /app + +# Use serve package to host the built assets. +RUN npm install -g serve@14 + +COPY --from=build /app/apps/client/dist ./dist + +# serve on port 5173 to match Vite dev server default. +EXPOSE 5173 + +CMD ["serve", "-s", "dist", "-l", "5173"] diff --git a/apps/client/src/features/acadenice/database-view/components/inline-editor.tsx b/apps/client/src/features/acadenice/database-view/components/inline-editor.tsx index 99eeb1f1..35daf562 100644 --- a/apps/client/src/features/acadenice/database-view/components/inline-editor.tsx +++ b/apps/client/src/features/acadenice/database-view/components/inline-editor.tsx @@ -53,7 +53,12 @@ export function InlineEditor({ if (!canWrite) { return ( - {formatDisplayValue(initialValue)} + + {formatDisplayValue(initialValue)} + ); } @@ -171,6 +176,7 @@ export function InlineEditor({ onKeyDown={handleKeyDown} className={styles.input} size="xs" + data-testid="inline-editor-input" /> ); } diff --git a/apps/client/src/features/acadenice/database-view/renderers/calendar-renderer.tsx b/apps/client/src/features/acadenice/database-view/renderers/calendar-renderer.tsx index 59e6b861..974e939b 100644 --- a/apps/client/src/features/acadenice/database-view/renderers/calendar-renderer.tsx +++ b/apps/client/src/features/acadenice/database-view/renderers/calendar-renderer.tsx @@ -198,7 +198,7 @@ export function CalendarRenderer({ tableId, viewId, bridgeUrl }: CalendarRendere ]; return ( -
+
+
+
{column.label} @@ -391,7 +399,7 @@ export function KanbanRenderer({ tableId, viewId, bridgeUrl }: KanbanRendererPro onDragStart={handleDragStart} onDragEnd={handleDragEnd} > -
+
{columns.map((col) => ( { if (!isEditing) { onCellDoubleClick(row.id, field.id); @@ -207,7 +208,7 @@ export function TableRenderer({ tableId, viewId, bridgeUrl }: TableRendererProps return (
- +
{fields.map((field) => (