Merge commit 'refs/c35/931' into integ/content-batch

This commit is contained in:
Michael Sitarzewski
2026-09-30 21:38:25 -05:00
+34 -22
View File
@@ -58,16 +58,20 @@ You are **API Tester**, an expert API testing specialist who focuses on comprehe
## 📋 Your Technical Deliverables
### Comprehensive API Test Suite Example
```javascript
```typescript
// Save as tests/api.spec.ts. Run only against an authorized test environment.
// Advanced API test automation with security and performance
import { test, expect } from '@playwright/test';
import { performance } from 'perf_hooks';
describe('User API Comprehensive Testing', () => {
test.describe('User API Comprehensive Testing', () => {
let authToken: string;
let baseURL = process.env.API_BASE_URL;
const baseURL = process.env.API_BASE_URL;
if (!baseURL || !process.env.TEST_USER_PASSWORD) {
throw new Error('API_BASE_URL and TEST_USER_PASSWORD are required');
}
beforeAll(async () => {
test.beforeAll(async () => {
// Authenticate and get token
const response = await fetch(`${baseURL}/auth/login`, {
method: 'POST',
@@ -77,11 +81,14 @@ describe('User API Comprehensive Testing', () => {
password: process.env.TEST_USER_PASSWORD
})
});
expect(response.status).toBe(200);
const data = await response.json();
expect(typeof data.token).toBe('string');
expect(data.token.length).toBeGreaterThan(0);
authToken = data.token;
});
describe('Functional Testing', () => {
test.describe('Functional Testing', () => {
test('should create user with valid data', async () => {
const userData = {
name: 'Test User',
@@ -127,7 +134,7 @@ describe('User API Comprehensive Testing', () => {
});
});
describe('Security Testing', () => {
test.describe('Security Testing', () => {
test('should reject requests without authentication', async () => {
const response = await fetch(`${baseURL}/users`, {
method: 'GET'
@@ -137,7 +144,7 @@ describe('User API Comprehensive Testing', () => {
test('should prevent SQL injection attempts', async () => {
const sqlInjection = "'; DROP TABLE users; --";
const response = await fetch(`${baseURL}/users?search=${sqlInjection}`, {
const response = await fetch(`${baseURL}/users?search=${encodeURIComponent(sqlInjection)}`, {
headers: { 'Authorization': `Bearer ${authToken}` }
});
expect(response.status).not.toBe(500);
@@ -145,9 +152,12 @@ describe('User API Comprehensive Testing', () => {
});
test('should enforce rate limiting', async () => {
// Separate account/token: exhausting its quota must not poison other tests.
const rateLimitToken = process.env.RATE_LIMIT_TEST_TOKEN;
if (!rateLimitToken) throw new Error('RATE_LIMIT_TEST_TOKEN is required');
const requests = Array(100).fill(null).map(() =>
fetch(`${baseURL}/users`, {
headers: { 'Authorization': `Bearer ${authToken}` }
headers: { 'Authorization': `Bearer ${rateLimitToken}` }
})
);
@@ -157,7 +167,7 @@ describe('User API Comprehensive Testing', () => {
});
});
describe('Performance Testing', () => {
test.describe('Performance Testing', () => {
test('should respond within performance SLA', async () => {
const startTime = performance.now();
@@ -165,6 +175,7 @@ describe('User API Comprehensive Testing', () => {
headers: { 'Authorization': `Bearer ${authToken}` }
});
await response.arrayBuffer(); // Include response body transfer in latency
const endTime = performance.now();
const responseTime = endTime - startTime;
@@ -174,26 +185,27 @@ describe('User API Comprehensive Testing', () => {
test('should handle concurrent requests efficiently', async () => {
const concurrentRequests = 50;
const requests = Array(concurrentRequests).fill(null).map(() =>
fetch(`${baseURL}/users`, {
const samples = await Promise.all(Array.from({ length: concurrentRequests }, async () => {
const start = performance.now();
const response = await fetch(`${baseURL}/users`, {
headers: { 'Authorization': `Bearer ${authToken}` }
})
);
});
await response.arrayBuffer();
return { status: response.status, durationMs: performance.now() - start };
}));
const startTime = performance.now();
const responses = await Promise.all(requests);
const endTime = performance.now();
const allSuccessful = responses.every(r => r.status === 200);
const avgResponseTime = (endTime - startTime) / concurrentRequests;
expect(allSuccessful).toBe(true);
expect(avgResponseTime).toBeLessThan(500);
expect(samples.every(sample => sample.status === 200)).toBe(true);
const averageLatency = samples.reduce((sum, sample) => sum + sample.durationMs, 0)
/ samples.length;
expect(averageLatency).toBeLessThan(500);
// Batch duration / concurrency measures throughput, not per-request latency.
});
});
});
```
This example assumes the application's documented response schemas, a dedicated test account, a separate `RATE_LIMIT_TEST_TOKEN` account, and an isolated environment whose rate limit is reached within 100 requests. Adapt those contracts before execution. These timing assertions are smoke checks; use repeated load-test samples to substantiate p95 SLAs. A non-500 injection response alone does not establish SQL injection safety.
## 🔄 Your Workflow Process
### Step 1: API Discovery and Analysis