Files
nextjs-elysia-allaos/docs/checklist-phase7-testing.md
phaichayon 043edff93a setup
2026-04-26 00:15:22 +07:00

673 lines
13 KiB
Markdown

# Phase 7: Testing - Checklist
## 📋 Overview
This phase covers comprehensive testing of the refactored CRM backend system, including unit tests, integration tests, and manual API testing.
---
## ✅ Completed Tasks
None yet - Phase 7 is the final phase and has not been started.
---
## 🧪 Testing Strategy
### Testing Pyramid
```
/\
/ \ E2E Tests (Manual/API)
/____\
/ \ Integration Tests
/________\
/ \ Unit Tests
/____________\
```
### Test Categories
1. **Unit Tests** - Test individual functions in isolation
2. **Integration Tests** - Test service layer with database
3. **API Tests** - Test endpoints with requests/responses
4. **Manual Tests** - Postman/curl testing
---
## 📝 Unit Tests
### Customer Service Tests
- [ ] `generateCrmCustomerCode()`
- [ ] Generates unique code per branch
- [ ] Increments correctly
- [ ] Handles empty branch
- [ ] `getCustomersByBranch()`
- [ ] Returns only branch customers
- [ ] Filters by status correctly
- [ ] Includes contacts
- [ ] Handles empty results
- [ ] `getCustomerById()`
- [ ] Returns correct customer
- [ ] Enforces branch access
- [ ] Returns null for non-existent
- [ ] Returns null for wrong branch
- [ ] `createCustomer()`
- [ ] Creates customer with correct branch
- [ ] Auto-generates CRM code
- [ ] Validates required fields
- [ ] Sets createdBy and updatedBy
- [ ] `updateCustomer()`
- [ ] Updates customer correctly
- [ ] Enforces branch access
- [ ] Updates erpCustomerCode
- [ ] Sets updatedBy
- [ ] `deleteCustomer()`
- [ ] Soft deletes customer
- [ ] Enforces branch access
- [ ] Returns error if already deleted
### Contact Service Tests
- [ ] `getVisibleContactsForCustomer()`
- [ ] Returns only user's contacts (createdBy == userId)
- [ ] Returns public contacts (isPublic == true)
- [ ] Enforces branch access
- [ ] Filters by customerId
- [ ] `createContact()`
- [ ] Creates contact with correct branch
- [ ] Sets createdBy to current user
- [ ] Sets isPublic to false by default
- [ ] Validates required fields
- [ ] `updateContact()`
- [ ] Updates contact correctly
- [ ] Only allows creator to update
- [ ] Can update isPublic flag
- [ ] Enforces branch access
- [ ] `shareContact()`
- [ ] Sets isPublic to true
- [ ] Only allows creator to share
- [ ] Returns error for non-existent contact
- [ ] `unshareContact()`
- [ ] Sets isPublic to false
- [ ] Only allows creator to unshare
- [ ] Returns error for non-existent contact
- [ ] `deleteContact()`
- [ ] Deletes contact correctly
- [ ] Only allows creator to delete
- [ ] Enforces branch access
### Quotation Service Tests
- [ ] `generateQuotationCode()`
- [ ] Generates unique code
- [ ] Follows pattern (Q-YYYY-XXXXX)
- [ ] `calculateBaseCurrencyAmount()`
- [ ] Converts to THB correctly
- [ ] Handles THB (exchangeRate = 1)
- [ ] Handles different currencies
- [ ] Returns null for invalid currency
- [ ] `validateQuotationStatus()`
- [ ] Allows editing DRAFT
- [ ] Prevents editing SENT
- [ ] Validates status transitions
- [ ] `createQuotation()`
- [ ] Creates quotation with correct branch
- [ ] Validates currency code
- [ ] Validates exchange rate
- [ ] Calculates baseCurrencyAmount
- [ ] Validates customer has visible contacts
- [ ] Sets revisionNo to null (initial)
- [ ] Sets parentQuotationId to null (initial)
- [ ] `updateQuotation()`
- [ ] Updates quotation correctly
- [ ] Enforces branch access
- [ ] Validates status (only DRAFT)
- [ ] Sets updatedBy
- [ ] `createRevision()`
- [ ] Clones quotation correctly
- [ ] Increments revisionNo
- [ ] Sets parentQuotationId
- [ ] Sets status to DRAFT
- [ ] Preserves currency and exchange rate
- [ ] `getQuotationVersions()`
- [ ] Returns all versions by code
- [ ] Includes different currencies
- [ ] Orders by revisionNo
---
## 🔗 Integration Tests
### Database Integration
- [ ] Test database connection
- [ ] Test transaction rollback
- [ ] Test concurrent access
- [ ] Test foreign key constraints
### Service Integration
- [ ] Test customer creation with contacts
- [ ] Test quotation creation with items
- [ ] Test revision creation
- [ ] Test contact visibility rules
- [ ] Test branch scoping
### API Integration
- [ ] Test authentication flow
- [ ] Test branch context injection
- [ ] Test error handling
- [ ] Test response formats
---
## 🌐 Manual API Tests
### Customer Endpoints
#### Get All Customers
```bash
GET /api/customers
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Query Params (optional):
status: active | inactive | pending
Expected Response:
{
"success": true,
"data": [...],
"count": 10,
"message": "Found 10 customer(s)"
}
```
#### Get Customer by ID
```bash
GET /api/customers/:id
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": {
"id": "...",
"branchId": "...",
"name": "...",
"crmCustomerCode": "...",
...
}
}
```
#### Create Customer
```bash
POST /api/customers
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Content-Type: application/json
Body:
{
"name": "Test Customer",
"email": "test@example.com",
"phone": "1234567890",
"company": "Test Company",
"address": "123 Test St",
"customerStatus": "active",
"customerType": "corporate",
"taxId": "1234567890123"
}
Expected Response:
{
"success": true,
"data": {
"id": "...",
"crmCustomerCode": "CUST-001", // Auto-generated
...
},
"message": "Customer created successfully"
}
```
#### Update Customer
```bash
PUT /api/customers/:id
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Content-Type: application/json
Body:
{
"name": "Updated Customer",
"erpCustomerCode": "ERP-001" // Optional
}
Expected Response:
{
"success": true,
"data": {...},
"message": "Customer updated successfully"
}
```
#### Delete Customer
```bash
DELETE /api/customers/:id
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": {
"id": "...",
"deletedAt": "2026-04-24T..."
},
"message": "Customer deleted successfully"
}
```
### Contact Endpoints
#### Get Visible Contacts
```bash
GET /api/customers/:customerId/contacts
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": [
{
"id": "...",
"name": "John Doe",
"email": "john@example.com",
"isPublic": false,
...
}
],
"count": 5,
"message": "Found 5 contact(s)"
}
```
#### Create Contact
```bash
POST /api/customers/:customerId/contacts
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Content-Type: application/json
Body:
{
"name": "John Doe",
"position": "Manager",
"phone": "9876543210",
"email": "john@example.com",
"isPrimary": true
}
Expected Response:
{
"success": true,
"data": {
"id": "...",
"name": "John Doe",
"isPublic": false, // Default
...
},
"message": "Contact created successfully"
}
```
#### Share Contact
```bash
POST /api/contacts/:contactId/share
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": {
"id": "...",
"name": "John Doe",
"isPublic": true, // Now shared
...
},
"message": "Contact shared successfully"
}
```
### Quotation Endpoints
#### Create Quotation
```bash
POST /api/quotations
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Content-Type: application/json
Body:
{
"customerId": "customer-uuid",
"quotationDate": "2026-04-24T10:00:00Z",
"validUntil": "2026-05-24T10:00:00Z",
"currencyCode": "USD",
"exchangeRate": 35.5,
"subtotal": "1000.00",
"discount": "50.00",
"taxRate": 7.0,
"taxAmount": "66.50",
"totalAmount": "1016.50",
"notes": "Test quotation"
}
Expected Response:
{
"success": true,
"data": {
"id": "...",
"code": "Q-2026-00001", // Auto-generated
"baseCurrencyAmount": "36085.75", // THB equivalent
"status": "new_job_draft",
"revisionNo": null,
...
},
"message": "Quotation created successfully"
}
```
#### Update Quotation (Draft Only)
```bash
PUT /api/quotations/:id
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Content-Type: application/json
Body:
{
"subtotal": "1200.00",
"totalAmount": "1219.80"
}
Expected Response (Success):
{
"success": true,
"data": {...},
"message": "Quotation updated successfully"
}
Expected Response (Error if SENT):
{
"success": false,
"error": "Quotation cannot be edited. Create a revision instead."
}
```
#### Create Revision
```bash
POST /api/quotations/:id/revision
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": {
"id": "...",
"code": "Q-2026-00001", // Same code
"revisionNo": 1, // Incremented
"parentQuotationId": "original-quotation-id",
"status": "new_job_draft", // Reset to draft
...
},
"message": "Revision created successfully"
}
```
#### Get Quotation Versions
```bash
GET /api/quotations/code/:code/versions
Headers:
Authorization: Bearer <token>
x-branch-id: <branch-uuid>
Expected Response:
{
"success": true,
"data": [
{
"id": "...",
"code": "Q-2026-00001",
"revisionNo": 0,
"currencyCode": "THB",
"totalAmount": "1000.00",
...
},
{
"id": "...",
"code": "Q-2026-00001",
"revisionNo": 1,
"currencyCode": "THB",
"totalAmount": "1200.00",
...
},
{
"id": "...",
"code": "Q-2026-00001",
"revisionNo": 0, // Different currency version
"currencyCode": "USD",
"totalAmount": "30.00",
...
}
],
"count": 3
}
```
---
## 🐛 Error Scenarios
### Authentication Errors
- [ ] Missing Authorization header
- [ ] Invalid token
- [ ] Expired token
- [ ] Missing x-branch-id header
- [ ] Invalid branch ID
- [ ] User has no access to branch
### Validation Errors
- [ ] Missing required fields
- [ ] Invalid email format
- [ ] Invalid currency code
- [ ] Negative exchange rate
- [ ] Invalid status transition
- [ ] Creating quotation without visible contacts
### Permission Errors
- [ ] Accessing customer from wrong branch
- [ ] Updating contact not owned by user
- [ ] Sharing contact not owned by user
- [ ] Deleting contact not owned by user
- [ ] Editing sent quotation (without revision)
- [ ] Accessing quotation from wrong branch
### Business Logic Errors
- [ ] Duplicate CRM customer code
- [ ] Duplicate ERP customer code
- [ ] Quotation with no items
- [ ] Invalid discount amount
- [ ] Invalid tax calculation
- [ ] Revision of revision (not allowed)
---
## 📊 Test Coverage Goals
### Minimum Coverage Targets
- **Unit Tests**: 80% code coverage
- **Integration Tests**: 60% code coverage
- **API Tests**: 100% endpoint coverage
### Critical Path Coverage
- [ ] Customer CRUD flow
- [ ] Contact visibility flow
- [ ] Quotation creation flow
- [ ] Revision creation flow
- [ ] Multi-currency conversion
- [ ] Branch scoping enforcement
---
## 🛠️ Testing Tools
### Recommended Tools
- **Unit Tests**: Jest, Vitest
- **Integration Tests**: Supertest, @elysiajs/testing
- **API Testing**: Postman, Insomnia, curl
- **Database Testing**: testcontainers, docker-compose
### Test Data
Create test data fixtures:
- [ ] Sample customers
- [ ] Sample contacts
- [ ] Sample quotations
- [ ] Sample quotation items
- [ ] Test users with different branch access
---
## 📝 Test Execution
### Run All Tests
```bash
npm test
```
### Run Unit Tests Only
```bash
npm run test:unit
```
### Run Integration Tests Only
```bash
npm run test:integration
```
### Run with Coverage
```bash
npm run test:coverage
```
### Run Specific Test File
```bash
npm test customers.service.test.ts
```
---
## 🎯 Success Criteria
Phase 7 is complete when:
- [ ] All unit tests pass (80% coverage)
- [ ] All integration tests pass (60% coverage)
- [ ] All API endpoints tested manually
- [ ] All error scenarios tested
- [ ] Critical path scenarios tested
- [ ] Test documentation complete
- [ ] CI/CD pipeline configured
---
## 📋 Remaining Tasks
- [ ] Set up test framework (Jest/Vitest)
- [ ] Write unit tests for customer service
- [ ] Write unit tests for quotation service
- [ ] Write integration tests
- [ ] Create Postman collection
- [ ] Execute manual API tests
- [ ] Document test results
- [ ] Fix any bugs found
---
## 🔄 Next Steps
After Phase 7:
- [ ] Create final project documentation
- [ ] Deploy to staging environment
- [ ] Conduct user acceptance testing (UAT)
- [ ] Deploy to production
- [ ] Monitor and maintain
---
**Phase 7 Status**: 🚧 **NOT STARTED**
**Overall Project Status**: 85% Complete (Phases 1-6 Done)