# 🎯 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
