================================================================================ TMS SERVER - AUTO PUSH & MANUAL PUSH TEST CASES Manual Testing Guide (Server-Side Verification) Date: April 11, 2026 ================================================================================ TABLE OF CONTENTS ----------------- 1. Background: How Push Works (Quick Overview) 2. Pre-Conditions & Test Setup 3. AUTO PUSH - Scenario A: Missing Version Push 4. AUTO PUSH - Scenario B: Outdated Version Push 5. AUTO PUSH - Scenario C: 30-Minute Cooldown Behaviour 6. MANUAL PUSH - via HTTP API (Single Device) 7. MANUAL PUSH - via HTTP API (Batch) 8. MANUAL PUSH - via HTTP API (Template Apply) 9. MANUAL PUSH - via Scheduled Push (Oban Jobs) 10. MANUAL PUSH - via LiveView UI (Web Dashboard) 11. NEGATIVE TEST CASES - Auto Push 12. NEGATIVE TEST CASES - Manual Push 13. VERIFICATION CHECKLIST (database + logs) 14. STATUS REFERENCE TABLE ================================================================================ 1. BACKGROUND: HOW PUSH WORKS (Quick Overview) ================================================================================ The TMS server pushes configuration to physical terminal devices over MQTT. There are two push modes: AUTO PUSH --------- Triggered automatically when the terminal sends a status message (heartbeat) to the MQTT topic: tms/status/{serial_number} The server checks the status message and does TWO things: 1. MISSING VERSION CHECK: If the terminal reports that it has NO version for any of the 4 config types (parameter_config, emv_config, keys_config, application), the server pushes ALL 4 configs immediately. 2. OUTDATED VERSION CHECK: If the terminal HAS a version but it does NOT match the active version stored in TMS, the server pushes only the outdated config(s). Has a 30-minute cooldown to avoid repeated pushes. MANUAL PUSH ----------- Triggered by a human (via Web UI or API call). Push types: - Single device push - Batch push (multiple devices at once) - Template apply (apply a named config template to a device) - Scheduled push (push at a future time via Oban background jobs) PUSH RESULT TRACKING -------------------- Every push (auto or manual) creates a record in: - parameter_push_logs table (one row per push, overall status) - parameter_push_details table (row per individual parameter inside the push) Push log status flow: pending -> sent -> acknowledged (or -> failed) ================================================================================ 2. PRE-CONDITIONS & TEST SETUP ================================================================================ Before running any test, verify the following: [check] TMS server is running: mix phx.server (http://localhost:4000) [check] MySQL is running: sudo systemctl status mysql [check] MQTT broker is reachable (see config/dev.exs for broker host/port) [check] At least one terminal is registered in tms_terminals table [check] At least one active parameter_template exists for the test device vendor + model combination [check] Active config_file_versions exist for emv_config, keys_config, application (needed for those config type tests) Useful DB queries before starting tests: -- Check terminal record SELECT serial_number, vendor, model, parameter_config_version, emv_config_version, keys_config_version, app_version FROM tms_terminals WHERE serial_number = 'YOUR_SERIAL'; -- Check recent push logs SELECT id, terminal_serial, config_type, status, trigger_reason, inserted_at FROM parameter_push_logs ORDER BY inserted_at DESC LIMIT 20; -- Check active templates SELECT id, name, vendor, model, version, is_active FROM parameter_templates WHERE is_active = 1; -- Check active config file versions SELECT id, config_type, vendor, model, version, is_active FROM config_file_versions WHERE is_active = 1; ================================================================================ 3. AUTO PUSH - SCENARIO A: MISSING VERSION PUSH ================================================================================ WHAT IT TESTS: When a terminal has NEVER received configs (all version fields are empty or NULL), the server detects this from the MQTT heartbeat and pushes ALL 4 configs automatically. -------------------------------------------------------------------------------- TC-AP-001: Auto Push triggered when terminal has NO versions at all -------------------------------------------------------------------------------- PRECONDITION: - Terminal exists in tms_terminals with version fields all NULL or empty - Active parameter_template exists for this terminal vendor + model - Active config_file_versions exist for emv_config, keys_config, application STEPS: 1. Simulate terminal sending an MQTT status message to: tms/status/YOUR_SERIAL with a payload where all 4 version fields are empty: { "org": { "device": [ {"name": "parameter_config", "version": ""}, {"name": "emv_config", "version": ""}, {"name": "keys_config", "version": ""}, {"name": "application", "version": ""} ] } } 2. Watch TMS server logs (terminal where mix phx.server runs): Look for: "AutoPushService" OR "trigger_missing_version_push" OR "Missing versions detected" 3. Query the push logs: SELECT id, terminal_serial, config_type, status, trigger_reason, inserted_at FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 10; EXPECTED RESULT: - 4 push log records are created (one per config type: parameter, emv_config, keys_config, application) - trigger_reason = 'missing_version' on each record - status starts as 'pending' then moves to 'sent' - If terminal acknowledges: status moves to 'acknowledged' PASS CRITERIA: [ ] 4 push log entries created [ ] trigger_reason = 'missing_version' on all 4 [ ] status = 'sent' (or 'acknowledged' if terminal responds) [ ] Server logs show auto push triggered -------------------------------------------------------------------------------- TC-AP-002: Auto Push triggered when only ONE version field is missing -------------------------------------------------------------------------------- PRECONDITION: - Terminal has some versions set but one is missing, e.g.: parameter_config_version = '1.0' (present) emv_config_version = NULL (missing) keys_config_version = '2.0' (present) app_version = '3.0' (present) STEPS: 1. Send MQTT status with: parameter_config version = "1.0" emv_config version = "" <- missing keys_config version = "2.0" application version = "3.0" 2. Check server logs for auto push trigger 3. Query push logs EXPECTED RESULT: - Auto push is triggered for ALL 4 config types (System pushes everything when ANY version is missing) - trigger_reason = 'missing_version' PASS CRITERIA: [ ] 4 push logs created (not just emv_config) [ ] trigger_reason = 'missing_version' [ ] ALL 4 config types pushed, not just the missing one ================================================================================ 4. AUTO PUSH - SCENARIO B: OUTDATED VERSION PUSH ================================================================================ WHAT IT TESTS: When a terminal HAS versions but they are OLDER than the active version in TMS, the server detects this and pushes only the outdated config(s). -------------------------------------------------------------------------------- TC-AP-003: Auto Push triggered when parameter_config version is outdated -------------------------------------------------------------------------------- PRECONDITION: - Terminal has: parameter_config_version = '1.0' (old) - Active template has version = '2.0' (newer - this is the target) - No recent push log for this terminal + parameter config in last 30 mins STEPS: 1. Send MQTT status message with: parameter_config version = "1.0" <- outdated emv_config version = CURRENT_ACTIVE_VERSION keys_config version = CURRENT_ACTIVE_VERSION application version = CURRENT_ACTIVE_VERSION 2. Check server logs for VersionComplianceChecker messages 3. Query push logs: SELECT id, config_type, status, trigger_reason, inserted_at FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 5; EXPECTED RESULT: - Only the parameter_config push log is created - Other config types (emv, keys, application) are NOT pushed - status = 'sent' or 'acknowledged' PASS CRITERIA: [ ] Only 1 push log created (config_type = 'parameter') [ ] emv_config, keys_config, application NOT pushed [ ] status = 'sent' or 'acknowledged' -------------------------------------------------------------------------------- TC-AP-004: Auto Push triggered when multiple configs are outdated -------------------------------------------------------------------------------- PRECONDITION: - Terminal has outdated versions for 2 config types: emv_config_version = '1.0' (old, active is '3.0') keys_config_version = '1.0' (old, active is '2.0') parameter_config_version matches active app_version matches active STEPS: 1. Send MQTT status with those 2 outdated versions, 2 correct versions 2. Check push logs EXPECTED RESULT: - 2 push logs created (emv_config and keys_config only) - parameter_config and application are NOT in the logs PASS CRITERIA: [ ] Exactly 2 push logs created [ ] Correct config types are targeted (emv_config + keys_config) [ ] parameter and application not pushed ================================================================================ 5. AUTO PUSH - SCENARIO C: 30-MINUTE COOLDOWN BEHAVIOUR ================================================================================ WHAT IT TESTS: When the same terminal sends multiple MQTT heartbeats in quick succession, the server should NOT send duplicate pushes. It blocks re-push for 30 minutes after a recent push for the same terminal + config type. -------------------------------------------------------------------------------- TC-AP-005: Second heartbeat within 30 minutes does NOT trigger another push -------------------------------------------------------------------------------- PRECONDITION: - Terminal has an outdated parameter_config version - First push has already happened (a push log with status pending/sent exists for this terminal + parameter, inserted within last 30 minutes) STEPS: 1. Send first MQTT status -> verify auto push was triggered (TC-AP-003) Note the push log record that was created. 2. Wait 2 minutes (do NOT wait 30 minutes) 3. Send second MQTT status with the SAME outdated version 4. Count push logs: SELECT COUNT(*) FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' AND config_type = 'parameter' AND inserted_at > NOW() - INTERVAL 5 MINUTE; EXPECTED RESULT: - Count = 1 (only the first push) - No new push log was created for the second heartbeat - Server logs show cooldown was applied: Look for: "recently pushed" OR "cooldown" OR "skipping" PASS CRITERIA: [ ] Still only 1 push log after second heartbeat [ ] Server logs confirm cooldown was applied -------------------------------------------------------------------------------- TC-AP-006: Push IS triggered again after 30-minute cooldown expires -------------------------------------------------------------------------------- STEPS: 1. After TC-AP-005 has run, manually age the push log timestamp for speed: UPDATE parameter_push_logs SET inserted_at = DATE_SUB(NOW(), INTERVAL 35 MINUTE) WHERE terminal_serial = 'YOUR_SERIAL' AND config_type = 'parameter' ORDER BY inserted_at DESC LIMIT 1; 2. Send another MQTT status with the outdated version 3. Check push logs: SELECT COUNT(*), MAX(inserted_at) FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' AND config_type = 'parameter'; EXPECTED RESULT: - A NEW push log is created (count increases by 1) - The new record has a recent inserted_at (within last minute) PASS CRITERIA: [ ] New push log appears [ ] inserted_at on new record is recent (within last 1 minute) ================================================================================ 6. MANUAL PUSH - VIA HTTP API (SINGLE DEVICE) ================================================================================ WHAT IT TESTS: A human or external system directly calls the API to push config to a single terminal immediately. -------------------------------------------------------------------------------- TC-MP-001: Manual push to a single device via API -------------------------------------------------------------------------------- STEPS: 1. Run (replace YOUR_SERIAL with a real terminal serial number): curl -X POST "http://localhost:4000/api/parameter/push/YOUR_SERIAL" -H "Content-Type: application/json" -d '{}' Alternative endpoint: curl -X POST "http://localhost:4000/api/terminals/YOUR_SERIAL/parameters/push" -H "Content-Type: application/json" 2. Observe the HTTP response: - Should be HTTP 200 - Response body should be JSON with status or message field 3. Query push logs: SELECT id, terminal_serial, config_type, status, trigger_reason, inserted_at FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 5; EXPECTED RESULT: - API returns HTTP 200 - Push log record is created - trigger_reason is NULL (manual push, not auto) - status goes from 'pending' to 'sent' PASS CRITERIA: [ ] HTTP 200 response received [ ] Push log created in DB [ ] trigger_reason is NULL (not 'missing_version') [ ] status = 'sent' or 'acknowledged' -------------------------------------------------------------------------------- TC-MP-002: Check push status of a device via API -------------------------------------------------------------------------------- STEPS: 1. After TC-MP-001, run: curl -X GET "http://localhost:4000/api/parameter/status/YOUR_SERIAL" 2. Review the JSON response EXPECTED RESULT: - HTTP 200 - Response shows the latest push status for the device - Includes config_type, status, inserted_at timestamps PASS CRITERIA: [ ] HTTP 200 [ ] Response contains push status info for the terminal [ ] Data matches what is in parameter_push_logs DB table ================================================================================ 7. MANUAL PUSH - VIA HTTP API (BATCH) ================================================================================ WHAT IT TESTS: Push config to multiple terminals in a single API call. -------------------------------------------------------------------------------- TC-MP-003: Batch push to multiple devices -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/batch/push" -H "Content-Type: application/json" -d '{ "device_serials": ["SERIAL_1", "SERIAL_2"] }' 2. Check API response 3. Query push logs for both serials: SELECT terminal_serial, config_type, status, inserted_at FROM parameter_push_logs WHERE terminal_serial IN ('SERIAL_1', 'SERIAL_2') ORDER BY inserted_at DESC; EXPECTED RESULT: - API returns success (HTTP 200) - Push logs created for EACH serial in the batch PASS CRITERIA: [ ] HTTP 200 [ ] Push log created for SERIAL_1 [ ] Push log created for SERIAL_2 [ ] Both records show trigger_reason = NULL (manual) ================================================================================ 8. MANUAL PUSH - VIA HTTP API (TEMPLATE APPLY) ================================================================================ WHAT IT TESTS: Apply a named parameter template to a terminal. The template values overwrite the terminal current config. -------------------------------------------------------------------------------- TC-MP-004: Apply a template to a single terminal -------------------------------------------------------------------------------- PRECONDITION: - An active parameter_template exists with a known ID STEPS: 1. Find a valid template ID: SELECT id, name, vendor, model, version FROM parameter_templates WHERE is_active = 1 LIMIT 5; 2. Run: curl -X POST "http://localhost:4000/api/terminals/YOUR_SERIAL/parameters/template/TEMPLATE_ID" -H "Content-Type: application/json" Or: curl -X POST "http://localhost:4000/api/parameter/template/apply/YOUR_SERIAL" -H "Content-Type: application/json" -d '{"template_id": TEMPLATE_ID}' 3. Check push logs EXPECTED RESULT: - Template values are merged with device overrides - Push is sent to the terminal - Push log shows push_type related to template ('template' or 'template_apply') PASS CRITERIA: [ ] HTTP 200 [ ] Push log created [ ] push_type reflects template operation [ ] status = 'sent' or 'acknowledged' -------------------------------------------------------------------------------- TC-MP-005: Batch template apply to multiple devices -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/template/batch/apply" -H "Content-Type: application/json" -d '{ "template_id": TEMPLATE_ID, "device_serials": ["SERIAL_1", "SERIAL_2"] }' EXPECTED RESULT: - Push log created for each device - All devices receive the same template values PASS CRITERIA: [ ] HTTP 200 [ ] Push log per device in the list ================================================================================ 9. MANUAL PUSH - VIA SCHEDULED PUSH (OBAN JOBS) ================================================================================ WHAT IT TESTS: A push that is queued for future execution (not immediate). Uses Oban background job processing. -------------------------------------------------------------------------------- TC-MP-006: Schedule a push for a specific future time -------------------------------------------------------------------------------- STEPS: 1. Run (replace the datetime with a time ~5 minutes from now): curl -X POST "http://localhost:4000/api/parameter/schedule/YOUR_SERIAL" -H "Content-Type: application/json" -d '{"scheduled_at": "2026-04-11T18:00:00Z"}' 2. Immediately check Oban jobs: SELECT id, queue, state, scheduled_at, args FROM oban_jobs WHERE queue = 'parameter_push' ORDER BY inserted_at DESC LIMIT 5; Job should be in state 'scheduled' 3. After the scheduled time passes, re-check: SELECT id, state, completed_at FROM oban_jobs WHERE queue = 'parameter_push' ORDER BY inserted_at DESC LIMIT 5; 4. Check push logs after job runs: SELECT * FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 3; EXPECTED RESULT: - Job appears in oban_jobs with state = 'scheduled' - At scheduled time: state changes to 'executing' then 'completed' - Push log is created when job runs PASS CRITERIA: [ ] Oban job exists with state = 'scheduled' [ ] After scheduled time: state = 'completed' [ ] Push log created at time of job execution -------------------------------------------------------------------------------- TC-MP-007: Immediate push via Oban (no scheduled_at provided) -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/schedule/YOUR_SERIAL" -H "Content-Type: application/json" -d '{}' 2. Check oban_jobs quickly - should be 'available' or 'executing' 3. Check push logs within ~30 seconds EXPECTED RESULT: - Job runs immediately (within seconds, not scheduled) - Push log created with status = 'sent' PASS CRITERIA: [ ] Oban job state = 'completed' shortly after [ ] Push log created ================================================================================ 10. MANUAL PUSH - VIA LIVEVEW UI (WEB DASHBOARD) ================================================================================ WHAT IT TESTS: The web interface for triggering manual pushes and viewing push status. -------------------------------------------------------------------------------- TC-UI-001: View push status in the dashboard -------------------------------------------------------------------------------- STEPS: 1. Open browser: http://localhost:4000 2. Navigate to Parameter Management -> Dashboard 3. Find the test terminal in the list 4. Check the displayed push status and version columns EXPECTED RESULT: - Terminal appears in the list - Push status, version info, and last push timestamp are visible - Data matches what is in the database PASS CRITERIA: [ ] Dashboard loads without error [ ] Terminal row is visible [ ] Status info is correct and current -------------------------------------------------------------------------------- TC-UI-002: Trigger manual push from web UI -------------------------------------------------------------------------------- STEPS: 1. On the dashboard, find the terminal row for YOUR_SERIAL 2. Click the "Push Parameters" or "Push" button next to that terminal 3. Confirm the action if a confirmation dialog appears 4. Observe the page - status should update live (LiveView page) 5. Verify in DB: SELECT * FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 1; EXPECTED RESULT: - Push triggered from UI - Page updates to show new status (pending/sent) without full page reload - DB record created PASS CRITERIA: [ ] Push button is functional [ ] UI shows feedback (success message or status update) [ ] Push log created in DB -------------------------------------------------------------------------------- TC-UI-003: View push logs from web UI -------------------------------------------------------------------------------- STEPS: 1. Navigate to Parameter Management -> Logs 2. Filter by the test terminal serial number 3. Check that both auto and manual push entries are visible EXPECTED RESULT: - All push records are listed - Each entry shows: serial, config_type, status, trigger_reason, timestamps - Auto push records show trigger_reason = 'missing_version' - Manual push records show trigger_reason as empty/null PASS CRITERIA: [ ] Logs page loads without error [ ] Log entries visible and filterable [ ] Correct trigger_reason displayed -------------------------------------------------------------------------------- TC-UI-004: Retry a failed push from web UI -------------------------------------------------------------------------------- PRECONDITION: - A push log with status = 'failed' exists for a terminal STEPS: 1. Go to Logs page 2. Find a failed log entry 3. Click the 'Retry' button on it 4. Watch the entry update EXPECTED RESULT: - A NEW push log appears with status 'pending' then 'sent' - The old failed log remains unchanged (not overwritten) PASS CRITERIA: [ ] Retry button triggers a new push [ ] Old failed record is untouched [ ] New push log appears with a recent inserted_at -------------------------------------------------------------------------------- TC-UI-005: Version Compliance view -------------------------------------------------------------------------------- STEPS: 1. Navigate to the Version Compliance page (look in admin menu or try: http://localhost:4000/version_compliance) 2. Check that each terminal shows one of these statuses per config type: up_to_date - terminal version matches TMS active version outdated - terminal version is older than TMS active version never_received - terminal has never reported a version no_target - no active template or version exists in TMS for this terminal vendor/model 3. Find an 'outdated' terminal and click 'Push' or 'Re-push' EXPECTED RESULT: - Compliance table shows correct status per terminal + config type - Re-push from this page triggers a new push log PASS CRITERIA: [ ] Version compliance table loads [ ] Statuses are correct (verified against DB data) [ ] Re-push action creates a new push log ================================================================================ 11. NEGATIVE TEST CASES - AUTO PUSH ================================================================================ -------------------------------------------------------------------------------- TC-NEG-AP-001: MQTT heartbeat for an UNKNOWN terminal serial -------------------------------------------------------------------------------- DESCRIPTION: Terminal sends a heartbeat but the serial number does not exist in the tms_terminals table. STEPS: 1. Send MQTT status message to: tms/status/UNKNOWN_SERIAL_9999 with any valid payload structure 2. Check TMS server logs for error or warning messages 3. Check push logs: SELECT * FROM parameter_push_logs WHERE terminal_serial = 'UNKNOWN_SERIAL_9999'; EXPECTED RESULT: - Server handles the unknown serial gracefully (NO crash) - NO push is attempted - NO push log record is created - Server logs show a warning like "terminal not found" or "unknown serial" - TMS continues to function normally for other messages PASS CRITERIA: [ ] Server does NOT crash [ ] No push log for the unknown serial [ ] Warning in logs (not an unhandled error) [ ] Server still processes subsequent messages normally -------------------------------------------------------------------------------- TC-NEG-AP-002: Terminal has no active template (no vendor/model match) -------------------------------------------------------------------------------- DESCRIPTION: Terminal exists in DB but its vendor + model has no active parameter_template in TMS. Auto push cannot proceed. PRECONDITION: - Verify no template: SELECT COUNT(*) FROM parameter_templates WHERE vendor = 'TERMINAL_VENDOR' AND model = 'TERMINAL_MODEL' AND is_active = 1; -- Should return 0 STEPS: 1. Send MQTT status with all empty versions for that terminal 2. Check server logs 3. Check push logs EXPECTED RESULT: - Server logs show: "no template found for vendor/model, skipping push" or similar warning - NO push log created - Server does NOT crash PASS CRITERIA: [ ] No crash [ ] No push log created [ ] Warning logged (clearly identifying the vendor/model with no template) -------------------------------------------------------------------------------- TC-NEG-AP-003: Malformed or corrupted MQTT status payload -------------------------------------------------------------------------------- DESCRIPTION: Terminal sends a heartbeat with invalid or incomplete JSON body. STEPS: 1. Send MQTT message to tms/status/YOUR_SERIAL with an invalid body: Option A - broken JSON: { "corrupt": "data", broken json here } Option B - empty payload: (empty string) Option C - missing the "org.device" array: {"hello": "world"} 2. Watch server logs immediately after sending EXPECTED RESULT: - Server handles parsing error gracefully (no crash) - Error is logged (JSON decode error or structure mismatch) - Subsequent MQTT messages still work normally - No push log created for that malformed message PASS CRITERIA: [ ] NO server crash / NO supervisor restarts [ ] Error logged [ ] Server continues processing other messages -------------------------------------------------------------------------------- TC-NEG-AP-004: MQTT broker becomes unreachable during auto push -------------------------------------------------------------------------------- DESCRIPTION: Auto push is triggered, but the MQTT broker goes down BEFORE the message is actually sent to the terminal. STEPS: 1. Trigger a condition that causes auto push (e.g. TC-AP-001 preconditions) 2. Stop or block the MQTT broker BEFORE the push message is sent 3. Watch server logs and push log status over the next few minutes EXPECTED RESULT: - Push log status moves to 'failed' (not stuck at 'pending' indefinitely) - Error is logged (MQTT connection error) - Server process does NOT crash - Server remains responsive at http://localhost:4000 PASS CRITERIA: [ ] Push log status = 'failed' [ ] Error logged [ ] Server still running and responsive -------------------------------------------------------------------------------- TC-NEG-AP-005: Active config_file_version missing for a config type -------------------------------------------------------------------------------- DESCRIPTION: Terminal needs an emv_config push, but NO active config_file_versions record exists for emv_config + this terminal vendor/model. PRECONDITION: - Verify no active emv_config version: SELECT COUNT(*) FROM config_file_versions WHERE config_type = 'emv_config' AND is_active = 1; -- Should return 0 (or none matching vendor/model) STEPS: 1. Send MQTT status with outdated emv_config version for this terminal 2. Check server logs 3. Check push logs EXPECTED RESULT: - Server skips the emv_config push with a warning - Warning logged: "no active config file version for emv_config" or similar - Other config types are still pushed if they are also outdated - No crash PASS CRITERIA: [ ] No crash [ ] emv_config push skipped (no push log for emv_config) [ ] Warning in logs [ ] Other outdated configs still pushed if applicable ================================================================================ 12. NEGATIVE TEST CASES - MANUAL PUSH ================================================================================ -------------------------------------------------------------------------------- TC-NEG-MP-001: API push to a non-existent terminal serial -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/push/NONEXISTENT_SERIAL_999" -H "Content-Type: application/json" 2. Note the HTTP status code and response body EXPECTED RESULT: - HTTP 404 (Not Found) or 422 (Unprocessable Entity) - Response body has a meaningful error message (e.g. "terminal not found") - NO push log created in DB PASS CRITERIA: [ ] Non-200 HTTP response (error code) [ ] Clear error message in response JSON [ ] No push log for NONEXISTENT_SERIAL_999 -------------------------------------------------------------------------------- TC-NEG-MP-002: Template apply without providing a template_id -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/template/apply/YOUR_SERIAL" -H "Content-Type: application/json" -d '{}' 2. Note the response EXPECTED RESULT: - HTTP 400 or 422 - Error message explaining that template_id is required PASS CRITERIA: [ ] Error response returned (not 200) [ ] Clear error message about missing template_id [ ] No push log created -------------------------------------------------------------------------------- TC-NEG-MP-003: Schedule push with an invalid date format -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/schedule/YOUR_SERIAL" -H "Content-Type: application/json" -d '{"scheduled_at": "not-a-valid-date"}' 2. Check response and check oban_jobs table EXPECTED RESULT: - HTTP 400 or 422 - Error about invalid datetime format - NO Oban job created in oban_jobs table PASS CRITERIA: [ ] Error response [ ] No job in oban_jobs for this request -------------------------------------------------------------------------------- TC-NEG-MP-004: Schedule push with a date in the past -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/schedule/YOUR_SERIAL" -H "Content-Type: application/json" -d '{"scheduled_at": "2020-01-01T00:00:00Z"}' 2. Check response and oban_jobs EXPECTED RESULT: Two acceptable behaviours - document which one this system does: - OPTION A: HTTP error with "scheduled time must be in the future" - OPTION B: Job created and runs immediately (treated as "now") In either case: NOT a silent failure or a job stuck forever in 'scheduled' PASS CRITERIA: [ ] Either a validation error OR the job completes immediately [ ] No orphaned job stuck in 'scheduled' state indefinitely -------------------------------------------------------------------------------- TC-NEG-MP-005: Batch push with an empty device list -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/batch/push" -H "Content-Type: application/json" -d '{"device_serials": []}' 2. Note the response EXPECTED RESULT: - HTTP 400 or a clear message: "no devices provided" or "list is empty" - No push logs created - NOT a 500 Internal Server Error PASS CRITERIA: [ ] Proper validation error response [ ] Not a 500 error [ ] No push logs created -------------------------------------------------------------------------------- TC-NEG-MP-006: Batch push with mixed valid and invalid serial numbers -------------------------------------------------------------------------------- STEPS: 1. Run: curl -X POST "http://localhost:4000/api/parameter/batch/push" -H "Content-Type: application/json" -d '{ "device_serials": ["VALID_SERIAL", "INVALID_SERIAL_999"] }' 2. Check response body 3. Check push logs: SELECT terminal_serial, status FROM parameter_push_logs WHERE terminal_serial IN ('VALID_SERIAL', 'INVALID_SERIAL_999') ORDER BY inserted_at DESC; EXPECTED RESULT: - Push log created for VALID_SERIAL - INVALID_SERIAL_999 is skipped with a warning or error in the response - Response indicates partial success (lists failures) - Server does NOT crash PASS CRITERIA: [ ] Push log for VALID_SERIAL only [ ] Response mentions INVALID_SERIAL_999 was not found [ ] HTTP 200 or 207 (partial success - document actual behaviour) -------------------------------------------------------------------------------- TC-NEG-MP-007: Apply a non-existent or inactive template ID -------------------------------------------------------------------------------- STEPS: 1. Run with a template_id that does not exist (e.g. 9999999): curl -X POST "http://localhost:4000/api/terminals/YOUR_SERIAL/parameters/template/9999999" -H "Content-Type: application/json" 2. Check response and push logs EXPECTED RESULT: - HTTP 404 or 422 - Error: "template not found" or "template is not active" - NO push log created (no push attempted) PASS CRITERIA: [ ] Error response [ ] No push log created -------------------------------------------------------------------------------- TC-NEG-MP-008: Manual push API when MQTT broker is unreachable -------------------------------------------------------------------------------- STEPS: 1. Stop or block MQTT broker connectivity 2. Run a manual push to a valid terminal: curl -X POST "http://localhost:4000/api/parameter/push/YOUR_SERIAL" -H "Content-Type: application/json" 3. Check the response, server logs, and push logs EXPECTED RESULT: - Push log created with status = 'failed' - API response indicates failure OR returns an error code - Server does NOT crash - Subsequent API requests still work PASS CRITERIA: [ ] Push log status = 'failed' (not stuck at 'pending') [ ] Server remains running and healthy [ ] Other API requests still work after this failure ================================================================================ 13. VERIFICATION CHECKLIST (DATABASE + LOGS) ================================================================================ After each test case, verify these points: DATABASE CHECKS --------------- parameter_push_logs table: - Record created? (YES / NO) - Correct terminal_serial? - Correct config_type? (parameter / emv_config / keys_config / application) - trigger_reason: 'missing_version' for auto push, NULL for manual - status flow: pending -> sent -> acknowledged OR -> failed - inserted_at is recent (within the last few minutes) Query: SELECT id, terminal_serial, config_type, status, trigger_reason, inserted_at FROM parameter_push_logs WHERE terminal_serial = 'YOUR_SERIAL' ORDER BY inserted_at DESC LIMIT 10; parameter_push_details table: - Detail rows exist linked to the push log (push_log_id) - Each row has a parameter_name and value - detail status = 'acknowledged' or 'failed' Query: SELECT d.id, d.parameter_name, d.status, d.push_log_id FROM parameter_push_details d JOIN parameter_push_logs l ON l.id = d.push_log_id WHERE l.terminal_serial = 'YOUR_SERIAL' ORDER BY d.inserted_at DESC LIMIT 20; tms_terminals table (updated after terminal ACKs the push): - parameter_config_version updated to new version - emv_config_version / keys_config_version / app_version updated Query: SELECT serial_number, parameter_config_version, emv_config_version, keys_config_version, app_version, updated_at FROM tms_terminals WHERE serial_number = 'YOUR_SERIAL'; oban_jobs table (for scheduled push tests only): - state progression: scheduled -> available -> executing -> completed - No job stuck in 'retryable' or 'discarded' state Query: SELECT id, queue, state, scheduled_at, completed_at, attempted_at FROM oban_jobs WHERE queue = 'parameter_push' ORDER BY inserted_at DESC LIMIT 10; SERVER LOG CHECKS ----------------- Open the terminal running: mix phx.server Watch for these log patterns during tests: AUTO PUSH: [info] AutoPushService: triggering push for serial ... [info] VersionComplianceChecker: outdated config detected ... [warn] AutoPushService: no template found for vendor/model, skipping ... [warn] VersionComplianceChecker: cooldown active, skipping push ... MANUAL PUSH: [info] ParameterPushService: sending parameters to terminal ... [info] ParameterPushWorker: performing push job ... ERRORS (negative test cases): [error] ParameterPushService: failed to send ... [error] MQTT connection error ... [warn] Terminal not found: ... MQTT MESSAGE VERIFICATION (Optional) -------------------------------------- Use an MQTT client (e.g. MQTT Explorer, mosquitto_sub) to subscribe to the outgoing push topics and verify messages are published: mosquitto_sub -h BROKER_HOST -p BROKER_PORT -t "tms/terminal/#" -v mosquitto_sub -h BROKER_HOST -p BROKER_PORT -t "tms/config/#" -v When a push is triggered, you should see a message published on the relevant topic with the config payload. ================================================================================ 14. STATUS REFERENCE TABLE ================================================================================ PUSH LOG STATUS VALUES: +-------------------+----------------------------------------------------+ | Status | Meaning | +-------------------+----------------------------------------------------+ | pending | Push queued, not yet sent over MQTT | | sent | MQTT message published, awaiting terminal ACK | | acknowledged | Terminal confirmed config was received and applied | | failed | Push failed (MQTT error, validation error, etc.) | +-------------------+----------------------------------------------------+ TRIGGER REASON VALUES: +----------------------+--------------------------------------------------+ | trigger_reason | Meaning | +----------------------+--------------------------------------------------+ | missing_version | Auto push: terminal had no version at all | | NULL (empty) | Manual push: triggered by user or API call | +----------------------+--------------------------------------------------+ VERSION COMPLIANCE STATUS VALUES (shown in the web UI): +-------------------+----------------------------------------------------+ | Status | Meaning | +-------------------+----------------------------------------------------+ | up_to_date | Reported version matches TMS active version | | outdated | Reported version is older than TMS active version | | never_received | Terminal has never reported this config version | | no_target | No active template or version exists in TMS | | | for this terminal vendor + model combination | +-------------------+----------------------------------------------------+ CONFIG TYPE VALUES: - parameter -> Terminal operating parameters - emv_config -> EMV chip card configuration (L3 config) - keys_config -> Encryption keys configuration - application -> Application or firmware package OBAN JOB STATES (for scheduled push): - scheduled -> Waiting for scheduled time - available -> Ready to be picked up by a worker - executing -> Currently being processed - completed -> Finished successfully - retryable -> Failed but will be retried - discarded -> Failed permanently (max retries exceeded) ================================================================================ END OF DOCUMENT ================================================================================ Total Test Cases: 31 - Auto Push Positive: 6 (TC-AP-001 to TC-AP-006) - Manual Push via API: 7 (TC-MP-001 to TC-MP-007) - Manual Push via UI: 5 (TC-UI-001 to TC-UI-005) - Negative Auto Push: 5 (TC-NEG-AP-001 to TC-NEG-AP-005) - Negative Manual Push: 8 (TC-NEG-MP-001 to TC-NEG-MP-008) ================================================================================