chore(sprint-5/etapa-6): limpieza técnica — E2E Supabase, fix flakiness guardar, docs cierre sprint
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
This commit is contained in:
40
TECH_DEBT.md
40
TECH_DEBT.md
@@ -47,6 +47,16 @@ en los 3 PDFs. Si hay truncamiento, evaluar:
|
||||
|
||||
## Deuda media — afecta DX o evolución del producto
|
||||
|
||||
### [INVESTIGATING] Clave de localStorage del auth E2E vs producción
|
||||
**Estado actual:** contradicción no resuelta entre dos hechos empíricos verificados:
|
||||
- En producción, `ProfileSheet.getAccessToken()` lee `supabase.auth.token` y funciona correctamente (Sprint 5 Etapa 4).
|
||||
- En E2E, `auth-setup.ts` escribe la sesión bajo `sb-${projectRef}-auth-token` y el smoke test "app header shows user avatar" pasa.
|
||||
**Hipótesis:** el cliente Supabase de la app (`src/lib/supabase.ts`) y el de `auth-setup.ts` podrían estar usando `storageKey` distinto. La documentación inline en `auth-setup.ts` explica el comportamiento observado pero no reconcilia la contradicción.
|
||||
**Impacto:** si el auth E2E no funciona realmente (sesión vacía), todos los specs con `storageState` serían inválidos — pasarían por ausencia de assertions fuertes, no porque el auth funcione.
|
||||
**Acción:** en Sprint 6, comparar el `localStorage` real en producción vs el `auth-state.json` del E2E. Ejecutar un spec que haga una query autenticada a Supabase y afirme que devuelve datos reales del usuario de test.
|
||||
**Archivos afectados:** `tests/e2e/setup/auth-setup.ts`, `src/lib/supabase.ts`.
|
||||
**Origen:** Sprint 5 Etapa 6 diagnóstico de auth-setup.
|
||||
|
||||
### [BACKLOG] `getCurrentUser()` en SupabaseAuthService — sin callers activos
|
||||
**Estado actual:** `SupabaseAuthService.getCurrentUser()` usa `getSession()` directamente (sin timeout, sin processLock workaround). Es la única excepción documentada a la regla — justificada porque necesita el objeto sesión completo, no solo una barrera. Sin callers activos hoy.
|
||||
**Impacto si no se resuelve:** ninguno mientras no tenga callers. Si en el futuro algún flujo llama `getCurrentUser()`, podría colgar el processLock si el servidor no responde.
|
||||
@@ -60,17 +70,27 @@ en los 3 PDFs. Si hay truncamiento, evaluar:
|
||||
**Archivos afectados:** `src/components/ProfileSheet.tsx`.
|
||||
**Origen:** Sprint 5 Etapa 4G (fix intermedio que quedó al resolverse la causa raíz en 4H).
|
||||
|
||||
### [BACKLOG] E2E specs con Dexie directo — reescribir para Supabase
|
||||
**Estado actual:** `export-pdf.spec.ts` y `validate-dod-etapa4.spec.ts` inyectan datos vía Dexie/IndexedDB directamente. Dexie fue eliminado en Sprint 4 Etapa 4 — estos specs fallan en cualquier entorno donde no exista la DB local del sprint anterior.
|
||||
**Impacto:** 2 specs permanentemente rojos. No bloquean build ni deploy, pero degradan la señal de la suite E2E.
|
||||
**Solución propuesta:** reescribir los fixtures de datos para insertar vía Supabase (usando el test user `martin.bernal@inquality.com.py` y el `service_role_key` en el setup de Playwright). Limpiar datos de test después de cada corrida.
|
||||
**Costo:** medio. Requiere diseño cuidadoso de fixtures para no interferir con datos de producción.
|
||||
### [RESOLVED] E2E specs con Dexie directo — reescribir para Supabase
|
||||
**Resultado:** `export-pdf.spec.ts` (test "Heatmap con gradiente real") y `validate-dod-etapa4.spec.ts` reescritos para inyectar datos vía `@supabase/supabase-js` con `SUPABASE_SERVICE_ROLE_KEY` (bypasa RLS), en lugar de IndexedDB directo. `afterAll` borra el proceso creado por cada test (cascada en `activities`/`simulations`). Si `SUPABASE_SERVICE_ROLE_KEY` no está configurada en `.env.test`, ambos tests hacen `test.skip()` con mensaje descriptivo en vez de fallar — ver `.env.example`. Diagnóstico previo de `auth-setup.ts` confirmó que la storageKey (`sb-${projectRef}-auth-token`) ya era correcta (no era parte del problema): `@supabase/supabase-js`'s `createClient()` sobrescribe el `STORAGE_KEY` default de `auth-js` con esa clave calculada desde la URL.
|
||||
**Sprint cerrado en:** Sprint 5 Etapa 6.
|
||||
|
||||
### [BACKLOG] E2E flakiness — "Guardar cambios" button timing en ActivityPanel
|
||||
**Estado actual:** 3 specs de PDF fallan intermitentemente porque Playwright no encuentra el botón "Guardar cambios" en estado habilitado. Validación manual confirma que el botón SÍ funciona correctamente — es un issue de timing en el test, no un bug real.
|
||||
**Causa probable:** el test hace click en la actividad y espera el botón sin suficiente guard sobre el estado inicial de `isDirty`.
|
||||
**Solución propuesta:** agregar `await page.waitForSelector('[data-testid="save-btn"]:not([disabled])')` o un `data-testid` explícito que permita espera determinística.
|
||||
**Costo:** bajo. Una línea por spec afectado.
|
||||
### [RESOLVED] E2E flakiness — "Guardar cambios" button timing en ActivityPanel
|
||||
**Resultado:** agregado `data-testid="save-activity-btn"` al botón en `ActivityPanel.tsx`. Specs afectados (`payback-etapa-2.spec.ts`, `export-roi.spec.ts`) reemplazan el click directo por `waitForSelector(':not([disabled])')` → click → `waitForSelector('[disabled]')` (confirma que el guardado se procesó). Confirmado estable en 3 corridas consecutivas sin fallos. `GlobalSettingsPanel.tsx` tiene el mismo patrón `isDirty`/disabled en su botón "Guardar configuración" pero no se tocó — fuera del scope de Etapa 6; queda como ítem nuevo abajo.
|
||||
**Sprint cerrado en:** Sprint 5 Etapa 6.
|
||||
|
||||
### [BACKLOG] GlobalSettingsPanel — mismo patrón de flakiness potencial que ActivityPanel
|
||||
**Estado actual:** `GlobalSettingsPanel.tsx` tiene un botón "Guardar configuración" con el mismo guard `disabled={!isDirty}` que `ActivityPanel.tsx` tenía antes de Etapa 6. La función `configureGlobal()` en `payback-etapa-2.spec.ts` y `export-roi.spec.ts` sigue usando `getByRole('button', { name: /Guardar/i }).click()` sin esperar a que se habilite — el mismo riesgo de flakiness, no confirmado como activo todavía.
|
||||
**Impacto:** potencial, no confirmado. Estos specs pasaron 3/3 en Etapa 6 sin tocar esta función.
|
||||
**Solución propuesta:** agregar `data-testid="save-global-btn"` a `GlobalSettingsPanel.tsx` y aplicar el mismo patrón de `waitForSelector` que se usó para `save-activity-btn`.
|
||||
**Costo:** bajo. Mismo patrón ya validado.
|
||||
**Origen:** Sprint 5 Etapa 6 — detectado durante el diagnóstico, explícitamente fuera del scope del prompt (solo `ActivityPanel.tsx` listado en archivos a modificar).
|
||||
|
||||
### [BACKLOG] 9 specs adicionales con el mismo patrón flaky de "Guardar" sin data-testid
|
||||
**Estado actual:** además de los 2 specs corregidos en Etapa 6, otros 9 archivos (`sprint-1-5-final.spec.ts`, `screenshots-etapa-3.spec.ts`, `etapa-4-pdfs.spec.ts` a `etapa-9-badge.spec.ts`, `etapa-11-polish.spec.ts`) usan el mismo `getByRole('button', { name: /Guardar/i }).click()` sin esperar a `isDirty`. No confirmados como flaky activamente — fuera del scope explícito de Etapa 6 (que listaba solo 2 archivos a modificar).
|
||||
**Impacto:** riesgo de flakiness latente, no confirmado.
|
||||
**Solución propuesta:** aplicar el mismo patrón `waitForSelector('[data-testid="save-activity-btn"]:not([disabled])')` ahora que el testid existe en producción.
|
||||
**Costo:** bajo, mecánico — mismo cambio repetido 9 veces.
|
||||
**Origen:** Sprint 5 Etapa 6 — identificado durante el grep de diagnóstico, no aplicado por respeto al scope explícito del prompt.
|
||||
|
||||
### [INVESTIGATING] Dexie live queries (sincronización store ↔ db)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user