From 7fe0ea94e1aca7cb1fc8d74fd4c694aaf28e21ed Mon Sep 17 00:00:00 2001 From: Bryant Austin Date: Tue, 5 May 2026 11:07:18 -0600 Subject: [PATCH] Added invalid handling --- src/services/test-runner.ts | 22 ++++++++++++++++++---- src/shared/results-shared.ts | 13 +++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/services/test-runner.ts b/src/services/test-runner.ts index b68627d..2071296 100644 --- a/src/services/test-runner.ts +++ b/src/services/test-runner.ts @@ -187,14 +187,19 @@ export class TestRunner { result.responseStatus = response.status; const responseBody = response.data; - const parsedExpected = cvl.parse(result.expected); + const invalid = result.invalid; + const parsedExpected = result.expected !== undefined ? cvl.parse(result.expected) : undefined; result.actual = resultExtractor.extract(responseBody, { - singletonListKeys: ValueMap.singletonListKeysFromExpected(parsedExpected), + singletonListKeys: + parsedExpected !== undefined + ? ValueMap.singletonListKeysFromExpected(parsedExpected) + : new Set(), }); - const invalid = result.invalid; if (invalid === 'true' || invalid === 'semantic') { - result.testStatus = response.status === 200 ? 'fail' : 'pass'; + result.testStatus = this.isExpectedInvalidResult(response.status, result.actual) + ? 'pass' + : 'fail'; } else { if (response.status === 200) { result.testStatus = resultsEqual(parsedExpected, result.actual) @@ -226,6 +231,15 @@ export class TestRunner { return result; } + private isExpectedInvalidResult(responseStatus: number, actual: any): boolean { + if (responseStatus !== 200) { + return true; + } + + const actualText = typeof actual === 'string' ? actual : JSON.stringify(actual); + return /EvaluationError:|OperationOutcome|Could not resolve call to operator/i.test(actualText); + } + private compareVersions(versionA: string | undefined, versionB: string | undefined): number { // Split into numeric parts (e.g., "1.5.2" → [1,5,2]) const partsA = String(versionA ?? '') diff --git a/src/shared/results-shared.ts b/src/shared/results-shared.ts index b910d55..e0474b9 100644 --- a/src/shared/results-shared.ts +++ b/src/shared/results-shared.ts @@ -48,14 +48,23 @@ export class Result implements InternalTestResult { } else { this.expected = test.output as string; } + } else if (this.invalid === 'true' || this.invalid === 'semantic') { + // Invalid tests are expected to fail during translation/evaluation. + // They do not need an ; allow the runner to execute them + // and mark them pass if the engine reports an error. + this.expected = undefined; } else { this.testStatus = 'skip'; this.skipMessage = 'No output specified'; } - this.capability = Array.isArray(test.capability) - ? test.capability.map(({ code, value }) => ({ code, value })) + const testCapabilities = Array.isArray(test.capability) + ? test.capability + : test.capability + ? [test.capability] : []; + + this.capability = testCapabilities.map(({ code, value }) => ({ code, value })); } }