This document provides comprehensive information about the testing infrastructure for the TypeScript client library.
The project uses Jest with ts-jest for unit testing TypeScript models and API client modules. The testing strategy focuses on:
- Model Tests: Validating TypeScript interfaces, type conversions (camelCase ↔ snake_case), and JSON serialization
- API Tests: Testing HTTP request formation, response parsing, error handling, and authentication
- Test Utilities: Reusable mocking helpers for consistent test patterns
src/
├── __tests__/
│ └── test-utils.ts # Shared test utilities and mock helpers
├── models/
│ ├── __tests__/
│ │ ├── Result.test.ts # Tests for Result model
│ │ ├── Project.test.ts # Tests for Project model
│ │ └── Run.test.ts # Tests for Run model
│ └── *.ts # Model files
└── apis/
├── __tests__/
│ ├── ProjectApi.test.ts # Tests for ProjectApi
│ └── ResultApi.test.ts # Tests for ResultApi
└── *.ts # API files
# Run all tests
yarn test
# Run tests in watch mode (re-runs on file changes)
yarn test:watch
# Run tests with coverage report
yarn test:coverageThe Jest configuration is in jest.config.js:
- Preset:
ts-jestfor TypeScript support - Test Environment: Node.js
- Test Pattern:
**/__tests__/**/*.test.ts - Coverage: HTML, LCOV, and text reports in
coverage/directory
As of the initial implementation:
- 3 Model Tests: Result, Project, Run (out of 36 models)
- 2 API Tests: ProjectApi, ResultApi (out of 16 APIs)
- 83 Total Tests: All passing ✓
- Coverage: ~26% overall
- Models tested: 100% coverage (Result.ts, Project.ts, Run.ts)
- APIs tested: ~80% coverage (ProjectApi.ts, ResultApi.ts)
The project currently has baseline coverage thresholds set:
- Statements: 25%
- Branches: 15%
- Functions: 15%
- Lines: 25%
These should be increased as more tests are added. A recommended target is 60-80% coverage for production code.
Model tests focus on:
- Interface validation: Type checking and property access
- Enum testing: Verifying all enum values are correct
- JSON conversion: Testing
FromJSONandToJSONfunctions - Round-trip conversion: Ensuring data integrity through conversion cycles
- Null/undefined handling: Testing optional and nullable fields
Example model test structure:
import { MyModel, MyModelFromJSON, MyModelToJSON } from '../MyModel';
describe('MyModel', () => {
describe('interface and types', () => {
it('should create a valid model with all fields', () => {
const model: MyModel = { /* ... */ };
expect(model.field).toBe('value');
});
});
describe('MyModelFromJSON', () => {
it('should convert JSON with snake_case to camelCase', () => {
const json = { my_field: 'value' };
const model = MyModelFromJSON(json);
expect(model.myField).toBe('value');
});
});
describe('JSON round-trip', () => {
it('should maintain data integrity', () => {
const original: MyModel = { /* ... */ };
const json = MyModelToJSON(original);
const restored = MyModelFromJSON(json);
expect(restored).toEqual(original);
});
});
});API tests focus on:
- Request formation: URL construction, headers, body serialization
- Response parsing: Correct handling of API responses
- HTTP methods: GET, POST, PUT, DELETE operations
- Query parameters: Pagination, filtering, etc.
- Authentication: Bearer token handling
- Error handling: 4xx, 5xx responses, network errors
Example API test structure:
import { MyApi } from '../MyApi';
import { Configuration } from '../../runtime';
import { createMockFetch, setupFetchMock, restoreFetch } from '../../__tests__/test-utils';
describe('MyApi', () => {
let api: MyApi;
let mockFetch: jest.Mock;
beforeEach(() => {
setupFetchMock();
const config = new Configuration({ basePath: 'http://localhost/api' });
api = new MyApi(config);
});
afterEach(() => {
restoreFetch();
});
describe('getData', () => {
it('should fetch data', async () => {
const mockData = { id: '123', name: 'test' };
mockFetch = createMockFetch(mockData);
global.fetch = mockFetch;
const result = await api.getData({ id: '123' });
expect(mockFetch).toHaveBeenCalledWith(
'http://localhost/api/data/123',
expect.objectContaining({ method: 'GET' })
);
expect(result.id).toBe('123');
});
});
});-
Snake Case in Mocks: API responses from the server use
snake_case, so mock data should use snake_case to match real API behavior:const mockResponse = { test_id: 'test-123', // ✓ Correct testId: 'test-123' // ✗ Incorrect };
-
URL Endpoints: Verify actual API URLs by checking the generated code or running integration tests
-
Authentication: Test both authenticated and unauthenticated scenarios
Located in src/__tests__/test-utils.ts:
createMockConfiguration(): Create a mock Configuration objectcreateMockResponse(): Create a mock fetch ResponsecreateMockFetch(): Create a single mock fetch functioncreateMockFetchSequence(): Create a fetch mock with multiple responsessetupFetchMock(): Initialize global fetch mockrestoreFetch(): Clean up fetch mock after testsvalidateObjectStructure(): Type-safe object validation
import { createMockFetch, setupFetchMock, restoreFetch } from '../../__tests__/test-utils';
// Setup
beforeEach(() => {
setupFetchMock();
});
afterEach(() => {
restoreFetch();
});
// In your test
const mockData = { id: '123' };
const mockFetch = createMockFetch(mockData, 200);
global.fetch = mockFetch;To add tests for additional models or APIs:
# Create test file
touch src/models/__tests__/NewModel.test.tsUse existing model tests as templates (Result.test.ts, Project.test.ts, Run.test.ts).
# Create test file
touch src/apis/__tests__/NewApi.test.tsUse existing API tests as templates (ProjectApi.test.ts, ResultApi.test.ts).
yarn testFor integration tests against a real Ibutsu server, see the separate integration test file:
# Set environment variables
export IBUTSU_API="https://your-server.com/api"
export IBUTSU_TOKEN="your-token"
# Run integration tests
yarn integrationSee integration-test.ts and README.md for more details.
The project uses pre-commit hooks for linting and formatting. To run all checks:
# Lint check
yarn lint
# Format check
yarn format:check
# Auto-fix issues
yarn lint:fix- Test Organization: Group related tests using nested
describeblocks - Test Naming: Use descriptive names that explain what is being tested
- Arrange-Act-Assert: Structure tests with clear setup, execution, and verification phases
- Mock Data: Use realistic mock data that matches actual API responses
- Coverage: Aim for high coverage but focus on meaningful tests over hitting metrics
- Edge Cases: Test null values, empty arrays, error conditions, and boundary conditions
- Async/Await: Always use async/await for asynchronous operations
- Isolation: Each test should be independent and not rely on other tests
- Ensure Node.js 22+ is installed:
node --version - Install dependencies:
yarn install - Check Jest is installed:
yarn list jest
- Ensure
setupFetchMock()is called inbeforeEach - Ensure
restoreFetch()is called inafterEach - Check that
global.fetch = mockFetchis set before calling the API
- Run
yarn test:coverageto see detailed coverage report - Open
coverage/index.htmlin a browser for visual coverage report - Focus on testing critical paths and common use cases first
To improve test coverage:
- Add tests for remaining models (33 more models)
- Add tests for remaining APIs (14 more APIs)
- Add tests for the runtime module
- Increase coverage thresholds gradually
- Add tests for edge cases and error conditions
- Consider adding integration tests for complex workflows