Ruletypescript
Testing Rule
Testing Conventions
Framework
- Use Vitest for all tests
- Import from
vitest:describe,it,expect,beforeEach,vi
Test Structure
import { describe, it, expect, beforeEach, vi } from 'vitest';
describe('ClassName', () => {
let instance: ClassName;
beforeEach(() => {
instance = new ClassName();
vi.clearAllMocks();
});
describe('methodName', () => {
it('should handle expected case', () => {
// Arrange
// Act
// Assert
});
it('should handle edge case', () => {
// ...
});
});
});
Mocking
- Use
vi.fn()for function mocks - Use
vi.spyOn()for spying on existing methods - Create mock classes that implement required interface methods
- Name mock classes with
Mockprefix:MockConnection,MockStorage
Mock Pattern
class MockConnection implements Pick<Connection, 'id' | 'send'> {
id: string;
sentEnvelopes: Envelope[] = [];
sendMock = vi.fn();
constructor(id: string) {
this.id = id;
}
send(envelope: Envelope): boolean {
this.sentEnvelopes.push(envelope);
this.sendMock(envelope);
return true;
}
}
Assertions
- Use specific matchers:
toEqual,toBe,toHaveBeenCalledWith - Prefer
toEqualfor object comparisons - Use
toHaveLengthfor array length checks - Use
toContainfor array membership
Async Tests
- Use
async/awaitpattern - Return promises from
itcallbacks when testing async code - Use
vi.waitFor()for polling assertions
File Naming
- Test files are co-located with source:
foo.ts->foo.test.ts - Integration tests use
.integration.test.tssuffix