Skip to content

Commit 7c5747e

Browse files
authored
Merge pull request #91 from cqframework/equal-lists-of-strings
Fixes for empty list handling
2 parents 54beeaf + 5bbc92a commit 7c5747e

6 files changed

Lines changed: 81 additions & 4 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cql-tests-runner",
3-
"version": "1.7.0",
3+
"version": "1.7.1",
44
"description": "Server API and command line tools for running CQL tests",
55
"type": "module",
66
"main": "dist/bin/cql-tests.js",

src/extractors/evaluation-error-extractor.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
import { BaseExtractor } from './base-extractor.js';
22

3+
function operationOutcomeMessage(resource: any): string {
4+
const issue = resource?.issue?.[0];
5+
const fromIssue =
6+
issue?.details?.text ?? issue?.diagnostics ?? (issue != null ? JSON.stringify(issue) : undefined);
7+
if (fromIssue != null) {
8+
return fromIssue;
9+
}
10+
return resource != null ? JSON.stringify(resource) : 'unknown';
11+
}
12+
313
export class EvaluationErrorExtractor extends BaseExtractor {
414
protected _process(parameter: any): any {
515
if (parameter.name === 'evaluation error') {
6-
return `EvaluationError:${parameter.resource.issue[0].details.text}`;
16+
return `EvaluationError:${operationOutcomeMessage(parameter.resource)}`;
717
}
818

919
return undefined;

src/extractors/value-map.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ export class ValueMap {
1212
if (!Array.isArray(parsed)) {
1313
return keys;
1414
}
15+
// Empty list `{}` parses to `[]`. Do not mark `return` as singleton-list: the
16+
// extractor already yields `[]` for FHIR empty-list encoding; wrapping would
17+
// produce `[[]]` vs expected `[]` (see cqframework/cql-tests-runner#90).
18+
if (parsed.length === 0) {
19+
return keys;
20+
}
1521
keys.add('return');
1622
for (const item of parsed) {
1723
if (Array.isArray(item)) {

test/extractResults-cql_operations.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { beforeAll, expect, test } from 'vitest';
22

33
import { ResultExtractor } from '../src/extractors/result-extractor.js';
4+
import { ValueMap } from '../src/extractors/value-map.js';
45
import { buildExtractor } from '../src/server/extractor-builder.js';
56

67
let extractor: ResultExtractor | null = null;
@@ -124,6 +125,36 @@ test('singleton list-typed return stays array when singletonListKeys includes re
124125
).toEqual(['a']);
125126
});
126127

128+
test('FHIR empty list stays [] when expected is empty list (issue #90)', () => {
129+
const emptyListParameters = {
130+
resourceType: 'Parameters',
131+
parameter: [
132+
{
133+
name: 'return',
134+
extension: [
135+
{
136+
url: 'http://hl7.org/fhir/StructureDefinition/cqf-cqlType',
137+
valueString: 'List<System.Any>',
138+
},
139+
],
140+
_valueBoolean: {
141+
extension: [
142+
{
143+
url: 'http://hl7.org/fhir/StructureDefinition/cqf-isEmptyList',
144+
valueBoolean: true,
145+
},
146+
],
147+
},
148+
},
149+
],
150+
};
151+
expect(
152+
extractor!.extract(emptyListParameters, {
153+
singletonListKeys: ValueMap.singletonListKeysFromExpected([]),
154+
})
155+
).toEqual([]);
156+
});
157+
127158
test('date response check', () => {
128159
expect(
129160
extractor!.extract({
@@ -286,6 +317,32 @@ test('error response check', () => {
286317
);
287318
});
288319

320+
test('evaluation error uses diagnostics when details.text is absent', () => {
321+
expect(
322+
extractor!.extract({
323+
resourceType: 'Parameters',
324+
parameter: [
325+
{
326+
name: 'evaluation error',
327+
resource: {
328+
resourceType: 'OperationOutcome',
329+
issue: [{ severity: 'error', diagnostics: 'CQL engine message' }],
330+
},
331+
},
332+
],
333+
})
334+
).toBe('EvaluationError:CQL engine message');
335+
});
336+
337+
test('evaluation error does not throw when resource shape is minimal', () => {
338+
expect(
339+
extractor!.extract({
340+
resourceType: 'Parameters',
341+
parameter: [{ name: 'evaluation error', resource: { resourceType: 'OperationOutcome', issue: [] } }],
342+
})
343+
).toBe('EvaluationError:{"resourceType":"OperationOutcome","issue":[]}');
344+
});
345+
289346
test('period datetime response check', () => {
290347
expect(
291348
extractor!.extract({

test/value-map.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ test('singletonListKeysFromExpected: non-array yields empty key set', () => {
2828
expect([...ValueMap.singletonListKeysFromExpected({ a: 1 })]).toEqual([]);
2929
});
3030

31+
test('singletonListKeysFromExpected: empty array adds no keys (issue #90)', () => {
32+
expect([...ValueMap.singletonListKeysFromExpected([])]).toEqual([]);
33+
});
34+
3135
test('singletonListKeysFromExpected: array adds return', () => {
3236
expect([...ValueMap.singletonListKeysFromExpected(['a'])]).toEqual(['return']);
3337
expect([...ValueMap.singletonListKeysFromExpected([1, 2])]).toEqual(['return']);

0 commit comments

Comments
 (0)