kamau1's picture
feat(project): add complete project setup workflow with service methods and API endpoints for regions, roles, subcontractors, and finalization including validation and authorization
4835b24
# User Invitation Test Guide
## Quick Start
Run the complete invitation flow test:
```bash
node tests/integration/test_invitation_flow.js
```
## What This Test Does
### Step-by-Step Flow
1. **Login as Platform Admin**
- Email: `lewis.kamau421@gmail.com`
- Password: `TestPass123`
- Gets authentication token
2. **Create Contractor Organization**
- Name: TechInstall Kenya Ltd
- Email: info@techinstall.co.ke
- Competencies: FTTH, Fixed Wireless, Fiber Splicing
- Returns existing if already created
3. **Invite User to Contractor**
- Email: `irene@example.com`
- Phone: `+254799456976`
- Role: `field_agent`
- Method: WhatsApp (with email fallback)
4. **Validate Invitation Token**
- Public endpoint (no auth required)
- Verifies token is valid and not expired
- Returns organization details
5. **List All Invitations**
- Shows all invitations created by admin
- Includes pagination info
## Expected Results
### Successful Test Output
```
πŸš€ SwiftOps User Invitation Flow Test
πŸ“ Server: https://kamau1-swiftops-backend.hf.space
πŸ‘€ Admin: lewis.kamau421@gmail.com
πŸ“§ Inviting: irene@example.com (+254799456976)
βœ… Login as Admin
βœ… Create Contractor
βœ… Invite User
πŸ“± Invitation URL:
https://swiftops.atomio.tech/accept-invitation?token=xxx
βœ… Validate Invitation
βœ… List Invitations
πŸŽ‰ All steps completed successfully!
```
### What Happens Next
1. **Irene receives WhatsApp message** on +254799456976:
```
Hi Irene,
You've been invited to join TechInstall Kenya Ltd on SwiftOps
as a Field Agent.
πŸ”— Accept your invitation here:
https://swiftops.atomio.tech/accept-invitation?token=xxx
⏰ This invitation expires in 72 hours.
```
2. **Irene clicks the link** β†’ Opens registration page
3. **Registration form shows**:
- Email: `irene@example.com` (pre-filled)
- Phone: `+254799456976` (pre-filled)
- Organization: TechInstall Kenya Ltd
- Role: Field Agent
- Fields to fill: First Name, Last Name, Password
4. **Irene submits form** β†’ Account created β†’ Auto logged in
## Notification Delivery
### WhatsApp (Primary)
- Sent via WaSender API
- Requires: `WASENDER_API_KEY`, `WASENDER_PHONE_NUMBER`
- Format: Plain text with link
### Email (Fallback)
- Sent via Resend API if WhatsApp fails
- Requires: `RESEND_API_KEY`, `RESEND_FROM_EMAIL`
- Format: Professional HTML template
### Delivery Tracking
The test shows:
- `whatsapp_sent: true/false`
- `whatsapp_sent_at: timestamp`
- `email_sent: true/false`
- `email_sent_at: timestamp`
## Testing Different Scenarios
### Test 1: Invite to Contractor
```javascript
// Already configured in test_invitation_flow.js
const INVITE_ROLE = 'field_agent';
const contractor_id = 'uuid';
```
### Test 2: Invite to Client
Modify the test to create a client instead:
```javascript
// In step2_CreateContractor, change to:
const response = await makeRequest('POST', '/api/v1/clients', {
name: 'Safaricom Kenya',
industry: 'Telecommunications',
main_email: 'info@safaricom.co.ke',
main_phone: '+254700000000',
default_sla_days: 7
}, authToken);
// In step3_InviteUser, change to:
client_id: clientId, // instead of contractor_id
role: 'client_admin' // or other client role
```
### Test 3: Different Roles
Change the role in the test:
```javascript
const INVITE_ROLE = 'contractor_admin'; // Admin role
const INVITE_ROLE = 'project_manager'; // Manager role
const INVITE_ROLE = 'dispatcher'; // Dispatcher role
const INVITE_ROLE = 'sales_agent'; // Sales role
```
### Test 4: Email-Only Delivery
Change invitation method:
```javascript
invitation_method: 'email' // Skip WhatsApp, use email only
```
### Test 5: Both Methods
Send via both channels:
```javascript
invitation_method: 'both' // Send WhatsApp AND email
```
## Troubleshooting
### Issue: "Cannot reach server"
**Solution:**
- Check server is running at `https://kamau1-swiftops-backend.hf.space`
- Verify network connectivity
- Try accessing `/health` endpoint
### Issue: "Login failed"
**Solution:**
- Verify admin credentials are correct
- Check if user exists in database
- Ensure Supabase Auth is configured
### Issue: "Create contractor failed"
**Solution:**
- Check if contractor already exists (should return existing)
- Verify admin has `platform_admin` role
- Check database connection
### Issue: "Invitation failed"
**Solution:**
- Verify contractor/client ID is valid
- Check role is valid for organization type
- Ensure no duplicate pending invitation exists
### Issue: "WhatsApp not sent"
**Solution:**
- Check `WASENDER_API_KEY` is set and valid
- Verify phone number format (+country code)
- System should fallback to email automatically
- Check test output for `whatsapp_error` field
### Issue: "Email not sent"
**Solution:**
- Check `RESEND_API_KEY` is set and valid
- Verify `RESEND_FROM_EMAIL` is verified in Resend
- Check test output for `email_error` field
## Manual Testing via API
### 1. Get Admin Token
```bash
curl -X POST "https://kamau1-swiftops-backend.hf.space/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "lewis.kamau421@gmail.com",
"password": "TestPass123"
}'
```
### 2. Create Contractor
```bash
curl -X POST "https://kamau1-swiftops-backend.hf.space/api/v1/contractors" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "TechInstall Kenya Ltd",
"description": "Leading field service provider",
"main_email": "info@techinstall.co.ke",
"main_phone": "+254700123456",
"competencies": ["FTTH", "Fixed Wireless"]
}'
```
### 3. Create Invitation
```bash
curl -X POST "https://kamau1-swiftops-backend.hf.space/api/v1/invitations" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "irene@example.com",
"phone": "+254799456976",
"role": "field_agent",
"contractor_id": "CONTRACTOR_ID",
"invitation_method": "whatsapp"
}'
```
### 4. Validate Token (No Auth)
```bash
curl -X POST "https://kamau1-swiftops-backend.hf.space/api/v1/invitations/validate" \
-H "Content-Type: application/json" \
-d '{
"token": "INVITATION_TOKEN"
}'
```
## Environment Variables Checklist
Before running tests, ensure these are set:
- [ ] `APP_DOMAIN=swiftops.atomio.tech`
- [ ] `APP_PROTOCOL=https`
- [ ] `INVITATION_TOKEN_EXPIRY_HOURS=72`
- [ ] `RESEND_API_KEY=re_xxx`
- [ ] `RESEND_FROM_EMAIL=swiftops@atomio.tech`
- [ ] `WASENDER_API_KEY=xxx`
- [ ] `WASENDER_PHONE_NUMBER=+254xxx`
- [ ] `WASENDER_API_URL=https://api.wasender.com/v1`
## Success Criteria
βœ… Admin can login
βœ… Contractor organization created (or existing returned)
βœ… Invitation created successfully
βœ… WhatsApp notification sent (or email fallback)
βœ… Invitation token is valid
βœ… Invitation appears in list
βœ… Irene receives invitation on WhatsApp
βœ… Invitation URL works
## Next Steps After Test
1. **Check WhatsApp** - Verify Irene received the message
2. **Test Acceptance** - Have Irene click the link and register
3. **Verify User Created** - Check user appears in database
4. **Test Login** - Irene should be able to login
5. **Check Permissions** - Verify Irene has correct role and org access
## Production Checklist
Before going live:
- [ ] Test with real phone numbers
- [ ] Verify WhatsApp delivery
- [ ] Test email fallback
- [ ] Check invitation expiry (72 hours)
- [ ] Test duplicate prevention
- [ ] Verify RLS policies work
- [ ] Test all user roles
- [ ] Check authorization rules
- [ ] Test invitation cancellation
- [ ] Test invitation resending