Spaces:
Sleeping
Sleeping
| /** | |
| * Complete Lesley's Profile - Full Test | |
| * Tests financial accounts, assets, and location updates | |
| */ | |
| const https = require('https'); | |
| const BASE_URL = 'https://kamau1-swiftops-backend.hf.space'; | |
| const ADMIN_EMAIL = 'lewis.kamau421@gmail.com'; | |
| const ADMIN_PASSWORD = 'TestPass123'; | |
| const LESLEY_EMAIL = 'lesley@example.com'; | |
| let adminToken = null; | |
| let lesleyUserId = null; | |
| let financialAccountId = null; | |
| let assetAssignmentId = null; | |
| const colors = { | |
| reset: '\x1b[0m', | |
| green: '\x1b[32m', | |
| red: '\x1b[31m', | |
| yellow: '\x1b[33m', | |
| blue: '\x1b[36m', | |
| magenta: '\x1b[35m', | |
| cyan: '\x1b[96m' | |
| }; | |
| function log(message, color = 'reset') { | |
| console.log(`${colors[color]}${message}${colors.reset}`); | |
| } | |
| function makeRequest(method, path, data = null, token = null) { | |
| return new Promise((resolve, reject) => { | |
| const url = new URL(path, BASE_URL); | |
| const options = { | |
| method, | |
| headers: { 'Content-Type': 'application/json' }, | |
| timeout: 30000 | |
| }; | |
| if (token) { | |
| options.headers['Authorization'] = `Bearer ${token}`; | |
| } | |
| log(` β ${method} ${path}`, 'yellow'); | |
| const req = https.request(url, options, (res) => { | |
| let body = ''; | |
| res.on('data', chunk => body += chunk); | |
| res.on('end', () => { | |
| try { | |
| const response = { status: res.statusCode, data: body ? JSON.parse(body) : null }; | |
| log(` β ${res.statusCode} ${res.statusMessage}`, 'yellow'); | |
| resolve(response); | |
| } catch (e) { | |
| log(` β ${res.statusCode} (non-JSON)`, 'yellow'); | |
| resolve({ status: res.statusCode, data: body }); | |
| } | |
| }); | |
| }); | |
| req.on('error', reject); | |
| req.on('timeout', () => { | |
| req.destroy(); | |
| reject(new Error('Request timeout')); | |
| }); | |
| if (data) req.write(JSON.stringify(data)); | |
| req.end(); | |
| }); | |
| } | |
| async function step1_Login() { | |
| log('\nπ Step 1: Login as Admin', 'blue'); | |
| const response = await makeRequest('POST', '/api/v1/auth/login', { | |
| email: ADMIN_EMAIL, | |
| password: ADMIN_PASSWORD | |
| }); | |
| if (response.status === 200) { | |
| adminToken = response.data.access_token; | |
| log('β Login successful', 'green'); | |
| log(` Token: ${adminToken.substring(0, 30)}...`); | |
| return true; | |
| } else { | |
| log(`β Login failed: ${response.status}`, 'red'); | |
| return false; | |
| } | |
| } | |
| async function step2_GetLesleyUserId() { | |
| log('\nπ Step 2: Get Lesley\'s User ID', 'blue'); | |
| const response = await makeRequest('GET', `/api/v1/users/search?email=${LESLEY_EMAIL}`, null, adminToken); | |
| if (response.status === 200 && response.data.length > 0) { | |
| const user = response.data[0]; | |
| lesleyUserId = user.id; | |
| log('β Found Lesley\'s user account', 'green'); | |
| log(` User ID: ${lesleyUserId}`); | |
| log(` Email: ${user.email}`); | |
| log(` Name: ${user.name}`); | |
| return true; | |
| } else { | |
| log('β Could not find Lesley\'s user account', 'red'); | |
| return false; | |
| } | |
| } | |
| async function step3_CreateFinancialAccount() { | |
| log('\nπ° Step 3: Create Financial Account', 'blue'); | |
| const response = await makeRequest('POST', `/api/v1/financial-accounts/user/${lesleyUserId}`, { | |
| account_name: 'M-Pesa Account', | |
| payout_method: 'mobile_money', | |
| mobile_money_provider: 'Safaricom', | |
| mobile_money_phone: '+254712345678', | |
| mobile_money_account_name: 'Lesley Wanjiru', | |
| is_primary: true | |
| }, adminToken); | |
| if (response.status === 201) { | |
| financialAccountId = response.data.id; | |
| log('β Financial account created', 'green'); | |
| log(` Account ID: ${financialAccountId}`); | |
| log(` Method: ${response.data.payout_method}`); | |
| log(` Name: ${response.data.account_name}`); | |
| log(` Phone: ${response.data.mobile_money_phone}`); | |
| log(` Provider: ${response.data.mobile_money_provider}`); | |
| log(` Primary: ${response.data.is_primary}`); | |
| return true; | |
| } else { | |
| log(`β Failed to create account: ${response.status}`, 'red'); | |
| log(` ${JSON.stringify(response.data, null, 2)}`); | |
| return false; | |
| } | |
| } | |
| async function step4_GetFinancialAccounts() { | |
| log('\nπ³ Step 4: Get Financial Accounts', 'blue'); | |
| const response = await makeRequest('GET', `/api/v1/financial-accounts/user/${lesleyUserId}`, null, adminToken); | |
| if (response.status === 200) { | |
| log('β Retrieved financial accounts', 'green'); | |
| log(` Total Accounts: ${response.data.length}`); | |
| response.data.forEach((acc, i) => { | |
| log(` ${i + 1}. ${acc.account_name} (${acc.payout_method})`); | |
| if (acc.mobile_money_phone) log(` Phone: ${acc.mobile_money_phone}`); | |
| if (acc.bank_account_number) log(` Account: ${acc.bank_account_number}`); | |
| }); | |
| return true; | |
| } else { | |
| log(`β Failed to get accounts: ${response.status}`, 'red'); | |
| return false; | |
| } | |
| } | |
| async function step5_UpdateLocation() { | |
| log('\nπ Step 5: Update Location', 'blue'); | |
| const response = await makeRequest('PUT', `/api/v1/profile/${lesleyUserId}/location`, { | |
| current_location_name: 'Nairobi Office', | |
| current_country: 'Kenya', | |
| current_region: 'Nairobi County', | |
| current_city: 'Nairobi', | |
| current_address_line1: 'Kenyatta Avenue', | |
| current_address_line2: 'Building 12, Floor 3', | |
| current_latitude: -1.286389, | |
| current_longitude: 36.817223, | |
| current_maps_link: 'https://maps.google.com/?q=-1.286389,36.817223' | |
| }, adminToken); | |
| if (response.status === 200) { | |
| log('β Location updated', 'green'); | |
| log(` Location: ${response.data.current_location_name}`); | |
| log(` City: ${response.data.current_city}`); | |
| log(` Country: ${response.data.current_country}`); | |
| log(` Address: ${response.data.current_address_line1}`); | |
| log(` Coordinates: ${response.data.current_latitude}, ${response.data.current_longitude}`); | |
| return true; | |
| } else { | |
| log(`β Failed to update location: ${response.status}`, 'red'); | |
| log(` ${JSON.stringify(response.data, null, 2)}`); | |
| return false; | |
| } | |
| } | |
| async function step6_AssignAsset() { | |
| log('\nπ§ Step 6: Assign Asset', 'blue'); | |
| const response = await makeRequest('POST', `/api/v1/asset-assignments/user/${lesleyUserId}`, { | |
| asset_type: 'PPE', | |
| asset_name: 'Safety Helmet', | |
| serial_number: 'HELMET-001', | |
| condition_on_assign: 'good', | |
| notes: 'Standard safety helmet for field work' | |
| }, adminToken); | |
| if (response.status === 201) { | |
| assetAssignmentId = response.data.id; | |
| log('β Asset assigned', 'green'); | |
| log(` Assignment ID: ${assetAssignmentId}`); | |
| log(` Asset: ${response.data.asset_name}`); | |
| log(` Type: ${response.data.asset_type}`); | |
| log(` Serial: ${response.data.serial_number}`); | |
| log(` Condition: ${response.data.condition_on_assign}`); | |
| return true; | |
| } else { | |
| log(`β Failed to assign asset: ${response.status}`, 'red'); | |
| log(` ${JSON.stringify(response.data, null, 2)}`); | |
| return false; | |
| } | |
| } | |
| async function step7_AssignMoreAssets() { | |
| log('\nπ οΈ Step 7: Assign More Assets', 'blue'); | |
| const assets = [ | |
| { | |
| asset_type: 'PPE', | |
| asset_name: 'Safety Vest', | |
| serial_number: 'VEST-042', | |
| condition_on_assign: 'good', | |
| notes: 'High visibility vest' | |
| }, | |
| { | |
| asset_type: 'Laptop', | |
| asset_name: 'Tablet', | |
| serial_number: 'TAB-156', | |
| condition_on_assign: 'good', | |
| notes: 'Samsung Galaxy Tab for field reporting' | |
| } | |
| ]; | |
| let success = 0; | |
| for (const asset of assets) { | |
| const response = await makeRequest('POST', `/api/v1/asset-assignments/user/${lesleyUserId}`, asset, adminToken); | |
| if (response.status === 201) { | |
| success++; | |
| log(` β Assigned: ${asset.asset_name}`, 'green'); | |
| } else { | |
| log(` β Failed: ${asset.asset_name}`, 'red'); | |
| } | |
| } | |
| log(`β Assigned ${success}/${assets.length} additional assets`, 'green'); | |
| return success === assets.length; | |
| } | |
| async function step8_GetAssetAssignments() { | |
| log('\nπ¦ Step 8: Get Asset Assignments', 'blue'); | |
| const response = await makeRequest('GET', `/api/v1/asset-assignments/user/${lesleyUserId}`, null, adminToken); | |
| if (response.status === 200) { | |
| log('β Retrieved asset assignments', 'green'); | |
| log(` Total Assets: ${response.data.length}`); | |
| response.data.forEach((asset, i) => { | |
| const status = asset.is_active ? 'π’ Active' : 'π΄ Returned'; | |
| log(` ${i + 1}. ${asset.asset_name} (${asset.asset_type}) - ${status}`); | |
| if (asset.serial_number) log(` Serial: ${asset.serial_number}`); | |
| }); | |
| return true; | |
| } else { | |
| log(`β Failed to get assets: ${response.status}`, 'red'); | |
| return false; | |
| } | |
| } | |
| async function step9_ValidateProfile() { | |
| log('\nβ Step 9: Validate Complete Profile', 'blue'); | |
| const response = await makeRequest('GET', `/api/v1/profile/${lesleyUserId}/validation`, null, adminToken); | |
| if (response.status === 200) { | |
| log('β Validation complete', 'green'); | |
| log(` Is Valid: ${response.data.is_valid}`); | |
| log(` Completion: ${response.data.completion_percentage}%`); | |
| if (response.data.missing_fields.length > 0) { | |
| log(` Missing: ${response.data.missing_fields.join(', ')}`, 'yellow'); | |
| } else { | |
| log(` All required fields complete! π`, 'green'); | |
| } | |
| if (response.data.warnings.length > 0) { | |
| log(` Warnings:`, 'yellow'); | |
| response.data.warnings.forEach(w => log(` - ${w}`, 'yellow')); | |
| } | |
| return true; | |
| } else { | |
| log(`β Validation failed: ${response.status}`, 'red'); | |
| return false; | |
| } | |
| } | |
| async function step10_GetFinalProfile() { | |
| log('\nπ Step 10: Get Final Profile Status', 'blue'); | |
| const response = await makeRequest('GET', `/api/v1/profile/${lesleyUserId}`, null, adminToken); | |
| if (response.status === 200) { | |
| const profile = response.data; | |
| log('β Final profile retrieved', 'green'); | |
| log(`\n Profile Completion: ${profile.completion_status.completion_percentage}%`); | |
| log(` ββββββββββββββββββββββββββββββββββββββββ`); | |
| log(` Basic Info: ${profile.completion_status.basic_info ? 'β' : 'β'}`); | |
| log(` Health Info: ${profile.completion_status.health_info ? 'β' : 'β'}`); | |
| log(` PPE Sizes: ${profile.completion_status.ppe_sizes ? 'β' : 'β'}`); | |
| log(` Location: ${profile.completion_status.location ? 'β' : 'β'}`); | |
| log(` Financial: ${profile.completion_status.financial_accounts ? 'β' : 'β'} (${profile.financial_accounts_count} accounts)`); | |
| log(` Assets: ${profile.asset_assignments_count} assigned`); | |
| log(` Documents: ${profile.completion_status.documents ? 'β' : 'β'} (${profile.documents_count} docs)`); | |
| return true; | |
| } else { | |
| log(`β Failed: ${response.status}`, 'red'); | |
| return false; | |
| } | |
| } | |
| async function runTest() { | |
| log('='.repeat(70), 'blue'); | |
| log('π― Complete Lesley\'s Profile - Full Test', 'blue'); | |
| log(' Testing: Financial Accounts, Assets, Location', 'cyan'); | |
| log('='.repeat(70), 'blue'); | |
| const results = []; | |
| // Setup | |
| if (!await step1_Login()) { | |
| log('\nβ Cannot continue without login', 'red'); | |
| process.exit(1); | |
| } | |
| results.push({ name: 'Login', status: true }); | |
| if (!await step2_GetLesleyUserId()) { | |
| log('\nβ Cannot continue without user ID', 'red'); | |
| process.exit(1); | |
| } | |
| results.push({ name: 'Get User ID', status: true }); | |
| // Financial Account Tests | |
| results.push({ name: 'Create Financial Account', status: await step3_CreateFinancialAccount() }); | |
| results.push({ name: 'Get Financial Accounts', status: await step4_GetFinancialAccounts() }); | |
| // Location Test | |
| results.push({ name: 'Update Location', status: await step5_UpdateLocation() }); | |
| // Asset Assignment Tests | |
| results.push({ name: 'Assign Asset', status: await step6_AssignAsset() }); | |
| results.push({ name: 'Assign More Assets', status: await step7_AssignMoreAssets() }); | |
| results.push({ name: 'Get Asset Assignments', status: await step8_GetAssetAssignments() }); | |
| // Validation | |
| results.push({ name: 'Validate Profile', status: await step9_ValidateProfile() }); | |
| results.push({ name: 'Get Final Status', status: await step10_GetFinalProfile() }); | |
| // Summary | |
| log('\n' + '='.repeat(70), 'blue'); | |
| log('π Test Summary', 'blue'); | |
| log('='.repeat(70), 'blue'); | |
| let passed = 0, failed = 0; | |
| results.forEach(r => { | |
| const icon = r.status ? 'β ' : 'β'; | |
| const color = r.status ? 'green' : 'red'; | |
| log(`${icon} ${r.name}`, color); | |
| if (r.status) passed++; else failed++; | |
| }); | |
| log('\n' + '-'.repeat(70)); | |
| log(`Total: ${results.length} | Passed: ${passed} | Failed: ${failed}`); | |
| if (failed === 0) { | |
| log('\nπ All tests passed! Profile is complete!', 'green'); | |
| log(`\n⨠Lesley's complete profile summary:`, 'magenta'); | |
| log(` User ID: ${lesleyUserId}`, 'magenta'); | |
| log(` Financial Account: ${financialAccountId}`, 'magenta'); | |
| log(` Asset Assignment: ${assetAssignmentId}`, 'magenta'); | |
| log(` All changes logged in audit_logs table`, 'magenta'); | |
| } else { | |
| log(`\nβ οΈ ${failed} step(s) failed`, 'red'); | |
| } | |
| } | |
| runTest().catch(error => { | |
| log(`\nπ₯ Fatal error: ${error.message}`, 'red'); | |
| console.error(error); | |
| process.exit(1); | |
| }); | |