# 🎯 THAM KHẢO NHANH: 3 Tệp Test Còn Thiếu ## Ưu tiên: CAO - Tất cả đều cần viết test ### 1️⃣ reject-listing.handler.spec.ts **Vị trí:** `apps/api/src/modules/admin/application/__tests__/` **Mẫu tham khảo:** `approve-listing.handler.spec.ts` **Phạm vi test cần có:** - ✅ Trường hợp thành công: Từ chối listing ở trạng thái PENDING_REVIEW thành công - ✅ Lỗi: NotFoundException khi listing không tồn tại - ✅ Lỗi: ValidationException khi trạng thái listing không hợp lệ - ✅ Xác minh: listingRepo.update() được gọi đúng một lần - ✅ Xác minh: ListingRejectedEvent được phát với dữ liệu chính xác **Code quan trọng:** - Command: RejectListingCommand(listingId, adminId, reason) - Handler: RejectListingHandler - Event: ListingRejectedEvent - Kết quả trả về: { listingId, status: 'REJECTED', message } --- ### 2️⃣ get-revenue-stats.handler.spec.ts **Vị trí:** `apps/api/src/modules/admin/application/__tests__/` **Mẫu tham khảo:** `get-dashboard-stats.handler.spec.ts` **Phạm vi test cần có:** - ✅ Query trả về RevenueStatsItem[] từ repository - ✅ Xác minh: adminQueryRepo.getRevenueStats() được gọi với startDate, endDate, groupBy - ✅ Hỗ trợ cả hai giá trị 'day' và 'month' cho groupBy - ✅ Mặc định groupBy là 'month' - ✅ Xử lý kết quả rỗng (mảng trống) **Code quan trọng:** - Query: GetRevenueStatsQuery(startDate, endDate, groupBy='month') - Handler: GetRevenueStatsHandler - Trả về: RevenueStatsItem[] với { period, totalRevenue, subscriptionRevenue, listingFeeRevenue, featuredListingRevenue, transactionCount } --- ### 3️⃣ user-deactivated.listener.spec.ts **Vị trí:** `apps/api/src/modules/admin/application/__tests__/` **Mẫu tham khảo:** `user-banned.listener.spec.ts` **Phạm vi test cần có:** - ✅ Event listener xử lý sự kiện 'user.deactivated' - ✅ Hết hạn các listing có trạng thái ACTIVE hoặc PENDING_REVIEW - ✅ Chỉ cập nhật listing của người dùng bị vô hiệu hóa - ✅ Ghi log ban đầu khi xử lý và kết quả - ✅ Xử lý trường hợp 0 listing được cập nhật - ✅ Xử lý trường hợp nhiều listing được cập nhật **Code quan trọng:** - Listener: UserDeactivatedListener - Event: UserDeactivatedEvent (async: true) - Hành động: prisma.listing.updateMany() với điều kiện sellerId khớp & status thuộc [ACTIVE, PENDING_REVIEW] - Ghi log: Khởi tạo + số lượng kết quả --- ## Mẫu Thiết Lập Mock ### Dành cho Handler (Command): ```typescript mockListingRepo = { findById, update, ... }; mockEventBus = { publish }; handler = new RejectListingHandler(mockListingRepo, mockEventBus); ``` ### Dành cho Query Handler: ```typescript mockAdminQueryRepo = { getRevenueStats }; handler = new GetRevenueStatsHandler(mockAdminQueryRepo); ``` ### Dành cho Listener: ```typescript mockPrisma = { listing: { updateMany }, user: { findUnique } }; mockLogger = { log }; listener = new UserDeactivatedListener(mockPrisma, mockLogger); ``` --- ## Danh Sách Kiểm Tra Test - [ ] reject-listing.handler.spec.ts đã được tạo - [ ] get-revenue-stats.handler.spec.ts đã được tạo - [ ] user-deactivated.listener.spec.ts đã được tạo - [ ] Tất cả test đều vượt qua: `npm test admin` - [ ] Báo cáo độ phủ hiển thị màu xanh cho cả 3 tệp