Files
api/services/nginx/app/tests/Unit/Selfserve/SelfserveOpenApiSpecTest.php
T
Jeppe Bundgaard 206b487fa2 Add new table and enhance studio layout logic
Introduce `department_selfserve_studio_layouts` table for department-specific layouts and implement advanced auto-layout functionality in the DepartmentSelfServeStudio module. Added custom node definitions, updated styling, and integrated new logics for sorting and visualizing nodes in the Vue Flow interface.
2026-04-28 14:21:31 +02:00

128 lines
6.2 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('/modules/self-serve/lane/wash/in-progress:');
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($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/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('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('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.');
});