Files
api/services/nginx/app/tests/Unit/Selfserve/SelfserveOpenApiSpecTest.php
T
Jeppe Bundgaard 72704b7806 Add "Get My Active Self-Serve Wash" endpoint and corresponding tests
- Introduced a new `/modules/self-serve/lane/wash/my-active-wash` endpoint to retrieve the authenticated customer's active self-serve wash.
- Implemented authentication and permission checks for secure access.
- Added detailed response handling for various scenarios, including 401, 403, and 404 statuses.
- Extended API documentation and OpenAPI spec to support the new endpoint.
- Updated unit and API tests to validate endpoint functionality and route wiring.
2026-06-02 10:29:15 +02:00

147 lines
7.5 KiB
PHP

<?php
function selfserve_openapi_content_or_skip(): string
{
$candidates = [
dirname(__DIR__, 6) . DIRECTORY_SEPARATOR . 'openapi.yaml',
dirname(__DIR__, 5) . DIRECTORY_SEPARATOR . 'openapi.yaml',
dirname(__DIR__, 4) . DIRECTORY_SEPARATOR . 'openapi.yaml',
dirname(__DIR__, 3) . DIRECTORY_SEPARATOR . 'openapi.yaml',
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'openapi.yaml',
];
foreach ($candidates as $candidate) {
if (!is_file($candidate)) {
continue;
}
$content = file_get_contents($candidate);
if ($content !== false) {
return $content;
}
}
test()->markTestSkipped('openapi.yaml is not available in this runtime environment.');
}
function selfserve_openapi_path_block_or_fail(string $content, string $path): string
{
$path_marker = ' ' . $path . ':';
$start = strpos($content, $path_marker);
if ($start === false) {
throw new RuntimeException("OpenAPI path block not found: {$path}");
}
$rest = substr($content, $start + strlen($path_marker));
$next_path = strpos($rest, "\n /");
if ($next_path === false) {
return substr($content, $start);
}
return substr($content, $start, strlen($path_marker) + $next_path);
}
it('documents self-serve machine type, eligibility, summary, and webhook endpoints', function (): void {
$content = selfserve_openapi_content_or_skip();
$allowedPathBlock = selfserve_openapi_path_block_or_fail($content, '/department/selfserve/vehicle/allowed');
$summaryPathBlock = selfserve_openapi_path_block_or_fail($content, '/department/selfserve/washes/summary');
expect($content)->toContain('/department/selfserve/machine-types:');
expect($content)->toContain('/department/selfserve/vehicle/allowed:');
expect($content)->toContain('/department/selfserve/washes/summary:');
expect($content)->toContain('/relay/button/press/post:');
expect($content)->toContain('/relay/machine/on/post:');
expect($content)->toContain('/modules/self-serve/lane/wash/in-progress:');
expect($content)->toContain('/modules/self-serve/lane/wash/my-active-wash:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine/status:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine/set:');
expect($content)->toContain('/modules/self-serve/lane/gate/open:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine_program_picker/status:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine_program_picker/set:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine_cleaner/status:');
expect($content)->toContain('/modules/self-serve/lane/relay/machine_cleaner/set:');
expect($allowedPathBlock)->toContain('name: vehicle_type_id');
expect($allowedPathBlock)->toContain('name: vehicle_type');
expect($allowedPathBlock)->toContain('may evaluate any registration plate');
expect($allowedPathBlock)->toContain('Persisted self-serve answers are only applied');
expect($summaryPathBlock)->toContain('name: vehicle_type_id');
expect($summaryPathBlock)->toContain('name: vehicle_type');
});
it('documents the all-in-one self-serve studio replacement API', function (): void {
$content = selfserve_openapi_content_or_skip();
expect($content)->toContain('/department/selfserve/studio/graph:');
expect($content)->toContain('/department/selfserve/studio/layout:');
expect($content)->toContain('/department/selfserve/studio/validate:');
expect($content)->toContain('/department/selfserve/studio/simulate:');
expect($content)->toContain('/department/selfserve/studio/path-outcomes:');
expect($content)->toContain('/department/selfserve/studio/path-outcomes/stream:');
expect($content)->toContain('/department/selfserve/studio/path-confirmations:');
expect($content)->toContain('/department/selfserve/studio/publish:');
expect($content)->toContain('/department/selfserve/studio/rollback:');
expect($content)->toContain('/department/selfserve/studio/gateway-action:');
expect($content)->toContain('SelfserveStudioGraph:');
expect($content)->toContain('SelfserveStudioGraphSaveRequest:');
expect($content)->toContain('SelfserveStudioLayout:');
expect($content)->toContain('SelfserveStudioPathOutcomesRequest:');
expect($content)->toContain('SelfserveStudioPathOutcomesResponse:');
expect($content)->toContain('SelfserveStudioPathResult:');
expect($content)->toContain('SelfserveStudioPathProgress:');
expect($content)->toContain('SelfserveStudioPathConfirmationRequest:');
expect($content)->toContain('SelfserveStudioPathConfirmation:');
expect($content)->toContain('projectSelfserveStudioPathOutcomes');
expect($content)->toContain('streamSelfserveStudioPathOutcomes');
expect($content)->toContain('confirmSelfserveStudioPath');
expect($content)->toContain('runSelfserveStudioGatewayAction');
});
it('defines reusable self-serve wash and machine type schemas', function (): void {
$content = selfserve_openapi_content_or_skip();
expect($content)->toContain('SelfserveMachineType:');
expect($content)->toContain('SelfserveVehicleAllowedResponse:');
expect($content)->toContain('SelfserveWashSummary:');
expect($content)->toContain('MachineButtonPressWebhookResponse:');
expect($content)->toContain('DepartmentSelfserveVehicleConditionMutationResponse:');
expect($content)->toContain('DepartmentLane:');
expect($content)->toContain('selfserve_enabled:');
expect($content)->toContain('blocked_reason:');
expect($content)->toContain('machine_type_id:');
expect($content)->toContain('SelfServeLaneMachineRelayStatus:');
expect($content)->toContain(' wash_started_at:');
});
it('documents in-progress self-serve wash start and machine relay fields', function (): void {
$content = selfserve_openapi_content_or_skip();
$inProgressPathBlock = selfserve_openapi_path_block_or_fail($content, '/modules/self-serve/lane/wash/in-progress');
expect($inProgressPathBlock)->toContain('included_minutes:');
expect($inProgressPathBlock)->toContain('machine_relay_enabled:');
expect($inProgressPathBlock)->toContain('machine_relay_enabled_at:');
expect($inProgressPathBlock)->toContain('machine_start_triggered_at:');
expect($inProgressPathBlock)->toContain('wash_started_at:');
});
it('documents self-serve machine wash included minutes in config schemas', function (): void {
$content = selfserve_openapi_content_or_skip();
expect($content)->toContain('SelfServeConfigEntry:');
expect($content)->toContain('machine_wash_minutes_included');
expect($content)->toContain('SelfServeConfig:');
});
it('documents property gate lane commands and sanitized gate failure responses', function (): void {
$content = selfserve_openapi_content_or_skip();
$commandPathBlock = selfserve_openapi_path_block_or_fail($content, '/modules/self-serve/lane/command');
$gateOpenPathBlock = selfserve_openapi_path_block_or_fail($content, '/modules/self-serve/lane/gate/open');
expect($commandPathBlock)->toContain('OPEN_PROPERTY_ACCESS_GATE');
expect($commandPathBlock)->toContain('OPEN_PROPERTY_EXIT_GATE');
expect($commandPathBlock)->toContain('Command execution failed');
expect($commandPathBlock)->toContain('Failed to execute command: Failed to open property access gate.');
expect($gateOpenPathBlock)->toContain('Gate open failed');
expect($gateOpenPathBlock)->toContain('Failed to open entrance gate.');
});