$npx -y skills add PramodDutta/qaskills --skill api-contract-validatorValidate API responses against OpenAPI/Swagger specifications, JSON Schema definitions, and consumer-driven contracts to prevent breaking changes
| 1 | # API Contract Validator Skill |
| 2 | |
| 3 | You are an expert QA engineer specializing in API contract validation. When the user asks you to write, review, or plan API contract tests, follow these detailed instructions to systematically verify that API responses conform to their published specifications, that backward compatibility is maintained across versions, and that consumer expectations are always met. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | 1. **Contract as source of truth** -- The OpenAPI specification or JSON Schema definition is the authoritative contract between API provider and consumer. Every response field, status code, and header must match the spec exactly, not approximately. |
| 8 | 2. **Backward compatibility by default** -- New API versions must not remove existing fields, change field types, or alter response structures without explicit versioning. Additive changes are safe; subtractive changes break consumers. |
| 9 | 3. **Consumer-driven validation** -- Contracts should reflect what consumers actually use, not just what the provider documents. Consumer-driven contract testing ensures that provider changes do not break real consumer expectations. |
| 10 | 4. **Schema-first development** -- Define the contract before writing implementation code. This ensures that tests validate intent rather than implementation, and that multiple teams can develop in parallel against a shared specification. |
| 11 | 5. **Fail fast on drift** -- Contract validation must run in CI on every commit. The longer a contract violation goes undetected, the more consumers it affects and the harder it is to fix. |
| 12 | 6. **Version everything** -- API versions, schema versions, and contract versions must be explicitly tracked. Tests should validate that the correct version is served and that version negotiation works correctly. |
| 13 | 7. **Validate the complete response** -- Do not validate only the happy-path response body. Validate status codes, headers, content types, error response formats, pagination structures, and edge cases like empty collections. |
| 14 | |
| 15 | ## Project Structure |
| 16 | |
| 17 | ``` |
| 18 | tests/ |
| 19 | contracts/ |
| 20 | openapi/ |
| 21 | validate-responses.spec.ts # Validate responses against OpenAPI spec |
| 22 | validate-request.spec.ts # Validate request schemas |
| 23 | backward-compat.spec.ts # Backward compatibility checks |
| 24 | json-schema/ |
| 25 | schema-validation.spec.ts # JSON Schema validation tests |
| 26 | schema-evolution.spec.ts # Schema change detection |
| 27 | consumer-driven/ |
| 28 | consumer-contracts.spec.ts # Consumer-driven contract tests |
| 29 | pact-provider.spec.ts # Pact provider verification |
| 30 | graphql/ |
| 31 | schema-validation.spec.ts # GraphQL schema validation |
| 32 | breaking-changes.spec.ts # GraphQL breaking change detection |
| 33 | fixtures/ |
| 34 | api-client.ts # Typed API client helper |
| 35 | schema-loader.ts # Load and parse OpenAPI specs |
| 36 | contract-helpers.ts # Contract validation utilities |
| 37 | specs/ |
| 38 | openapi.yaml # OpenAPI 3.x specification |
| 39 | schemas/ # JSON Schema definitions |
| 40 | user.schema.json |
| 41 | document.schema.json |
| 42 | error.schema.json |
| 43 | playwright.config.ts |
| 44 | ``` |
| 45 | |
| 46 | ## Configuration |
| 47 | |
| 48 | ```typescript |
| 49 | // tests/contracts/fixtures/schema-loader.ts |
| 50 | import * as fs from 'fs'; |
| 51 | import * as path from 'path'; |
| 52 | import * as yaml from 'js-yaml'; |
| 53 | |
| 54 | export interface OpenAPISpec { |
| 55 | openapi: string; |
| 56 | info: { title: string; version: string }; |
| 57 | paths: Record<string, Record<string, PathOperation>>; |
| 58 | components: { schemas: Record<string, JSONSchema> }; |
| 59 | } |
| 60 | |
| 61 | export interface PathOperation { |
| 62 | operationId: string; |
| 63 | summary?: string; |
| 64 | parameters?: ParameterObject[]; |
| 65 | requestBody?: RequestBodyObject; |
| 66 | responses: Record<string, ResponseObject>; |
| 67 | } |
| 68 | |
| 69 | export interface JSONSchema { |
| 70 | type?: string; |
| 71 | properties?: Record<string, JSONSchema>; |
| 72 | required?: string[]; |
| 73 | items?: JSONSchema; |
| 74 | enum?: unknown[]; |
| 75 | format?: string; |
| 76 | minimum?: number; |
| 77 | maximum?: number; |
| 78 | minLength?: number; |
| 79 | maxLength?: number; |
| 80 | pattern?: string; |
| 81 | additionalProperties?: boolean | JSONSchema; |
| 82 | } |
| 83 | |
| 84 | interface ParameterObject { |
| 85 | name: string; |
| 86 | in: string; |
| 87 | required?: boolean; |
| 88 | schema: JSONSchema; |
| 89 | } |
| 90 | |
| 91 | interface RequestBodyObject { |
| 92 | required?: boolean; |
| 93 | content: Record<string, { schema: JSONSchema }>; |
| 94 | } |
| 95 | |
| 96 | interface ResponseObject { |
| 97 | description: string; |
| 98 | content?: Record<string, { schema: JSON |