Communitygithub.com

lguidolin/graphql-contract-testing

用于撰写UI和测试共享的GraphQL查询/变更,或构建路由/模式契约及冒烟测试。症状包括:将查询复制到测试中、测试断言查询文本、模式变更未破坏UI构建、或RLS/权限漂移。关键词:graphql-codegen、类型文档、契约测试、路由冒烟测试。

graphql-contract-testing 是什么?

该技能旨在通过契约测试在GraphQL的边界层建立控制机制。核心原则是断言数据形状和访问语义,而非查询字符串本身。它要求每个操作作为类型文档在已知位置定义一次,并导出供UI和测试共同导入,从而避免复制导致的契约失效。支持在编译时通过 graphql-codegen 和 tsc 检测数据库到UI的漂移,在运行时通过种子数据库和真实调用路径检测UI到数据库的权限漂移。此外,还包含路由契约和冒烟测试,确保每个路由都能渲染出基本元素集,且路由的增删必须对应测试变更。该技能适用于Claude Code、Cursor等AI代理及CI流水线,帮助开发者建立可靠的GraphQL边界防护。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lguidolin/agent-skills/tree/main/skills/graphql-contract-testing

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

GraphQL 契约测试

概述

测试位于层与层之间的接缝上,当一侧移动而另一方未同意时就会失败——这是应用于边界的测试即控制(tests-as-a-control)。核心规则:对契约——消费者依赖的数据形状和访问语义——进行断言,绝不要针对查询字符串本身。 因格式化的查询编辑而失败的测试是一种变更检测反模式;因保证的形状或权限变动而失败的测试才是一种控制。

§1 — GraphQL 查询契约

  • 每个操作仅作为类型文档在已知位置定义一次,导出以供导入。 UI 导入它;测试导入完全相同的制品——绝不复写或重新输入。将查询复制到测试中会悄然杀死契约(编辑 UI 查询不再破坏测试)。DRY 原则承担起了责任。
  • 它通过构造在双向中起作用:
    • 数据库 → UI 漂移,在编译时。 graphql-codegen 根据实时模式生成 TypeScript 类型。重命名或删除一个已使用的字段,tsc 会在每个使用点和共享文档上失败——在用户看到空白面板之前构建就失败了。这就是为什么强制要求针对实时模式进行 codegen。
    • UI → 数据库 / 权限漂移,在运行时。 共享文档通过真实的调用路径,在角色上下文中对种子测试数据库运行,并对返回的形状和访问结果进行断言——而不是查询文本。
  • 契约测试和 RLS 角色矩阵是同一个测试框架。 将同一份文档通过 PostGraphile 以角色 A(期望数据)和角色 B(期望被拒绝/空数据)运行。一个机制证明三件事:查询仍然匹配模式,UI 假设仍然成立,RLS 仍然强制执行边界。

实际例子——真实 bug 如何被捕获

  • 数据库→UI: 一次迁移移除了 equipment.is_active。Codegen 根据新模式重新生成;生成的类型失去该字段;tsc 在共享文档和每个使用该字段的组件上失败——在构建时、合并前就被捕获。 没有测试断言“查询文本 == X”。
  • UI→数据库: 一名开发者拓宽了 UI 查询以拉取 cancellation_reason(RLS 仅向高级角色暴露它)。以普通成员身份运行的运行时测试断言普通成员可见的形状,现在得到了 null/被拒绝,并失败——强制要求回答“我们是否打算暴露这个?”

§2 — 路由契约和冒烟测试

  • 路由从单一来源枚举。 每个路由都有一个冒烟测试:无错误渲染 + 显示最小必需元素集(一个标题、一个地标、一个关键控件——不是详细的交互)。
  • 添加/删除路由会强制匹配的测试变更 — 新 URL 缺少冒烟测试就不完整;删除的 URL 会删除其测试。URL 从不悄然出现或消失。
  • 明确不进行详细的 UI/交互测试 — 有意的,范围受限。问题是“这个 URL 能否工作并渲染核心内容”,别无他求。

强制执行: CI 中的 graphql-codegen + tsc(阻塞)用于编译时部分;CI 中针对种子数据库的运行时契约 + 路由冒烟测试用于运行时部分。

完整原理说明:宪法第十五条,打包在 engineering-constitution/references/engineering-constitution.md 中。

Individual skills in this repo

This repo contains 18 individual skills — each has its own dedicated page.

lguidolin/change-hygiene-and-code-craft

Use when writing or refactoring code, structuring a commit or PR, or deciding whether to abstract duplication. Symptoms — mixing reorg with logic changes, a PR doing several things at once, a file growing large, the second copy of similar code, or unsure whether to DRY something up.

lguidolin/cloud-delivery-aks

Use when deploying to Kubernetes or Azure Kubernetes Service (AKS), configuring cloud secrets, setting up progressive rollout/canary, per-PR ephemeral environments, or k8s health probes. Keywords — Kubernetes, AKS, Key Vault, Argo Rollouts, Flagger, canary, blue-green, liveness, readiness, PodDisruptionBudget, HPA, rollback, GHCR.

lguidolin/commit-history-rewrite

Use when an existing repository has messy commit history that needs to conform to conventional commits before adopting release-please, or when intermediate WIP/fixup/merge commits need to be cleaned up.

lguidolin/conventional-commits-and-releases

Use when committing, writing a commit message, opening a PR that will be squash-merged, or configuring automated versioning/changelogs. Keywords — conventional commits, release-please, semver, feat/fix/chore, breaking change, changelog.

lguidolin/defense-in-depth-security

Use when handling untrusted input, secrets, authentication/authorization, or dependencies — or threat-modeling a new surface. Keywords — STRIDE, threat model, least privilege, secrets management, supply chain, dependency scanning, input validation, audit log, defense in depth.

lguidolin/designing-before-building

Use when starting a feature, fixing a non-trivial bug, or about to write implementation code — before any code exists. Symptoms you need this: "this is simple, I'll just code it", reaching for the editor before a design is approved, or an idea that hasn't been turned into a spec and plan.

lguidolin/engineering-constitution

Use when starting work in a project that follows the engineering constitution, orienting to its rules, or deciding which engineering practice applies to a task — spec writing, commits, testing, security, deploys, database, or UI work.

lguidolin/init-repo-CI

Use when setting up a new repository with conventional commits, release-please, and CI automation, or when retrofitting an existing repository that lacks automated versioning and PR validation workflows.

lguidolin/interface-craft-and-accessibility

Use when building or styling UI — components, layouts, forms, design tokens — or making accessibility decisions. Keywords — a11y, WCAG, keyboard navigation, focus state, contrast, design system, minimalist UI, component reuse, ARIA, semantic HTML.

lguidolin/merge-gates-and-automation

Use when setting up or changing CI, pre-push hooks, or a task runner, or deciding what must pass before merge. Symptoms — tempted to put authoritative checks only in a local hook, skip CI, bypass with --no-verify, or unsure what gates a merge vs. runs locally.

lguidolin/observability-and-slos

Use when adding logging, metrics, tracing, health checks, SLOs, or alerting — or when building a service surface that needs to be operable and debuggable. Keywords — structured logs, OpenTelemetry, correlation id, RED metrics, liveness, readiness, SLI, SLO, error budget, alerting.

lguidolin/performance-and-scale

Use when working on hot paths, list endpoints, pagination, data-access in loops, or public interfaces/schemas. Symptoms — unbounded queries, N+1 access, no latency budget, optimizing without measuring, or changing an interface many consumers depend on. Keywords — pagination, N+1, Hyrum's Law, performance budget, bundle size.

lguidolin/postgres-postgraphile-rls-and-sql

Use when writing PostgreSQL, PostGraphile config, Row-Level Security policies, SQL schema files, or working on the Browser→App→PostGraphile→Postgres data path. Keywords — RLS, SECURITY DEFINER, search_path, pgSettings, grants, roles, GraphQL depth limit, query cost, statement_timeout, SQL file organization.

lguidolin/recording-decisions

Use when a design or architecture decision has been made and needs to be captured — writing a decision record or ADR, updating a decision index, noting a deferred idea, or superseding a past decision. Keywords — ADR, decision record, rationale, rejected alternatives, dependency index.

lguidolin/resilience-and-deploy-safety

Use when planning a deploy, designing a rollback, or responding to an incident or writing a postmortem. Keywords — deploy safety, rollback, immutable artifact, progressive delivery, canary, blast radius, incident response, blameless postmortem, error budget.

lguidolin/ship-it

Use when the user wants to ship work — push, PR, archive decision records, merge, and clean up. Handles the full lifecycle from committing final changes through post-merge cleanup including converting specs/plans to compact decision records.

lguidolin/tests-as-a-control

Use when writing or modifying tests, when a test breaks during a refactor, or when testing permission/role rules. Symptoms — tempted to edit a test to make it pass, testing only the happy path, a deny-test that started passing, flaky tests, or unsure what to assert.

lguidolin/zero-downtime-migrations

Use when changing a database schema where data must survive the change — adding/removing/renaming columns, constraints, indexes, or backfilling. Symptoms — a destructive migration bundled with a code deploy, a NOT NULL column with a backfill, a table-locking UPDATE, or a rename. Keywords — expand/contract, parallel change, backfill, NOT VALID, CREATE INDEX CONCURRENTLY, graphile-migrate.

相关技能