set($value); return $property; } function selfserve_session_harness( string $status, ?string $completedAt, ?string $washStartedAt = '2026-04-28 10:00:00', ?string $machineStartTriggeredAt = null ): selfserve_wash_sessions_o { $session = (new ReflectionClass(selfserve_wash_sessions_o::class))->newInstanceWithoutConstructor(); $session->status = selfserve_session_property('status', 'string', $status); $session->completed_at = selfserve_session_property('completed_at', 'datetime', $completedAt); $session->wash_started_at = selfserve_session_property('wash_started_at', 'datetime', $washStartedAt); $session->machine_start_triggered_at = selfserve_session_property('machine_start_triggered_at', 'datetime', $machineStartTriggeredAt); return $session; } it('treats terminal self-serve wash session statuses as closed', function (): void { expect(selfserve_wash_sessions_o::isTerminalStatus('COMPLETED'))->toBeTrue() ->and(selfserve_wash_sessions_o::isTerminalStatus('FORCE_STOPPED'))->toBeTrue() ->and(selfserve_wash_sessions_o::isTerminalStatus('MACHINE_STARTED'))->toBeFalse() ->and(selfserve_wash_sessions_o::terminalStatusSqlList())->toBe("'COMPLETED','FORCE_STOPPED'"); expect(selfserve_session_harness('MACHINE_STARTED', null)->isOpen())->toBeTrue() ->and(selfserve_session_harness('COMPLETED', null)->isOpen())->toBeFalse() ->and(selfserve_session_harness('MACHINE_STARTED', '2026-04-28 10:30:00')->isOpen())->toBeFalse(); }); it('freezes elapsed self-serve wash minutes at completion time', function (): void { expect(selfserve_session_harness('COMPLETED', '2026-04-28 10:42:00')->getElapsedMinutes())->toBe(42) ->and(selfserve_session_harness('COMPLETED', '2026-04-28 10:35:00', null, '2026-04-28 10:05:00')->getElapsedMinutes())->toBe(30) ->and(selfserve_session_harness('COMPLETED', '2026-04-28 09:59:00')->getElapsedMinutes())->toBe(0); });