Sink/.cursor/rules/coding-standards.mdc
ccbikai a6ea1391f2 feat(test): add comprehensive testing guidelines
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.
2025-05-28 19:50:56 +08:00

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.