From 9b61f1b371c1b8d0d989e4cee64dcd4301a75686 Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sat, 29 Nov 2025 18:12:33 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 12 + README.md | 3 + commands/api-contract-tester.md | 555 ++++++++++++++++++++++++++++++++ plugin.lock.json | 45 +++ 4 files changed, 615 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 commands/api-contract-tester.md create mode 100644 plugin.lock.json diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..8750dc4 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "api-contract-tester", + "description": "ClaudeForge Enterprise API Contract Testing Architect delivering comprehensive consumer-driven contract testing methodologies, schema validation excellence, and microservice integration verification that transforms API reliability from manual testing into intelligent automation and compatibility assurance", + "version": "1.0.0", + "author": { + "name": "ClaudeForge Community", + "url": "https://github.com/claudeforge/marketplace" + }, + "commands": [ + "./commands" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f49b221 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# api-contract-tester + +ClaudeForge Enterprise API Contract Testing Architect delivering comprehensive consumer-driven contract testing methodologies, schema validation excellence, and microservice integration verification that transforms API reliability from manual testing into intelligent automation and compatibility assurance diff --git a/commands/api-contract-tester.md b/commands/api-contract-tester.md new file mode 100644 index 0000000..e253872 --- /dev/null +++ b/commands/api-contract-tester.md @@ -0,0 +1,555 @@ +--- +allowed-tools: Bash, Read, Write, Edit, Grep, Glob +description: ClaudeForge API contract testing and validation with Pact, Postman, and consumer-driven contract strategies. +--- + +# ClaudeForge API Contract Tester + +ClaudeForge intelligent API contract testing system that ensures API compatibility, validates contracts between consumers and providers, and maintains backward compatibility through comprehensive consumer-driven contract testing strategies. + +## Purpose + +Transform API testing from manual validation to intelligent automation that ensures contract compliance, prevents breaking changes, and maintains seamless integration between microservices and external consumers. + +## Features + +- **Contract Testing**: Consumer-driven contract testing with Pact and other frameworks +- **Schema Validation**: JSON Schema, OpenAPI, and GraphQL schema validation +- **API Testing**: Automated REST and GraphQL API testing with comprehensive coverage +- **Backward Compatibility**: Detect breaking changes before deployment +- **Mock Services**: Generate mock servers from contracts for parallel development +- **Contract Publishing**: Centralized contract registry with versioning +- **CI/CD Integration**: Seamless integration with continuous deployment pipelines +- **Detailed Reporting**: Comprehensive test reports with failure analysis + +## Usage + +```bash +/api-contract-tester [type] [options] +``` + +Target: $ARGUMENTS (if specified, otherwise analyze current scope) + +### Contract Testing Types + +**Pact Consumer Testing:** +```bash +/api-contract-tester pact-consumer --service=UserService --provider=AuthAPI +``` +Generates consumer-side Pact tests with: +- Consumer expectations definition +- Request/response matching rules +- State management for test scenarios +- Pact file generation for provider verification +- Mock provider server for isolated testing +- Flexible matching (type, regex, equality) +- Header and query parameter validation +- JSON body structure verification + +**Pact Provider Testing:** +```bash +/api-contract-tester pact-provider --service=AuthAPI --contracts=./pacts +``` +Verifies provider against consumer contracts with: +- Contract verification against running service +- State setup for provider verification +- Provider state callbacks implementation +- Detailed verification reports +- Breaking change detection +- Version compatibility checking +- Pact broker integration +- Automated verification in CI/CD + +**Postman Collection Testing:** +```bash +/api-contract-tester postman --collection=./api-tests.json --environment=staging +``` +Executes Postman collection tests including: +- Environment variable management +- Pre-request scripts execution +- Response assertions and validation +- Test script execution +- Collection runner automation +- Data-driven testing with CSV/JSON +- Authentication flows (OAuth, JWT, API Key) +- Chained requests with variable passing + +### Schema Validation + +**OpenAPI Validation:** +```bash +/api-contract-tester openapi --spec=./openapi.yaml --endpoint=/api/users +``` +Validates API against OpenAPI specification: +- Request validation (path, query, body, headers) +- Response validation (status, headers, body) +- Schema compliance checking +- Required field validation +- Data type enforcement +- Format validation (email, uri, date-time) +- Enum value verification +- Range and length constraints + +**JSON Schema Validation:** +```bash +/api-contract-tester json-schema --schema=./user.schema.json --data=./response.json +``` +Performs JSON Schema validation with: +- Schema draft version support (draft-07, 2019-09, 2020-12) +- Type validation (string, number, object, array) +- Required properties enforcement +- Additional properties control +- Pattern matching with regex +- Format validators (email, hostname, ipv4, uuid) +- Nested schema validation +- Conditional schema application + +**GraphQL Schema Validation:** +```bash +/api-contract-tester graphql --schema=./schema.graphql --query=./queries/*.graphql +``` +Validates GraphQL queries and mutations: +- Query syntax validation +- Schema type checking +- Field existence verification +- Argument type validation +- Fragment usage validation +- Directive usage verification +- Deprecated field detection +- Query complexity analysis + +### Consumer-Driven Contract Testing + +**Contract Definition:** +```bash +/api-contract-tester define-contract --consumer=WebApp --provider=OrderAPI +``` +Creates contract definitions with: +- Consumer expectations specification +- Request format definition (method, path, headers, body) +- Response expectations (status, headers, body) +- State preconditions for scenarios +- Matching rules for flexible validation +- Example values for documentation +- Contract versioning strategy +- Change log documentation + +**Contract Verification:** +```bash +/api-contract-tester verify-contract --provider=OrderAPI --version=1.2.0 +``` +Verifies provider against contracts including: +- All consumer contract verification +- State setup for test scenarios +- Concurrent verification execution +- Detailed mismatch reporting +- Version compatibility matrix +- Breaking change alerts +- Regression detection +- Performance benchmarking + +**Contract Publishing:** +```bash +/api-contract-tester publish --broker=https://pact-broker.example.com --version=1.2.0 +``` +Publishes contracts to broker with: +- Contract upload to centralized registry +- Version tagging and labeling +- Branch-specific contracts +- Environment deployment tracking +- Contract diffing and comparison +- Consumer notification on changes +- Webhook triggers for CI/CD +- Access control and authentication + +### Integration Testing + +**REST API Testing:** +```bash +/api-contract-tester rest --baseUrl=https://api.example.com --tests=./tests/*.spec.js +``` +Executes REST API tests with: +- HTTP method testing (GET, POST, PUT, DELETE, PATCH) +- Status code assertions +- Response time validation +- Header validation +- Cookie handling and assertion +- Authentication and authorization +- Rate limiting verification +- Error handling validation +- Retry and timeout configuration + +**GraphQL API Testing:** +```bash +/api-contract-tester graphql --endpoint=https://api.example.com/graphql +``` +Tests GraphQL endpoints including: +- Query execution and validation +- Mutation testing with side effects +- Subscription testing for real-time updates +- Error handling and error codes +- Partial response handling +- Batch query execution +- Query performance monitoring +- Cache behavior verification + +**Microservice Integration:** +```bash +/api-contract-tester integration --services=./docker-compose.yml +``` +Performs integration testing with: +- Multi-service orchestration +- Service dependency management +- Contract verification across services +- End-to-end workflow testing +- Message queue testing +- Event-driven architecture validation +- Service discovery verification +- Circuit breaker testing + +## Code Generation Examples + +### Pact Consumer Test (JavaScript) +```javascript +const { Pact } = require('@pact-foundation/pact'); +const { like, eachLike, term } = require('@pact-foundation/pact').Matchers; +const path = require('path'); + +describe('User Service Consumer', () => { + const provider = new Pact({ + consumer: 'WebApp', + provider: 'UserService', + port: 8080, + log: path.resolve(process.cwd(), 'logs', 'pact.log'), + dir: path.resolve(process.cwd(), 'pacts'), + logLevel: 'INFO' + }); + + beforeAll(() => provider.setup()); + afterEach(() => provider.verify()); + afterAll(() => provider.finalize()); + + describe('GET /users/:id', () => { + beforeEach(() => { + return provider.addInteraction({ + state: 'user with ID 123 exists', + uponReceiving: 'a request for user 123', + withRequest: { + method: 'GET', + path: '/users/123', + headers: { + 'Accept': 'application/json', + 'Authorization': term({ + matcher: 'Bearer \\w+', + generate: 'Bearer token123' + }) + } + }, + willRespondWith: { + status: 200, + headers: { + 'Content-Type': 'application/json' + }, + body: { + id: like(123), + username: like('john_doe'), + email: term({ + matcher: '\\S+@\\S+\\.\\S+', + generate: 'john@example.com' + }), + profile: { + firstName: like('John'), + lastName: like('Doe'), + age: like(30) + }, + roles: eachLike('user'), + createdAt: term({ + matcher: '\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}', + generate: '2023-01-15T10:30:00' + }) + } + } + }); + }); + + it('returns user successfully', async () => { + const response = await fetch('http://localhost:8080/users/123', { + headers: { + 'Authorization': 'Bearer token123', + 'Accept': 'application/json' + } + }); + + expect(response.status).toBe(200); + const user = await response.json(); + expect(user.id).toBe(123); + expect(user.email).toMatch(/\S+@\S+\.\S+/); + }); + }); + + describe('POST /users', () => { + beforeEach(() => { + return provider.addInteraction({ + state: 'no existing user with email john@example.com', + uponReceiving: 'a request to create a new user', + withRequest: { + method: 'POST', + path: '/users', + headers: { + 'Content-Type': 'application/json', + 'Authorization': term({ + matcher: 'Bearer \\w+', + generate: 'Bearer token123' + }) + }, + body: { + username: 'john_doe', + email: 'john@example.com', + password: like('securePassword123'), + profile: { + firstName: 'John', + lastName: 'Doe' + } + } + }, + willRespondWith: { + status: 201, + headers: { + 'Content-Type': 'application/json', + 'Location': term({ + matcher: '/users/\\d+', + generate: '/users/123' + }) + }, + body: { + id: like(123), + username: 'john_doe', + email: 'john@example.com', + createdAt: term({ + matcher: '\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}', + generate: '2023-01-15T10:30:00' + }) + } + } + }); + }); + + it('creates user successfully', async () => { + const response = await fetch('http://localhost:8080/users', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer token123' + }, + body: JSON.stringify({ + username: 'john_doe', + email: 'john@example.com', + password: 'securePassword123', + profile: { firstName: 'John', lastName: 'Doe' } + }) + }); + + expect(response.status).toBe(201); + expect(response.headers.get('Location')).toMatch(/\/users\/\d+/); + }); + }); +}); +``` + +### Pact Provider Verification (Node.js) +```javascript +const { Verifier } = require('@pact-foundation/pact'); +const path = require('path'); +const server = require('./server'); + +describe('User Service Provider', () => { + let app; + const PORT = 8081; + + beforeAll(async () => { + app = await server.listen(PORT); + }); + + afterAll(async () => { + await app.close(); + }); + + it('validates expectations of WebApp', () => { + const opts = { + provider: 'UserService', + providerBaseUrl: `http://localhost:${PORT}`, + pactBrokerUrl: 'https://pact-broker.example.com', + pactBrokerToken: process.env.PACT_BROKER_TOKEN, + publishVerificationResult: true, + providerVersion: process.env.GIT_COMMIT, + providerVersionBranch: process.env.GIT_BRANCH, + consumerVersionSelectors: [ + { mainBranch: true }, + { deployedOrReleased: true } + ], + stateHandlers: { + 'user with ID 123 exists': async () => { + // Setup: Create user with ID 123 in test database + await database.users.create({ + id: 123, + username: 'john_doe', + email: 'john@example.com', + profile: { firstName: 'John', lastName: 'Doe', age: 30 }, + roles: ['user'], + createdAt: '2023-01-15T10:30:00' + }); + }, + 'no existing user with email john@example.com': async () => { + // Setup: Ensure no user exists with this email + await database.users.deleteMany({ email: 'john@example.com' }); + } + }, + beforeEach: async () => { + // Clean database before each verification + await database.reset(); + } + }; + + return new Verifier(opts).verifyProvider(); + }); +}); +``` + +### OpenAPI Validation (Python) +```python +from openapi_spec_validator import validate_spec +from openapi_core import create_spec +from openapi_core.validation.request.validators import RequestValidator +from openapi_core.validation.response.validators import ResponseValidator +import yaml +import requests + +class APIContractTester: + def __init__(self, spec_path, base_url): + with open(spec_path, 'r') as f: + self.spec_dict = yaml.safe_load(f) + + # Validate OpenAPI spec is valid + validate_spec(self.spec_dict) + + self.spec = create_spec(self.spec_dict) + self.base_url = base_url + self.request_validator = RequestValidator(self.spec) + self.response_validator = ResponseValidator(self.spec) + + def test_endpoint(self, method, path, headers=None, body=None, expected_status=200): + """Test API endpoint against OpenAPI contract""" + + # Build full URL + url = f"{self.base_url}{path}" + + # Validate request against OpenAPI spec + request = self._build_request(method, path, headers, body) + request_validation = self.request_validator.validate(request) + + if request_validation.errors: + raise ValueError(f"Request validation failed: {request_validation.errors}") + + # Make actual HTTP request + response = requests.request(method, url, headers=headers, json=body) + + # Validate response against OpenAPI spec + openapi_response = self._build_response(response, path, method) + response_validation = self.response_validator.validate(openapi_response) + + if response_validation.errors: + raise ValueError(f"Response validation failed: {response_validation.errors}") + + # Assert expected status code + assert response.status_code == expected_status, \ + f"Expected {expected_status}, got {response.status_code}" + + return response + + def test_all_endpoints(self): + """Test all endpoints defined in OpenAPI spec""" + results = [] + + for path, path_item in self.spec_dict['paths'].items(): + for method, operation in path_item.items(): + if method in ['get', 'post', 'put', 'delete', 'patch']: + try: + print(f"Testing {method.upper()} {path}") + self.test_endpoint(method.upper(), path) + results.append({ + 'path': path, + 'method': method, + 'status': 'PASS' + }) + except Exception as e: + results.append({ + 'path': path, + 'method': method, + 'status': 'FAIL', + 'error': str(e) + }) + + return results + + def validate_breaking_changes(self, old_spec_path): + """Detect breaking changes between API versions""" + with open(old_spec_path, 'r') as f: + old_spec = yaml.safe_load(f) + + breaking_changes = [] + + # Check for removed endpoints + for path in old_spec['paths']: + if path not in self.spec_dict['paths']: + breaking_changes.append(f"Removed endpoint: {path}") + + # Check for removed operations + for path, operations in old_spec['paths'].items(): + if path in self.spec_dict['paths']: + for method in operations: + if method not in self.spec_dict['paths'][path]: + breaking_changes.append(f"Removed operation: {method.upper()} {path}") + + return breaking_changes + +# Usage example +tester = APIContractTester('./openapi.yaml', 'https://api.example.com') +results = tester.test_all_endpoints() + +for result in results: + print(f"{result['method'].upper()} {result['path']}: {result['status']}") +``` + +## Best Practices + +### Contract Testing Strategy +- **Consumer-Driven**: Let consumers define their expectations +- **Version Compatibility**: Test against multiple provider versions +- **State Management**: Define clear provider states for scenarios +- **Matching Flexibility**: Use type matching over exact matching where appropriate +- **Regular Verification**: Run provider verification on every deployment + +### CI/CD Integration +- **Automated Execution**: Run contract tests in CI pipeline +- **Pact Broker**: Use centralized contract registry for collaboration +- **Can-I-Deploy**: Check contract compatibility before deployment +- **Version Tagging**: Tag contracts with deployment environments +- **Webhook Triggers**: Trigger provider verification on consumer changes + +### Schema Validation +- **Comprehensive Coverage**: Validate all request/response combinations +- **Error Scenarios**: Test error responses and edge cases +- **Backward Compatibility**: Detect breaking changes before release +- **Documentation Sync**: Keep schemas synchronized with actual API +- **Version Strategy**: Maintain multiple schema versions for gradual migration + +### Testing Best Practices +- **Isolated Tests**: Each test should be independent +- **Fast Execution**: Keep test execution time minimal +- **Clear Assertions**: Make test failures easy to understand +- **Test Data**: Use realistic test data that covers edge cases +- **Mocking Strategy**: Mock external dependencies appropriately + +--- + +**ClaudeForge API Contract Tester** - Enterprise-grade API contract testing with consumer-driven strategies, comprehensive validation, and seamless CI/CD integration for reliable microservice architectures. diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..df16361 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,45 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:claudeforge/marketplace:plugins/commands/api-contract-tester", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "b2e73342b2d6cfd12ff5fbf657d22b27cfb04dd4", + "treeHash": "8322dcd2bfa544f5d865294f153ead343b57b605f4867b71060e98955a697f59", + "generatedAt": "2025-11-28T10:15:25.292863Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "api-contract-tester", + "description": "ClaudeForge Enterprise API Contract Testing Architect delivering comprehensive consumer-driven contract testing methodologies, schema validation excellence, and microservice integration verification that transforms API reliability from manual testing into intelligent automation and compatibility assurance", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "6751f64b1cc1211827de825b9c2aab1b9f49fac7bc92385353b3c3b1ee7f7aad" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "ffa4002b9392a3379d20e13f571e4a127d768af9892284229f9b7637b46e8b2f" + }, + { + "path": "commands/api-contract-tester.md", + "sha256": "e3b2a5228ccfee30272e515c258b91ce4bfa1b21e01f82f7fd7d8ba29b0b80fc" + } + ], + "dirSha256": "8322dcd2bfa544f5d865294f153ead343b57b605f4867b71060e98955a697f59" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file