import { promises as fs } from 'fs'; import path from 'path'; import { ConformanceCheck, SpecVersion } from '../types'; import { getClientScenarioForAuthorizationServer, matchesSpecVersion } from '../scenarios'; import { createResultDir, formatPrettyChecks } from './utils'; import { AuthorizationServerOptions } from '../schemas'; export async function runAuthorizationServerConformanceTest( options: AuthorizationServerOptions, scenarioName: string, details: Record, outputDir?: string, specVersion?: SpecVersion ): Promise<{ checks: ConformanceCheck[]; resultDir?: string; scenarioDescription: string; }> { let resultDir: string | undefined; if (outputDir) { resultDir = createResultDir( outputDir, scenarioName, 'authorization-server' ); await fs.mkdir(resultDir, { recursive: true }); } // Scenario is guaranteed to exist by CLI validation const scenario = getClientScenarioForAuthorizationServer(scenarioName)!; console.log( `Running client scenario for authorization server '${scenarioName}' against server: ${options.url}` ); const checks = await scenario.run(options, details); const filtered = specVersion ? checks.filter( (c) => !c.source || matchesSpecVersion(c.source, specVersion) ) : checks; if (resultDir) { await fs.writeFile( path.join(resultDir, 'checks.json'), JSON.stringify(filtered, null, 2) ); console.log(`Results saved to ${resultDir}`); } return { checks: filtered, resultDir, scenarioDescription: scenario.description }; } export function printAuthorizationServerResults( checks: ConformanceCheck[], scenarioDescription: string, verbose: boolean = false ): { passed: number; failed: number; denominator: number; warnings: number; } { const denominator = checks.filter( (c) => c.status === 'SUCCESS' || c.status === 'FAILURE' ).length; const passed = checks.filter((c) => c.status === 'SUCCESS').length; const failed = checks.filter((c) => c.status === 'FAILURE').length; const warnings = checks.filter((c) => c.status === 'WARNING').length; if (verbose) { console.log(JSON.stringify(checks, null, 2)); } else { console.log(`Checks:\n${formatPrettyChecks(checks)}`); } console.log(`\nTest Results:`); console.log( `Passed: ${passed}/${denominator}, ${failed} failed, ${warnings} warnings` ); if (failed > 0) { console.log('\n=== Failed Checks ==='); checks .filter((c) => c.status === 'FAILURE') .forEach((c) => { console.log(`\n - ${c.name}: ${c.description}`); if (c.errorMessage) { console.log(` Error: ${c.errorMessage}`); } }); } return { passed, failed, denominator, warnings }; } export function printAuthorizationServerSummary( allResults: { scenario: string; checks: ConformanceCheck[] }[] ): { totalPassed: number; totalFailed: number } { console.log('\n\n=== SUMMARY ==='); let totalPassed = 0; let totalFailed = 0; for (const result of allResults) { const passed = result.checks.filter((c) => c.status === 'SUCCESS').length; const failed = result.checks.filter((c) => c.status === 'FAILURE').length; totalPassed += passed; totalFailed += failed; const status = failed === 0 ? '✓' : '✗'; console.log( `${status} ${result.scenario}: ${passed} passed, ${failed} failed` ); } console.log(`\nTotal: ${totalPassed} passed, ${totalFailed} failed`); return { totalPassed, totalFailed }; }