Establishes clear testing standards and best practices: - Mandates unit testing for all API endpoints - Defines test organization and file structure - Introduces testing scope and strategy - Documents best practices for writing tests - Sets minimum coverage requirements (80%) - Adds test data management guidelines Updates project documentation to reflect testing requirements and development workflow. Includes practical examples of good testing patterns and proper test organization.
393 lines
9.9 KiB
Text
393 lines
9.9 KiB
Text
---
|
|
description:
|
|
globs:
|
|
alwaysApply: false
|
|
---
|
|
# Coding Standards
|
|
|
|
## Code Quality
|
|
|
|
### TypeScript Requirements
|
|
- All new code must use TypeScript
|
|
- Enable strict type checking
|
|
- Avoid using `any` type, prefer specific types
|
|
- Define interfaces or type aliases for complex objects
|
|
|
|
```typescript
|
|
// ✅ Good practice
|
|
interface LinkData {
|
|
slug: string
|
|
url: string
|
|
createdAt: Date
|
|
expiresAt?: Date
|
|
}
|
|
|
|
// ❌ Avoid
|
|
const linkData: any = { ... }
|
|
```
|
|
|
|
### Function and Variable Naming
|
|
- Use descriptive names
|
|
- Function names should start with verbs
|
|
- Boolean variables use `is`, `has`, `should` prefixes
|
|
- Constants use UPPER_SNAKE_CASE
|
|
|
|
```typescript
|
|
// ✅ Good practice
|
|
const isValidUrl = (url: string): boolean => { ... }
|
|
const hasExpired = computed(() => { ... })
|
|
const MAX_SLUG_LENGTH = 50
|
|
|
|
// ❌ Avoid
|
|
const check = (u: string) => { ... }
|
|
const expired = computed(() => { ... })
|
|
const maxLen = 50
|
|
```
|
|
|
|
## Security Requirements
|
|
|
|
### Input Validation
|
|
- All user input must be validated using Zod
|
|
- API endpoints must validate request parameters
|
|
- Frontend forms use vee-validate + Zod
|
|
|
|
```typescript
|
|
// API input validation
|
|
import { z } from 'zod'
|
|
|
|
const createLinkSchema = z.object({
|
|
url: z.string().url(),
|
|
slug: z.string().min(1).max(50).optional(),
|
|
expiresAt: z.string().datetime().optional()
|
|
})
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const body = await readBody(event)
|
|
const validatedData = createLinkSchema.parse(body)
|
|
// ...
|
|
})
|
|
```
|
|
|
|
### Authentication
|
|
- Use Site Token for authentication
|
|
- Sensitive operations require permission verification
|
|
- Don't store sensitive information on the client
|
|
|
|
### Data Sanitization
|
|
- Sanitize user-input HTML content
|
|
- Validate URL format and security
|
|
- Prevent XSS and injection attacks
|
|
|
|
## Performance Best Practices
|
|
|
|
### Reactive Data
|
|
- Use `ref` and `reactive` appropriately
|
|
- Avoid unnecessary reactive wrapping
|
|
- Use `readonly` to protect data
|
|
|
|
```typescript
|
|
// ✅ Good practice
|
|
const { data: links, pending } = await $fetch('/api/links')
|
|
const filteredLinks = computed(() =>
|
|
links.value.filter(link => link.isActive)
|
|
)
|
|
|
|
// ❌ Avoid
|
|
const links = ref([])
|
|
const filteredLinks = ref([])
|
|
watch(links, () => {
|
|
filteredLinks.value = links.value.filter(link => link.isActive)
|
|
})
|
|
```
|
|
|
|
### Async Operations
|
|
- Use `async/await` instead of Promise chains
|
|
- Handle errors and loading states properly
|
|
- Avoid blocking UI operations
|
|
|
|
```typescript
|
|
// ✅ Good practice
|
|
const { data, error, pending } = await useFetch('/api/links')
|
|
|
|
// Error handling
|
|
try {
|
|
const result = await $fetch('/api/link/create', { ... })
|
|
} catch (error) {
|
|
// Handle error
|
|
}
|
|
```
|
|
|
|
## Code Organization
|
|
|
|
### File Structure
|
|
- Each file should export only one main functionality
|
|
- Group related functionality in the same directory
|
|
- Use `index.ts` as directory entry point
|
|
|
|
### Import/Export
|
|
- Use ES6 module syntax
|
|
- Organize imports alphabetically
|
|
- Separate third-party and local imports
|
|
|
|
```typescript
|
|
// Third-party libraries
|
|
import { ref, computed } from 'vue'
|
|
import { z } from 'zod'
|
|
|
|
// Local imports
|
|
import type { LinkData } from '~/types'
|
|
import { validateUrl } from '~/utils/validation'
|
|
```
|
|
|
|
### Comments and Documentation
|
|
- Add comments for complex logic
|
|
- Use JSDoc comments for public APIs
|
|
- Keep comments in sync with code
|
|
|
|
```typescript
|
|
/**
|
|
* Create a new short link
|
|
* @param url - Original URL
|
|
* @param slug - Custom slug (optional)
|
|
* @returns Created link data
|
|
*/
|
|
export async function createLink(url: string, slug?: string): Promise<LinkData> {
|
|
// Implementation logic
|
|
}
|
|
```
|
|
|
|
## Testing Standards
|
|
|
|
### Unit Testing Requirements
|
|
- **Mandatory for all `server/api` endpoints** - Every API route must have comprehensive unit tests
|
|
- Use Vitest as the primary testing framework with Nuxt Test Utils
|
|
- Follow the Test-Driven Development (TDD) approach when possible
|
|
- Maintain test coverage above 80% for API endpoints
|
|
|
|
### Testing Scope and Strategy
|
|
- **API Layer**: Test all endpoints in [server/api/](mdc:server/api/) directory
|
|
- **Validation Logic**: Test Zod schemas and input validation
|
|
- **Error Handling**: Verify error responses and status codes
|
|
- **Authentication**: Test token validation and authorization flows
|
|
- **Business Logic**: Cover edge cases and critical functionality
|
|
|
|
### Test File Organization
|
|
```typescript
|
|
// File naming convention
|
|
tests/api/link/create.test.ts // Unit tests for API endpoints
|
|
tests/api/helpers/fixtures.ts // Shared test data
|
|
tests/sink.spec.ts // Integration/E2E tests
|
|
```
|
|
|
|
### Testing Best Practices
|
|
- **Write descriptive test names** that explain the behavior being tested
|
|
- **Test both happy path and error scenarios**
|
|
- **Use meaningful assertions** that validate expected behavior
|
|
- **Keep tests independent** - no test should depend on another test's state
|
|
- **Mock external dependencies** to ensure test reliability
|
|
|
|
```typescript
|
|
// ✅ Good test structure
|
|
describe('POST /api/link/create', () => {
|
|
it('should create a new link with valid URL and custom slug', async () => {
|
|
const response = await $fetch('/api/link/create', {
|
|
method: 'POST',
|
|
body: { url: 'https://example.com', slug: 'my-link' }
|
|
})
|
|
|
|
expect(response.success).toBe(true)
|
|
expect(response.data.slug).toBe('my-link')
|
|
expect(response.data.url).toBe('https://example.com')
|
|
})
|
|
|
|
it('should reject requests with invalid URL format', async () => {
|
|
await expect($fetch('/api/link/create', {
|
|
method: 'POST',
|
|
body: { url: 'not-a-valid-url' }
|
|
})).rejects.toThrow()
|
|
})
|
|
})
|
|
```
|
|
|
|
### Test Data Management
|
|
- Use factory functions for creating test data
|
|
- Store common test fixtures in `tests/api/helpers/fixtures.ts`
|
|
- Avoid hardcoded values in tests; use constants and variables
|
|
|
|
```typescript
|
|
// ✅ Good test data management
|
|
const validLinkPayload = {
|
|
url: 'https://example.com',
|
|
slug: 'test-slug',
|
|
expiresAt: new Date(Date.now() + 86400000).toISOString()
|
|
}
|
|
|
|
const invalidUrlPayload = {
|
|
url: 'invalid-url-format',
|
|
slug: 'test-slug'
|
|
}
|
|
```
|
|
|
|
### Running and Maintaining Tests
|
|
- Run tests locally before pushing changes: `npm run test`
|
|
- Use watch mode during development: `npm run test:watch`
|
|
- Generate coverage reports: `npm run test:coverage`
|
|
- Tests must pass in CI/CD pipeline before merging
|
|
|
|
## Git Commit Conventions
|
|
|
|
### Commit Message Format
|
|
Follow the conventional commit specification:
|
|
```
|
|
type(scope): brief description
|
|
|
|
Optional body explaining what and why vs how
|
|
|
|
Optional footer with issue references
|
|
```
|
|
|
|
### Commit Types
|
|
- **feat**: New feature implementation
|
|
- **fix**: Bug fix or issue resolution
|
|
- **docs**: Documentation updates only
|
|
- **style**: Code formatting changes (no functional impact)
|
|
- **refactor**: Code restructuring without changing functionality
|
|
- **perf**: Performance optimization
|
|
- **test**: Adding or modifying tests
|
|
- **chore**: Build process, dependency updates, or auxiliary tool changes
|
|
- **ci**: Continuous integration configuration changes
|
|
|
|
### Scope Examples
|
|
- **api**: Changes to server/api endpoints
|
|
- **ui**: Frontend components or styling
|
|
- **auth**: Authentication related changes
|
|
- **db**: Database or data storage changes
|
|
- **config**: Configuration file updates
|
|
|
|
### Writing Good Commit Messages
|
|
|
|
#### Good Examples
|
|
```bash
|
|
feat(api): add AI-powered slug generation endpoint
|
|
|
|
Integrate Cloudflare AI Workers to automatically generate
|
|
meaningful slugs based on URL content and page titles.
|
|
|
|
- Add new /api/link/ai endpoint
|
|
- Implement content analysis logic
|
|
- Update link creation flow to support AI suggestions
|
|
- Add comprehensive test coverage
|
|
|
|
Closes #123
|
|
```
|
|
|
|
```bash
|
|
fix(auth): resolve token validation edge case
|
|
|
|
Handle expired tokens more gracefully by returning proper
|
|
401 status code instead of throwing unhandled exceptions.
|
|
|
|
Fixes #456
|
|
```
|
|
|
|
```bash
|
|
test(api): add comprehensive coverage for link endpoints
|
|
|
|
- Add unit tests for create, edit, delete operations
|
|
- Include validation error scenarios
|
|
- Test authentication requirements
|
|
- Achieve 85% coverage for link management APIs
|
|
```
|
|
|
|
#### Avoid These Patterns
|
|
```bash
|
|
# ❌ Too vague
|
|
fix: stuff
|
|
|
|
# ❌ Not descriptive
|
|
update code
|
|
|
|
# ❌ Multiple concerns in one commit
|
|
feat: add new API endpoint and fix UI bug and update docs
|
|
|
|
# ❌ All caps or inconsistent formatting
|
|
FIX: BROKEN AUTH SYSTEM
|
|
```
|
|
|
|
### Commit Best Practices
|
|
|
|
#### Single Responsibility
|
|
Each commit should represent one logical change:
|
|
- One feature addition
|
|
- One bug fix
|
|
- One refactoring operation
|
|
- One documentation update
|
|
|
|
#### Atomic Commits
|
|
Commits should be complete and functional:
|
|
- Code compiles without errors
|
|
- Tests pass
|
|
- No broken functionality introduced
|
|
|
|
#### Meaningful Descriptions
|
|
- Use imperative mood ("add feature" not "added feature")
|
|
- Capitalize the first letter
|
|
- No period at the end of the subject line
|
|
- Keep subject line under 50 characters
|
|
- Use body for detailed explanations when needed
|
|
|
|
### Branch Naming Conventions
|
|
```bash
|
|
# Feature branches
|
|
feature/ai-slug-generation
|
|
feature/link-expiration
|
|
|
|
# Bug fix branches
|
|
fix/auth-token-validation
|
|
fix/mobile-responsive-layout
|
|
|
|
# Documentation branches
|
|
docs/api-endpoint-guide
|
|
docs/deployment-instructions
|
|
|
|
# Hotfix branches
|
|
hotfix/security-vulnerability
|
|
hotfix/production-crash
|
|
```
|
|
|
|
### Pull Request Guidelines
|
|
|
|
#### PR Title Format
|
|
Use the same format as commit messages:
|
|
```
|
|
feat(api): add AI-powered slug generation
|
|
fix(auth): resolve token validation edge case
|
|
docs(readme): update installation instructions
|
|
```
|
|
|
|
#### PR Description Template
|
|
```markdown
|
|
## Summary
|
|
Brief description of changes made
|
|
|
|
## Type of Change
|
|
- [ ] Bug fix
|
|
- [ ] New feature
|
|
- [ ] Documentation update
|
|
- [ ] Refactoring
|
|
- [ ] Performance improvement
|
|
|
|
## Testing
|
|
- [ ] Unit tests added/updated
|
|
- [ ] Integration tests pass
|
|
- [ ] Manual testing completed
|
|
|
|
## Checklist
|
|
- [ ] Code follows project style guidelines
|
|
- [ ] Self-review completed
|
|
- [ ] Documentation updated if needed
|
|
- [ ] Tests cover new functionality
|
|
- [ ] No breaking changes introduced
|
|
```
|
|
|
|
This standardized approach ensures clean, readable commit history and makes it easier to track changes, generate changelogs, and collaborate effectively with team members.
|