client(); } function api_fixtures(): ApiFixtures { return api_test_runtime()->fixtures(); } function usesApiSuite(): void { // The API lifecycle is bound via Tests\Support\Api\ApiTestCase in tests/Pest.php. } function api_test_covers(string $operation, string $kind = 'happy'): void { if ($operation === '' || $kind === '') { throw new InvalidArgumentException('API coverage markers require an operation and coverage kind.'); } } function assert_api_envelope(ApiResponse $response): ApiResponse { return $response->assertEnvelope(); } function edge_test_broker_secret(): string { try { $configured = api_test_runtime()->queryOne( "SELECT `value` FROM `module_config` WHERE `module` = 'edgegateway' AND `variable` = 'broker_shared_secret' LIMIT 1" ); $secret = trim((string)($configured['value'] ?? '')); if ($secret !== '') { return $secret; } } catch (\Throwable) { } $secret = trim((string)(getenv('EDGE_BROKER_SHARED_SECRET') ?: '')); return $secret !== '' ? $secret : 'truckwash-edge-test-secret'; } /** * @param array $extraHeaders * @return array */ function edge_test_broker_headers(array $extraHeaders = []): array { return array_merge([ 'X-Edge-Broker-Secret' => edge_test_broker_secret(), ], $extraHeaders); }