Files
goodgo-platform/docs/audits/README_TEST_COVERAGE.md
Ho Ngoc Hai b8512ebff4 docs: consolidate audit and analysis reports into docs/audits/
Move 36 root-level audit/analysis documents and 7 web app audit documents
into docs/audits/ directory to declutter the project root. Remove stale
EXPLORATION_SUMMARY.txt.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-11 01:37:50 +07:00

9.1 KiB

Test Coverage Documentation

Overview

This directory contains comprehensive documentation for writing tests for 17 untested source files across the inquiries, leads, and reviews modules of the GoodGo Platform API.

Files Included

1. TEST_COVERAGE_ANALYSIS.md (1,841 lines, 55KB)

  • Complete implementations of all 17 untested files
  • Full source code for each file
  • Detailed explanation of what each method does
  • Test scenarios for each component
  • Reference test patterns from existing test files
  • Comprehensive test patterns and examples

2. TEST_COVERAGE_QUICK_REFERENCE.md (301 lines, 9.1KB)

  • Quick lookup guide for all 17 files
  • Test checklists by file type (repositories, VOs, DTOs, controllers)
  • Module-specific test scenarios
  • Priority matrix (critical, high, medium)
  • Recommended test execution order
  • Mock setup templates
  • Key formulas to verify

3. TEST_TEMPLATES.md (500+ lines)

  • Ready-to-use test templates for:
    • Repository tests
    • Value Object tests
    • DTO tests
    • Controller tests
  • Helper tests for pagination calculations
  • Helper tests for aggregation formulas
  • DTO validation helper tests

Quick Start

For a quick overview:

  1. Read the Quick Reference first (5-10 minutes)
  2. Identify which file type you want to test
  3. Jump to the appropriate section in TEST_TEMPLATES.md
  4. Copy the template and adapt it to your file

For comprehensive understanding:

  1. Start with the Quick Reference overview
  2. Read the relevant module section in TEST_COVERAGE_ANALYSIS.md
  3. Use TEST_TEMPLATES.md as implementation guide
  4. Reference the example test patterns in the Analysis document

File Organization by Module

Inquiries Module (4 files)

✗ prisma-inquiry.repository.ts     — 6 methods, pagination, relationships
✗ inquiries.controller.ts           — 4 endpoints, guards
✗ create-inquiry.dto.ts             — 3 validations
✗ list-inquiries.dto.ts             — 2 validations (pagination)

Leads Module (6 files)

✗ prisma-lead.repository.ts         — 6 methods, stats aggregation
✗ lead-score.vo.ts                  — Range validation (0-100)
✗ leads.controller.ts               — 5 endpoints, role guards
✗ create-lead.dto.ts                — 6 validations
✗ list-leads.dto.ts                 — Status enum, pagination
✗ update-lead-status.dto.ts         — Status enum

Reviews Module (5 files)

✗ prisma-review.repository.ts       — 7 methods, distribution stats
✗ rating.vo.ts                      — Integer range validation (1-5)
✗ reviews.controller.ts             — 5 endpoints, mixed auth
✗ create-review.dto.ts              — 4 validations
✗ list-reviews.dto.ts               — 2 DTO classes, pagination

Testing Priority Levels

🔴 CRITICAL (Business Logic)

  1. PrismaReviewRepository.getStats() — Distribution calculation is complex
  2. PrismaLeadRepository.getStatsByAgent() — Conversion rate formula
  3. Rating.vo — Must validate 1-5 integers only
  4. LeadScore.vo — Must validate 0-100 range

Start here — These are the most business-critical validations

🟡 HIGH (Data Integrity)

  1. Repository CRUD operations
  2. Pagination calculations
  3. Relationship mapping (user joins, listing traversal)
  4. Controller command/query dispatch

Test second — These ensure data consistency

🟢 MEDIUM (Validation & Guards)

  1. DTO field validations
  2. Enum constraints
  3. Optional field handling
  4. Authentication/Authorization guards

Test last — These are framework-level concerns

Test Execution Roadmap

Week 1: Value Objects & DTOs (8-10 test files)

  • LeadScore.vo.ts (1 file, 4-5 test cases)
  • Rating.vo.ts (1 file, 4-5 test cases)
  • All 10 DTO files (using templates, minimal variations)

Estimated time: 3-5 hours total

Week 2: Controllers (2 test files)

  • InquiriesController (4 endpoints + guards)
  • LeadsController (5 endpoints + guards)
  • ReviewsController (5 endpoints + mixed auth)

Estimated time: 2-3 hours total

Week 3: Repositories (3 test files)

  • PrismaInquiryRepository (6 methods)
  • PrismaLeadRepository (6 methods + aggregation)
  • PrismaReviewRepository (7 methods + distribution)

Estimated time: 4-6 hours total

Total Estimated Time: 9-14 hours

Key Testing Patterns

Repositories

// Mock all Prisma methods in beforeEach
mockPrisma = {
  [model]: { 
    findUnique: vi.fn(), 
    findMany: vi.fn(), 
    create: vi.fn(), 
    update: vi.fn(), 
    count: vi.fn() 
  }
};

// Test happy path and error cases
// Verify pagination calculations
// Verify data transformation (toDomain)

Value Objects

// Test valid cases
const result = ValueObject.create(validValue);
expect(result.isOk()).toBe(true);

// Test invalid cases
const result = ValueObject.create(invalidValue);
expect(result.isErr()).toBe(true);
expect(result.unwrapErr()).toBe('error message');

DTOs

// Use validate() from class-validator
const errors = await validate(dto);
expect(errors).toHaveLength(0); // or > 0 for invalid cases

// Test type transformation with class-transformer
// Test optional field handling

Controllers

// Mock CommandBus and QueryBus
mockCommandBus.execute.mockResolvedValue(expectedResult);

// Verify command/query construction
const command = mockCommandBus.execute.mock.calls[0][0];
expect(command.userId).toBe(expectedUserId);

Critical Formulas to Test

Pagination

skip = (page - 1) * take
totalPages = Math.ceil(total / take)
take = Math.min(limit, 100)  // Clamped to 100 max

Lead Statistics

conversionRate = (CONVERTED_count / total_leads) * 100  // 2 decimals
avgScore = (sum_of_scores / non_null_count)            // 1 decimal, null if no scores

Review Statistics

averageRating = (sum_of_ratings / total_reviews)       // 1 decimal
distribution = { 1: count, 2: count, 3: count, 4: count, 5: count }

Import Statements You'll Need

// Testing utilities
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';

// NestJS utilities (for controller tests)
import type { EventBus, CommandBus, QueryBus } from '@nestjs/cqrs';

// Domain classes
import { InquiryEntity } from './domain/entities/inquiry.entity';
import { LeadEntity } from './domain/entities/lead.entity';
import { ReviewEntity } from './domain/entities/review.entity';
import { LeadScore } from './domain/value-objects/lead-score.vo';
import { Rating } from './domain/value-objects/rating.vo';

Common Test Data

User IDs

user-1, user-2, user-3, user-agent-1

Lead Statuses

NEW, CONTACTED, QUALIFIED, NEGOTIATING, CONVERTED, LOST

Pagination Defaults

page: 1, limit: 20 (max 100)

Rating Range

1-5 stars (integer only)

Lead Score Range

0-100 (any number)

References

Existing Test Files (Use as Reference)

  • src/modules/inquiries/application/__tests__/create-inquiry.handler.spec.ts (20 lines pattern)
  • src/modules/leads/application/__tests__/create-lead.handler.spec.ts (20 lines pattern)
  • src/modules/reviews/presentation/__tests__/reviews.controller.spec.ts (135 lines pattern)

Full Implementations

All 17 file implementations are in TEST_COVERAGE_ANALYSIS.md with line-by-line explanations.

Troubleshooting

Issue: "Cannot find module" when mocking

Solution: Use as any casting for mocked dependencies

const repo = new PrismaInquiryRepository(mockPrisma as any);

Issue: Validation tests not working

Solution: Make sure you're using plainToClass for DTOs with transformers

const dto = plainToClass(CreateLeadDto, plainObject);

Issue: Pagination calculations don't match

Solution: Remember that limit is clamped to 100

const take = Math.min(limit, 100);  // Always do this

Issue: Stats calculations have rounding errors

Solution: Check decimal place requirements:

  • conversionRate: 2 decimals (multiply by 10000, divide by 100)
  • avgScore: 1 decimal (multiply by 10, divide by 10)
  • averageRating: 1 decimal (multiply by 10, divide by 10)

Next Steps

  1. Pick your starting file from Week 1 (recommend LeadScore.vo first — simplest)
  2. Open the template matching that file type in TEST_TEMPLATES.md
  3. Copy the template to your test file location
  4. Adapt the template with your specific imports and data
  5. Run tests and verify they pass
  6. Move to next file following the roadmap

Support Resources

  • Full implementations: See TEST_COVERAGE_ANALYSIS.md
  • Quick lookup: See TEST_COVERAGE_QUICK_REFERENCE.md
  • Code templates: See TEST_TEMPLATES.md
  • Reference tests: Check existing spec files in the modules

Last Updated: 2026-04-11
Total Files Documented: 17 untested source files
Total Documentation: 2,142 lines of analysis and templates
Estimated Testing Time: 9-14 hours total