Files
goodgo-platform/docs/audits/TEST_COVERAGE_QUICK_REFERENCE_ROOT.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 Quick Reference Guide

17 Untested Source Files Overview

INQUIRIES MODULE (4 files)

1. prisma-inquiry.repository.ts    — 6 methods to test + 1 private mapper
2. inquiries.controller.ts          — 4 endpoints to test + guard validation
3. create-inquiry.dto.ts            — 3 field validations
4. list-inquiries.dto.ts            — 2 field validations (pagination)

LEADS MODULE (6 files)

5. prisma-lead.repository.ts        — 6 methods + stats aggregation
6. lead-score.vo.ts                 — Value object: range 0-100
7. leads.controller.ts              — 5 endpoints + class-level role guard
8. create-lead.dto.ts               — 6 field validations
9. list-leads.dto.ts                — Status enum + pagination
10. update-lead-status.dto.ts       — Status enum validation

REVIEWS MODULE (5 files)

11. prisma-review.repository.ts     — 7 methods + stats with distribution
12. rating.vo.ts                    — Value object: range 1-5 (integers only)
13. reviews.controller.ts           — 5 endpoints + mixed auth
14. create-review.dto.ts            — 4 field validations
15. list-reviews.dto.ts             — 2 DTOs: ListReviewsByTargetDto, ReviewStatsDto

REFERENCE PATTERNS (2 test files)

16. create-inquiry.handler.spec.ts  — Handler test pattern
17. create-lead.handler.spec.ts     — Handler test pattern
18. reviews.controller.spec.ts      — Controller test pattern

Quick Test Scenarios by Type

REPOSITORIES (3 files)

Test checklist for each repository:

  • findById() returns entity or null
  • save() creates record with correct data mapping
  • Paginated methods respect limit cap (100 max)
  • Pagination calculation: skip = (page - 1) * take
  • Relationships are joined correctly
  • Aggregations calculate correctly (stats methods)
  • Optional fields handling (null coercion)
  • ISO date formatting in DTOs

Specific to PrismaInquiryRepository:

  • countUnreadByAgent() aggregation
  • findByListing() includes property.title
  • findByAgent() joins through listing.agentId

Specific to PrismaLeadRepository:

  • findByAgent() optional status filter
  • getStatsByAgent() calculates:
    • totalLeads count
    • byStatus object (dict of counts)
    • conversionRate: (CONVERTED / total) * 100 (2 decimals)
    • avgScore: average of non-null scores (1 decimal)

Specific to PrismaReviewRepository:

  • findByUserAndTarget() unique constraint query
  • getStats() builds distribution object (keys 1-5)
  • averageRating calculation: (sum / total) * 10 / 10 (1 decimal)

VALUE OBJECTS (2 files)

Test checklist:

  • create() with valid value returns Result.ok()
  • create() with invalid value returns Result.err() with correct message
  • Getter returns props.value
  • Invalid cases covered (negative, > max, non-integer, null)

LeadScore validation:

✓ Valid: 0, 50, 100
✗ Invalid: -1, 101, 2.5, null, "50"
Error: "Điểm lead phải từ 0 đến 100"

Rating validation:

✓ Valid: 1, 2, 3, 4, 5
✗ Invalid: 0, 6, 2.5, null, "5"
Error: "Đánh giá phải từ 1 đến 5 sao"

CONTROLLERS (2 files)

Test checklist:

  • Each endpoint dispatches correct command/query type
  • Parameters are mapped correctly from DTO
  • Optional fields become null (e.g., phone ?? null → null)
  • Default pagination values applied (page: 1, limit: 20)
  • CurrentUser decorator extracts user.sub correctly
  • Guard enforcement (@UseGuards, @Roles)
  • Return types match (e.g., { deleted: true })

InquiriesController specifics:

  • POST /inquiries: phone optional → null
  • GET /inquiries/listing/:listingId: requires JWT
  • GET /inquiries/agent/me: requires JWT + AGENT role
  • PATCH /inquiries/:id/read: requires JWT + AGENT role

LeadsController specifics:

  • ALL endpoints require JWT + AGENT role (class-level @Roles)
  • POST /leads: score optional, score range validation in command
  • GET /leads: status filter optional
  • GET /leads/stats: aggregation query
  • PATCH /leads/:id/status: only status field in command
  • DELETE /leads/🆔 agentId verification in command

ReviewsController specifics:

  • POST /reviews: requires JWT (AuthGuard)
  • GET /reviews: NO auth required (stats are public)
  • GET /reviews/stats: NO auth required
  • GET /reviews/me: requires JWT
  • DELETE /reviews/🆔 requires JWT + ownership check in command

DTOs (10 files)

Test checklist:

  • Required fields throw ValidationException if missing
  • String max/min length validated
  • Number min/max validated
  • Enum @IsIn() validates allowed values
  • Type transformation (class-transformer @Type)
  • Email format validated (@IsEmail)
  • Optional fields (@IsOptional) don't throw if omitted

Pagination standard (used in 5 DTOs):

  • page: optional, @Min(1), default 1
  • limit: optional, @Min(1), @Max(100), default 20
  • Both use @Type(() => Number) for string→number transformation

Enum validations:

  • LeadStatus: ['NEW', 'CONTACTED', 'QUALIFIED', 'NEGOTIATING', 'CONVERTED', 'LOST']
  • Used in: ListLeadsDto, UpdateLeadStatusDto

Test Priority Matrix

🔴 CRITICAL (Business Logic)

  1. PrismaReviewRepository.getStats() - distribution calculation
  2. PrismaLeadRepository.getStatsByAgent() - conversion rate formula
  3. Rating.vo - must be 1-5 integers only
  4. LeadScore.vo - must be 0-100 range

🟡 HIGH (Data Integrity)

  1. All repository CRUD methods
  2. Pagination calculations
  3. Relationship mapping (user joins, listing joins)
  4. Controller parameter mapping

🟢 MEDIUM (Validation)

  1. DTO field validations
  2. Enum constraints
  3. Optional field handling
  4. Guard enforcement

Test Execution Order Recommendation

  1. Value Objects (2 files) - 2 simple test files
  2. DTOs (10 files) - Use class-validator testing patterns
  3. Controllers (2 files) - Command/query dispatch tests
  4. Repositories (3 files) - Data layer tests with mocked Prisma

Mock Setup Template

For Repositories:

const mockPrisma = {
  inquiry: { findUnique: vi.fn(), findMany: vi.fn(), create: vi.fn(), update: vi.fn(), delete: vi.fn(), count: vi.fn() },
};
const repo = new PrismaInquiryRepository(mockPrisma as any);

For Controllers:

const mockCommandBus = { execute: vi.fn() };
const mockQueryBus = { execute: vi.fn() };
const controller = new InquiriesController(mockCommandBus as any, mockQueryBus as any);

For Value Objects:

const result = LeadScore.create(75);
expect(result.isOk()).toBe(true);
expect(result.unwrap().value).toBe(75);

For DTOs:

import { validate } from 'class-validator';
const dto = new CreateLeadDto();
dto.name = 'Nguyễn Văn A';
dto.phone = '0901234567';
// ... set other required fields
const errors = await validate(dto);
expect(errors).toHaveLength(0);

Key Formulas to Verify

Pagination:

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

Lead Conversion Rate:

conversionRate = (convertedCount / totalLeads) * 100
Result: rounded to 2 decimals (e.g., 33.33)

Lead Average Score:

avgScore = scoreSum / scoreCount (where score !== null)
Result: rounded to 1 decimal (e.g., 75.5)

Review Average Rating:

averageRating = (sum / totalReviews) 
Result: rounded to 1 decimal (e.g., 4.5)

Review Distribution:

distribution: { 1: count, 2: count, 3: count, 4: count, 5: count }
Must initialize all 5 keys, even if 0

File Locations for Reference

/Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/api/

Inquiries:
  src/modules/inquiries/infrastructure/repositories/prisma-inquiry.repository.ts
  src/modules/inquiries/presentation/controllers/inquiries.controller.ts
  src/modules/inquiries/presentation/dto/create-inquiry.dto.ts
  src/modules/inquiries/presentation/dto/list-inquiries.dto.ts

Leads:
  src/modules/leads/infrastructure/repositories/prisma-lead.repository.ts
  src/modules/leads/domain/value-objects/lead-score.vo.ts
  src/modules/leads/presentation/controllers/leads.controller.ts
  src/modules/leads/presentation/dto/create-lead.dto.ts
  src/modules/leads/presentation/dto/list-leads.dto.ts
  src/modules/leads/presentation/dto/update-lead-status.dto.ts

Reviews:
  src/modules/reviews/infrastructure/repositories/prisma-review.repository.ts
  src/modules/reviews/domain/value-objects/rating.vo.ts
  src/modules/reviews/presentation/controllers/reviews.controller.ts
  src/modules/reviews/presentation/dto/create-review.dto.ts
  src/modules/reviews/presentation/dto/list-reviews.dto.ts

Next Steps

  1. Copy reference test patterns:

    • Create inquiry and lead handlers already have good test patterns
    • Controller test for reviews shows endpoint testing approach
  2. Start with repositories:

    • Most complex (Prisma mocking)
    • Most critical (data layer)
    • Established patterns in existing tests
  3. Test DTOs second:

    • Quick feedback (class-validator validation)
    • 10 files but mostly simple
  4. Controllers and VOs last:

    • Build on repository/DTO tests
    • Depend on handler tests (if testing full flow)