Communitygithub.com

lguidolin/graphql-contract-testing

用於撰寫 UI 與測試會共用的 GraphQL 查詢/變更,或建立路由/結構合約與煙霧測試。症狀:將查詢複製到測試中、測試斷言查詢文字、結構變更未破壞 UI 建置、或 RLS/權限偏移。關鍵字:graphql-codegen、typed document、合約測試、路由煙霧測試。

graphql-contract-testing 是什麼?

此技能專注於 GraphQL 合約測試,透過在層級之間設立「控制」型的測試,確保任何一方在未經另一方同意的情況下變更時,測試會立即失敗。其核心原則是針對合約(消費者依賴的資料形狀與存取語意)進行斷言,而非針對查詢字串本身。這能避免因無關緊要的查詢編輯而誤判,僅在保證的形狀或權限變動時才觸發失敗。 技能支援 GraphQL 查詢合約與路由合約兩大類別。查詢合約要求每個操作以類型化文件形式存在於已知位置,並由 UI 與測試共同匯入,避免複製貼上。透過 `graphql-codegen` 從即時 schema 產生 TypeScript 型別,讓資料庫到 UI 的偏移在建置階段就被捕捉;同時,透過在測試資料庫中執行實際呼叫路徑,並基於角色權限斷言回傳形狀與存取結果,捕捉 UI 到資料庫的權限偏移。路由煙霧測試則要求每個路由都有一個對應的測試,確保其可渲染且包含必要元素。 此技能適用於任何使用 GraphQL 的前端專案,特別是需要精確控制 API 與 UI 之間合約的團隊。它能在 CI 流程中同時涵蓋編譯時期與執行時期的驗證,有效預防因 schema 變更或權限調整導致的 UI 錯誤。

相容平台~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 從即時 schema 產生 TypeScript 型別。重新命名或刪除一個被使用的欄位,tsc 會在每個使用點以及共享文件上失敗——在使用者看到空白面板之前,建置就會中斷。這就是為什麼必須針對即時 schema 進行程式碼生成。
    • UI → 資料庫 / 權限偏移,在執行時期。 共享文件透過實際呼叫路徑,在角色上下文中對已注入資料的測試資料庫執行,並針對回傳的形狀與存取結果進行斷言——而非查詢文字。
  • 合約測試與 RLS 角色矩陣是同一套架構。 將同一份文件以角色 A(預期取得資料)和角色 B(預期被拒絕/為空)身分透過 PostGraphile 執行。一個機制驗證三件事:查詢仍符合 schema、UI 假設仍成立、RLS 仍強制執行邊界。

實際範例——真實 bug 如何被捕捉

  • 資料庫→UI: 一次遷移移除了 equipment.is_active。Codegen 從新 schema 重新生成;生成的型別失去該欄位;tsc 在共享文件和所有使用它的元件上失敗——在建置階段、合併前就被捕捉。 沒有測試斷言「查詢文字 == X」。
  • UI→資料庫: 開發者擴展了 UI 查詢以拉取 cancellation_reason(RLS 僅向較高等級角色暴露該欄位)。以普通成員身分執行的執行時期測試斷言了成員可見的形狀,現在得到 null/被拒絕,並失敗——強迫思考「我們有意暴露這個嗎?」

§2 — 路由合約與煙霧測試

  • 從單一來源列舉路由。 每個路由都有一個煙霧測試:渲染無錯誤 + 顯示一個最小必要元素集合(一個標題、一個地標、一個關鍵控制項——而非詳細互動)。
  • 新增/移除路由會強制對應的測試變更——沒有煙霧測試的新 URL 是不完整的;已移除的 URL 會移除其測試。URL 絕不會沉默地出現或消失。
  • 明確來說不是詳細的 UI/互動測試——有意識地、範圍有限。問題是「這個 URL 是否能夠運作並渲染基本要素」,僅此而已。

強制執行: CI 中使用 graphql-codegen + tsc(阻斷式)處理編譯時期部分;CI 中針對注入資料的資料庫執行執行時期合約與路由煙霧測試。

完整原理說明:組織章程第 XV 條,收錄於 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.

相關技能