* feat: check for CIMD of authorization server metadata * feat(runner): support per-check spec-version gating via ConformanceCheck.source * fix(auth): CIMD is SHOULD — emit WARNING; gate via check.source; reuse SpecReferences * test(runner): matchesSpecVersion gates introducedIn:'2025-11-25' correctly --------- Co-authored-by: Takashi Norimatsu <takashi.norimatsu.ws@hitachi.com>
128 lines
3.5 KiB
TypeScript
128 lines
3.5 KiB
TypeScript
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<string, unknown>,
|
|
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 };
|
|
}
|