Skip to main content Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-api-design --skill testingO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Explorador de arquivos
6 arquivos Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
name testing version 2.0.0 description API testing strategies and contract testing sasmp_version 1.3.0 bonded_agent 05-security-compliance bond_type PRIMARY_BOND atomic_design {"single_responsibility":"API testing patterns and automation","boundaries":{"includes":["unit_testing","integration_testing","contract_testing","load_testing"],"excludes":["implementation_code","deployment","monitoring"]}} parameter_validation {"schema":{"type":"object","properties":{"test_type":{"type":"string","enum":["unit","integration","contract","e2e","load","security"]},"coverage_target":{"type":"number","minimum":0,"maximum":100}}}} retry_config {"enabled":true,"max_attempts":3,"backoff":{"type":"linear","initial_delay_ms":1000}} logging {"level":"INFO","fields":["test_type","passed","failed","duration_ms"]} dependencies {"skills":["security-patterns"],"agents":["05-security-compliance"]}
API Testing Skill
Purpose
Implement comprehensive API testing strategies.
Testing Pyramid
╱╲
╱E2E╲ Few, slow, expensive
╱──────╲
╱ Contract╲ Consumer-driven contracts
╱────────────╲
╱ Integration ╲ API + Database
╱────────────────╲
╱ Unit Tests ╲ Fast, many, cheap
╱────────────────────╲
Unit Testing
Controller/Handler Tests
import { describe, it, expect, vi, beforeEach } from 'vitest' ;
import { UserController } from './user.controller' ;
import { UserService } from './user.service' ;
describe ('UserController' , () => {
let controller : UserController ;
let mockUserService : jest.Mocked <UserService >;
beforeEach (() => {
mockUserService = {
findById : vi.fn (),
create : vi.fn (),
update : vi.fn (),
delete : vi.fn (),
};
controller = new UserController (mockUserService);
});
describe ('getUser' , () => {
it ('should return user when found' , async () => {
const mockUser = { : , : , : };
mockUserService. . (mockUser);
result = controller. ( );
(result). ({ : mockUser });
(mockUserService. ). ( );
});
( , () => {
mockUserService. . ( );
(controller. ( )). . ( );
});
});
( , {
( , () => {
input = { : , : };
created = { : , ...input };
mockUserService. . (created);
result = controller. (input);
(result. . ). ( );
});
( , () => {
invalidInput = { : , : };
(controller. (invalidInput)). . ( );
});
});
});
id
'123'
name
'John'
email
'john@test.com'
findById
mockResolvedValue
const
await
getUser
'123'
expect
toEqual
data
expect
findById
toHaveBeenCalledWith
'123'
it
'should throw NotFoundException when user not found'
async
findById
mockResolvedValue
null
await
expect
getUser
'999'
rejects
toThrow
'User not found'
describe
'createUser'
() =>
it
'should create and return new user'
async
const
email
'new@test.com'
name
'New User'
const
id
'456'
create
mockResolvedValue
const
await
createUser
expect
data
id
toBe
'456'
it
'should validate input'
async
const
email
'invalid'
name
''
await
expect
createUser
rejects
toThrow
'Validation'
Service/Business Logic Tests describe ('UserService' , () => {
let service : UserService ;
let mockRepository : jest.Mocked <UserRepository >;
beforeEach (() => {
mockRepository = {
findById : vi.fn (),
save : vi.fn (),
delete : vi.fn (),
};
service = new UserService (mockRepository);
});
describe ('create' , () => {
it ('should hash password before saving' , async () => {
const input = { email : 'test@test.com' , name : 'Test' , password : 'secret123' };
await service.create (input);
expect (mockRepository.save ).toHaveBeenCalledWith (
expect.objectContaining ({
email : 'test@test.com' ,
passwordHash : expect.not .stringContaining ('secret123' ),
})
);
});
it ('should throw ConflictError for duplicate email' , async () => {
mockRepository.save .mockRejectedValue ({ code : '23505' });
await expect (service.create ({ email : 'existing@test.com' }))
.rejects .toThrow ('Email already exists' );
});
});
});
Integration Testing import { describe, it, expect, beforeAll, afterAll } from 'vitest' ;
import request from 'supertest' ;
import { app } from './app' ;
import { db } from './database' ;
describe ('Users API Integration' , () => {
beforeAll (async () => {
await db.migrate .latest ();
await db.seed .run ();
});
afterAll (async () => {
await db.destroy ();
});
describe ('GET /api/v1/users' , () => {
it ('should return paginated list' , async () => {
const res = await request (app)
.get ('/api/v1/users?page=1&limit=10' )
.set ('Authorization' , `Bearer ${testToken} ` )
.expect (200 );
expect (res.body .data ).toBeInstanceOf (Array );
expect (res.body .pagination ).toMatchObject ({
page : 1 ,
limit : 10 ,
total : expect.any (Number ),
});
});
});
describe ('POST /api/v1/users' , () => {
it ('should persist user to database' , async () => {
const userData = {
email : 'integration@test.com' ,
name : 'Integration Test' ,
password : 'SecurePass123!' ,
};
const res = await request (app)
.post ('/api/v1/users' )
.set ('Authorization' , `Bearer ${adminToken} ` )
.send (userData)
.expect (201 );
const dbUser = await db ('users' )
.where ('id' , res.body .data .id )
.first ();
expect (dbUser).toBeDefined ();
expect (dbUser.email ).toBe (userData.email );
});
});
});
Contract Testing (Pact)
Consumer Side import { Pact } from '@pact-foundation/pact' ;
import { UserApiClient } from './user-api-client' ;
describe ('User API Contract' , () => {
const provider = new Pact ({
consumer : 'WebApp' ,
provider : 'UserService' ,
port : 1234 ,
});
beforeAll (() => provider.setup ());
afterAll (() => provider.finalize ());
afterEach (() => provider.verify ());
describe ('get user by id' , () => {
it ('should return user when exists' , async () => {
await provider.addInteraction ({
state : 'user with id 123 exists' ,
uponReceiving : 'a request for user 123' ,
withRequest : {
method : 'GET' ,
path : '/api/v1/users/123' ,
headers : { Accept : 'application/json' },
},
willRespondWith : {
status : 200 ,
headers : { 'Content-Type' : 'application/json' },
body : {
data : {
id : '123' ,
name : like ('John Doe' ),
email : like ('john@example.com' ),
},
},
},
});
const client = new UserApiClient ('http://localhost:1234' );
const user = await client.getUser ('123' );
expect (user.id ).toBe ('123' );
});
});
});
Provider Side import { Verifier } from '@pact-foundation/pact' ;
describe ('Pact Verification' , () => {
it ('should validate consumer contracts' , async () => {
const verifier = new Verifier ({
providerBaseUrl : 'http://localhost:3000' ,
pactBrokerUrl : process.env .PACT_BROKER_URL ,
provider : 'UserService' ,
publishVerificationResult : true ,
stateHandlers : {
'user with id 123 exists' : async () => {
await db ('users' ).insert ({ id : '123' , name : 'John' , email : 'john@test.com' });
},
},
});
await verifier.verifyProvider ();
});
});
Load Testing (k6)
import http from 'k6/http' ;
import { check, sleep } from 'k6' ;
export const options = {
stages : [
{ duration : '1m' , target : 50 },
{ duration : '3m' , target : 50 },
{ duration : '1m' , target : 100 },
{ duration : '1m' , target : 0 },
],
thresholds : {
http_req_duration : ['p(95)<500' ],
http_req_failed : ['rate<0.01' ],
},
};
export default function ( ) {
const token = __ENV.API_TOKEN ;
const listRes = http.get ('http://api.example.com/api/v1/users?limit=20' , {
headers : { Authorization : `Bearer ${token} ` },
});
check (listRes, {
'list status 200' : (r ) => r.status === 200 ,
'list has data' : (r ) => JSON .parse (r.body ).data .length > 0 ,
});
sleep (1 );
const getRes = http.get ('http://api.example.com/api/v1/users/123' , {
headers : { Authorization : `Bearer ${token} ` },
});
check (getRes, {
'get status 200' : (r ) => r.status === 200 ,
});
sleep (1 );
}
Run: k6 run --env API_TOKEN=xxx load-test.js
Security Testing describe ('Security Tests' , () => {
describe ('Authentication' , () => {
it ('should reject requests without token' , async () => {
await request (app)
.get ('/api/v1/users' )
.expect (401 );
});
it ('should reject expired tokens' , async () => {
await request (app)
.get ('/api/v1/users' )
.set ('Authorization' , `Bearer ${expiredToken} ` )
.expect (401 );
});
});
describe ('Authorization' , () => {
it ('should prevent accessing other users data' , async () => {
await request (app)
.get ('/api/v1/users/other-user-id' )
.set ('Authorization' , `Bearer ${userToken} ` )
.expect (403 );
});
});
describe ('Input Validation' , () => {
it ('should reject SQL injection attempts' , async () => {
await request (app)
.get (`/api/v1/users?search='; DROP TABLE users; --` )
.set ('Authorization' , `Bearer ${token} ` )
.expect (400 );
});
it ('should sanitize XSS in input' , async () => {
const res = await request (app)
.post ('/api/v1/users' )
.set ('Authorization' , `Bearer ${adminToken} ` )
.send ({ name : '<script>alert("xss")</script>' })
.expect (201 );
expect (res.body .data .name ).not .toContain ('<script>' );
});
});
describe ('Rate Limiting' , () => {
it ('should block after exceeding limit' , async () => {
for (let i = 0 ; i < 100 ; i++) {
await request (app).get ('/api/v1/users' );
}
await request (app)
.get ('/api/v1/users' )
.expect (429 );
});
});
});
Troubleshooting Issue Cause Solution Flaky tests Shared state Isolate test data Slow integration tests Database setup Use transactions Contract mismatches Schema changes Version contracts Load test failures Connection limits Check pool size
Quality Checklist