Testing
This project uses Vitest for testing with a comprehensive test suite covering all CLI commands.
Running Tests
# Run all tests
npm test
# Run tests with coverage report
npm test -- --coverage
# Run tests in watch mode (during development)
npm run test:watch
# Run specific test file
npm test -- src/__tests__/commands/auth.test.ts
Test Structure
src/__tests__/
├── setup.ts # Global test setup (console mocking)
├── commands/ # Unit tests for each command
│ ├── auth.test.ts # login, logout, whoami
│ ├── browse.test.ts # list, show, daily, random
│ ├── solve.test.ts # pick, test, submit
│ ├── progress.test.ts # stat, submissions, today
│ ├── timer.test.ts # timer
│ ├── config.test.ts # config
│ ├── notes.test.ts # notes, bookmark
│ ├── collab.test.ts # collab host/join/sync/compare/leave/status
│ └── sync.test.ts # sync
└── integration/
└── cli.test.ts # Integration tests (runs actual CLI binary)
Test Categories
Unit Tests (~90 tests)
Test individual command logic with mocked dependencies:
- API client is mocked to avoid network calls
- Storage modules are mocked to avoid file system access
- All command options and input variations are tested
Integration Tests (~40 tests)
Run the actual compiled CLI binary to catch:
- Missing shebang in
dist/index.js - Broken imports or build errors
- Commands not registered with Commander.js
- Missing command aliases
- Help text and error handling
Coverage
Current coverage by area:
| Area | Coverage |
|---|---|
| Commands | ~68% |
| Overall | ~48% |
Lower overall coverage is expected because we mock:
src/api/client.ts- LeetCode API callssrc/storage/*- Configuration persistencesrc/utils/display.ts- Console output formatting
These are intentionally mocked in unit tests to isolate command logic.
Writing New Tests
When adding a new command:
- Create a test file in
src/__tests__/commands/ - Mock dependencies using
vi.mock() - Import the command function after mocking
- Test all options and input variations
- Add an integration test in
cli.test.tsfor command registration
Example test structure:
import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock dependencies first
vi.mock('../../api/client.js', () => ({
leetcodeClient: {
// Mock methods
},
}));
// Import after mocking
import { myCommand } from '../../commands/myCommand.js';
describe('myCommand', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should handle basic usage', async () => {
await myCommand({});
// assertions
});
});
CI Integration
Tests run automatically on every push via GitHub Actions. The CI workflow:
- Builds the project (
npm run build) - Runs all tests (
npm test) - Fails the build if any test fails