Add self-serve API fixtures and enhance session synchronization logic

- Implement `createSelfServeScenario` to generate comprehensive self-serve test fixtures, including departments, lanes, tasks, and sessions.
- Add `syncRelayState` parameter to `synchronizeSession` for decoupled relay hardware synchronization.
- Update relevant routes and tests to reflect changes in session synchronization methods.
- Enhance Shelly request handling by blocking real device interactions in test mode with detailed logging.
This commit is contained in:
Jeppe Bundgaard
2026-04-28 12:28:29 +02:00
parent 55f8f25fd7
commit 72df2244ca
10 changed files with 494 additions and 14 deletions
+53
View File
@@ -16,6 +16,10 @@ class shelly implements shelly_i
private const SHELLY_RATE_LIMIT_WAIT_TIMEOUT_SECONDS = 20;
private const SHELLY_RATE_LIMIT_WINDOW_MILLISECONDS = 2000;
private const SHELLY_RATE_LIMIT_GATE_KEY = 'shelly_cloud_rate_limit_gate';
/**
* @var array<int,array<string,mixed>>
*/
private static array $blocked_request_log = [];
/**
* Configuration of the shelly module
@@ -38,6 +42,19 @@ class shelly implements shelly_i
$this->shelly_search = new shelly_search_a();
}
public static function resetBlockedRequestLog(): void
{
self::$blocked_request_log = [];
}
/**
* @return array<int,array<string,mixed>>
*/
public static function blockedRequestLog(): array
{
return self::$blocked_request_log;
}
/**
* @inheritDoc
* @throws Exception If the module is not enabled, the license plate is invalid, the daily limit is exceeded, or the secret key is invalid
@@ -146,6 +163,7 @@ class shelly implements shelly_i
* -H 'Content-Type: application/json' \
* -d '<BODY>'
*/
$this->guardRealShellyRequest('POST', $endpoint, $data);
// Require the module to be enabled
self::requireModuleEnabled();
self::requireValidSecretKey();
@@ -192,6 +210,7 @@ class shelly implements shelly_i
*/
function sendGetRequest(string $endpoint, array $data): array|object|null
{
$this->guardRealShellyRequest('GET', $endpoint, $data);
self::requireModuleEnabled();
self::requireValidSecretKey();
self::requireValidServerURL();
@@ -238,6 +257,40 @@ class shelly implements shelly_i
return $url . $separator . http_build_query($query);
}
/**
* @param array<string,mixed> $data
* @throws Exception
*/
private function guardRealShellyRequest(string $method, string $endpoint, array $data): void
{
if (!$this->shouldBlockRealShellyRequest()) {
return;
}
$record = [
'method' => strtoupper($method),
'endpoint' => $endpoint,
'data' => $data,
'at' => date('c'),
];
self::$blocked_request_log[] = $record;
$log_path = trim((string)(getenv('TRUCKWASH_TEST_SHELLY_GUARD_LOG') ?: ''));
if ($log_path !== '') {
$encoded = json_encode($record, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if (is_string($encoded)) {
@file_put_contents($log_path, $encoded . PHP_EOL, FILE_APPEND | LOCK_EX);
}
}
throw new Exception('Real Shelly requests are blocked in test mode: ' . strtoupper($method) . ' ' . $endpoint);
}
private function shouldBlockRealShellyRequest(): bool
{
return trim((string)(getenv('TRUCKWASH_TEST_BLOCK_REAL_SHELLY') ?: '')) === '1';
}
/**
* @throws Exception
*/