markTestSkipped('API tests are disabled. Run with RUN_API_TESTS=1.'); } $manifest = require app_path('tests/Api/api_coverage_manifest.php'); $allOperations = array_merge($manifest['openapi_operations'], $manifest['manual_operations']); $happyOnlyOperations = $manifest['happy_only_operations']; $coverage = []; foreach (glob(app_path('tests/Api/*Test.php')) as $file) { if (basename($file) === 'ApiCoverageManifestTest.php') { continue; } $contents = (string)file_get_contents($file); preg_match_all( '/api_test_covers\(\s*[\'"]([^\'"]+)[\'"]\s*,\s*[\'"]([^\'"]+)[\'"]\s*\)/', $contents, $matches, PREG_SET_ORDER ); foreach ($matches as $match) { $coverage[$match[1]][$match[2]] = true; } } foreach ($allOperations as $operation) { expect($coverage[$operation]['happy'] ?? false) ->toBeTrue('Missing happy-path coverage marker for ' . $operation . '.'); if (in_array($operation, $happyOnlyOperations, true)) { continue; } expect(($coverage[$operation]['failure'] ?? false) || ($coverage[$operation]['auth'] ?? false)) ->toBeTrue('Missing failure/auth coverage marker for ' . $operation . '.'); } }); it('keeps the OpenAPI manifest entries aligned with the API spec', function (): void { if (!api_tests_enabled()) { $this->markTestSkipped('API tests are disabled. Run with RUN_API_TESTS=1.'); } $manifest = require app_path('tests/Api/api_coverage_manifest.php'); $lines = file(app_path('openapi.yaml'), FILE_IGNORE_NEW_LINES); expect($lines)->not->toBeFalse(); $operationsInSpec = []; $currentPath = null; foreach ($lines as $line) { if (preg_match('/^ {2}(\/[^:]+):\s*$/', $line, $pathMatch) === 1) { $currentPath = $pathMatch[1]; continue; } if ($currentPath === null) { continue; } if (preg_match('/^ {4}([a-z]+):\s*$/', $line, $methodMatch) === 1) { $operationsInSpec[] = strtoupper($methodMatch[1]) . ' ' . $currentPath; } } foreach ($manifest['openapi_operations'] as $operation) { expect($operationsInSpec)->toContain($operation); } });