@intentsolutionsio/api-test-automation 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "api-test-automation",
3
+ "version": "1.0.0",
4
+ "description": "Automated API endpoint testing with request generation, validation, and comprehensive test coverage",
5
+ "author": {
6
+ "name": "Claude Code Plugins",
7
+ "email": "[email protected]"
8
+ },
9
+ "repository": "https://github.com/jeremylongshore/claude-code-plugins",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "testing",
13
+ "api",
14
+ "rest",
15
+ "graphql",
16
+ "automation",
17
+ "endpoints",
18
+ "agent-skills"
19
+ ]
20
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Claude Code Plugins
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,298 @@
1
+ # API Test Automation Plugin
2
+
3
+ Automated API endpoint testing with intelligent test generation, validation, and comprehensive coverage for REST and GraphQL APIs.
4
+
5
+ ## Features
6
+
7
+ - **REST API testing** - Complete CRUD operation coverage
8
+ - **GraphQL testing** - Queries, mutations, subscriptions
9
+ - **Authentication** - Multiple auth methods (Bearer, OAuth, API keys)
10
+ - **Contract testing** - Validate against OpenAPI/Swagger specs
11
+ - **Automatic test generation** - Analyze endpoints and generate tests
12
+ - **Comprehensive validation** - Status codes, headers, body structure
13
+ - **Performance testing** - Response time assertions
14
+ - **Security testing** - Auth bypass, injection attempts
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ /plugin install api-test-automation@claude-code-plugins-plus
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ The API testing agent activates automatically when you mention API testing needs. You can also invoke directly:
25
+
26
+ ### Generate tests for REST API
27
+
28
+ ```
29
+ Generate API tests for the user management endpoints in src/routes/users.js
30
+ ```
31
+
32
+ ### Test GraphQL API
33
+
34
+ ```
35
+ Create GraphQL API tests for the product queries and mutations
36
+ ```
37
+
38
+ ### Validate against OpenAPI spec
39
+
40
+ ```
41
+ Generate contract tests validating against openapi.yaml
42
+ ```
43
+
44
+ ### Test authentication flows
45
+
46
+ ```
47
+ Create tests for JWT authentication including login, refresh, and protected endpoints
48
+ ```
49
+
50
+ ## What Gets Generated
51
+
52
+ ### 1. Complete Test Suites
53
+
54
+ ```javascript
55
+ // RESTful API test example
56
+ describe('User API', () => {
57
+ // Authentication tests
58
+ describe('POST /api/auth/login', () => {
59
+ it('should return JWT token with valid credentials', async () => {
60
+ const response = await api.post('/api/auth/login', {
61
+ email: '[email protected]',
62
+ password: 'password123'
63
+ });
64
+
65
+ expect(response.status).toBe(200);
66
+ expect(response.data).toHaveProperty('token');
67
+ expect(response.data).toHaveProperty('user');
68
+ expect(response.data.user.email).toBe('[email protected]');
69
+ });
70
+
71
+ it('should return 401 with invalid credentials', async () => {
72
+ const response = await api.post('/api/auth/login', {
73
+ email: '[email protected]',
74
+ password: 'wrongpassword'
75
+ });
76
+
77
+ expect(response.status).toBe(401);
78
+ expect(response.data.error).toBe('Invalid credentials');
79
+ });
80
+ });
81
+
82
+ // CRUD operations
83
+ describe('GET /api/users', () => {
84
+ it('should require authentication', async () => {
85
+ const response = await api.get('/api/users');
86
+ expect(response.status).toBe(401);
87
+ });
88
+
89
+ it('should return user list with valid token', async () => {
90
+ const response = await api.get('/api/users', {
91
+ headers: { Authorization: `Bearer ${authToken}` }
92
+ });
93
+
94
+ expect(response.status).toBe(200);
95
+ expect(Array.isArray(response.data)).toBe(true);
96
+ expect(response.data[0]).toHaveProperty('id');
97
+ expect(response.data[0]).toHaveProperty('email');
98
+ });
99
+ });
100
+
101
+ describe('POST /api/users', () => {
102
+ it('should create user with valid data', async () => {
103
+ const newUser = {
104
+ email: '[email protected]',
105
+ name: 'John Doe',
106
+ role: 'user'
107
+ };
108
+
109
+ const response = await api.post('/api/users', newUser, {
110
+ headers: { Authorization: `Bearer ${adminToken}` }
111
+ });
112
+
113
+ expect(response.status).toBe(201);
114
+ expect(response.data.email).toBe(newUser.email);
115
+ expect(response.data).toHaveProperty('id');
116
+ });
117
+
118
+ it('should validate required fields', async () => {
119
+ const response = await api.post('/api/users', {}, {
120
+ headers: { Authorization: `Bearer ${adminToken}` }
121
+ });
122
+
123
+ expect(response.status).toBe(400);
124
+ expect(response.data.errors).toContain('email');
125
+ });
126
+ });
127
+ });
128
+ ```
129
+
130
+ ### 2. Authentication Helpers
131
+
132
+ ```javascript
133
+ // Authentication utility functions
134
+ async function loginUser(email, password) {
135
+ const response = await api.post('/api/auth/login', { email, password });
136
+ return response.data.token;
137
+ }
138
+
139
+ async function createTestUser(role = 'user') {
140
+ const user = {
141
+ email: `test-${Date.now()}@example.com`,
142
+ password: 'test123',
143
+ role
144
+ };
145
+ await api.post('/api/users', user, { headers: { Authorization: adminToken } });
146
+ return loginUser(user.email, user.password);
147
+ }
148
+ ```
149
+
150
+ ### 3. Test Data Factories
151
+
152
+ ```javascript
153
+ // Factory functions for test data
154
+ const userFactory = {
155
+ valid: () => ({
156
+ email: `user-${Date.now()}@example.com`,
157
+ name: 'Test User',
158
+ password: 'securePassword123'
159
+ }),
160
+
161
+ invalid: () => ({
162
+ email: 'invalid-email',
163
+ name: '',
164
+ password: '123' // Too short
165
+ })
166
+ };
167
+ ```
168
+
169
+ ### 4. GraphQL Tests
170
+
171
+ ```javascript
172
+ describe('GraphQL API', () => {
173
+ describe('Query: user', () => {
174
+ it('should fetch user by ID', async () => {
175
+ const query = `
176
+ query GetUser($id: ID!) {
177
+ user(id: $id) {
178
+ id
179
+ email
180
+ name
181
+ }
182
+ }
183
+ `;
184
+
185
+ const response = await graphql.query(query, { id: userId });
186
+
187
+ expect(response.errors).toBeUndefined();
188
+ expect(response.data.user.id).toBe(userId);
189
+ });
190
+ });
191
+
192
+ describe('Mutation: createUser', () => {
193
+ it('should create new user', async () => {
194
+ const mutation = `
195
+ mutation CreateUser($input: CreateUserInput!) {
196
+ createUser(input: $input) {
197
+ id
198
+ email
199
+ }
200
+ }
201
+ `;
202
+
203
+ const response = await graphql.mutate(mutation, {
204
+ input: { email: '[email protected]', name: 'New User' }
205
+ });
206
+
207
+ expect(response.errors).toBeUndefined();
208
+ expect(response.data.createUser).toHaveProperty('id');
209
+ });
210
+ });
211
+ });
212
+ ```
213
+
214
+ ## Test Coverage
215
+
216
+ The agent generates tests for:
217
+
218
+ ### Success Scenarios
219
+ - Valid requests with proper authentication
220
+ - Correct data formats and required fields
221
+ - Expected response structures
222
+
223
+ ### Error Scenarios
224
+ - Missing or invalid authentication
225
+ - Validation errors (bad data formats)
226
+ - Missing required fields
227
+ - Unauthorized access (wrong permissions)
228
+ - Resource not found (404)
229
+ - Conflict errors (409, duplicates)
230
+
231
+ ### Edge Cases
232
+ - Empty request bodies
233
+ - Null/undefined values
234
+ - Boundary values (min/max lengths)
235
+ - Special characters in inputs
236
+ - Large payloads
237
+
238
+ ### Performance
239
+ - Response time thresholds
240
+ - Payload size validation
241
+ - Concurrent request handling
242
+
243
+ ## Best Practices Applied
244
+
245
+ - **Descriptive test names** - Clear what is tested and expected
246
+ - **Test isolation** - No dependencies between tests
247
+ - **Proper cleanup** - Delete test data after tests
248
+ - **Authentication management** - Reusable auth helpers
249
+ - **Data factories** - Generate test data dynamically
250
+ - **Comprehensive assertions** - Validate all critical fields
251
+ - **Error testing** - Both success and failure paths
252
+ - **Documentation** - Comments for complex scenarios
253
+
254
+ ## Requirements
255
+
256
+ - Claude Code CLI
257
+ - HTTP client library (axios, requests, etc.)
258
+ - Testing framework (Jest, pytest, RSpec, etc.)
259
+ - API access (local or test environment)
260
+
261
+ ## Configuration
262
+
263
+ Create API test configuration:
264
+
265
+ ```json
266
+ {
267
+ "baseURL": "http://localhost:3000/api",
268
+ "timeout": 5000,
269
+ "auth": {
270
+ "type": "bearer",
271
+ "tokenEndpoint": "/auth/login"
272
+ },
273
+ "testUsers": {
274
+ "admin": {
275
+ "email": "[email protected]",
276
+ "password": "admin123"
277
+ },
278
+ "user": {
279
+ "email": "[email protected]",
280
+ "password": "user123"
281
+ }
282
+ }
283
+ }
284
+ ```
285
+
286
+ ## Tips
287
+
288
+ 1. **Start with happy paths** - Ensure basic functionality works
289
+ 2. **Test authentication first** - Auth issues block other tests
290
+ 3. **Use realistic test data** - Match production data patterns
291
+ 4. **Check response times** - Add performance assertions
292
+ 5. **Test error messages** - Verify helpful error responses
293
+ 6. **Validate data types** - Not just presence, but correct types
294
+ 7. **Clean up test data** - Prevent database pollution
295
+
296
+ ## License
297
+
298
+ MIT
@@ -0,0 +1,192 @@
1
+ ---
2
+ name: api-tester
3
+ description: >
4
+ Specialized agent for automated API endpoint testing and validation
5
+ ---
6
+ # API Test Automation Agent
7
+
8
+ You are a specialized API testing agent that automates endpoint testing with comprehensive validation and reporting.
9
+
10
+ ## Your Capabilities
11
+
12
+ ### 1. REST API Testing
13
+ - **CRUD operations** - GET, POST, PUT, PATCH, DELETE
14
+ - **Request validation** - Headers, body, query parameters
15
+ - **Response validation** - Status codes, headers, body structure
16
+ - **Authentication** - Bearer tokens, API keys, OAuth, Basic Auth
17
+ - **Error scenarios** - 4xx/5xx responses, invalid inputs
18
+
19
+ ### 2. GraphQL Testing
20
+ - **Query testing** - Read operations with various selectors
21
+ - **Mutation testing** - Create, update, delete operations
22
+ - **Subscription testing** - Real-time data streams
23
+ - **Error handling** - GraphQL error responses
24
+ - **Schema validation** - Type checking, required fields
25
+
26
+ ### 3. API Contract Testing
27
+ - **OpenAPI/Swagger** - Validate against spec
28
+ - **Schema validation** - JSON Schema, Joi, Yup
29
+ - **Breaking change detection** - Compare API versions
30
+ - **Documentation sync** - Ensure docs match implementation
31
+
32
+ ### 4. Test Scenario Generation
33
+ - **Happy path tests** - Successful operations
34
+ - **Edge cases** - Boundary values, empty data
35
+ - **Error cases** - Invalid inputs, unauthorized access
36
+ - **Performance tests** - Response time validation
37
+ - **Security tests** - Injection attempts, auth bypass
38
+
39
+ ## When to Activate
40
+
41
+ Activate when the user needs to:
42
+ - Test REST or GraphQL API endpoints
43
+ - Validate API responses against schemas
44
+ - Generate API test suites
45
+ - Automate endpoint regression testing
46
+ - Verify authentication and authorization
47
+ - Check API performance and reliability
48
+
49
+ ## Approach
50
+
51
+ ### For Test Generation
52
+
53
+ 1. **Analyze API specification** (if available)
54
+ - OpenAPI/Swagger docs
55
+ - GraphQL schema
56
+ - Postman collections
57
+ - Existing API code
58
+
59
+ 2. **Identify endpoints to test**
60
+ - List all HTTP methods per route
61
+ - Note authentication requirements
62
+ - Identify related endpoints
63
+
64
+ 3. **Generate test cases**
65
+ - Valid requests (happy path)
66
+ - Invalid requests (error handling)
67
+ - Edge cases (boundaries, nulls)
68
+ - Authentication scenarios
69
+ - Authorization checks (different roles)
70
+
71
+ 4. **Create test file**
72
+ - Framework-specific syntax (Jest, pytest, RSpec)
73
+ - Request builders
74
+ - Response assertions
75
+ - Mock data factories
76
+ - Setup/teardown hooks
77
+
78
+ ### For Test Execution
79
+
80
+ 1. **Setup phase**
81
+ - Load environment variables
82
+ - Initialize HTTP client
83
+ - Authenticate (if needed)
84
+ - Prepare test data
85
+
86
+ 2. **Execute tests**
87
+ - Send HTTP requests
88
+ - Capture responses
89
+ - Validate status codes
90
+ - Check response structure
91
+ - Verify response data
92
+
93
+ 3. **Report results**
94
+ - Passed/failed tests
95
+ - Response times
96
+ - Error details
97
+ - Coverage metrics
98
+
99
+ 4. **Cleanup**
100
+ - Delete test data
101
+ - Clear authentication
102
+ - Reset state
103
+
104
+ ## Test Structure
105
+
106
+ Generate tests following this pattern:
107
+
108
+ ```javascript
109
+ describe('API Endpoint: POST /api/users', () => {
110
+ describe('Authentication', () => {
111
+ it('should return 401 without auth token', async () => {
112
+ const response = await api.post('/api/users', userData);
113
+ expect(response.status).toBe(401);
114
+ });
115
+ });
116
+
117
+ describe('Success scenarios', () => {
118
+ it('should create user with valid data', async () => {
119
+ const response = await api.post('/api/users', validUser, { auth: token });
120
+ expect(response.status).toBe(201);
121
+ expect(response.data).toHaveProperty('id');
122
+ expect(response.data.email).toBe(validUser.email);
123
+ });
124
+ });
125
+
126
+ describe('Validation errors', () => {
127
+ it('should return 400 for invalid email', async () => {
128
+ const response = await api.post('/api/users', { email: 'invalid' }, { auth: token });
129
+ expect(response.status).toBe(400);
130
+ expect(response.data.errors).toContain('email');
131
+ });
132
+ });
133
+
134
+ describe('Edge cases', () => {
135
+ it('should handle duplicate email gracefully', async () => {
136
+ await api.post('/api/users', existingUser, { auth: token });
137
+ const response = await api.post('/api/users', existingUser, { auth: token });
138
+ expect(response.status).toBe(409);
139
+ });
140
+ });
141
+ });
142
+ ```
143
+
144
+ ## Validation Rules
145
+
146
+ Always validate:
147
+ - **Status codes** - Correct HTTP status
148
+ - **Response structure** - Expected JSON shape
149
+ - **Data types** - String, number, boolean, array, object
150
+ - **Required fields** - All mandatory fields present
151
+ - **Data formats** - Email, URL, date, UUID formats
152
+ - **Response headers** - Content-Type, Cache-Control, etc.
153
+ - **Response time** - Performance thresholds
154
+ - **Error messages** - Clear, helpful error responses
155
+
156
+ ## Authentication Patterns
157
+
158
+ Handle common auth patterns:
159
+ - **Bearer tokens** - `Authorization: Bearer <token>`
160
+ - **API keys** - Header or query parameter
161
+ - **OAuth 2.0** - Token exchange flow
162
+ - **Basic Auth** - Username:password encoding
163
+ - **Session cookies** - Cookie-based authentication
164
+ - **JWT tokens** - Validate and refresh tokens
165
+
166
+ ## Tools and Libraries
167
+
168
+ Use appropriate tools for the language:
169
+ - **JavaScript/TypeScript**: axios, supertest, node-fetch
170
+ - **Python**: requests, httpx, pytest-httpx
171
+ - **Java**: RestAssured, OkHttp
172
+ - **Go**: net/http, httptest
173
+ - **Ruby**: Faraday, HTTParty
174
+
175
+ ## Output Format
176
+
177
+ Provide:
178
+ 1. **Complete test file** with all necessary imports
179
+ 2. **Test data fixtures** or factories
180
+ 3. **Authentication helpers** (if needed)
181
+ 4. **README** with setup instructions
182
+ 5. **Environment variables** needed
183
+
184
+ ## Best Practices
185
+
186
+ - **Test isolation** - Each test is independent
187
+ - **Clear descriptions** - Descriptive test names
188
+ - **Proper assertions** - Validate all critical fields
189
+ - **Error handling** - Test both success and failure
190
+ - **Performance checks** - Include response time assertions
191
+ - **Documentation** - Comment complex test scenarios
192
+ - **Maintainability** - DRY principle, reusable helpers
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@intentsolutionsio/api-test-automation",
3
+ "version": "1.0.0",
4
+ "description": "Automated API endpoint testing with request generation, validation, and comprehensive test coverage",
5
+ "keywords": [
6
+ "testing",
7
+ "api",
8
+ "rest",
9
+ "graphql",
10
+ "automation",
11
+ "endpoints",
12
+ "agent-skills",
13
+ "claude-code",
14
+ "claude-plugin",
15
+ "tonsofskills"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/jeremylongshore/claude-code-plugins-plus-skills.git",
20
+ "directory": "plugins/testing/api-test-automation"
21
+ },
22
+ "homepage": "https://tonsofskills.com/plugins/api-test-automation",
23
+ "bugs": "https://github.com/jeremylongshore/claude-code-plugins-plus-skills/issues",
24
+ "license": "MIT",
25
+ "author": {
26
+ "name": "Claude Code Plugins",
27
+ "email": "[email protected]"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "files": [
33
+ "README.md",
34
+ ".claude-plugin",
35
+ "skills",
36
+ "agents"
37
+ ],
38
+ "scripts": {
39
+ "postinstall": "node -e \"console.log(\\\"\\\\n→ This npm package is a tracking/proof artifact. Install the plugin via:\\\\n ccpi install api-test-automation\\\\n or /plugin install api-test-automation@claude-code-plugins-plus in Claude Code\\\\n\\\")\""
40
+ }
41
+ }
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: automating-api-testing
3
+ description: |
4
+ Test automate API endpoint testing including request generation, validation, and comprehensive test coverage for REST and GraphQL APIs.
5
+ Use when testing API contracts, validating OpenAPI specifications, or ensuring endpoint reliability.
6
+ Trigger with phrases like "test the API", "generate API tests", or "validate API contracts".
7
+
8
+ allowed-tools: Read, Write, Edit, Grep, Glob, Bash(test:api-*)
9
+ version: 1.0.0
10
+ author: Jeremy Longshore <jeremy@intentsolutions.io>
11
+ license: MIT
12
+ compatible-with: claude-code, codex, openclaw
13
+ tags: [testing, api, graphql]
14
+ ---
15
+ # API Test Automation
16
+
17
+ ## Overview
18
+
19
+ Automate comprehensive API endpoint testing for REST and GraphQL APIs including request generation, response validation, schema compliance, authentication flows, and error handling. Supports Supertest (Node.js), REST-assured (Java), httpx/pytest (Python), Postman/Newman collections, and Pact for consumer-driven contract testing.
20
+
21
+ ## Prerequisites
22
+
23
+ - API testing library installed (Supertest, REST-assured, httpx, or Postman/Newman)
24
+ - API specification file (OpenAPI/Swagger YAML/JSON or GraphQL SDL)
25
+ - Target API running in a test environment with seeded data
26
+ - Authentication credentials or API keys for protected endpoints
27
+ - JSON Schema validator (Ajv, jsonschema, or built-in framework assertions)
28
+
29
+ ## Instructions
30
+
31
+ 1. Read the API specification and extract all endpoints:
32
+ - Parse OpenAPI spec to catalog every path, HTTP method, request schema, and response schema.
33
+ - For GraphQL APIs, introspect the schema to list queries, mutations, and subscriptions.
34
+ - Document authentication requirements per endpoint (API key, Bearer token, OAuth, none).
35
+ 2. Generate test cases for each endpoint:
36
+ - **Success cases**: Send valid requests matching the schema and assert 200/201 responses.
37
+ - **Validation errors**: Send requests with missing required fields, wrong types, and out-of-range values; assert 400 responses.
38
+ - **Authentication**: Test with valid, expired, and missing credentials; assert 200, 401, and 403 respectively.
39
+ - **Not found**: Request non-existent resources; assert 404 responses.
40
+ - **Idempotency**: Send the same PUT/DELETE request twice and verify consistent behavior.
41
+ 3. Validate response structure against schemas:
42
+ - Assert response Content-Type matches expected (application/json, etc.).
43
+ - Validate response body against the OpenAPI response schema using JSON Schema validation.
44
+ - Check response headers (Cache-Control, Rate-Limit headers, CORS headers).
45
+ - Verify pagination metadata (total count, page number, next/previous links).
46
+ 4. Test CRUD lifecycle for resource endpoints:
47
+ - Create a resource (POST) and capture the ID.
48
+ - Read it back (GET) and verify all fields match.
49
+ - Update it (PUT/PATCH) and verify changes persisted.
50
+ - Delete it (DELETE) and verify subsequent GET returns 404.
51
+ 5. Test error handling and edge cases:
52
+ - Send excessively large payloads and verify 413 or graceful rejection.
53
+ - Send requests with unsupported Content-Types and verify 415.
54
+ - Test rate limiting by sending rapid sequential requests.
55
+ - Verify error response format is consistent (standard error schema).
56
+ 6. For GraphQL APIs, test specifically:
57
+ - Valid queries return expected data shapes.
58
+ - Invalid queries return descriptive error messages.
59
+ - Query depth limiting prevents deeply nested abuse queries.
60
+ - Mutation input validation matches schema constraints.
61
+ 7. Generate a test coverage report mapping endpoints to test cases.
62
+
63
+ ## Output
64
+
65
+ - API test files organized by resource in `tests/api/`
66
+ - Request/response examples for API documentation
67
+ - Schema compliance report for each endpoint
68
+ - Endpoint coverage matrix showing tested vs. untested endpoints and methods
69
+ - CI pipeline step running API tests against staging environment
70
+
71
+ ## Error Handling
72
+
73
+ | Error | Cause | Solution |
74
+ |-------|-------|---------|
75
+ | Connection refused | API server not running or wrong base URL | Verify server is up with a health check before test suite starts; check `BASE_URL` config |
76
+ | 401 on all requests | Authentication token expired or misconfigured | Refresh token in test setup; verify `Authorization` header format; check token scopes |
77
+ | Schema validation fails unexpectedly | API response includes extra fields not in spec | Update OpenAPI spec to include new fields; use `additionalProperties: true` if expected |
78
+ | Test data conflicts | Another test modified or deleted the resource | Use unique test data per test; create resources in `beforeEach`; avoid shared fixtures |
79
+ | Rate limit hit during test run | Too many requests in quick succession | Add delays between requests or use authenticated sessions with higher limits; run tests serially |
80
+
81
+ ## Examples
82
+
83
+ **Supertest REST API test suite:**
84
+ ```typescript
85
+ import request from 'supertest';
86
+ import { app } from '../src/app';
87
+
88
+ describe('GET /api/products', () => {
89
+ it('returns a paginated product list', async () => {
90
+ const res = await request(app)
91
+ .get('/api/products?page=1&limit=10')
92
+ .set('Authorization', `Bearer ${token}`)
93
+ .expect(200) # HTTP 200 OK
94
+ .expect('Content-Type', /json/);
95
+
96
+ expect(res.body.data).toBeInstanceOf(Array);
97
+ expect(res.body.data.length).toBeLessThanOrEqual(10);
98
+ expect(res.body.meta).toMatchObject({ page: 1, limit: 10 });
99
+ });
100
+
101
+ it('returns 401 without authentication', async () => { # HTTP 401 Unauthorized
102
+ await request(app).get('/api/products').expect(401); # HTTP 401 Unauthorized
103
+ });
104
+ });
105
+
106
+ describe('POST /api/products', () => {
107
+ it('creates a product with valid data', async () => {
108
+ const res = await request(app)
109
+ .post('/api/products')
110
+ .set('Authorization', `Bearer ${token}`)
111
+ .send({ name: 'Widget', price: 9.99, category: 'tools' })
112
+ .expect(201); # HTTP 201 Created
113
+
114
+ expect(res.body).toMatchObject({ name: 'Widget', price: 9.99 });
115
+ expect(res.body.id).toBeDefined();
116
+ });
117
+
118
+ it('returns 400 for missing required fields', async () => { # HTTP 400 Bad Request
119
+ await request(app)
120
+ .post('/api/products')
121
+ .set('Authorization', `Bearer ${token}`)
122
+ .send({ name: 'Widget' }) // missing price
123
+ .expect(400); # HTTP 400 Bad Request
124
+ });
125
+ });
126
+ ```
127
+
128
+ **GraphQL API test:**
129
+ ```typescript
130
+ it('fetches user by ID', async () => {
131
+ const query = `query { user(id: "1") { id name email } }`;
132
+ const res = await request(app)
133
+ .post('/graphql')
134
+ .send({ query })
135
+ .expect(200); # HTTP 200 OK
136
+
137
+ expect(res.body.data.user).toMatchObject({ id: '1', name: 'Alice' });
138
+ expect(res.body.errors).toBeUndefined();
139
+ });
140
+ ```
141
+
142
+ ## Resources
143
+
144
+ - Supertest: https://github.com/ladjs/supertest
145
+ - REST-assured (Java): https://rest-assured.io/
146
+ - httpx (Python): https://www.python-httpx.org/
147
+ - Newman (Postman CLI): https://learning.postman.com/docs/collections/using-newman-cli/
148
+ - OpenAPI specification: https://spec.openapis.org/oas/v3.1.0
149
+ - Ajv JSON Schema validator: https://ajv.js.org/
@@ -0,0 +1,7 @@
1
+ # Assets
2
+
3
+ Bundled resources for api-test-automation skill
4
+
5
+ - [ ] test_suite_template.js: Template for generating API test suites, including placeholders for different test cases and assertions.
6
+ - [ ] example_openapi.yaml: Example OpenAPI specification file for demonstration and testing purposes.
7
+ - [ ] example_graphql_schema.graphql: Example GraphQL schema file for testing GraphQL APIs.
@@ -0,0 +1,98 @@
1
+ # Example GraphQL schema file for testing GraphQL APIs.
2
+ # This schema defines a simple book catalog with authors.
3
+
4
+ # Types
5
+ type Book {
6
+ id: ID!
7
+ title: String!
8
+ author: Author!
9
+ publicationYear: Int
10
+ genre: String
11
+ }
12
+
13
+ type Author {
14
+ id: ID!
15
+ name: String!
16
+ books: [Book!]!
17
+ }
18
+
19
+ # Queries
20
+ type Query {
21
+ # Get a book by its ID
22
+ book(id: ID!): Book
23
+
24
+ # Get all books
25
+ books: [Book!]!
26
+
27
+ # Get an author by their ID
28
+ author(id: ID!): Author
29
+
30
+ # Get all authors
31
+ authors: [Author!]!
32
+
33
+ # Search for books by title or author name
34
+ search(query: String!): [Book!]!
35
+ }
36
+
37
+ # Mutations
38
+ type Mutation {
39
+ # Create a new book
40
+ createBook(
41
+ title: String!
42
+ authorId: ID!
43
+ publicationYear: Int
44
+ genre: String
45
+ ): Book
46
+
47
+ # Update an existing book
48
+ updateBook(
49
+ id: ID!
50
+ title: String
51
+ authorId: ID
52
+ publicationYear: Int
53
+ genre: String
54
+ ): Book
55
+
56
+ # Delete a book by its ID
57
+ deleteBook(id: ID!): ID
58
+
59
+ # Create a new author
60
+ createAuthor(name: String!): Author
61
+ }
62
+
63
+ # Input types (optional, for more complex mutations)
64
+ # input CreateBookInput {
65
+ # title: String!
66
+ # authorId: ID!
67
+ # publicationYear: Int
68
+ # genre: String
69
+ # }
70
+
71
+ # Placeholder for subscriptions (if needed)
72
+ # type Subscription {
73
+ # newBook: Book
74
+ # }
75
+
76
+ # Further instructions:
77
+ # 1. This is a basic example. Extend it with more complex types, fields, and relationships as needed.
78
+ # 2. Consider adding input types for mutations to improve clarity and validation.
79
+ # 3. Implement resolvers for each query and mutation to connect to your data source.
80
+ # 4. Use directives for authorization, caching, and other features.
81
+ # 5. Use scalars for custom data types (e.g., Date, URL).
82
+ # 6. Example query to get a specific book:
83
+ # query {
84
+ # book(id: "123") {
85
+ # id
86
+ # title
87
+ # author {
88
+ # name
89
+ # }
90
+ # }
91
+ # }
92
+ # 7. Example mutation to create a book:
93
+ # mutation {
94
+ # createBook(title: "New Book", authorId: "456", publicationYear: 2023, genre: "Fiction") {
95
+ # id
96
+ # title
97
+ # }
98
+ # }
@@ -0,0 +1,216 @@
1
+ # OpenAPI Specification for Example API
2
+
3
+ openapi: 3.0.0
4
+ info:
5
+ title: Example API
6
+ version: 1.0.0
7
+ description: A sample API for demonstration purposes.
8
+ termsOfService: example-value # Add your terms of service URL here
9
+ contact:
10
+ name: API Support
11
+ url: example-value # Add your support URL here
12
+ email: support@example.com
13
+ license:
14
+ name: Apache 2.0
15
+ url: https://www.apache.org/licenses/000-docs/001-BL-LICN-license.txt-2.0.html
16
+
17
+ servers:
18
+ - url: https://api.example.com/v1
19
+ description: Production server
20
+
21
+ paths:
22
+ /users:
23
+ get:
24
+ summary: Get all users
25
+ description: Retrieves a list of all users.
26
+ operationId: getUsers
27
+ tags:
28
+ - users
29
+ responses:
30
+ '200':
31
+ description: Successful operation
32
+ content:
33
+ application/json:
34
+ schema:
35
+ type: array
36
+ items:
37
+ $ref: '#/components/schemas/User'
38
+ '500':
39
+ description: Internal server error
40
+ post:
41
+ summary: Create a new user
42
+ description: Creates a new user in the system.
43
+ operationId: createUser
44
+ tags:
45
+ - users
46
+ requestBody:
47
+ required: true
48
+ content:
49
+ application/json:
50
+ schema:
51
+ $ref: '#/components/schemas/UserCreate'
52
+ responses:
53
+ '201':
54
+ description: User created successfully
55
+ content:
56
+ application/json:
57
+ schema:
58
+ $ref: '#/components/schemas/User'
59
+ '400':
60
+ description: Bad request
61
+ '500':
62
+ description: Internal server error
63
+
64
+ /users/{userId}:
65
+ get:
66
+ summary: Get user by ID
67
+ description: Retrieves a user by their ID.
68
+ operationId: getUserById
69
+ tags:
70
+ - users
71
+ parameters:
72
+ - name: userId
73
+ in: path
74
+ description: ID of the user to retrieve.
75
+ required: true
76
+ schema:
77
+ type: integer
78
+ format: int64
79
+ responses:
80
+ '200':
81
+ description: Successful operation
82
+ content:
83
+ application/json:
84
+ schema:
85
+ $ref: '#/components/schemas/User'
86
+ '404':
87
+ description: User not found
88
+ '500':
89
+ description: Internal server error
90
+ put:
91
+ summary: Update user by ID
92
+ description: Updates an existing user.
93
+ operationId: updateUser
94
+ tags:
95
+ - users
96
+ parameters:
97
+ - name: userId
98
+ in: path
99
+ description: ID of the user to update.
100
+ required: true
101
+ schema:
102
+ type: integer
103
+ format: int64
104
+ requestBody:
105
+ required: true
106
+ content:
107
+ application/json:
108
+ schema:
109
+ $ref: '#/components/schemas/UserUpdate'
110
+ responses:
111
+ '200':
112
+ description: Successful operation
113
+ content:
114
+ application/json:
115
+ schema:
116
+ $ref: '#/components/schemas/User'
117
+ '400':
118
+ description: Bad request
119
+ '404':
120
+ description: User not found
121
+ '500':
122
+ description: Internal server error
123
+ delete:
124
+ summary: Delete user by ID
125
+ description: Deletes a user by their ID.
126
+ operationId: deleteUser
127
+ tags:
128
+ - users
129
+ parameters:
130
+ - name: userId
131
+ in: path
132
+ description: ID of the user to delete.
133
+ required: true
134
+ schema:
135
+ type: integer
136
+ format: int64
137
+ responses:
138
+ '204':
139
+ description: User deleted successfully (No Content)
140
+ '404':
141
+ description: User not found
142
+ '500':
143
+ description: Internal server error
144
+
145
+ components:
146
+ schemas:
147
+ User:
148
+ type: object
149
+ properties:
150
+ id:
151
+ type: integer
152
+ format: int64
153
+ description: Unique identifier for the user
154
+ username:
155
+ type: string
156
+ description: User's username
157
+ email:
158
+ type: string
159
+ format: email
160
+ description: User's email address
161
+ firstName:
162
+ type: string
163
+ description: User's first name
164
+ lastName:
165
+ type: string
166
+ description: User's last name
167
+ required:
168
+ - id
169
+ - username
170
+ - email
171
+
172
+ UserCreate:
173
+ type: object
174
+ properties:
175
+ username:
176
+ type: string
177
+ description: User's username
178
+ email:
179
+ type: string
180
+ format: email
181
+ description: User's email address
182
+ firstName:
183
+ type: string
184
+ description: User's first name
185
+ lastName:
186
+ type: string
187
+ description: User's last name
188
+ required:
189
+ - username
190
+ - email
191
+
192
+ UserUpdate:
193
+ type: object
194
+ properties:
195
+ username:
196
+ type: string
197
+ description: User's username
198
+ email:
199
+ type: string
200
+ format: email
201
+ description: User's email address
202
+ firstName:
203
+ type: string
204
+ description: User's first name
205
+ lastName:
206
+ type: string
207
+ description: User's last name
208
+
209
+ securitySchemes:
210
+ bearerAuth: # Define security scheme name
211
+ type: http
212
+ scheme: bearer
213
+ bearerFormat: JWT
214
+
215
+ security:
216
+ - bearerAuth: [] # Apply the security scheme to all endpoints (globally)
@@ -0,0 +1,99 @@
1
+ /**
2
+ * test_suite_template.js
3
+ *
4
+ * Template for generating API test suites. This template provides a structure
5
+ * for creating comprehensive test cases for various API endpoints.
6
+ *
7
+ * @example
8
+ * // Example usage (after replacing placeholders):
9
+ * const testSuite = require('./test_suite_template');
10
+ *
11
+ * const config = {
12
+ * baseURL: 'https://api.example.com',
13
+ * endpoint: '/users',
14
+ * method: 'GET',
15
+ * description: 'Retrieve all users'
16
+ * };
17
+ *
18
+ * const testCase = testSuite(config);
19
+ *
20
+ * describe(config.description, () => {
21
+ * it('should return a 200 OK status', async () => {
22
+ * const response = await testCase.request();
23
+ * expect(response.status).toBe(200);
24
+ * });
25
+ * // Add more test cases here...
26
+ * });
27
+ */
28
+
29
+ /**
30
+ * Generates a test suite based on the provided configuration.
31
+ *
32
+ * @param {object} config - Configuration object for the test suite.
33
+ * @param {string} config.baseURL - The base URL of the API.
34
+ * @param {string} config.endpoint - The API endpoint to test.
35
+ * @param {string} config.method - The HTTP method to use (GET, POST, PUT, DELETE, etc.).
36
+ * @param {string} config.description - A description of the test case.
37
+ * @param {object} [config.headers] - Optional headers to include in the request.
38
+ * @param {object} [config.body] - Optional request body.
39
+ * @param {string} [config.authenticationType] - Optional authentication type (e.g., 'Bearer', 'OAuth', 'API Key').
40
+ * @param {string} [config.authenticationToken] - Optional authentication token or API key.
41
+ * @returns {object} An object containing the request function.
42
+ */
43
+ module.exports = (config) => {
44
+ const axios = require('axios'); // Consider making axios a configurable dependency if needed
45
+
46
+ /**
47
+ * Executes the API request based on the configuration.
48
+ *
49
+ * @async
50
+ * @function request
51
+ * @returns {Promise<object>} A promise that resolves to the API response.
52
+ * @throws {Error} If the request fails.
53
+ */
54
+ async function request() {
55
+ try {
56
+ const requestConfig = {
57
+ method: config.method,
58
+ url: config.baseURL + config.endpoint,
59
+ headers: config.headers || {},
60
+ data: config.body || null, // Use data for POST/PUT requests, params for GET
61
+ // params: config.method === 'GET' ? config.body : null // Alternate: use params for GET requests
62
+ };
63
+
64
+ // Authentication handling
65
+ if (config.authenticationType === 'Bearer' && config.authenticationToken) {
66
+ requestConfig.headers.Authorization = `Bearer ${config.authenticationToken}`;
67
+ } else if (config.authenticationType === 'API Key' && config.authenticationToken) {
68
+ // Example API Key header - adjust based on API requirements
69
+ requestConfig.headers['X-API-Key'] = config.authenticationToken;
70
+ } // Add more authentication types as needed
71
+
72
+ const response = await axios(requestConfig);
73
+ return response;
74
+ } catch (error) {
75
+ // Handle errors appropriately (e.g., log, re-throw, or return a custom error object)
76
+ console.error(`Request failed for ${config.description}:`, error.message);
77
+ throw error; // Re-throw the error for the test to handle
78
+ }
79
+ }
80
+
81
+ return {
82
+ request,
83
+
84
+ // Add more helper functions here if needed (e.g., for data validation)
85
+ validateResponseSchema: (response, schema) => {
86
+ // Placeholder: Implement schema validation logic using a library like Joi or Ajv
87
+ // Example:
88
+ // const validationResult = schema.validate(response.data);
89
+ // if (validationResult.error) {
90
+ // throw new Error(`Schema validation failed: ${validationResult.error.message}`);
91
+ // }
92
+ },
93
+ extractDataFromResponse: (response, path) => {
94
+ // Placeholder: Implement logic to extract data from the response using a library like lodash.get
95
+ // Example:
96
+ // return _.get(response.data, path);
97
+ }
98
+ };
99
+ };
@@ -0,0 +1,4 @@
1
+ # References
2
+
3
+ Bundled resources for api-test-automation skill
4
+
@@ -0,0 +1,7 @@
1
+ # Scripts
2
+
3
+ Bundled resources for api-test-automation skill
4
+
5
+ - [ ] generate_test_suite.py: Generates comprehensive test suites for REST and GraphQL APIs based on endpoint analysis and specifications.
6
+ - [ ] validate_api_response.py: Validates API responses against predefined schemas or OpenAPI specifications.
7
+ - [ ] authentication_test.py: Automates authentication testing, including various methods like Bearer tokens, OAuth, and API keys.
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ api-test-automation - Generator Script
4
+ Generates comprehensive test suites for REST and GraphQL APIs based on endpoint analysis and specifications.
5
+ Generated: 2025-12-10 03:48:17
6
+ """
7
+
8
+ import os
9
+ import json
10
+ import argparse
11
+ from pathlib import Path
12
+ from datetime import datetime
13
+
14
+ class Generator:
15
+ def __init__(self, config: Dict):
16
+ self.config = config
17
+ self.output_dir = Path(config.get('output', './output'))
18
+ self.output_dir.mkdir(parents=True, exist_ok=True)
19
+
20
+ def generate_markdown(self, title: str, content: str) -> Path:
21
+ """Generate markdown document."""
22
+ filename = f"{title.lower().replace(' ', '_')}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
23
+ file_path = self.output_dir / filename
24
+
25
+ md_content = f"""# {title}
26
+
27
+ Generated by api-test-automation
28
+ Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
29
+
30
+ ## Overview
31
+ {content}
32
+
33
+ ## Configuration
34
+ ```json
35
+ {json.dumps(self.config, indent=2)}
36
+ ```
37
+
38
+ ## Category
39
+ testing
40
+
41
+ ## Plugin
42
+ api-test-automation
43
+ """
44
+
45
+ file_path.write_text(md_content)
46
+ return file_path
47
+
48
+ def generate_json(self, data: Dict) -> Path:
49
+ """Generate JSON output."""
50
+ filename = f"output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
51
+ file_path = self.output_dir / filename
52
+
53
+ output_data = {
54
+ "generated_by": "api-test-automation",
55
+ "timestamp": datetime.now().isoformat(),
56
+ "category": "testing",
57
+ "plugin": "api-test-automation",
58
+ "data": data,
59
+ "config": self.config
60
+ }
61
+
62
+ with open(file_path, 'w') as f:
63
+ json.dump(output_data, f, indent=2)
64
+
65
+ return file_path
66
+
67
+ def generate_script(self, name: str, template: str) -> Path:
68
+ """Generate executable script."""
69
+ filename = f"{name}.sh"
70
+ file_path = self.output_dir / filename
71
+
72
+ script_content = f"""#!/bin/bash
73
+ # Generated by api-test-automation
74
+ # Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
75
+
76
+ set -e # Exit on error
77
+
78
+ echo "🚀 Running {name}..."
79
+
80
+ # Template content
81
+ {template}
82
+
83
+ echo "✅ Completed successfully"
84
+ """
85
+
86
+ file_path.write_text(script_content)
87
+ file_path.chmod(0o755) # Make executable
88
+ return file_path
89
+
90
+ def main():
91
+ parser = argparse.ArgumentParser(description="Generates comprehensive test suites for REST and GraphQL APIs based on endpoint analysis and specifications.")
92
+ parser.add_argument('--type', choices=['markdown', 'json', 'script'], default='markdown')
93
+ parser.add_argument('--output', '-o', default='./output', help='Output directory')
94
+ parser.add_argument('--config', '-c', help='Configuration file')
95
+ parser.add_argument('--title', default='api-test-automation Output')
96
+ parser.add_argument('--content', help='Content to include')
97
+
98
+ args = parser.parse_args()
99
+
100
+ config = {'output': args.output}
101
+ if args.config and Path(args.config).exists():
102
+ with open(args.config) as f:
103
+ config.update(json.load(f))
104
+
105
+ generator = Generator(config)
106
+
107
+ print(f"🔧 Generating {args.type} output...")
108
+
109
+ if args.type == 'markdown':
110
+ output_file = generator.generate_markdown(
111
+ args.title,
112
+ args.content or "Generated content"
113
+ )
114
+ elif args.type == 'json':
115
+ output_file = generator.generate_json(
116
+ {"title": args.title, "content": args.content}
117
+ )
118
+ else: # script
119
+ output_file = generator.generate_script(
120
+ args.title.lower().replace(' ', '_'),
121
+ args.content or "# Add your script content here"
122
+ )
123
+
124
+ print(f"✅ Generated: {output_file}")
125
+ return 0
126
+
127
+ if __name__ == "__main__":
128
+ import sys
129
+ sys.exit(main())