feat: [TESIS-107] read the integrations listing out of the envelope - #50
Conversation
The backend settles the response convention in ADR-015: a collection travels wrapped in `data`, a single resource travels bare. `GET /integrations` was the one listing answering a bare array, and it now wraps like the rest. The hook carried a comment explaining that this endpoint was the exception. That comment was the symptom the card is about — if the rule existed, nobody would need to be reminded per endpoint. It is gone, and so are the two other notes describing the inconsistency in the inventory and orders frontiers, replaced by the rule itself. Three examples cover the hook, which had none. One of them fails if anyone reads the response as a bare array again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012xAtddb53LRNVLuyTXyELp
Sanntinat
left a comment
There was a problem hiding this comment.
Revisión — TESIS-107 front (PR #50) · El listado de integraciones sale del envelope
Revisión contra origin/master de proyecto-web, sobre TESIS-107-response-envelope (dc40af4), con la card TESIS-107 y su lado del backend (proyecto-api#86, revisado aparte) al lado.
| Check | Resultado |
|---|---|
npm run test (local, sobre la rama) |
54 archivos · 455 tests · 0 failures (3 nuevos) |
npm run lint · prettier --check . · npm run build (local) |
Limpios |
| CI (GitHub Actions) | Lint & Format · Branch Naming Convention · Unit Tests · Build: success |
Rama vs master |
3 commits atrás (TESIS-117, TESIS-58, TESIS-61). El merge es limpio: 59 archivos · 538 tests · 0 failures |
| Conflictos con los demás PRs abiertos | Ninguno |
✅ El cambio es el que corresponde, y el único que hacía falta
useIntegrationsleedata.dataconApiResponse<IntegrationNode[]>, igual que el resto de los hooks de la feature. Es el único consumidor de/integrations: lo busqué en todosrc/, y el resto de las apariciones son la ruta de la pantalla y su test de navegación, que no tocan la respuesta.- Los tres comentarios-trampa se reemplazan por la regla. El de
inventory/api.tsconserva lo que sí es propio del recurso (indexno traestocks), que es un dato del endpoint y no una inconsistencia. Es la lectura correcta del criterio de la card. - El contrato cierra de los dos lados:
api#86lo fija enintegrations_spec.rbyapi_contract_spec.rb(keys == ['data']), y este PR enuseIntegrations.test.tsx.
✅ El test nuevo tiene dientes
Hice que el hook devolviera la respuesta cruda (return data) y falló reads the listing out of the data envelope, solo. Los otros dos siguen verdes, y está bien que así sea: prueban la URL y que un error no se disfrace de lista vacía.
🟡 Menores
- Una falla local que no es de este PR: en la primera corrida me falló por timeout
ProductDetailPage.test.tsx › opens the edit form when it is reached with the intent of editing(5159 ms contra un límite de 5000). Estaba corriendo la suite de la API en paralelo. Aislado pasa, y sin carga la suite entera pasa dos veces seguidas. Este PR no toca esa pantalla, pero es un test que, con la máquina cargada, queda al borde del timeout. - Evidencia: la tabla todavía dice «(adjuntar captura del panel con la tarjeta de Integraciones)».
- Con #87 (TESIS-108) encima,
/integrationssumametay pasa a paginar de a 100. No cambia nada acá: el hook leedatay el panel no pagina.
⚠️ Orden de merge (bien anunciado)
Es un cambio que rompe: con este PR y sin api#86, el hook lee data.data de un array y el panel queda sin integraciones. api#86 primero y éste inmediatamente después, como dice la descripción. Como pedí cambios en api#86, este PR espera a que ese se resuelva, aunque por sí mismo está listo.
Los criterios de la card (lado front)
- El frontend consume la forma nueva.
- No quedan comentarios describiendo inconsistencias. Los tres se reemplazaron por la regla.
- Hay un test que falla si alguien rompe el envelope. Verificado rompiéndolo.
Veredicto
APPROVE.
Chico, preciso y con el test que faltaba: el hook no tenía ninguno. Para mergear, esperar a api#86, y conviene traer master antes (el merge es limpio).
🔗 Link
Es el lado del frontend de la misma card. El backend fija la convención de respuesta y envuelve
GET /integrations, que era el único listado que contestaba un array pelado.El orden es: api#86 primero, éste después. Al revés, el panel se queda sin integraciones el rato que pase entre los dos.
📝 Descripción
Lee el listado de integraciones desde el envelope y borra los comentarios que describían la inconsistencia.
Los comentarios eran el síntoma de la card. Había tres repartidos por la frontera:
hooks/useIntegrations.ts: «acá no hayApiResponse<T>… la respuesta es un array plano y no{ data: [...] }»dashboard/types.ts: «Responde un array plano, sin el envoltorio{ data }deApiResponse»inventory/api.ts: «indexenvuelve en{ data: [...] }, peroshowyupdatedevuelven el objeto pelado»Si la regla existiera, ninguno haría falta. Los tres se reemplazan por la regla misma, que ahora está escrita en el ADR-015 del backend: una colección viaja envuelta, un recurso solo viaja pelado. El de
inventoryconserva lo que sí es propio de ese recurso y no es deducible —queindexusaProductListSerializery no traestocks—, porque eso no es una inconsistencia sino un dato del endpoint.🛠️ Cambios realizados
features/dashboard/hooks/useIntegrations.ts— leedata.dataconApiResponse<IntegrationNode[]>, como el resto de los hooks de la feature.features/dashboard/types.ts,features/inventory/api.ts,features/orders/api.ts— los comentarios-trampa, reemplazados por la regla.useIntegrations.test.tsx, nuevo. El hook no tenía ninguno.🧪 Cómo probarlo (Opcional)
Precondiciones: backend con api#86 mergeado corriendo en
localhost:3000, seeds del tenantnorte, sesión iniciada./dashboard. La tarjeta Integraciones lista los nodos igual que antes, con su estado de sincronización.integrationsencendido,/integrationsmuestra la sección completa.GET /integrationsresponde{ "data": [ ... ] }y la pantalla lo consume sin tocar nada más.📸 Evidencia (Opcional)
¿Afecta la arquitectura o genera un nuevo patrón?
No para el frontend: al contrario, elimina la excepción. Ahora los cuatro
api.tsconsumen la misma regla y ningún hook necesita explicar la suya.Verificación:
npm run lint,prettier --check .,npm run buildynpm run test(455 tests, 0 fallas; eran 452).Los tests tienen dientes: cambié el hook para que devolviera la respuesta cruda y el ejemplo del envelope se puso en rojo.
🤖 Generated with Claude Code
https://claude.ai/code/session_012xAtddb53LRNVLuyTXyELp