diff --git a/services/nginx/app/tests/HTTP/self-serve-force-machine-disable.http b/services/nginx/app/tests/HTTP/self-serve-force-machine-disable.http new file mode 100644 index 00000000..f8ea70ac --- /dev/null +++ b/services/nginx/app/tests/HTTP/self-serve-force-machine-disable.http @@ -0,0 +1,14 @@ +### Force disable MACHINE relay (superusers only) -> expect 200 +POST http://localhost/modules/self-serve/lane/force/machine/disable +Content-Type: application/json +Authorization: Bearer {{admin_token}} + +{ + "lane_id": 1 +} + +> {% +client.test("Force disabling MACHINE should succeed (200)", function() { + client.assert(response.status === 200, "Expected 200 OK, got " + response.status); +}); +%} diff --git a/services/nginx/app/tests/HTTP/self-serve-force-machine-enable.http b/services/nginx/app/tests/HTTP/self-serve-force-machine-enable.http new file mode 100644 index 00000000..d0713952 --- /dev/null +++ b/services/nginx/app/tests/HTTP/self-serve-force-machine-enable.http @@ -0,0 +1,16 @@ +### Force enable MACHINE relay (superusers only) -> expect 200 +POST http://localhost/modules/self-serve/lane/force/machine/enable +Content-Type: application/json +Authorization: Bearer {{admin_token}} + +{ + "lane_id": 1, + "duration": 2, + "license_plate": "TEST1234" +} + +> {% +client.test("Force enabling MACHINE should succeed (200)", function() { + client.assert(response.status === 200, "Expected 200 OK, got " + response.status); +}); +%} diff --git a/services/nginx/app/tests/selfserve/ForceMachineRelayBypassTest.php b/services/nginx/app/tests/selfserve/ForceMachineRelayBypassTest.php new file mode 100644 index 00000000..08e40ae5 --- /dev/null +++ b/services/nginx/app/tests/selfserve/ForceMachineRelayBypassTest.php @@ -0,0 +1,70 @@ +lane($laneId); + +// Clear allowed services to simulate a state where MACHINE would normally be gated +try { + $lane->setLaneCache($laneId, $lane::CACHE_SELFSERVE_LANE_KEY_ALLOWED_SERVICES, []); + ok('Cleared allowed services for lane ' . $laneId); +} catch (Exception $e) { + fail('Failed to clear allowed services: ' . $e->getMessage()); +} + +// Ensure lane is not in a clearly invalid status (CLOSED/MAINTENANCE/FAULT) +try { + // If lane reports CLOSED/MAINTENANCE/FAULT here, this is an environment/setup issue for the test + $status = $lane->getLaneStatus(); + if (in_array($status->name, ['CLOSED', 'MAINTENANCE', 'FAULT'], true)) { + warn('Lane is in status ' . $status->name . ' — force method will refuse as designed. Skipping state assertions.'); + } +} catch (Exception $e) { + // Non-fatal for this test +} + +// Call the force bypass method; we expect it to bypass the allowed-services gating. +// Any hardware/network/module config error after that is acceptable in test env. +$bypassedGating = false; +try { + $lane->forceTurnOnMachineRelay(1); // 1s auto-off if hardware honors it + $bypassedGating = true; + warn('forceTurnOnMachineRelay returned without exception. Assuming environment allowed a real toggle.'); +} catch (Exception $e) { + if (stripos($e->getMessage(), 'not allowed') !== false) { + fail('Bypass did not work: received a gating "not allowed" error'); + } else { + ok('Bypass reached hardware/network layer (non-gating error acceptable in tests): ' . $e->getMessage()); + $bypassedGating = true; + } +} + +if ($bypassedGating) { + ok('ForceMachineRelayBypassTest completed successfully.'); +} else { + fail('ForceMachineRelayBypassTest did not confirm bypass behavior.'); +} + +echo "\nForceMachineRelayBypassTest finished.\n";