# Testing Patterns **Analysis Date:** 2026-04-27 ## Test Framework Status **Current State:** **Minimal test coverage - testing infrastructure in place but not actively used** ### Jest (Server) **Runner:** - Jest 30.x - Config: Inline in `server/package.json` (lines 88-104) **Run Commands:** ```bash cd server npm test # Run all unit tests (seeks *.spec.ts files) npm run test:watch # Watch mode for development npm run test:cov # Generate coverage report npm run test:debug # Debug mode with breakpoints npm run test:e2e # Run end-to-end tests (config: test/jest-e2e.json) ``` **Configuration Details:** ```json { "moduleFileExtensions": ["js", "json", "ts"], "rootDir": "src", "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "collectCoverageFrom": ["**/*.(t|j)s"], "coverageDirectory": "../coverage", "testEnvironment": "node" } ``` **Testing Libraries:** - Jest 30.x (test runner) - ts-jest (TypeScript support) - @nestjs/testing (NestJS module testing utilities) - supertest (HTTP request testing) ### Vitest (Client) **Status:** Not installed. No vitest config present in `client/package.json` **Implications:** Client has zero automated test infrastructure. Any future testing would require adding vitest and configuring it. ## Test File Organization **Server:** - Location: Unit tests alongside source in `src/`, E2E tests in `test/` - Naming: `*.spec.ts` for unit tests, `*.e2e-spec.ts` for integration tests - Example: No unit test files currently exist in `server/src/` **Current Test Suite:** - Location: `server/test/app.e2e-spec.ts` - Scope: Single basic integration test for app startup - Status: Placeholder test (checks 'Hello World!' endpoint that doesn't exist) **Client:** - No test files present - No test directory structure ## Test Structure (Server) **E2E Test Example** (`server/test/app.e2e-spec.ts`): ```typescript import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import request from 'supertest'; import { AppModule } from './../src/app.module'; describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/ (GET)', () => { return request(app.getHttpServer()) .get('/') .expect(200) .expect('Hello World!'); }); }); ``` **Patterns:** - `describe()` for test suites - `it()` for individual tests (or `test()`) - `beforeEach()` for setup (module initialization) - Async/await for async operations - Chained `.expect()` assertions with supertest ## Mocking ### Server (Jest/NestJS) **Framework:** @nestjs/testing provides test module builder **Pattern Observed:** ```typescript const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], // Or specific module imports }).compile(); const service = moduleFixture.get(ServiceName); ``` **What to Mock:** - Database (Prisma) - would use mock provider - External APIs - would use jest.mock() - Services with dependencies - inject via module builder **What NOT to Mock:** - NestJS core decorators - Guards/Middleware (test through integration) - Database schema (use test database) ### Client **No mocking patterns established yet** - testing infrastructure not present. Would require: - Vitest for runner - `@testing-library/react` for component testing - Mock fetch/axios calls - Mock WebSocket connections ## Fixtures and Factories **Server:** **Test Data Approach:** Not fully established, but patterns available: - Prisma seed scripts exist in `server/prisma/`: - `seed.ts` - Basic seed - `seed-equipment.ts` - 5,482 equipment items - `seed-feats.ts` - Feat database - Could be reused for test fixtures **Location:** Would be in test directory or integrated with jest setup **No factory pattern observed** - tests would need to build objects inline or create helper functions **Client:** **Not applicable** - no test infrastructure ## Coverage **Requirements:** None enforced (no CI/CD pipeline checking coverage) **View Coverage:** ```bash cd server npm run test:cov # Generates: server/coverage/ ``` **Current Coverage:** Unknown (no tests running) **Gaps:** **Entire codebase untested** - Auth module: No unit tests (`server/src/modules/auth/`) - Characters module: No unit tests (`server/src/modules/characters/`) - Battle module: No unit tests (`server/src/modules/battle/`) - WebSocket gateway: No tests - Guards/Decorators: No tests - Client components: No tests - Client hooks: No tests - State management (Zustand): No tests ## Test Types ### Unit Tests **Not currently used** **When implemented, pattern would be:** - Test individual services in isolation - Mock Prisma client - Location: `server/src/modules/[module]/[module].service.spec.ts` - Example test structure (not yet used): ```typescript describe('AuthService', () => { let service: AuthService; let prisma: PrismaService; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [AuthService, { provide: PrismaService, useValue: mockPrisma }], }).compile(); service = module.get(AuthService); }); it('should register user', async () => { // Test implementation }); }); ``` ### Integration Tests **Single example:** `server/test/app.e2e-spec.ts` **Scope:** - Tests full HTTP request/response cycle - Uses real app instance - Uses Test.createTestingModule() to create app **Pattern:** ```typescript return request(app.getHttpServer()) .post('/auth/login') .send({ identifier: 'user', password: 'pass' }) .expect(200) .expect((res) => { expect(res.body.token).toBeDefined(); }); ``` **Would need:** Database test fixtures, cleanup between tests ### E2E Tests **Config:** `server/test/jest-e2e.json` **Difference from Integration:** - Run against deployed/separate server - Test user workflows end-to-end - Full database setup/teardown **Currently:** Not implemented beyond placeholder ## Common Patterns ### Async Testing **Server (Jest):** ```typescript it('should load data', async () => { const result = await service.loadData(); expect(result).toBeDefined(); }); ``` - async/await preferred - Supertest chainable: `request().post().send().expect()` **Client (not yet implemented):** Would use: ```typescript const { result } = await renderHook(() => useCharacterSocket()); await waitFor(() => expect(result.current.socket).toBeDefined()); ``` ### Error Testing **Not yet implemented, but pattern would be:** **Server:** ```typescript it('should throw NotFoundException', async () => { await expect(service.getCharacter('invalid-id')) .rejects .toThrow(NotFoundException); }); ``` **Actual exception handling verified through:** - Controllers catch exceptions - Guards handle auth failures - Integration tests verify HTTP status codes ## Critical Test Gaps **High Priority (Authentication):** - AuthService.register() - conflicts, hashing, JWT generation - AuthService.login() - invalid credentials, token generation - JWT guard - token validation, public routes - File: `server/src/modules/auth/auth.service.ts` (lines 20-104) **High Priority (Character Management):** - CharactersService access control (checkCampaignAccess, checkCharacterAccess) - HP updates and state sync via WebSocket - Condition application (dying, wounded, doomed mechanics) - Item management (equip, invest, notes) - File: `server/src/modules/characters/characters.service.ts` **High Priority (Real-time Sync):** - CharactersGateway connection authentication - WebSocket message broadcasting - Concurrent client updates - File: `server/src/modules/characters/characters.gateway.ts` **Medium Priority (Client UI):** - HpControl component (damage, heal, direct modes) - AddConditionModal (search, filtering, validation) - Character import from Pathbuilder JSON - File: `client/src/features/characters/components/` **Medium Priority (Validation):** - DTO validation (CreateCharacterDto, LoginDto) - Prisma query results - File: `server/src/modules/*/dto/` ## Recommendations for Implementation **Phase 1 (Auth):** 1. Write AuthService unit tests with mocked Prisma 2. Write JwtAuthGuard tests 3. Write integration tests for login/register endpoints **Phase 2 (Character CRUD):** 1. Test CharactersService access control 2. Test HP update logic 3. Test condition application **Phase 3 (WebSocket):** 1. Mock socket.io for gateway tests 2. Test connection/disconnect 3. Test broadcast patterns **Phase 4 (Client):** 1. Setup vitest 2. Test HpControl component 3. Test modal components 4. Test Zustand store --- *Testing analysis: 2026-04-27*