Add fake classes for relay logic and refactor relay shutdown without pre-checking status
Introduce helper classes `SelfserveWashCompletionRelayValueFake`, `SelfserveWashCompletionDepartmentLaneFake`, `SelfserveWashCompletionRelayLaneFake`, and `SelfserveWashCompletionFlowHarness` to simulate relay logic for unit tests. Refactor `turnOffRelayIfConfiguredAndOn` to `turnOffRelayIfConfigured`, removing relay status pre-check for cleaner and machine relays when completing a wash session, and test associated relay actions.
This commit is contained in:
@@ -273,28 +273,19 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
return;
|
||||
}
|
||||
|
||||
$this->turnOffRelayIfConfiguredAndOn($lane, selfserve_lane_relay::MACHINE);
|
||||
$this->turnOffRelayIfConfiguredAndOn($lane, selfserve_lane_relay::MACHINE_CLEANER);
|
||||
$this->turnOffRelayIfConfigured($lane, selfserve_lane_relay::MACHINE);
|
||||
$this->turnOffRelayIfConfigured($lane, selfserve_lane_relay::MACHINE_CLEANER);
|
||||
} catch (\Throwable) {
|
||||
// Best effort only; session completion flow must continue.
|
||||
}
|
||||
}
|
||||
|
||||
protected function turnOffRelayIfConfiguredAndOn(selfserve_lane $lane, selfserve_lane_relay $relay): void
|
||||
protected function turnOffRelayIfConfigured(selfserve_lane $lane, selfserve_lane_relay $relay): void
|
||||
{
|
||||
if (!$this->isRelayConfiguredForLane($lane, $relay)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$status = $lane->getRelayStatus($relay);
|
||||
if ((bool)($status['on'] ?? false) !== true) {
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// If relay status can't be read, still attempt turn-off as best effort.
|
||||
}
|
||||
|
||||
try {
|
||||
$lane->setRelayStatusHard($relay, false);
|
||||
} catch (\Throwable) {
|
||||
@@ -723,14 +714,14 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
|
||||
protected function enableMachineRelayIfAllowed(array $snapshot, selfserve_wash_sessions_o $session): void
|
||||
{
|
||||
if ((bool)$session->machine_relay_enabled->value() === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$laneId = (int)$snapshot['lane']['id'];
|
||||
$lane = (new selfserve())->lane($laneId);
|
||||
$this->enableCleanerRelayForStartedWash($lane);
|
||||
|
||||
if ((bool)$session->machine_relay_enabled->value() === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$session->markRelayEnabled();
|
||||
$this->logSessionEvent((int)$session->id, selfserve_wash_event_type::MACHINE_RELAY_ENABLED, [
|
||||
'lane_id' => $laneId,
|
||||
|
||||
@@ -22,6 +22,11 @@ it('keeps cleaner relay enable wired into machine relay start paths', function (
|
||||
expect($enableMachineRelayMethodOffset)->not->toBeFalse();
|
||||
$enableMachineRelayMethod = substr($washFlow, (int)$enableMachineRelayMethodOffset, 1200);
|
||||
expect($enableMachineRelayMethod)->toContain('$this->enableCleanerRelayForStartedWash($lane);');
|
||||
$cleanerEnableOffset = strpos($enableMachineRelayMethod, '$this->enableCleanerRelayForStartedWash($lane);');
|
||||
$alreadyEnabledGuardOffset = strpos($enableMachineRelayMethod, 'if ((bool)$session->machine_relay_enabled->value() === true)');
|
||||
expect($cleanerEnableOffset)->not->toBeFalse()
|
||||
->and($alreadyEnabledGuardOffset)->not->toBeFalse()
|
||||
->and($cleanerEnableOffset)->toBeLessThan($alreadyEnabledGuardOffset);
|
||||
|
||||
expect($moduleRoute)->not->toBeFalse();
|
||||
$machineEnableRouteOffset = strpos($moduleRoute, '/modules/self-serve/lane/relay/machine/enable');
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
<?php
|
||||
|
||||
app_require('classes/object_property.php');
|
||||
app_require('objects/department_lanes_o.php');
|
||||
app_require('modules/selfserve/classes/selfserve_lane.php');
|
||||
app_require('modules/selfserve/classes/selfserve_wash_flow.php');
|
||||
app_require('modules/selfserve/helpers/selfserve_lane_relay.php');
|
||||
|
||||
use modules\selfserve\classes\selfserve_lane;
|
||||
use modules\selfserve\classes\selfserve_wash_flow;
|
||||
use modules\selfserve\helpers\selfserve_lane_relay;
|
||||
|
||||
class SelfserveWashCompletionRelayValueFake extends \classes\object_property
|
||||
{
|
||||
public function __construct(private readonly mixed $storedValue) {}
|
||||
|
||||
public function value(): mixed
|
||||
{
|
||||
return $this->storedValue;
|
||||
}
|
||||
}
|
||||
|
||||
class SelfserveWashCompletionDepartmentLaneFake extends \objects\department_lanes_o
|
||||
{
|
||||
public function __construct(string $machineRelayId = 'relay-machine', string $cleanerRelayId = 'relay-cleaner')
|
||||
{
|
||||
$this->relay_machine_id = new SelfserveWashCompletionRelayValueFake($machineRelayId);
|
||||
$this->relay_machine_cleaner_id = new SelfserveWashCompletionRelayValueFake($cleanerRelayId);
|
||||
$this->relay_machine_program_picker_id = new SelfserveWashCompletionRelayValueFake('');
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SelfserveWashCompletionRelayLaneFake extends selfserve_lane
|
||||
{
|
||||
/** @var selfserve_lane_relay[] */
|
||||
public array $statusReads = [];
|
||||
/** @var array<int,array{0:selfserve_lane_relay,1:bool}> */
|
||||
public array $relayWrites = [];
|
||||
|
||||
public function __construct(bool $reportedOn)
|
||||
{
|
||||
$this->id = 77;
|
||||
$this->reportedOn = $reportedOn;
|
||||
$this->department_lane = new SelfserveWashCompletionDepartmentLaneFake();
|
||||
}
|
||||
|
||||
private bool $reportedOn;
|
||||
|
||||
public function getRelayStatus(selfserve_lane_relay $relay): array
|
||||
{
|
||||
$this->statusReads[] = $relay;
|
||||
return ['on' => $this->reportedOn];
|
||||
}
|
||||
|
||||
public function setRelayStatusHard(selfserve_lane_relay $relay, bool $on): bool
|
||||
{
|
||||
$this->relayWrites[] = [$relay, $on];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SelfserveWashCompletionFlowHarness extends selfserve_wash_flow
|
||||
{
|
||||
public function __construct() {}
|
||||
|
||||
public function turnOffConfiguredRelay(selfserve_lane $lane, selfserve_lane_relay $relay): void
|
||||
{
|
||||
$this->turnOffRelayIfConfigured($lane, $relay);
|
||||
}
|
||||
}
|
||||
|
||||
it('forces machine and cleaner relays off when a self-serve wash session is completed', function (): void {
|
||||
$washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));
|
||||
|
||||
@@ -10,14 +84,27 @@ it('forces machine and cleaner relays off when a self-serve wash session is comp
|
||||
expect($methodOffset)->not->toBeFalse();
|
||||
$methodBody = substr($washFlow, (int)$methodOffset, 1500);
|
||||
|
||||
expect($methodBody)->toContain('$this->turnOffRelayIfConfiguredAndOn($lane, selfserve_lane_relay::MACHINE);');
|
||||
expect($methodBody)->toContain('$this->turnOffRelayIfConfiguredAndOn($lane, selfserve_lane_relay::MACHINE_CLEANER);');
|
||||
expect($methodBody)->toContain('$this->turnOffRelayIfConfigured($lane, selfserve_lane_relay::MACHINE);');
|
||||
expect($methodBody)->toContain('$this->turnOffRelayIfConfigured($lane, selfserve_lane_relay::MACHINE_CLEANER);');
|
||||
|
||||
$helperOffset = strpos($washFlow, 'protected function turnOffRelayIfConfiguredAndOn');
|
||||
$helperOffset = strpos($washFlow, 'protected function turnOffRelayIfConfigured');
|
||||
expect($helperOffset)->not->toBeFalse();
|
||||
$helperBody = substr($washFlow, (int)$helperOffset, 1500);
|
||||
|
||||
expect($helperBody)->toContain('$status = $lane->getRelayStatus($relay);');
|
||||
expect($helperBody)->toContain("if ((bool)(\$status['on'] ?? false) !== true)");
|
||||
expect($helperBody)->toContain('$lane->setRelayStatusHard($relay, false);');
|
||||
expect($helperBody)->not->toContain('$lane->getRelayStatus($relay)');
|
||||
});
|
||||
|
||||
it('always dispatches completion relay off for configured machine relays without a status precheck', function (): void {
|
||||
$lane = new SelfserveWashCompletionRelayLaneFake(reportedOn: false);
|
||||
$flow = new SelfserveWashCompletionFlowHarness();
|
||||
|
||||
$flow->turnOffConfiguredRelay($lane, selfserve_lane_relay::MACHINE);
|
||||
$flow->turnOffConfiguredRelay($lane, selfserve_lane_relay::MACHINE_CLEANER);
|
||||
|
||||
expect($lane->statusReads)->toBe([])
|
||||
->and($lane->relayWrites)->toBe([
|
||||
[selfserve_lane_relay::MACHINE, false],
|
||||
[selfserve_lane_relay::MACHINE_CLEANER, false],
|
||||
]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user