¿Qué hace Pruebas de Contrato GraphQL?
Descripción general
Pruebas que se sitúan en la costura entre capas y se rompen cuando un lado se mueve sin el consentimiento del otro — tests-as-a-control aplicado a los límites. La regla cardinal: afirmar sobre el contrato — la forma de los datos y las semánticas de acceso que el consumidor depende — nunca sobre la cadena de consulta en sí misma. Una prueba que se rompe por una edición cosmética de consulta es un antipatrón de detector de cambios; una prueba que se rompe cuando la forma garantizada o el permiso se mueve es un control.
§1 — El Contrato de Consulta GraphQL
- Cada operación se escribe una vez como un documento con tipo en una ubicación conocida, exportada para ser importada. La interfaz de usuario la importa; la prueba importa el mismo artefacto — nunca una copia reescrita. Copiar una consulta en una prueba mata silenciosamente el contrato (editar la consulta de la UI ya no rompe la prueba). DRY se vuelve crítico.
- Se rompe en ambas direcciones, por construcción:
- Deriva DB → UI, en tiempo de compilación.
graphql-codegengenera tipos TypeScript a partir del esquema en vivo. Renombrar o eliminar un campo usado ytscfalla en cada uso y en el documento compartido — la compilación se rompe antes de que un usuario vea un panel en blanco. Esta es la razón por la que el codegen contra el esquema en vivo es obligatorio. - Deriva UI → DB / permisos, en tiempo de ejecución. El documento compartido se ejecuta contra una base de datos de prueba sembrada a través de la ruta de llamada real, bajo contexto de rol, afirmando sobre la forma devuelta y el resultado del acceso — no el texto de la consulta.
- Deriva DB → UI, en tiempo de compilación.
- Las pruebas de contrato y la matriz de roles RLS son el mismo arnés. Ejecute el mismo documento a través de PostGraphile como rol A (espere datos) y rol B (espere denegado/vacío). Un mecanismo prueba tres cosas: la consulta aún coincide con el esquema, las suposiciones de la UI aún se mantienen, RLS aún aplica el límite.
Ejemplo práctico — cómo se detecta un error real
- DB→UI: una migración elimina
equipment.is_active. Codegen regenera desde el nuevo esquema; el tipo generado pierde el campo;tscfalla en el documento compartido y en cada componente que lo usa — detectado en la compilación, antes del merge. Ninguna prueba afirma "texto de consulta == X". - UI→DB: un desarrollador amplía la consulta de la UI para obtener
cancellation_reason(RLS lo expone solo a roles elevados). La prueba de tiempo de ejecución que se ejecuta como un miembro común afirma la forma visible para el miembro, ahora recibe null/denegado, y falla — forzando "¿queríamos exponer esto?"
§2 — Pruebas de Contrato de Rutas y Pruebas de Humo
- Rutas enumeradas desde una sola fuente. Cada ruta tiene una prueba de humo: se renderiza sin error + muestra un conjunto mínimo de elementos requeridos (un encabezado, un punto de referencia, un control clave — no interacción detallada).
- Agregar/eliminar una ruta fuerza un cambio de prueba correspondiente — una nueva URL está incompleta sin su prueba de humo; una URL eliminada elimina su prueba. Las URLs nunca aparecen o desaparecen silenciosamente.
- Explícitamente NO es pruebas detalladas de UI/interacción — deliberado, de alcance limitado. La pregunta es "¿esta URL funciona y renderiza lo esencial?", nada más.
Aplicación: graphql-codegen + tsc en CI (bloqueante) para la parte de tiempo de compilación; pruebas de contrato de tiempo de ejecución + pruebas de humo de rutas en CI contra una base de datos sembrada.
Justificación completa: Artículo XV de la constitución, empaquetado en engineering-constitution/references/engineering-constitution.md.