Skip to content

Commit e6a6e3a

Browse files
Release/0.9.5 (#171)
* bump version to 0.9.5 * fixes issue with default test config settings * adds CqlSolution * enhances CQL Explorer multiple-projects support * adds check for no test cases * update change log * fix tests causing issue with github actions * fix issue with windows paths
1 parent 0218196 commit e6a6e3a

22 files changed

Lines changed: 615 additions & 106 deletions

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Change Log
22

33

4+
5+
## v0.9.5 (prerelease)
6+
7+
Date: 2026-05-28
8+
9+
* adds check for no test cases
10+
* enhances CQL Explorer multiple-projects support
11+
* adds CqlSolution
12+
* fixes issue with default test config settings
13+
* bump version to 0.9.5
14+
15+
416
## v0.9.4 (prerelease)
517

618
Date: 2026-05-14

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: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cql",
3-
"version": "0.9.4",
3+
"version": "0.9.5",
44
"displayName": "Clinical Quality Language (CQL)",
55
"description": "Syntax highlighting, linting, and execution for the HL7 Clinical Quality Language (CQL) for VS Code",
66
"publisher": "cqframework",
@@ -228,6 +228,18 @@
228228
"icon": "$(run-all)",
229229
"category": "CQL Explorer"
230230
},
231+
{
232+
"command": "cql.explorer.project.execute-select",
233+
"title": "Select and Execute Libraries",
234+
"category": "CQL Explorer",
235+
"icon": "$(play)"
236+
},
237+
{
238+
"command": "cql.explorer.project.execute-all",
239+
"title": "Execute All Libraries",
240+
"icon": "$(run-all)",
241+
"category": "CQL Explorer"
242+
},
231243
{
232244
"command": "cql.explorer.test-case.filter",
233245
"title": "Filter Test Cases",
@@ -405,6 +417,14 @@
405417
"command": "cql.explorer.test-case.execute-all",
406418
"when": "false"
407419
},
420+
{
421+
"command": "cql.explorer.project.execute-all",
422+
"when": "false"
423+
},
424+
{
425+
"command": "cql.explorer.project.execute-select",
426+
"when": "false"
427+
},
408428
{
409429
"command": "cql.explorer.expand-all",
410430
"when": "false"
@@ -540,12 +560,32 @@
540560
"command": "cql.explorer.test-case.clear-filter",
541561
"when": "view == cql-libraries && viewItem =~ /cql-testcase-root-filtered/",
542562
"group": "inline@3"
563+
},
564+
{
565+
"command": "cql.explorer.project.execute-select",
566+
"when": "view == cql-libraries && viewItem == cql-project-root",
567+
"group": "1:project"
568+
},
569+
{
570+
"command": "cql.explorer.project.execute-all",
571+
"when": "view == cql-libraries && viewItem == cql-project-root",
572+
"group": "1:project"
573+
},
574+
{
575+
"command": "cql.explorer.project.execute-select",
576+
"when": "view == cql-libraries && viewItem == cql-project-root",
577+
"group": "inline@1"
578+
},
579+
{
580+
"command": "cql.explorer.project.execute-all",
581+
"when": "view == cql-libraries && viewItem == cql-project-root",
582+
"group": "inline@2"
543583
}
544584
],
545585
"view/title": [
546586
{
547587
"command": "cql.execute.select-libraries",
548-
"when": "view == cql-libraries",
588+
"when": "view == cql-libraries && cql.solutionLoaded",
549589
"group": "navigation@1"
550590
},
551591
{
@@ -623,25 +663,7 @@
623663
"fileMatch": "**/input/tests/config.jsonc",
624664
"url": "./schemas/cql-config.schema.json"
625665
}
626-
],
627-
"configuration": {
628-
"title": "CQL",
629-
"properties": {
630-
"cql.execute.resultFormat": {
631-
"type": "string",
632-
"enum": [
633-
"individual",
634-
"flat"
635-
],
636-
"enumDescriptions": [
637-
"Save one JSON result file per test case to input/tests/results/{libraryName}/TestCaseResult-{patientId}.json",
638-
"Save all test case results for a library to a single text file at input/tests/results/{libraryName}.txt"
639-
],
640-
"default": "individual",
641-
"description": "Controls how Execute CQL results are saved."
642-
}
643-
}
644-
}
666+
]
645667
},
646668
"resolutions": {
647669
"color-name": "1.1.3"
@@ -658,7 +680,7 @@
658680
"cql-language-server": {
659681
"groupId": "org.opencds.cqf.cql.ls",
660682
"artifactId": "cql-ls-server",
661-
"version": "4.6.0"
683+
"version": "4.7.0"
662684
}
663685
},
664686
"devDependencies": {

src/__test__/resources/simple-project/input/tests/Measure/LibWithTests/1111/.gitkeep

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"testCasesToExclude": [],
3+
"resultFormat": "flat"
4+
}

src/__test__/suite/commands/execute-cql.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ suite('loadTestConfig()', () => {
178178
const configPath = path.join(tmpDir, 'config.json');
179179
fs.writeFileSync(configPath, JSON.stringify(config));
180180
const result = loadTestConfig(Uri.file(configPath));
181-
expect(result.resultFormat).to.be.undefined;
181+
expect(result.resultFormat).to.equal('flat');
182182
});
183183

184184
test('returns individual resultFormat when config specifies individual', () => {

src/__test__/suite/cql-explorer/buildTree.test.ts

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect } from 'chai';
22
import * as path from 'path';
33
import * as vscode from 'vscode';
44
import { Uri, workspace } from 'vscode';
5-
import { CqlLibrary, CqlProject, CqlTestCase } from '../../../cql-explorer/cqlProject';
5+
import { CqlLibrary, CqlProject, CqlTestCase } from '../../../model/cqlProject';
66
import {
77
CqlLibraryRootTreeItem,
88
CqlLibraryTreeItem,
@@ -12,7 +12,7 @@ import {
1212
CqlTestCaseTreeItem,
1313
buildTree,
1414
} from '../../../cql-explorer/cqlProjectTreeDataProvider';
15-
import { DeviationKind } from '../../../cql-explorer/igLayoutDetector';
15+
import { DeviationKind } from '../../../model/igLayoutDetector';
1616

1717
suite('CqlProjectTreeDataProvider.nodeId()', () => {
1818
// Expected nodeId values per platform:
@@ -245,6 +245,73 @@ suite('buildTree — multi-project and deviations', () => {
245245
});
246246
});
247247

248+
suite('buildTree — hideEmpty project filtering (multi-project)', () => {
249+
const wsRoot = workspace.workspaceFolders![0].uri;
250+
251+
function makeLib(name: string): CqlLibrary {
252+
return new CqlLibrary(Uri.joinPath(wsRoot, `input/cql/${name}.cql`));
253+
}
254+
255+
function makeLoadedLib(name: string): CqlLibrary {
256+
const lib = makeLib(name);
257+
lib.testCaseLoadState = 'loaded';
258+
return lib;
259+
}
260+
261+
function fakeProject(name: string, libs: CqlLibrary[]): CqlProject {
262+
return {
263+
igRoot: `/fake/${name}`,
264+
name,
265+
projectDeviations: new Set<DeviationKind>(),
266+
Libraries: libs,
267+
} as unknown as CqlProject;
268+
}
269+
270+
test('hideEmpty=false keeps projects with no test cases', () => {
271+
const emptyLib = makeLoadedLib('EmptyLib');
272+
const p1 = fakeProject('ProjectA', [emptyLib]);
273+
const p2 = fakeProject('ProjectB', [makeLib('OtherLib')]);
274+
const items = buildTree([p1, p2], false);
275+
expect(items).to.have.length(2);
276+
});
277+
278+
test('hideEmpty=true hides a project whose only library has no test cases', () => {
279+
const emptyLib = makeLoadedLib('EmptyLib');
280+
const p1 = fakeProject('EmptyProject', [emptyLib]);
281+
const libWithTests = makeLoadedLib('LibWithTests');
282+
libWithTests.addTestCase(
283+
new CqlTestCase(Uri.joinPath(wsRoot, 'input/tests/Measure/LibWithTests/1111')),
284+
);
285+
const p2 = fakeProject('NonEmptyProject', [libWithTests]);
286+
const items = buildTree([p1, p2], true);
287+
expect(items).to.have.length(1);
288+
expect((items[0] as CqlProjectRootTreeItem).cqlProject.name).to.equal('NonEmptyProject');
289+
});
290+
291+
test('hideEmpty=true keeps a project that has at least one library with test cases', () => {
292+
const emptyLib = makeLoadedLib('EmptyLib');
293+
const libWithTests = makeLoadedLib('LibWithTests');
294+
libWithTests.addTestCase(
295+
new CqlTestCase(Uri.joinPath(wsRoot, 'input/tests/Measure/LibWithTests/1111')),
296+
);
297+
const p1 = fakeProject('MixedProject', [emptyLib, libWithTests]);
298+
const p2 = fakeProject('OtherProject', [makeLoadedLib('OtherEmpty')]);
299+
const items = buildTree([p1, p2], true);
300+
expect(items).to.have.length(1);
301+
expect((items[0] as CqlProjectRootTreeItem).cqlProject.name).to.equal('MixedProject');
302+
});
303+
304+
test('hideEmpty=true keeps a project whose library testCaseLoadState is not loaded', () => {
305+
const loadingLib = makeLib('LoadingLib'); // testCaseLoadState = 'not-loaded'
306+
const p1 = fakeProject('LoadingProject', [loadingLib]);
307+
const p2 = fakeProject('EmptyProject', [makeLoadedLib('EmptyLib')]);
308+
const items = buildTree([p1, p2], true);
309+
// p1 is kept because its library hasn't finished loading
310+
expect(items).to.have.length(1);
311+
expect((items[0] as CqlProjectRootTreeItem).cqlProject.name).to.equal('LoadingProject');
312+
});
313+
});
314+
248315
suite('CqlProjectTreeDataProvider.nodeId() — CqlProjectRootTreeItem', () => {
249316
test('CqlProjectRootTreeItem ID equals igRoot', () => {
250317
const wsRoot = workspace.workspaceFolders![0].uri;

src/__test__/suite/cql-explorer/cqlLibraryRootTreeItem.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai';
22
import * as vscode from 'vscode';
33
import { Uri, workspace } from 'vscode';
4-
import { CqlLibrary, CqlTestCase } from '../../../cql-explorer/cqlProject';
4+
import { CqlLibrary, CqlTestCase } from '../../../model/cqlProject';
55
import {
66
CqlLibraryRootTreeItem,
77
CqlResultsRootTreeItem,

src/__test__/suite/cql-explorer/cqlTestCaseRootTreeItem.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai';
22
import * as vscode from 'vscode';
33
import { Uri, workspace } from 'vscode';
4-
import { CqlLibrary, CqlTestCase } from '../../../cql-explorer/cqlProject';
4+
import { CqlLibrary, CqlTestCase } from '../../../model/cqlProject';
55
import {
66
CqlTestCaseRootTreeItem,
77
} from '../../../cql-explorer/cqlProjectTreeDataProvider';

src/__test__/suite/cql-explorer/cqlTestCaseTreeItem.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from 'chai';
22
import { Uri, workspace } from 'vscode';
3-
import { CqlTestCase } from '../../../cql-explorer/cqlProject';
3+
import { CqlTestCase } from '../../../model/cqlProject';
44
import { CqlTestCaseTreeItem } from '../../../cql-explorer/cqlProjectTreeDataProvider';
55

66
suite('CqlTestCaseTreeItem', () => {

0 commit comments

Comments
 (0)