# โœ… Development Checklist & Testing ## ๐ŸŽฏ Pre-Deployment Checklist ### Configuration โœ“ - [ ] Update `REFERENCE_LATITUDE` dan `REFERENCE_LONGITUDE` di `AttendanceConfig.kt` - [ ] Set `ALLOWED_RADIUS_METERS` ke nilai yang benar - [ ] Update `STUDENT_NPM` dan `STUDENT_NAMA` - [ ] Verify webhook URLs (`WEBHOOK_PRODUCTION` dan `WEBHOOK_TEST`) - [ ] Set `PHOTO_QUALITY` ke nilai optimal (80 recommended) ### Permissions โœ“ - [ ] AndroidManifest.xml include semua required permissions - [ ] Location permissions (FINE_LOCATION, COARSE_LOCATION) - [ ] Camera permission - [ ] Internet permission ### Location Validation โœ“ - [ ] LocationValidator.calculateDistance() bekerja dengan benar - [ ] isLocationValid() mengembalikan hasil yang akurat - [ ] getValidationMessage() menampilkan pesan yang jelas - [ ] Haversine formula calculation sudah tested - [ ] Edge cases sudah di-handle (same location, very far, etc) ### API Integration โœ“ - [ ] N8nService bisa serialize Bitmap ke Base64 - [ ] Request body JSON format sesuai dengan N8n expectation - [ ] Response codes (200, 400, 500) ditangani dengan baik - [ ] Error messages user-friendly dan informatif - [ ] Timeout handling sudah implemented - [ ] Test dengan WEBHOOK_TEST dulu sebelum PRODUCTION ### UI/UX โœ“ - [ ] PhotoPreviewCard menampilkan foto dengan benar - [ ] LocationStatusCard menampilkan koordinat dan jarak akurat - [ ] ErrorAlertCard dismissable dan muncul saat ada error - [ ] SubmitButtonWithLoader loading state visible - [ ] Loading spinner saat ambil GPS - [ ] Loading spinner saat submit - [ ] Form disabled sampai semua data ready - [ ] Scrollable untuk device dengan screen kecil ### Error Handling โœ“ - [ ] GPS tidak tersedia โ†’ clear error message - [ ] Permission denied โ†’ actionable error message - [ ] Network error โ†’ suggest retry - [ ] Location invalid โ†’ show distance info - [ ] Foto tidak ambil โ†’ prompt untuk retry - [ ] Server error โ†’ indicate temporary issue - [ ] All errors dismissable atau auto-clear ### State Management โœ“ - [ ] AttendanceState properly initialized - [ ] State updates immutable (menggunakan .copy()) - [ ] LaunchedEffect untuk side effects - [ ] Permission launchers properly connected - [ ] State reset setelah successful submission ### Testing โœ“ - [ ] Unit tests LocationValidator berjalan sukses - [ ] All distance calculations accurate - [ ] Edge cases (distance=0, very far) handled - [ ] Manual test: permission flow - [ ] Manual test: GPS acquisition - [ ] Manual test: photo capture - [ ] Manual test: form validation - [ ] Manual test: webhook submission --- ## ๐Ÿงช Manual Testing Scenarios ### Scenario 1: Happy Path (Semua Berjalan Baik) ``` 1. โœ“ App launch โ†’ Request location permission 2. โœ“ Grant permission โ†’ GPS location acquired 3. โœ“ LocationStatusCard shows valid location + distance 4. โœ“ User click "Ambil Foto" โ†’ Camera app opens 5. โœ“ Take selfie โ†’ Photo preview shows 6. โœ“ PhotoPreviewCard displays foto correctly 7. โœ“ All validation checks pass 8. โœ“ Submit button enabled 9. โœ“ Click "Kirim Absensi" โ†’ Loading shows 10. โœ“ Response 200 โ†’ Success toast appears 11. โœ“ Form auto-reset after 2 seconds ``` **Expected Result**: โœ… Success message shown, form reset --- ### Scenario 2: Location Outside Radius ``` 1. โœ“ GPS location acquired: -7.05, 110.45 (far away) 2. โœ“ LocationStatusCard shows "โœ— Lokasi tidak valid" 3. โœ“ Shows distance exceeded radius 4. โœ“ Submit button remains DISABLED 5. โœ“ User can't submit until inside radius ``` **Expected Result**: โœ… Form disabled, validation error clear --- ### Scenario 3: Permission Denied ``` 1. โœ“ App launch โ†’ Permission dialog appears 2. โœ“ User click "Deny" โ†’ Error message shows 3. โœ“ Error: "Izin lokasi ditolak" 4. โœ“ User can open Settings to grant permission manually ``` **Expected Result**: โœ… Clear error, actionable message --- ### Scenario 4: Camera Not Available ``` 1. โœ“ User click "Ambil Foto" 2. โœ— Device tidak support camera 3. โœ“ Permission denied โ†’ Error message shows 4. โœ“ Error: "Izin kamera ditolak" ``` **Expected Result**: โœ… Graceful handling, clear message --- ### Scenario 5: Network Error ``` 1. โœ“ All validation pass, ready to submit 2. โœ— Internet disconnected 3. โœ“ Submit attempt โ†’ Network error occurs 4. โœ“ Error message: "Tidak dapat terhubung ke server" 5. โœ“ Loading spinner goes away 6. โœ“ User can retry submission ``` **Expected Result**: โœ… Error handled, user can retry --- ### Scenario 6: Server Error (5xx) ``` 1. โœ“ All validation pass, ready to submit 2. โœ“ Internet OK, but server returns 500 3. โœ“ Error message shown: "Gagal kirim ke server" 4. โœ“ Suggest checking later or contacting admin 5. โœ“ User can retry ``` **Expected Result**: โœ… Error message clear, retry available --- ## ๐Ÿ”„ Testing with Different Locations ### Test Case 1: Inside Radius (Valid) ``` Reference: -7.0, 110.4 Test Location: -7.0005, 110.4005 Distance: ~50m Expected: โœ“ VALID ``` ### Test Case 2: On Radius Boundary ``` Reference: -7.0, 110.4 Test Location: -7.0008, 110.4008 Distance: ~113m Radius: 100m Expected: โœ— INVALID (just outside) ``` ### Test Case 3: Far Away ``` Reference: -7.0, 110.4 Test Location: -7.1, 110.5 Distance: ~15km+ Expected: โœ— INVALID ``` --- ## ๐Ÿ“ฑ Device Testing ### Minimum Requirements - [ ] Android 8.0 (API 28) or higher - [ ] 100MB free storage (APK + photo temp) - [ ] Active internet connection - [ ] Location services enabled - [ ] Google Play Services installed ### Test Devices - [ ] Physical device (recommended) - [ ] Emulator with Google Play Services - [ ] Different Android versions (8, 10, 12, 13, 14) - [ ] Different screen sizes (small, normal, large) ### Test Scenarios per Device ``` Device 1: Samsung Galaxy (Android 14) [ ] Location acquisition [ ] Photo capture quality [ ] Network stability [ ] UI rendering Device 2: Emulator (Android 12) [ ] Permission flows [ ] GPS emulation [ ] Network simulation [ ] Error handling ``` --- ## ๐Ÿ› Debug Mode Checklist ### Enable Logging ```kotlin // Di MainActivity atau N8nService android.util.Log.d("AbsensiApp", "Location: $latitude, $longitude") android.util.Log.d("AbsensiApp", "Distance: $distance meters") android.util.Log.d("AbsensiApp", "Validation: $isValid") android.util.Log.d("N8nService", "Request: ${json.toString()}") android.util.Log.d("N8nService", "Response: $responseCode") ``` ### Check Logcat ```bash # Filter logs adb logcat | grep "AbsensiApp" adb logcat | grep "N8nService" # View all logs View โ†’ Tool Windows โ†’ Logcat (in Android Studio) ``` ### Monitor Network - [ ] Fiddler or Charles Proxy untuk intercept requests - [ ] Verify JSON payload format - [ ] Check response codes and messages ### Test GPS Simulation (Emulator) ``` Extended Controls โ†’ Location โ†’ Set latitude/longitude Or use GPX file untuk simulate route ``` --- ## โœจ Performance Checklist ### App Performance - [ ] App startup time < 3 seconds - [ ] Location acquisition < 5 seconds - [ ] Photo capture responsive (no lag) - [ ] Network request timeout configured (30s) - [ ] No memory leaks in state management - [ ] Bitmap properly disposed after submission ### UI Responsiveness - [ ] Main thread not blocked by long operations - [ ] Network calls on background thread - [ ] Permission requests on main thread - [ ] State updates propagate quickly - [ ] No janky animations/scrolls --- ## ๐Ÿ”’ Security Checklist ### Data Protection - [ ] GPS coordinates obfuscated/adjusted if needed - [ ] Photo compressed to reasonable size - [ ] HTTPS used for API calls - [ ] Sensitive data not logged - [ ] Hardcoded NPM/nama moved to config - [ ] No credentials in code ### Permission Security - [ ] Only request necessary permissions - [ ] Graceful degradation if permission denied - [ ] No forced prompts for optional features - [ ] Runtime permissions properly handled --- ## ๐Ÿ“Š Pre-Release Checklist ### Code Quality - [ ] No TODOs or FIXMEs remaining - [ ] All error paths handled - [ ] No hardcoded strings (use resources) - [ ] Proper error messages for users - [ ] Code formatted and commented - [ ] No debugging logs in release build ### Build Configuration - [ ] Correct minSdk/targetSdk set - [ ] ProGuard/R8 configured for release - [ ] Signing key configured - [ ] Version code incremented - [ ] Version name updated in build.gradle ### Documentation - [ ] README.md complete - [ ] DOKUMENTASI.md updated - [ ] PANDUAN_IMPLEMENTASI.md accurate - [ ] QUICK_REFERENCE.md helpful - [ ] Code comments clear and useful ### Testing Complete - [ ] All unit tests pass - [ ] Manual testing scenarios completed - [ ] Different device/OS combinations tested - [ ] Error scenarios all handled - [ ] Performance acceptable - [ ] No crash on common operations --- ## ๐Ÿš€ Release Steps 1. **Finalize Configuration** ``` [ ] Update AttendanceConfig with production values [ ] Set WEBHOOK_PRODUCTION as default ``` 2. **Build Release APK** ```bash ./gradlew assembleRelease ``` 3. **Sign APK** (if needed) ```bash jarsigner -verbose -sigalg SHA1withRSA \ -digestalg SHA1 \ -keystore keystore.jks \ app-release-unsigned.apk alias_name ``` 4. **Test Release APK** ``` [ ] Install on device [ ] Test all scenarios [ ] Verify permissions work [ ] Test location validation [ ] Test API submission ``` 5. **Deploy** ``` [ ] Upload to Play Store / distribute APK [ ] Monitor for crashes/feedback [ ] Be ready to support users ``` --- ## ๐Ÿ“ž Post-Launch Support ### Monitor - [ ] Crash Analytics (Firebase if available) - [ ] User feedback and reviews - [ ] N8n webhook logs - [ ] Server/network issues ### Maintenance - [ ] Fix any reported bugs - [ ] Update coordinates if location changes - [ ] Monitor API response times - [ ] Keep Play Services updated --- **Status**: Ready for deployment โœ… **Last Checked**: January 14, 2026