Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "development-skills",
|
||||||
|
"description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Brock"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# development-skills
|
||||||
|
|
||||||
|
Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling
|
||||||
61
plugin.lock.json
Normal file
61
plugin.lock.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:Dieshen/claude_marketplace:plugins/development-skills",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "134df0ad0157ab8c4a7949e6ee174e8ab103b97a",
|
||||||
|
"treeHash": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8",
|
||||||
|
"generatedAt": "2025-11-28T10:10:25.019332Z",
|
||||||
|
"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": "development-skills",
|
||||||
|
"description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "b63b769ddbc49ca1e54f77089671ed4891448dff61554eeb8bc0d4b68603aa90"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "5cf7c8c173b9207f7eeb0663a4f803536d4f953a63b667413cdbe3f28a082e6a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/api-doc-generator.md",
|
||||||
|
"sha256": "b87823388a1c9d28206d39ee8f433b0e324765dad04a58fb3709a971505d83dc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/test-case-generator.md",
|
||||||
|
"sha256": "7ec6472e7008006d6a6c54612238d16ee6086d3b18a866509c04e993e9d1ec5b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/code-review.md",
|
||||||
|
"sha256": "54e5bec5fe6679d1504377cdb918162552974a7ecfc18631677cc467e6c2e044"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/performance-profiler.md",
|
||||||
|
"sha256": "b9ff62ecbf7a04b234163edcf86d690444838ef93eb079f7053207cdc8a6e885"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/adr-generator.md",
|
||||||
|
"sha256": "7cecaee6863728bf78ce605bdd2c43b95a80188eebd8e11e383ef9728f6ea322"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
325
skills/adr-generator.md
Normal file
325
skills/adr-generator.md
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
# Architecture Decision Record (ADR) Generator Skill
|
||||||
|
|
||||||
|
Generate Architecture Decision Records to document important architectural decisions.
|
||||||
|
|
||||||
|
## ADR Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# ADR-{number}: {Title}
|
||||||
|
|
||||||
|
## Status
|
||||||
|
{Proposed | Accepted | Deprecated | Superseded by ADR-XXX}
|
||||||
|
|
||||||
|
## Context
|
||||||
|
What is the issue that we're seeing that is motivating this decision or change?
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
What is the change that we're proposing and/or doing?
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
What becomes easier or more difficult to do because of this change?
|
||||||
|
|
||||||
|
### Positive
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
### Negative
|
||||||
|
- ...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
### Neutral
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## Alternatives Considered
|
||||||
|
What other options were evaluated?
|
||||||
|
|
||||||
|
### Alternative 1: {Name}
|
||||||
|
**Description**: ...
|
||||||
|
|
||||||
|
**Pros**:
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Cons**:
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Why not chosen**: ...
|
||||||
|
|
||||||
|
### Alternative 2: {Name}
|
||||||
|
**Description**: ...
|
||||||
|
|
||||||
|
**Pros**:
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Cons**:
|
||||||
|
- ...
|
||||||
|
|
||||||
|
**Why not chosen**: ...
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
Any specific implementation details or considerations.
|
||||||
|
|
||||||
|
## References
|
||||||
|
- Link to relevant documentation
|
||||||
|
- Link to related ADRs
|
||||||
|
- Link to discussions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common ADR Topics
|
||||||
|
|
||||||
|
### 1. Technology Selection
|
||||||
|
- Programming languages
|
||||||
|
- Frameworks and libraries
|
||||||
|
- Databases
|
||||||
|
- Cloud providers
|
||||||
|
- Message queues
|
||||||
|
- Caching solutions
|
||||||
|
|
||||||
|
### 2. Architecture Patterns
|
||||||
|
- Microservices vs Monolith
|
||||||
|
- Event-driven architecture
|
||||||
|
- CQRS and Event Sourcing
|
||||||
|
- API Gateway patterns
|
||||||
|
- Service mesh adoption
|
||||||
|
|
||||||
|
### 3. Data Management
|
||||||
|
- Database choice (SQL vs NoSQL)
|
||||||
|
- Data modeling approach
|
||||||
|
- Caching strategy
|
||||||
|
- Data migration strategy
|
||||||
|
- Backup and recovery
|
||||||
|
|
||||||
|
### 4. Security
|
||||||
|
- Authentication mechanism
|
||||||
|
- Authorization approach
|
||||||
|
- Encryption standards
|
||||||
|
- Secret management
|
||||||
|
- API security
|
||||||
|
|
||||||
|
### 5. Development Practices
|
||||||
|
- Branching strategy
|
||||||
|
- Code review process
|
||||||
|
- Testing strategy
|
||||||
|
- CI/CD pipeline
|
||||||
|
- Deployment strategy
|
||||||
|
|
||||||
|
### 6. Infrastructure
|
||||||
|
- Hosting platform
|
||||||
|
- Containerization strategy
|
||||||
|
- Orchestration platform
|
||||||
|
- Monitoring and logging
|
||||||
|
- Disaster recovery
|
||||||
|
|
||||||
|
## Example ADR
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# ADR-001: Use PostgreSQL for Primary Database
|
||||||
|
|
||||||
|
## Status
|
||||||
|
Accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
We need to select a database for our new e-commerce platform. The system needs to:
|
||||||
|
- Handle complex relational data (users, orders, products, inventory)
|
||||||
|
- Support ACID transactions for financial data
|
||||||
|
- Scale to millions of records
|
||||||
|
- Provide good query performance
|
||||||
|
- Support full-text search
|
||||||
|
- Be well-supported and documented
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
We will use PostgreSQL 16 as our primary database.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
### Positive
|
||||||
|
- **ACID compliance**: Ensures data consistency for financial transactions
|
||||||
|
- **Rich data types**: JSON, arrays, and custom types provide flexibility
|
||||||
|
- **Full-text search**: Built-in FTS capabilities reduce dependency on external search engines
|
||||||
|
- **Mature ecosystem**: Excellent tooling, extensions, and community support
|
||||||
|
- **Strong consistency**: Suitable for financial and inventory data
|
||||||
|
- **Performance**: Query planner and indexing options provide good performance
|
||||||
|
- **Cost-effective**: Open-source with no licensing fees
|
||||||
|
- **Extensions**: PostGIS for location, pg_cron for scheduling, etc.
|
||||||
|
|
||||||
|
### Negative
|
||||||
|
- **Vertical scaling**: Harder to scale horizontally compared to NoSQL
|
||||||
|
- **Operational complexity**: Requires expertise for tuning and maintenance
|
||||||
|
- **Read replicas**: Additional setup for read-heavy scaling
|
||||||
|
- **Storage**: Can be more storage-intensive than some alternatives
|
||||||
|
|
||||||
|
### Neutral
|
||||||
|
- **Learning curve**: Team has SQL experience, so moderate learning curve
|
||||||
|
- **Hosting**: Available on all major cloud providers
|
||||||
|
|
||||||
|
## Alternatives Considered
|
||||||
|
|
||||||
|
### Alternative 1: MySQL
|
||||||
|
**Description**: Popular open-source relational database
|
||||||
|
|
||||||
|
**Pros**:
|
||||||
|
- Widely used and supported
|
||||||
|
- Good performance for read-heavy workloads
|
||||||
|
- Large ecosystem
|
||||||
|
|
||||||
|
**Cons**:
|
||||||
|
- Less advanced features than PostgreSQL
|
||||||
|
- JSON support not as robust
|
||||||
|
- Less powerful full-text search
|
||||||
|
- Some storage engines lack ACID compliance
|
||||||
|
|
||||||
|
**Why not chosen**: PostgreSQL offers more advanced features that align better with our requirements (JSON, full-text search, complex queries).
|
||||||
|
|
||||||
|
### Alternative 2: MongoDB
|
||||||
|
**Description**: Document-oriented NoSQL database
|
||||||
|
|
||||||
|
**Pros**:
|
||||||
|
- Flexible schema
|
||||||
|
- Horizontal scaling
|
||||||
|
- Fast writes
|
||||||
|
- Good for rapidly changing data models
|
||||||
|
|
||||||
|
**Cons**:
|
||||||
|
- Eventually consistent (can be configured for strong consistency with performance impact)
|
||||||
|
- Less suitable for complex relational queries
|
||||||
|
- Transactions across collections more complex
|
||||||
|
- Not ideal for financial data
|
||||||
|
|
||||||
|
**Why not chosen**: Our data is highly relational and requires strong ACID guarantees for financial transactions.
|
||||||
|
|
||||||
|
### Alternative 3: Amazon DynamoDB
|
||||||
|
**Description**: Fully managed NoSQL database service
|
||||||
|
|
||||||
|
**Pros**:
|
||||||
|
- Fully managed, no ops overhead
|
||||||
|
- Excellent scalability
|
||||||
|
- Low latency
|
||||||
|
- Pay per usage
|
||||||
|
|
||||||
|
**Cons**:
|
||||||
|
- Vendor lock-in
|
||||||
|
- Limited query capabilities
|
||||||
|
- More expensive at scale
|
||||||
|
- Requires different data modeling approach
|
||||||
|
|
||||||
|
**Why not chosen**: Relational model better fits our use case, and we want to avoid vendor lock-in.
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
1. **Version**: Use PostgreSQL 16 for latest features
|
||||||
|
2. **Hosting**: Deploy on AWS RDS for managed service benefits
|
||||||
|
3. **Extensions**: Enable pg_trgm for fuzzy search, pg_stat_statements for monitoring
|
||||||
|
4. **Connection Pooling**: Use PgBouncer for connection management
|
||||||
|
5. **Backup**: Daily automated backups with point-in-time recovery
|
||||||
|
6. **Monitoring**: CloudWatch metrics + custom dashboard
|
||||||
|
7. **Read Replicas**: Configure 2 read replicas for read-heavy queries
|
||||||
|
8. **Migration**: Use TypeORM migrations for schema changes
|
||||||
|
|
||||||
|
## References
|
||||||
|
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
|
||||||
|
- [AWS RDS PostgreSQL](https://aws.amazon.com/rds/postgresql/)
|
||||||
|
- [Database Comparison Spike](https://company.com/docs/db-comparison)
|
||||||
|
- [Team Discussion Thread](https://company.slack.com/archives/C123/p456)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Number ADRs Sequentially
|
||||||
|
Use ADR-001, ADR-002, etc. Never reuse numbers.
|
||||||
|
|
||||||
|
### 2. Keep ADRs Immutable
|
||||||
|
Once accepted, don't modify. Create new ADR to supersede if needed.
|
||||||
|
|
||||||
|
### 3. Be Specific
|
||||||
|
Include concrete technical details, not vague statements.
|
||||||
|
|
||||||
|
### 4. Document Trade-offs
|
||||||
|
Every decision has pros and cons. Document both honestly.
|
||||||
|
|
||||||
|
### 5. Link Related ADRs
|
||||||
|
Reference related decisions to show evolution.
|
||||||
|
|
||||||
|
### 6. Update Status
|
||||||
|
Mark as Deprecated or Superseded when decision changes.
|
||||||
|
|
||||||
|
### 7. Include Team Input
|
||||||
|
Document that stakeholders were consulted.
|
||||||
|
|
||||||
|
### 8. Write for Future Readers
|
||||||
|
Someone reading 2 years later should understand why the decision was made.
|
||||||
|
|
||||||
|
### 9. Keep It Concise
|
||||||
|
Aim for 1-2 pages. Link to detailed analysis separately.
|
||||||
|
|
||||||
|
### 10. Review Periodically
|
||||||
|
Revisit ADRs annually to ensure they're still relevant.
|
||||||
|
|
||||||
|
## ADR Lifecycle
|
||||||
|
|
||||||
|
1. **Proposed**: Initial draft, under discussion
|
||||||
|
2. **Accepted**: Team has agreed, implementation can proceed
|
||||||
|
3. **Implemented**: Decision has been executed
|
||||||
|
4. **Deprecated**: No longer recommended but not formally replaced
|
||||||
|
5. **Superseded**: Replaced by a newer ADR
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
Store ADRs in version control:
|
||||||
|
```
|
||||||
|
docs/
|
||||||
|
architecture/
|
||||||
|
decisions/
|
||||||
|
001-use-postgresql.md
|
||||||
|
002-adopt-microservices.md
|
||||||
|
003-use-react-native.md
|
||||||
|
README.md (index of all ADRs)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Index Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Architecture Decision Records
|
||||||
|
|
||||||
|
## Active
|
||||||
|
- [ADR-001: Use PostgreSQL for Primary Database](001-use-postgresql.md)
|
||||||
|
- [ADR-002: Adopt Microservices Architecture](002-adopt-microservices.md)
|
||||||
|
|
||||||
|
## Superseded
|
||||||
|
- [ADR-003: Use Redux for State Management](003-use-redux.md) - Superseded by ADR-010
|
||||||
|
|
||||||
|
## Deprecated
|
||||||
|
- None
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lightweight Alternative
|
||||||
|
|
||||||
|
For smaller decisions, use a simplified format:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Decision: {Title}
|
||||||
|
|
||||||
|
## Context
|
||||||
|
Brief context (2-3 sentences)
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
What we're doing (2-3 sentences)
|
||||||
|
|
||||||
|
## Trade-offs
|
||||||
|
- **Pro**: ...
|
||||||
|
- **Pro**: ...
|
||||||
|
- **Con**: ...
|
||||||
|
- **Con**: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
Before accepting an ADR:
|
||||||
|
- [ ] Context clearly explains the problem
|
||||||
|
- [ ] Decision is specific and actionable
|
||||||
|
- [ ] Consequences (positive and negative) are documented
|
||||||
|
- [ ] At least 2 alternatives were considered
|
||||||
|
- [ ] Trade-offs are honestly assessed
|
||||||
|
- [ ] Implementation notes provide enough detail
|
||||||
|
- [ ] References are included
|
||||||
|
- [ ] Stakeholders have reviewed
|
||||||
|
- [ ] ADR number is assigned
|
||||||
|
- [ ] Status is set correctly
|
||||||
567
skills/api-doc-generator.md
Normal file
567
skills/api-doc-generator.md
Normal file
@@ -0,0 +1,567 @@
|
|||||||
|
# API Documentation Generator Skill
|
||||||
|
|
||||||
|
Automatically generate comprehensive API documentation from code.
|
||||||
|
|
||||||
|
## OpenAPI 3.0 Generation
|
||||||
|
|
||||||
|
### From Express.js/TypeScript
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /api/users:
|
||||||
|
* get:
|
||||||
|
* summary: List all users
|
||||||
|
* tags: [Users]
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: page
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: Page number
|
||||||
|
* - in: query
|
||||||
|
* name: limit
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: Items per page
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Success
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* users:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* $ref: '#/components/schemas/User'
|
||||||
|
* pagination:
|
||||||
|
* $ref: '#/components/schemas/Pagination'
|
||||||
|
*/
|
||||||
|
app.get('/api/users', async (req, res) => {
|
||||||
|
// Implementation
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete OpenAPI Spec Template
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: My API
|
||||||
|
version: 1.0.0
|
||||||
|
description: Comprehensive API for managing users and resources
|
||||||
|
contact:
|
||||||
|
name: API Support
|
||||||
|
email: support@example.com
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
url: https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: https://api.example.com/v1
|
||||||
|
description: Production server
|
||||||
|
- url: https://staging-api.example.com/v1
|
||||||
|
description: Staging server
|
||||||
|
- url: http://localhost:3000/v1
|
||||||
|
description: Development server
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- name: Users
|
||||||
|
description: User management endpoints
|
||||||
|
- name: Authentication
|
||||||
|
description: Authentication endpoints
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/auth/login:
|
||||||
|
post:
|
||||||
|
summary: User login
|
||||||
|
tags: [Authentication]
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- password
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
example: user@example.com
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
format: password
|
||||||
|
example: SecurePass123!
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Login successful
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
token:
|
||||||
|
type: string
|
||||||
|
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||||
|
user:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
'401':
|
||||||
|
description: Invalid credentials
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
/users:
|
||||||
|
get:
|
||||||
|
summary: List users
|
||||||
|
tags: [Users]
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/PageParam'
|
||||||
|
- $ref: '#/components/parameters/LimitParam'
|
||||||
|
- in: query
|
||||||
|
name: search
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Search term
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Success
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
pagination:
|
||||||
|
$ref: '#/components/schemas/Pagination'
|
||||||
|
|
||||||
|
post:
|
||||||
|
summary: Create user
|
||||||
|
tags: [Users]
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CreateUserInput'
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: User created
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/Unauthorized'
|
||||||
|
|
||||||
|
/users/{id}:
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/UserIdParam'
|
||||||
|
|
||||||
|
get:
|
||||||
|
summary: Get user by ID
|
||||||
|
tags: [Users]
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Success
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
'404':
|
||||||
|
$ref: '#/components/responses/NotFound'
|
||||||
|
|
||||||
|
patch:
|
||||||
|
summary: Update user
|
||||||
|
tags: [Users]
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UpdateUserInput'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: User updated
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
|
||||||
|
delete:
|
||||||
|
summary: Delete user
|
||||||
|
tags: [Users]
|
||||||
|
security:
|
||||||
|
- BearerAuth: []
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: User deleted
|
||||||
|
'404':
|
||||||
|
$ref: '#/components/responses/NotFound'
|
||||||
|
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
BearerAuth:
|
||||||
|
type: http
|
||||||
|
scheme: bearer
|
||||||
|
bearerFormat: JWT
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
UserIdParam:
|
||||||
|
in: path
|
||||||
|
name: id
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: User ID
|
||||||
|
|
||||||
|
PageParam:
|
||||||
|
in: query
|
||||||
|
name: page
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
default: 1
|
||||||
|
description: Page number
|
||||||
|
|
||||||
|
LimitParam:
|
||||||
|
in: query
|
||||||
|
name: limit
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maximum: 100
|
||||||
|
default: 20
|
||||||
|
description: Items per page
|
||||||
|
|
||||||
|
schemas:
|
||||||
|
User:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- email
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
example: usr_123abc
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
example: user@example.com
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: John Doe
|
||||||
|
role:
|
||||||
|
type: string
|
||||||
|
enum: [user, admin]
|
||||||
|
default: user
|
||||||
|
createdAt:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
updatedAt:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
|
||||||
|
CreateUserInput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- name
|
||||||
|
- password
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
minLength: 1
|
||||||
|
maxLength: 100
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
format: password
|
||||||
|
minLength: 8
|
||||||
|
|
||||||
|
UpdateUserInput:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
|
||||||
|
Pagination:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
page:
|
||||||
|
type: integer
|
||||||
|
limit:
|
||||||
|
type: integer
|
||||||
|
totalPages:
|
||||||
|
type: integer
|
||||||
|
totalItems:
|
||||||
|
type: integer
|
||||||
|
hasNext:
|
||||||
|
type: boolean
|
||||||
|
hasPrevious:
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
Error:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
details:
|
||||||
|
type: object
|
||||||
|
|
||||||
|
responses:
|
||||||
|
BadRequest:
|
||||||
|
description: Bad request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
Unauthorized:
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
|
||||||
|
NotFound:
|
||||||
|
description: Not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Error'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate from Code
|
||||||
|
|
||||||
|
### TypeScript/Express
|
||||||
|
```typescript
|
||||||
|
import swaggerJsdoc from 'swagger-jsdoc';
|
||||||
|
import swaggerUi from 'swagger-ui-express';
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
definition: {
|
||||||
|
openapi: '3.0.0',
|
||||||
|
info: {
|
||||||
|
title: 'My API',
|
||||||
|
version: '1.0.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
apis: ['./src/routes/*.ts'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const specs = swaggerJsdoc(options);
|
||||||
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python/FastAPI (Auto-generated)
|
||||||
|
```python
|
||||||
|
from fastapi import FastAPI, Query
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI(
|
||||||
|
title="My API",
|
||||||
|
description="API documentation",
|
||||||
|
version="1.0.0"
|
||||||
|
)
|
||||||
|
|
||||||
|
class User(BaseModel):
|
||||||
|
id: str
|
||||||
|
email: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
@app.get("/users", response_model=list[User])
|
||||||
|
async def list_users(
|
||||||
|
page: int = Query(1, ge=1, description="Page number"),
|
||||||
|
limit: int = Query(20, ge=1, le=100, description="Items per page")
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
List all users with pagination.
|
||||||
|
|
||||||
|
Returns a paginated list of users.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
# Docs auto-generated at /docs
|
||||||
|
```
|
||||||
|
|
||||||
|
## README API Documentation
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# API Documentation
|
||||||
|
|
||||||
|
## Base URL
|
||||||
|
```
|
||||||
|
https://api.example.com/v1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
All endpoints require Bearer token authentication:
|
||||||
|
```
|
||||||
|
Authorization: Bearer YOUR_TOKEN_HERE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
### List Users
|
||||||
|
```http
|
||||||
|
GET /users?page=1&limit=20
|
||||||
|
```
|
||||||
|
|
||||||
|
**Query Parameters**:
|
||||||
|
- `page` (integer, optional): Page number, default 1
|
||||||
|
- `limit` (integer, optional): Items per page, default 20, max 100
|
||||||
|
- `search` (string, optional): Search term
|
||||||
|
|
||||||
|
**Response 200**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": "usr_123",
|
||||||
|
"email": "user@example.com",
|
||||||
|
"name": "John Doe",
|
||||||
|
"role": "user",
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": {
|
||||||
|
"page": 1,
|
||||||
|
"totalPages": 5,
|
||||||
|
"totalItems": 95
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create User
|
||||||
|
```http
|
||||||
|
POST /users
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"email": "newuser@example.com",
|
||||||
|
"name": "New User",
|
||||||
|
"password": "SecurePass123!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response 201**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "usr_456",
|
||||||
|
"email": "newuser@example.com",
|
||||||
|
"name": "New User",
|
||||||
|
"role": "user",
|
||||||
|
"createdAt": "2024-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Responses
|
||||||
|
|
||||||
|
All errors follow this format:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "ERROR_CODE",
|
||||||
|
"message": "Human-readable message",
|
||||||
|
"details": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Status Codes
|
||||||
|
- `200` - Success
|
||||||
|
- `201` - Created
|
||||||
|
- `204` - No Content
|
||||||
|
- `400` - Bad Request
|
||||||
|
- `401` - Unauthorized
|
||||||
|
- `403` - Forbidden
|
||||||
|
- `404` - Not Found
|
||||||
|
- `422` - Validation Error
|
||||||
|
- `429` - Rate Limit Exceeded
|
||||||
|
- `500` - Internal Server Error
|
||||||
|
|
||||||
|
## Rate Limiting
|
||||||
|
- 100 requests per minute per IP
|
||||||
|
- 1000 requests per hour per user
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### JavaScript/Fetch
|
||||||
|
```javascript
|
||||||
|
const response = await fetch('https://api.example.com/v1/users', {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python/Requests
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
response = requests.get(
|
||||||
|
'https://api.example.com/v1/users',
|
||||||
|
headers={'Authorization': f'Bearer {token}'}
|
||||||
|
)
|
||||||
|
data = response.json()
|
||||||
|
```
|
||||||
|
|
||||||
|
### cURL
|
||||||
|
```bash
|
||||||
|
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
||||||
|
https://api.example.com/v1/users
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
## Postman Collection
|
||||||
|
|
||||||
|
Generate Postman collection from OpenAPI:
|
||||||
|
```bash
|
||||||
|
openapi2postmanv2 -s openapi.yaml -o postman_collection.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Be Comprehensive**: Document all endpoints, parameters, and responses
|
||||||
|
2. **Provide Examples**: Include real request/response examples
|
||||||
|
3. **Document Errors**: Show all possible error responses
|
||||||
|
4. **Code Samples**: Provide examples in multiple languages
|
||||||
|
5. **Keep Updated**: Auto-generate from code when possible
|
||||||
|
6. **Version APIs**: Include version in URL or headers
|
||||||
|
7. **Security**: Document authentication clearly
|
||||||
|
8. **Rate Limits**: Specify rate limiting rules
|
||||||
|
9. **Changelog**: Maintain API changelog
|
||||||
|
10. **Interactive Docs**: Use Swagger UI or similar
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
- **Swagger UI**: Interactive API documentation
|
||||||
|
- **Redoc**: Beautiful API documentation
|
||||||
|
- **Postman**: API testing and documentation
|
||||||
|
- **Insomnia**: API client and documentation
|
||||||
|
- **Stoplight**: API design and documentation platform
|
||||||
220
skills/code-review.md
Normal file
220
skills/code-review.md
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
# Code Review Skill
|
||||||
|
|
||||||
|
Perform comprehensive code reviews following industry best practices.
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
### 1. Code Quality
|
||||||
|
- [ ] Follows coding standards and style guide
|
||||||
|
- [ ] No code duplication (DRY principle)
|
||||||
|
- [ ] Functions are small and focused (SRP)
|
||||||
|
- [ ] Meaningful variable and function names
|
||||||
|
- [ ] Appropriate use of comments (why, not what)
|
||||||
|
- [ ] No magic numbers or strings
|
||||||
|
- [ ] Proper error handling
|
||||||
|
|
||||||
|
### 2. Architecture & Design
|
||||||
|
- [ ] SOLID principles applied
|
||||||
|
- [ ] Appropriate design patterns used
|
||||||
|
- [ ] Separation of concerns
|
||||||
|
- [ ] Dependency injection where appropriate
|
||||||
|
- [ ] No circular dependencies
|
||||||
|
- [ ] Interfaces used for abstraction
|
||||||
|
- [ ] Proper layering/modularity
|
||||||
|
|
||||||
|
### 3. Security
|
||||||
|
- [ ] No hardcoded secrets or credentials
|
||||||
|
- [ ] Input validation and sanitization
|
||||||
|
- [ ] SQL injection prevention
|
||||||
|
- [ ] XSS prevention
|
||||||
|
- [ ] CSRF protection where needed
|
||||||
|
- [ ] Proper authentication/authorization
|
||||||
|
- [ ] Secure data transmission
|
||||||
|
- [ ] No sensitive data in logs
|
||||||
|
|
||||||
|
### 4. Performance
|
||||||
|
- [ ] Efficient algorithms and data structures
|
||||||
|
- [ ] No N+1 queries
|
||||||
|
- [ ] Proper indexing for database queries
|
||||||
|
- [ ] Caching implemented where appropriate
|
||||||
|
- [ ] No unnecessary computations
|
||||||
|
- [ ] Lazy loading where appropriate
|
||||||
|
- [ ] Resource cleanup (connections, files)
|
||||||
|
|
||||||
|
### 5. Testing
|
||||||
|
- [ ] Unit tests present and passing
|
||||||
|
- [ ] Integration tests where needed
|
||||||
|
- [ ] Test coverage is adequate (>80% for critical paths)
|
||||||
|
- [ ] Edge cases tested
|
||||||
|
- [ ] Error conditions tested
|
||||||
|
- [ ] Tests are maintainable
|
||||||
|
- [ ] No flaky tests
|
||||||
|
|
||||||
|
### 6. Error Handling
|
||||||
|
- [ ] All errors properly caught and handled
|
||||||
|
- [ ] Meaningful error messages
|
||||||
|
- [ ] Proper logging at appropriate levels
|
||||||
|
- [ ] No swallowed exceptions
|
||||||
|
- [ ] Graceful degradation
|
||||||
|
- [ ] Retry logic where appropriate
|
||||||
|
|
||||||
|
### 7. Documentation
|
||||||
|
- [ ] README updated if needed
|
||||||
|
- [ ] API documentation present
|
||||||
|
- [ ] Complex logic explained
|
||||||
|
- [ ] Public APIs documented
|
||||||
|
- [ ] Breaking changes noted
|
||||||
|
- [ ] Migration guide if needed
|
||||||
|
|
||||||
|
### 8. Dependencies
|
||||||
|
- [ ] No unnecessary dependencies
|
||||||
|
- [ ] Dependencies are up to date
|
||||||
|
- [ ] No known vulnerabilities
|
||||||
|
- [ ] License compatibility checked
|
||||||
|
- [ ] Bundle size impact considered
|
||||||
|
|
||||||
|
### 9. Database
|
||||||
|
- [ ] Migrations are reversible
|
||||||
|
- [ ] Indexes on foreign keys
|
||||||
|
- [ ] No missing indexes for queries
|
||||||
|
- [ ] Proper transaction handling
|
||||||
|
- [ ] Connection pooling used
|
||||||
|
- [ ] Data validation at DB level
|
||||||
|
|
||||||
|
### 10. API Design
|
||||||
|
- [ ] RESTful principles followed
|
||||||
|
- [ ] Consistent naming conventions
|
||||||
|
- [ ] Proper HTTP methods and status codes
|
||||||
|
- [ ] Versioning strategy in place
|
||||||
|
- [ ] Rate limiting considered
|
||||||
|
- [ ] Pagination for list endpoints
|
||||||
|
|
||||||
|
## Review Process
|
||||||
|
|
||||||
|
1. **Understand the Context**
|
||||||
|
- Read the PR/commit description
|
||||||
|
- Understand what problem is being solved
|
||||||
|
- Review linked issues/tickets
|
||||||
|
|
||||||
|
2. **High-Level Review**
|
||||||
|
- Check overall architecture
|
||||||
|
- Verify design decisions
|
||||||
|
- Look for major issues
|
||||||
|
|
||||||
|
3. **Detailed Review**
|
||||||
|
- Go through code line by line
|
||||||
|
- Check against checklist above
|
||||||
|
- Note issues by severity
|
||||||
|
|
||||||
|
4. **Security Review**
|
||||||
|
- Look for security vulnerabilities
|
||||||
|
- Check authentication/authorization
|
||||||
|
- Verify input validation
|
||||||
|
|
||||||
|
5. **Performance Review**
|
||||||
|
- Look for performance issues
|
||||||
|
- Check database queries
|
||||||
|
- Review caching strategy
|
||||||
|
|
||||||
|
6. **Test Review**
|
||||||
|
- Verify test coverage
|
||||||
|
- Check test quality
|
||||||
|
- Run tests locally
|
||||||
|
|
||||||
|
7. **Provide Feedback**
|
||||||
|
- Categorize by severity: Critical, Major, Minor, Suggestion
|
||||||
|
- Be specific and constructive
|
||||||
|
- Provide examples or alternatives
|
||||||
|
- Acknowledge good practices
|
||||||
|
|
||||||
|
## Severity Levels
|
||||||
|
|
||||||
|
**Critical**: Must be fixed before merge
|
||||||
|
- Security vulnerabilities
|
||||||
|
- Data loss scenarios
|
||||||
|
- Breaking changes without migration
|
||||||
|
- Production-breaking bugs
|
||||||
|
|
||||||
|
**Major**: Should be fixed before merge
|
||||||
|
- Performance issues
|
||||||
|
- Architectural violations
|
||||||
|
- Missing error handling
|
||||||
|
- Inadequate test coverage
|
||||||
|
|
||||||
|
**Minor**: Can be fixed later
|
||||||
|
- Code style issues
|
||||||
|
- Missing comments
|
||||||
|
- Minor refactoring opportunities
|
||||||
|
|
||||||
|
**Suggestion**: Optional improvements
|
||||||
|
- Alternative approaches
|
||||||
|
- Future enhancements
|
||||||
|
- Code organization ideas
|
||||||
|
|
||||||
|
## Example Review Comments
|
||||||
|
|
||||||
|
### Good Comments
|
||||||
|
✅ "Consider using a Map instead of nested loops here for O(1) lookups. Current implementation is O(n²) which could be slow with large datasets."
|
||||||
|
|
||||||
|
✅ "This endpoint is missing authentication. Should we add the @RequireAuth decorator?"
|
||||||
|
|
||||||
|
✅ "Great use of the strategy pattern here! This makes adding new payment methods much easier."
|
||||||
|
|
||||||
|
### Bad Comments
|
||||||
|
❌ "This is wrong."
|
||||||
|
❌ "Why did you do it this way?"
|
||||||
|
❌ "I would have done X instead."
|
||||||
|
|
||||||
|
## Automated Checks
|
||||||
|
|
||||||
|
Run these before manual review:
|
||||||
|
```bash
|
||||||
|
# Linting
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
npm run type-check
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
npm run test
|
||||||
|
|
||||||
|
# Security scan
|
||||||
|
npm audit
|
||||||
|
|
||||||
|
# Code coverage
|
||||||
|
npm run test:coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
## Focus Areas by Language
|
||||||
|
|
||||||
|
### JavaScript/TypeScript
|
||||||
|
- Proper use of async/await
|
||||||
|
- No console.log in production
|
||||||
|
- TypeScript types used correctly
|
||||||
|
- React hooks rules followed
|
||||||
|
|
||||||
|
### Python
|
||||||
|
- PEP 8 compliance
|
||||||
|
- Type hints used
|
||||||
|
- Virtual environment used
|
||||||
|
- Requirements.txt updated
|
||||||
|
|
||||||
|
### Go
|
||||||
|
- Error handling (don't ignore errors)
|
||||||
|
- Proper defer usage
|
||||||
|
- Channel and goroutine safety
|
||||||
|
- Context usage for cancellation
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
- Ownership rules followed
|
||||||
|
- No unsafe blocks without justification
|
||||||
|
- Error handling with Result/Option
|
||||||
|
- Lifetime annotations correct
|
||||||
|
|
||||||
|
## Post-Review
|
||||||
|
|
||||||
|
After review is complete:
|
||||||
|
- Mark as approved if all critical/major issues resolved
|
||||||
|
- Request changes if issues remain
|
||||||
|
- Follow up on suggested improvements
|
||||||
|
- Document any technical debt created
|
||||||
421
skills/performance-profiler.md
Normal file
421
skills/performance-profiler.md
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
# Performance Profiler Skill
|
||||||
|
|
||||||
|
Analyze code performance and provide optimization recommendations.
|
||||||
|
|
||||||
|
## Performance Analysis Checklist
|
||||||
|
|
||||||
|
### 1. Algorithm Complexity
|
||||||
|
- [ ] Time complexity documented (O(n), O(n²), etc.)
|
||||||
|
- [ ] Space complexity analyzed
|
||||||
|
- [ ] No nested loops where not necessary
|
||||||
|
- [ ] Efficient data structures chosen
|
||||||
|
- [ ] Binary search used instead of linear where possible
|
||||||
|
|
||||||
|
### 2. Database Performance
|
||||||
|
- [ ] Queries use appropriate indexes
|
||||||
|
- [ ] No N+1 query problems
|
||||||
|
- [ ] Connection pooling implemented
|
||||||
|
- [ ] Batch operations used for bulk updates
|
||||||
|
- [ ] Query execution plans analyzed
|
||||||
|
|
||||||
|
### 3. Caching
|
||||||
|
- [ ] Expensive computations cached
|
||||||
|
- [ ] API responses cached appropriately
|
||||||
|
- [ ] Cache invalidation strategy in place
|
||||||
|
- [ ] CDN used for static assets
|
||||||
|
- [ ] Redis/Memcached for distributed caching
|
||||||
|
|
||||||
|
### 4. Network & I/O
|
||||||
|
- [ ] API calls batched where possible
|
||||||
|
- [ ] Compression enabled (gzip, brotli)
|
||||||
|
- [ ] HTTP/2 or HTTP/3 used
|
||||||
|
- [ ] Keep-alive connections
|
||||||
|
- [ ] Parallel requests for independent data
|
||||||
|
|
||||||
|
### 5. Frontend Performance
|
||||||
|
- [ ] Code splitting implemented
|
||||||
|
- [ ] Lazy loading for routes/components
|
||||||
|
- [ ] Images optimized and lazy loaded
|
||||||
|
- [ ] Virtual scrolling for long lists
|
||||||
|
- [ ] Debouncing/throttling on events
|
||||||
|
- [ ] Memoization for expensive renders
|
||||||
|
|
||||||
|
### 6. Memory Management
|
||||||
|
- [ ] No memory leaks
|
||||||
|
- [ ] Event listeners cleaned up
|
||||||
|
- [ ] Large objects garbage collected
|
||||||
|
- [ ] Streams used for large files
|
||||||
|
- [ ] WeakMap/WeakSet for cached objects
|
||||||
|
|
||||||
|
## Performance Profiling Tools
|
||||||
|
|
||||||
|
### Node.js
|
||||||
|
```javascript
|
||||||
|
// Built-in profiler
|
||||||
|
node --prof app.js
|
||||||
|
node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt
|
||||||
|
|
||||||
|
// Chrome DevTools
|
||||||
|
node --inspect app.js
|
||||||
|
// Then open chrome://inspect
|
||||||
|
|
||||||
|
// Clinic.js
|
||||||
|
clinic doctor -- node app.js
|
||||||
|
clinic flame -- node app.js
|
||||||
|
clinic bubbleprof -- node app.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Browser
|
||||||
|
```javascript
|
||||||
|
// Performance API
|
||||||
|
performance.mark('start');
|
||||||
|
// ... code to measure
|
||||||
|
performance.mark('end');
|
||||||
|
performance.measure('myOperation', 'start', 'end');
|
||||||
|
const measures = performance.getEntriesByType('measure');
|
||||||
|
console.log(measures[0].duration);
|
||||||
|
|
||||||
|
// Chrome DevTools Performance tab
|
||||||
|
// Record → Run code → Stop → Analyze flame graph
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
```python
|
||||||
|
import cProfile
|
||||||
|
import pstats
|
||||||
|
|
||||||
|
# Profile function
|
||||||
|
cProfile.run('my_function()', 'output.prof')
|
||||||
|
|
||||||
|
# Analyze results
|
||||||
|
stats = pstats.Stats('output.prof')
|
||||||
|
stats.sort_stats('cumulative')
|
||||||
|
stats.print_stats(20) # Top 20 functions
|
||||||
|
|
||||||
|
# Line profiler
|
||||||
|
from line_profiler import LineProfiler
|
||||||
|
lp = LineProfiler()
|
||||||
|
lp.add_function(my_function)
|
||||||
|
lp.run('my_function()')
|
||||||
|
lp.print_stats()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Performance Issues & Fixes
|
||||||
|
|
||||||
|
### Issue 1: N+1 Queries
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: N+1 queries
|
||||||
|
const users = await User.findAll();
|
||||||
|
for (const user of users) {
|
||||||
|
user.posts = await Post.findAll({ where: { userId: user.id } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Single query with join
|
||||||
|
const users = await User.findAll({
|
||||||
|
include: [{ model: Post }]
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ Better: DataLoader for batching
|
||||||
|
const postLoader = new DataLoader(async (userIds) => {
|
||||||
|
const posts = await Post.findAll({
|
||||||
|
where: { userId: { $in: userIds } }
|
||||||
|
});
|
||||||
|
return userIds.map(id => posts.filter(p => p.userId === id));
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue 2: Inefficient Loops
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: O(n²)
|
||||||
|
function findDuplicates(arr: number[]): number[] {
|
||||||
|
const duplicates = [];
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
for (let j = i + 1; j < arr.length; j++) {
|
||||||
|
if (arr[i] === arr[j]) {
|
||||||
|
duplicates.push(arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return duplicates;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: O(n)
|
||||||
|
function findDuplicates(arr: number[]): number[] {
|
||||||
|
const seen = new Set();
|
||||||
|
const duplicates = new Set();
|
||||||
|
for (const num of arr) {
|
||||||
|
if (seen.has(num)) {
|
||||||
|
duplicates.add(num);
|
||||||
|
}
|
||||||
|
seen.add(num);
|
||||||
|
}
|
||||||
|
return Array.from(duplicates);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue 3: Large Lists Without Virtualization
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: Renders all 10,000 items
|
||||||
|
{items.map(item => <ItemCard key={item.id} {...item} />)}
|
||||||
|
|
||||||
|
// ✅ Good: Virtual scrolling
|
||||||
|
import { FixedSizeList } from 'react-window';
|
||||||
|
|
||||||
|
<FixedSizeList
|
||||||
|
height={600}
|
||||||
|
itemCount={items.length}
|
||||||
|
itemSize={80}
|
||||||
|
width="100%"
|
||||||
|
>
|
||||||
|
{({ index, style }) => (
|
||||||
|
<div style={style}>
|
||||||
|
<ItemCard {...items[index]} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</FixedSizeList>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue 4: Unnecessary Re-renders
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: Re-renders on every parent render
|
||||||
|
function ExpensiveComponent({ data }) {
|
||||||
|
const processed = processData(data); // Runs every render
|
||||||
|
return <div>{processed}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Memoized
|
||||||
|
const ExpensiveComponent = React.memo(({ data }) => {
|
||||||
|
const processed = useMemo(() => processData(data), [data]);
|
||||||
|
return <div>{processed}</div>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue 5: Blocking Operations
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: Blocks event loop
|
||||||
|
function processLargeFile() {
|
||||||
|
const data = fs.readFileSync('large-file.json'); // Blocks!
|
||||||
|
return JSON.parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Async
|
||||||
|
async function processLargeFile() {
|
||||||
|
const data = await fs.promises.readFile('large-file.json', 'utf8');
|
||||||
|
return JSON.parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Better: Streaming
|
||||||
|
function processLargeFileStream() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const stream = fs.createReadStream('large-file.json');
|
||||||
|
let data = '';
|
||||||
|
stream.on('data', chunk => data += chunk);
|
||||||
|
stream.on('end', () => resolve(JSON.parse(data)));
|
||||||
|
stream.on('error', reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Benchmarking
|
||||||
|
|
||||||
|
### JavaScript/TypeScript
|
||||||
|
```typescript
|
||||||
|
import Benchmark from 'benchmark';
|
||||||
|
|
||||||
|
const suite = new Benchmark.Suite();
|
||||||
|
|
||||||
|
suite
|
||||||
|
.add('Array.forEach', () => {
|
||||||
|
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||||
|
arr.forEach(x => x * 2);
|
||||||
|
})
|
||||||
|
.add('for loop', () => {
|
||||||
|
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] * 2;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.add('Array.map', () => {
|
||||||
|
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||||
|
arr.map(x => x * 2);
|
||||||
|
})
|
||||||
|
.on('cycle', (event) => {
|
||||||
|
console.log(String(event.target));
|
||||||
|
})
|
||||||
|
.on('complete', function() {
|
||||||
|
console.log('Fastest is ' + this.filter('fastest').map('name'));
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
```python
|
||||||
|
import timeit
|
||||||
|
|
||||||
|
def method1():
|
||||||
|
return [x * 2 for x in range(1000)]
|
||||||
|
|
||||||
|
def method2():
|
||||||
|
return list(map(lambda x: x * 2, range(1000)))
|
||||||
|
|
||||||
|
time1 = timeit.timeit(method1, number=10000)
|
||||||
|
time2 = timeit.timeit(method2, number=10000)
|
||||||
|
|
||||||
|
print(f"Method 1: {time1:.4f}s")
|
||||||
|
print(f"Method 2: {time2:.4f}s")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Query Optimization
|
||||||
|
|
||||||
|
### Analyze Slow Queries
|
||||||
|
```sql
|
||||||
|
-- PostgreSQL: Enable slow query logging
|
||||||
|
ALTER SYSTEM SET log_min_duration_statement = 1000; -- Log queries > 1s
|
||||||
|
SELECT pg_reload_conf();
|
||||||
|
|
||||||
|
-- View slow queries
|
||||||
|
SELECT
|
||||||
|
calls,
|
||||||
|
total_exec_time,
|
||||||
|
mean_exec_time,
|
||||||
|
max_exec_time,
|
||||||
|
query
|
||||||
|
FROM pg_stat_statements
|
||||||
|
ORDER BY mean_exec_time DESC
|
||||||
|
LIMIT 20;
|
||||||
|
|
||||||
|
-- Explain query
|
||||||
|
EXPLAIN ANALYZE
|
||||||
|
SELECT u.*, COUNT(p.id) as post_count
|
||||||
|
FROM users u
|
||||||
|
LEFT JOIN posts p ON u.id = p.user_id
|
||||||
|
GROUP BY u.id;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add Indexes
|
||||||
|
```sql
|
||||||
|
-- Before: Sequential scan
|
||||||
|
SELECT * FROM users WHERE email = 'user@example.com';
|
||||||
|
-- Seq Scan on users (cost=0.00..180.00 rows=1)
|
||||||
|
|
||||||
|
-- Add index
|
||||||
|
CREATE INDEX idx_users_email ON users(email);
|
||||||
|
|
||||||
|
-- After: Index scan
|
||||||
|
-- Index Scan using idx_users_email on users (cost=0.42..8.44 rows=1)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Memory Leak Detection
|
||||||
|
|
||||||
|
### Node.js
|
||||||
|
```javascript
|
||||||
|
// Detect memory leaks
|
||||||
|
const heapdump = require('heapdump');
|
||||||
|
|
||||||
|
// Take heap snapshot
|
||||||
|
heapdump.writeSnapshot(`./heap-${Date.now()}.heapsnapshot`);
|
||||||
|
|
||||||
|
// Compare snapshots in Chrome DevTools
|
||||||
|
// Memory → Load → Compare snapshots
|
||||||
|
|
||||||
|
// Monitor memory usage
|
||||||
|
setInterval(() => {
|
||||||
|
const used = process.memoryUsage();
|
||||||
|
console.log({
|
||||||
|
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
|
||||||
|
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
|
||||||
|
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
|
||||||
|
external: `${Math.round(used.external / 1024 / 1024)}MB`,
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Budget
|
||||||
|
|
||||||
|
Define acceptable performance metrics:
|
||||||
|
|
||||||
|
### Web Application
|
||||||
|
- **First Contentful Paint (FCP)**: < 1.8s
|
||||||
|
- **Largest Contentful Paint (LCP)**: < 2.5s
|
||||||
|
- **Time to Interactive (TTI)**: < 3.8s
|
||||||
|
- **Total Blocking Time (TBT)**: < 200ms
|
||||||
|
- **Cumulative Layout Shift (CLS)**: < 0.1
|
||||||
|
- **Bundle Size**: < 200KB (gzipped)
|
||||||
|
|
||||||
|
### API
|
||||||
|
- **Response Time (p50)**: < 100ms
|
||||||
|
- **Response Time (p95)**: < 500ms
|
||||||
|
- **Response Time (p99)**: < 1000ms
|
||||||
|
- **Throughput**: > 1000 req/s
|
||||||
|
- **Error Rate**: < 0.1%
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- **Query Time (avg)**: < 50ms
|
||||||
|
- **Connection Pool**: < 80% utilization
|
||||||
|
- **Cache Hit Rate**: > 90%
|
||||||
|
|
||||||
|
## Optimization Priority
|
||||||
|
|
||||||
|
1. **Measure First**: Profile before optimizing
|
||||||
|
2. **Focus on Bottlenecks**: 20% of code causes 80% of issues
|
||||||
|
3. **User-Facing First**: Optimize what users experience
|
||||||
|
4. **Low-Hanging Fruit**: Easy wins first
|
||||||
|
5. **Monitor Continuously**: Set up alerts for regressions
|
||||||
|
|
||||||
|
## Performance Testing
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Load testing with autocannon
|
||||||
|
import autocannon from 'autocannon';
|
||||||
|
|
||||||
|
autocannon({
|
||||||
|
url: 'http://localhost:3000/api/users',
|
||||||
|
connections: 100,
|
||||||
|
duration: 30,
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer token'
|
||||||
|
}
|
||||||
|
}, (err, result) => {
|
||||||
|
console.log('Requests/sec:', result.requests.average);
|
||||||
|
console.log('Latency p50:', result.latency.p50);
|
||||||
|
console.log('Latency p99:', result.latency.p99);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Report Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Performance Analysis Report
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
- **Current Performance**: X req/s, Yms avg response
|
||||||
|
- **Target Performance**: A req/s, Bms avg response
|
||||||
|
- **Gap**: Need to improve by Z%
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
### Critical Issues
|
||||||
|
1. **N+1 Query in /api/users** (Impact: High)
|
||||||
|
- Current: 500ms avg response time
|
||||||
|
- Each user triggers 10 additional queries
|
||||||
|
- **Recommendation**: Add eager loading with `include`
|
||||||
|
- **Expected Impact**: Reduce to 50ms (10x improvement)
|
||||||
|
|
||||||
|
### Major Issues
|
||||||
|
2. **Large Bundle Size** (Impact: Medium)
|
||||||
|
- Current: 800KB (gzipped)
|
||||||
|
- **Recommendation**: Code splitting, lazy loading
|
||||||
|
- **Expected Impact**: Reduce to 200KB
|
||||||
|
|
||||||
|
## Optimization Roadmap
|
||||||
|
|
||||||
|
1. **Week 1**: Fix N+1 queries (High impact, Low effort)
|
||||||
|
2. **Week 2**: Implement caching (High impact, Medium effort)
|
||||||
|
3. **Week 3**: Code splitting (Medium impact, Medium effort)
|
||||||
|
4. **Week 4**: Database indexing (Medium impact, Low effort)
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
- Response time reduced by 60%
|
||||||
|
- Throughput increased by 3x
|
||||||
|
- Error rate reduced to < 0.1%
|
||||||
|
```
|
||||||
346
skills/test-case-generator.md
Normal file
346
skills/test-case-generator.md
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
# Test Case Generator Skill
|
||||||
|
|
||||||
|
Generate comprehensive test cases from requirements and code.
|
||||||
|
|
||||||
|
## Test Case Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Test Case: {ID} - {Title}
|
||||||
|
|
||||||
|
**Priority**: Critical | High | Medium | Low
|
||||||
|
**Type**: Unit | Integration | E2E | Performance | Security
|
||||||
|
**Status**: Pending | Pass | Fail | Blocked
|
||||||
|
|
||||||
|
### Preconditions
|
||||||
|
- System is running
|
||||||
|
- User is authenticated
|
||||||
|
- Database contains test data
|
||||||
|
|
||||||
|
### Test Steps
|
||||||
|
1. Navigate to login page
|
||||||
|
2. Enter valid credentials
|
||||||
|
3. Click "Login" button
|
||||||
|
4. Verify redirect to dashboard
|
||||||
|
|
||||||
|
### Expected Results
|
||||||
|
- User is logged in
|
||||||
|
- Dashboard displays user's name
|
||||||
|
- Session token is stored
|
||||||
|
- Analytics event is fired
|
||||||
|
|
||||||
|
### Actual Results
|
||||||
|
{To be filled during test execution}
|
||||||
|
|
||||||
|
### Test Data
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "test@example.com",
|
||||||
|
"password": "Test123!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- Database seeded with test user
|
||||||
|
- Email service mocked
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
- Tests authentication flow
|
||||||
|
- Covers happy path
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate Unit Tests
|
||||||
|
|
||||||
|
### From Function Specification
|
||||||
|
|
||||||
|
**Function**: `calculateDiscount(price: number, couponCode: string): number`
|
||||||
|
|
||||||
|
**Requirements**:
|
||||||
|
- Apply 10% discount for "SAVE10"
|
||||||
|
- Apply 20% discount for "SAVE20"
|
||||||
|
- Return original price for invalid codes
|
||||||
|
- Throw error for negative prices
|
||||||
|
|
||||||
|
**Generated Tests**:
|
||||||
|
```typescript
|
||||||
|
describe('calculateDiscount', () => {
|
||||||
|
it('should apply 10% discount with SAVE10 code', () => {
|
||||||
|
expect(calculateDiscount(100, 'SAVE10')).toBe(90);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply 20% discount with SAVE20 code', () => {
|
||||||
|
expect(calculateDiscount(100, 'SAVE20')).toBe(80);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original price for invalid code', () => {
|
||||||
|
expect(calculateDiscount(100, 'INVALID')).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original price for empty code', () => {
|
||||||
|
expect(calculateDiscount(100, '')).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for negative price', () => {
|
||||||
|
expect(() => calculateDiscount(-10, 'SAVE10')).toThrow('Price must be positive');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle zero price', () => {
|
||||||
|
expect(calculateDiscount(0, 'SAVE10')).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle decimal prices', () => {
|
||||||
|
expect(calculateDiscount(99.99, 'SAVE10')).toBeCloseTo(89.99, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be case insensitive for coupon codes', () => {
|
||||||
|
expect(calculateDiscount(100, 'save10')).toBe(90);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Matrix Generation
|
||||||
|
|
||||||
|
### Feature: User Registration
|
||||||
|
|
||||||
|
| Test Case | Email | Password | Name | Expected Result |
|
||||||
|
|-----------|-------|----------|------|-----------------|
|
||||||
|
| TC-001 | valid@email.com | Password123! | John Doe | Success |
|
||||||
|
| TC-002 | invalid-email | Password123! | John Doe | Validation Error |
|
||||||
|
| TC-003 | valid@email.com | short | John Doe | Password too short |
|
||||||
|
| TC-004 | valid@email.com | nouppercasenumber! | John Doe | Password requirements not met |
|
||||||
|
| TC-005 | valid@email.com | Password123! | "" | Name required error |
|
||||||
|
| TC-006 | duplicate@email.com | Password123! | Jane Doe | Email already exists |
|
||||||
|
| TC-007 | valid@email.com | Password123! | A | Success (minimum length) |
|
||||||
|
| TC-008 | valid@email.com | Password123! | {101 chars} | Name too long error |
|
||||||
|
|
||||||
|
## Edge Cases Identification
|
||||||
|
|
||||||
|
For any feature, generate tests for:
|
||||||
|
|
||||||
|
### Input Validation
|
||||||
|
- Minimum boundary (0, 1, "")
|
||||||
|
- Maximum boundary (MAX_INT, max length)
|
||||||
|
- Just below minimum (-1, empty string)
|
||||||
|
- Just above maximum (MAX_INT + 1, max length + 1)
|
||||||
|
- Invalid types (null, undefined, NaN)
|
||||||
|
- Special characters (', ", <, >, &, SQL injection)
|
||||||
|
- Unicode characters (emoji, RTL text)
|
||||||
|
|
||||||
|
### State Transitions
|
||||||
|
- Initial state → Valid transition → Expected state
|
||||||
|
- Invalid state transitions
|
||||||
|
- Concurrent state changes
|
||||||
|
- Idempotency (multiple identical requests)
|
||||||
|
|
||||||
|
### Error Conditions
|
||||||
|
- Network failures
|
||||||
|
- Timeout scenarios
|
||||||
|
- Partial data
|
||||||
|
- Corrupted data
|
||||||
|
- Permission denied
|
||||||
|
- Resource exhaustion
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Single item
|
||||||
|
- Empty list
|
||||||
|
- Large dataset (10K+ items)
|
||||||
|
- Concurrent requests
|
||||||
|
- Memory leaks
|
||||||
|
- Long-running operations
|
||||||
|
|
||||||
|
## Integration Test Generation
|
||||||
|
|
||||||
|
### API Endpoint Testing
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
describe('POST /api/users', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await db.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create user with valid data', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/api/users')
|
||||||
|
.send({
|
||||||
|
email: 'test@example.com',
|
||||||
|
name: 'Test User',
|
||||||
|
password: 'Test123!'
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.status).toBe(201);
|
||||||
|
expect(response.body).toHaveProperty('id');
|
||||||
|
expect(response.body.email).toBe('test@example.com');
|
||||||
|
|
||||||
|
// Verify in database
|
||||||
|
const user = await db.users.findByEmail('test@example.com');
|
||||||
|
expect(user).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject duplicate email', async () => {
|
||||||
|
await db.users.create({ email: 'existing@example.com' });
|
||||||
|
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/api/users')
|
||||||
|
.send({ email: 'existing@example.com', name: 'Test', password: 'Test123!' });
|
||||||
|
|
||||||
|
expect(response.status).toBe(409);
|
||||||
|
expect(response.body.code).toBe('EMAIL_EXISTS');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hash password before storing', async () => {
|
||||||
|
const password = 'PlainTextPassword';
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.post('/api/users')
|
||||||
|
.send({ email: 'test@example.com', name: 'Test', password });
|
||||||
|
|
||||||
|
const user = await db.users.findByEmail('test@example.com');
|
||||||
|
expect(user.password).not.toBe(password);
|
||||||
|
expect(user.password).toMatch(/^\$2[aby]\$.{56}$/); // bcrypt format
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## E2E Test Scenarios
|
||||||
|
|
||||||
|
### User Journey: Complete Purchase
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
test('user can complete purchase from product page to confirmation', async ({ page }) => {
|
||||||
|
// 1. Login
|
||||||
|
await page.goto('/login');
|
||||||
|
await page.fill('[name="email"]', 'buyer@example.com');
|
||||||
|
await page.fill('[name="password"]', 'Test123!');
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
await expect(page).toHaveURL('/dashboard');
|
||||||
|
|
||||||
|
// 2. Browse and add to cart
|
||||||
|
await page.goto('/products/laptop-pro');
|
||||||
|
await page.click('[data-testid="add-to-cart"]');
|
||||||
|
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
|
||||||
|
|
||||||
|
// 3. Go to cart
|
||||||
|
await page.click('[data-testid="cart-icon"]');
|
||||||
|
await expect(page).toHaveURL('/cart');
|
||||||
|
await expect(page.locator('[data-testid="cart-item"]')).toHaveCount(1);
|
||||||
|
|
||||||
|
// 4. Proceed to checkout
|
||||||
|
await page.click('[data-testid="checkout-button"]');
|
||||||
|
await expect(page).toHaveURL('/checkout');
|
||||||
|
|
||||||
|
// 5. Fill shipping info
|
||||||
|
await page.fill('[name="address"]', '123 Main St');
|
||||||
|
await page.fill('[name="city"]', 'New York');
|
||||||
|
await page.fill('[name="zip"]', '10001');
|
||||||
|
await page.click('[data-testid="continue-payment"]');
|
||||||
|
|
||||||
|
// 6. Fill payment info (test card)
|
||||||
|
await page.fill('[name="cardNumber"]', '4242424242424242');
|
||||||
|
await page.fill('[name="expiry"]', '12/25');
|
||||||
|
await page.fill('[name="cvc"]', '123');
|
||||||
|
|
||||||
|
// 7. Place order
|
||||||
|
await page.click('[data-testid="place-order"]');
|
||||||
|
|
||||||
|
// 8. Verify confirmation
|
||||||
|
await expect(page).toHaveURL(/\/orders\/[a-zA-Z0-9]+/);
|
||||||
|
await expect(page.locator('text=Order Confirmed')).toBeVisible();
|
||||||
|
|
||||||
|
// 9. Verify email sent (mock)
|
||||||
|
expect(emailService.send).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
to: 'buyer@example.com',
|
||||||
|
subject: expect.stringContaining('Order Confirmation')
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Data Generation
|
||||||
|
|
||||||
|
### Factory Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class UserFactory {
|
||||||
|
static create(overrides?: Partial<User>): User {
|
||||||
|
return {
|
||||||
|
id: faker.datatype.uuid(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
name: faker.name.fullName(),
|
||||||
|
role: 'user',
|
||||||
|
createdAt: new Date(),
|
||||||
|
...overrides
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static createAdmin(overrides?: Partial<User>): User {
|
||||||
|
return this.create({ role: 'admin', ...overrides });
|
||||||
|
}
|
||||||
|
|
||||||
|
static createMany(count: number): User[] {
|
||||||
|
return Array.from({ length: count }, () => this.create());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
const user = UserFactory.create({ email: 'specific@example.com' });
|
||||||
|
const admin = UserFactory.createAdmin();
|
||||||
|
const users = UserFactory.createMany(100);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checklist for Complete Test Coverage
|
||||||
|
|
||||||
|
### Functionality
|
||||||
|
- [ ] Happy path (expected usage)
|
||||||
|
- [ ] Alternative paths
|
||||||
|
- [ ] Error conditions
|
||||||
|
- [ ] Edge cases
|
||||||
|
- [ ] Boundary conditions
|
||||||
|
|
||||||
|
### Data
|
||||||
|
- [ ] Valid data
|
||||||
|
- [ ] Invalid data
|
||||||
|
- [ ] Missing data (null, undefined)
|
||||||
|
- [ ] Empty data
|
||||||
|
- [ ] Extreme values
|
||||||
|
|
||||||
|
### State
|
||||||
|
- [ ] Initial state
|
||||||
|
- [ ] Valid state transitions
|
||||||
|
- [ ] Invalid state transitions
|
||||||
|
- [ ] Final/terminal states
|
||||||
|
|
||||||
|
### Integration
|
||||||
|
- [ ] Database operations
|
||||||
|
- [ ] External API calls
|
||||||
|
- [ ] File system operations
|
||||||
|
- [ ] Third-party services
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- [ ] Authentication required
|
||||||
|
- [ ] Authorization enforced
|
||||||
|
- [ ] Input sanitization
|
||||||
|
- [ ] SQL injection prevention
|
||||||
|
- [ ] XSS prevention
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] Response time acceptable
|
||||||
|
- [ ] Handles high load
|
||||||
|
- [ ] No memory leaks
|
||||||
|
- [ ] Efficient queries
|
||||||
|
|
||||||
|
### Usability
|
||||||
|
- [ ] Error messages clear
|
||||||
|
- [ ] Loading states shown
|
||||||
|
- [ ] Success feedback provided
|
||||||
|
- [ ] Accessibility requirements met
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Test Behavior, Not Implementation**: Focus on what the code does, not how
|
||||||
|
2. **One Assert Per Test**: Makes failures easier to diagnose
|
||||||
|
3. **Descriptive Names**: Test name should describe what and why
|
||||||
|
4. **Arrange-Act-Assert**: Clear test structure
|
||||||
|
5. **Independent Tests**: No dependencies between tests
|
||||||
|
6. **Fast Tests**: Unit tests should run in milliseconds
|
||||||
|
7. **Deterministic**: Same input always produces same output
|
||||||
|
8. **Readable**: Tests serve as documentation
|
||||||
Reference in New Issue
Block a user