sof-mssql 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +346 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +85 -0
- package/dist/cli.js.map +1 -0
- package/dist/fhirpath/transpiler.d.ts +18 -0
- package/dist/fhirpath/transpiler.d.ts.map +1 -0
- package/dist/fhirpath/transpiler.js +82 -0
- package/dist/fhirpath/transpiler.js.map +1 -0
- package/dist/fhirpath/visitor.d.ts +153 -0
- package/dist/fhirpath/visitor.d.ts.map +1 -0
- package/dist/fhirpath/visitor.js +1295 -0
- package/dist/fhirpath/visitor.js.map +1 -0
- package/dist/generated/grammar/fhirpathLexer.d.ts +88 -0
- package/dist/generated/grammar/fhirpathLexer.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathLexer.js +598 -0
- package/dist/generated/grammar/fhirpathLexer.js.map +1 -0
- package/dist/generated/grammar/fhirpathListener.d.ts +589 -0
- package/dist/generated/grammar/fhirpathListener.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathListener.js +4 -0
- package/dist/generated/grammar/fhirpathListener.js.map +1 -0
- package/dist/generated/grammar/fhirpathParser.d.ts +470 -0
- package/dist/generated/grammar/fhirpathParser.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathParser.js +3022 -0
- package/dist/generated/grammar/fhirpathParser.js.map +1 -0
- package/dist/generated/grammar/fhirpathVisitor.d.ts +372 -0
- package/dist/generated/grammar/fhirpathVisitor.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathVisitor.js +4 -0
- package/dist/generated/grammar/fhirpathVisitor.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/load.d.ts +14 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +115 -0
- package/dist/load.js.map +1 -0
- package/dist/loader/connection.d.ts +36 -0
- package/dist/loader/connection.d.ts.map +1 -0
- package/dist/loader/connection.js +106 -0
- package/dist/loader/connection.js.map +1 -0
- package/dist/loader/discovery.d.ts +38 -0
- package/dist/loader/discovery.d.ts.map +1 -0
- package/dist/loader/discovery.js +107 -0
- package/dist/loader/discovery.js.map +1 -0
- package/dist/loader/index.d.ts +24 -0
- package/dist/loader/index.d.ts.map +1 -0
- package/dist/loader/index.js +193 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/progress.d.ts +70 -0
- package/dist/loader/progress.d.ts.map +1 -0
- package/dist/loader/progress.js +206 -0
- package/dist/loader/progress.js.map +1 -0
- package/dist/loader/stream.d.ts +21 -0
- package/dist/loader/stream.d.ts.map +1 -0
- package/dist/loader/stream.js +103 -0
- package/dist/loader/stream.js.map +1 -0
- package/dist/loader/tables.d.ts +43 -0
- package/dist/loader/tables.d.ts.map +1 -0
- package/dist/loader/tables.js +88 -0
- package/dist/loader/tables.js.map +1 -0
- package/dist/loader/types.d.ts +134 -0
- package/dist/loader/types.d.ts.map +1 -0
- package/dist/loader/types.js +8 -0
- package/dist/loader/types.js.map +1 -0
- package/dist/parser.d.ts +60 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +226 -0
- package/dist/parser.js.map +1 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.d.ts +52 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.d.ts.map +1 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.js +144 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.js.map +1 -0
- package/dist/queryGenerator/ForEachProcessor.d.ts +127 -0
- package/dist/queryGenerator/ForEachProcessor.d.ts.map +1 -0
- package/dist/queryGenerator/ForEachProcessor.js +351 -0
- package/dist/queryGenerator/ForEachProcessor.js.map +1 -0
- package/dist/queryGenerator/PathParser.d.ts +64 -0
- package/dist/queryGenerator/PathParser.d.ts.map +1 -0
- package/dist/queryGenerator/PathParser.js +164 -0
- package/dist/queryGenerator/PathParser.js.map +1 -0
- package/dist/queryGenerator/SelectClauseBuilder.d.ts +63 -0
- package/dist/queryGenerator/SelectClauseBuilder.d.ts.map +1 -0
- package/dist/queryGenerator/SelectClauseBuilder.js +196 -0
- package/dist/queryGenerator/SelectClauseBuilder.js.map +1 -0
- package/dist/queryGenerator/SelectCombinationExpander.d.ts +42 -0
- package/dist/queryGenerator/SelectCombinationExpander.d.ts.map +1 -0
- package/dist/queryGenerator/SelectCombinationExpander.js +95 -0
- package/dist/queryGenerator/SelectCombinationExpander.js.map +1 -0
- package/dist/queryGenerator/WhereClauseBuilder.d.ts +20 -0
- package/dist/queryGenerator/WhereClauseBuilder.d.ts.map +1 -0
- package/dist/queryGenerator/WhereClauseBuilder.js +63 -0
- package/dist/queryGenerator/WhereClauseBuilder.js.map +1 -0
- package/dist/queryGenerator/index.d.ts +10 -0
- package/dist/queryGenerator/index.d.ts.map +1 -0
- package/dist/queryGenerator/index.js +19 -0
- package/dist/queryGenerator/index.js.map +1 -0
- package/dist/queryGenerator.d.ts +61 -0
- package/dist/queryGenerator.d.ts.map +1 -0
- package/dist/queryGenerator.js +187 -0
- package/dist/queryGenerator.js.map +1 -0
- package/dist/tests/sqlOnFhir.test.d.ts +11 -0
- package/dist/tests/sqlOnFhir.test.d.ts.map +1 -0
- package/dist/tests/sqlOnFhir.test.js +24 -0
- package/dist/tests/sqlOnFhir.test.js.map +1 -0
- package/dist/tests/utils/database.d.ts +38 -0
- package/dist/tests/utils/database.d.ts.map +1 -0
- package/dist/tests/utils/database.js +258 -0
- package/dist/tests/utils/database.js.map +1 -0
- package/dist/tests/utils/generator.d.ts +58 -0
- package/dist/tests/utils/generator.d.ts.map +1 -0
- package/dist/tests/utils/generator.js +195 -0
- package/dist/tests/utils/generator.js.map +1 -0
- package/dist/tests/utils/reporter.d.ts +83 -0
- package/dist/tests/utils/reporter.d.ts.map +1 -0
- package/dist/tests/utils/reporter.js +245 -0
- package/dist/tests/utils/reporter.js.map +1 -0
- package/dist/tests/utils/sqlOnFhir.d.ts +33 -0
- package/dist/tests/utils/sqlOnFhir.d.ts.map +1 -0
- package/dist/tests/utils/sqlOnFhir.js +281 -0
- package/dist/tests/utils/sqlOnFhir.js.map +1 -0
- package/dist/tests/utils/testContext.d.ts +18 -0
- package/dist/tests/utils/testContext.d.ts.map +1 -0
- package/dist/tests/utils/testContext.js +25 -0
- package/dist/tests/utils/testContext.js.map +1 -0
- package/dist/tests/utils/types.d.ts +31 -0
- package/dist/tests/utils/types.d.ts.map +1 -0
- package/dist/tests/utils/types.js +9 -0
- package/dist/tests/utils/types.js.map +1 -0
- package/dist/types.d.ts +288 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Database setup and teardown utilities for Vitest tests.
|
|
4
|
+
*
|
|
5
|
+
* Provides functions to manage database connections, table creation,
|
|
6
|
+
* and test data lifecycle during Vitest test execution.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.setupDatabase = setupDatabase;
|
|
10
|
+
exports.cleanupDatabase = cleanupDatabase;
|
|
11
|
+
exports.setupTestData = setupTestData;
|
|
12
|
+
exports.cleanupTestData = cleanupTestData;
|
|
13
|
+
exports.getDatabasePool = getDatabasePool;
|
|
14
|
+
const mssql_1 = require("mssql");
|
|
15
|
+
// Global connection pool
|
|
16
|
+
let globalPool = null;
|
|
17
|
+
let isConnected = false;
|
|
18
|
+
// Track inserted row IDs for each test for cleanup
|
|
19
|
+
const globalTestData = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* Database configuration loaded from environment variables.
|
|
22
|
+
*/
|
|
23
|
+
const getDatabaseConfig = () => {
|
|
24
|
+
return {
|
|
25
|
+
server: process.env.MSSQL_HOST ?? "localhost",
|
|
26
|
+
port: parseInt(process.env.MSSQL_PORT ?? "1433"),
|
|
27
|
+
database: process.env.MSSQL_DATABASE ?? "testdb",
|
|
28
|
+
user: process.env.MSSQL_USER ?? "sa",
|
|
29
|
+
password: process.env.MSSQL_PASSWORD ?? "",
|
|
30
|
+
pool: {
|
|
31
|
+
max: 30, // Support concurrent test execution
|
|
32
|
+
min: 5,
|
|
33
|
+
idleTimeoutMillis: 30000,
|
|
34
|
+
},
|
|
35
|
+
options: {
|
|
36
|
+
encrypt: process.env.MSSQL_ENCRYPT !== "false",
|
|
37
|
+
trustServerCertificate: process.env.MSSQL_TRUST_CERT !== "false",
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get table configuration from environment variables.
|
|
43
|
+
* Uses a test-specific table name to avoid conflicts with production data.
|
|
44
|
+
*/
|
|
45
|
+
const getTableConfig = () => ({
|
|
46
|
+
tableName: process.env.MSSQL_TEST_TABLE ?? "fhir_resources_test",
|
|
47
|
+
schemaName: process.env.MSSQL_SCHEMA ?? "dbo",
|
|
48
|
+
resourceIdColumn: "id",
|
|
49
|
+
resourceJsonColumn: "json",
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Setup database connection and create the FHIR resources table.
|
|
53
|
+
* This should be called once before running tests.
|
|
54
|
+
*/
|
|
55
|
+
async function setupDatabase() {
|
|
56
|
+
if (isConnected) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const config = getDatabaseConfig();
|
|
60
|
+
// ConnectionPool constructor accepts either a config object or a connection string
|
|
61
|
+
globalPool = new mssql_1.ConnectionPool(config);
|
|
62
|
+
try {
|
|
63
|
+
await globalPool.connect();
|
|
64
|
+
isConnected = true;
|
|
65
|
+
// Create the table if it doesn't exist
|
|
66
|
+
await createTableIfNotExists();
|
|
67
|
+
// Clear any existing test data from previous runs
|
|
68
|
+
await clearTestTable();
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`Failed to setup database: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Cleanup database connection.
|
|
76
|
+
* This should be called once after all tests are complete.
|
|
77
|
+
*/
|
|
78
|
+
async function cleanupDatabase() {
|
|
79
|
+
if (globalPool && isConnected) {
|
|
80
|
+
try {
|
|
81
|
+
await globalPool.close();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Ignore cleanup errors
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
globalPool = null;
|
|
88
|
+
isConnected = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Setup test data by inserting FHIR resources into the table.
|
|
94
|
+
* This should be called before each test case.
|
|
95
|
+
*
|
|
96
|
+
* @param resources - FHIR resources to insert
|
|
97
|
+
* @param testId - Unique test identifier for isolation (prepended to resource IDs)
|
|
98
|
+
*/
|
|
99
|
+
async function setupTestData(resources, testId) {
|
|
100
|
+
if (!globalPool || !isConnected) {
|
|
101
|
+
throw new Error("Database not connected. Call setupDatabase() first.");
|
|
102
|
+
}
|
|
103
|
+
const tableConfig = getTableConfig();
|
|
104
|
+
// Keep track of inserted IDs for cleanup
|
|
105
|
+
const insertedIds = [];
|
|
106
|
+
// Insert test resources with test_id for isolation
|
|
107
|
+
for (let i = 0; i < resources.length; i++) {
|
|
108
|
+
const resource = resources[i];
|
|
109
|
+
try {
|
|
110
|
+
const insertSql = `
|
|
111
|
+
INSERT INTO [${tableConfig.schemaName}].[${tableConfig.tableName}]
|
|
112
|
+
([resource_type], [${tableConfig.resourceJsonColumn}], [test_id])
|
|
113
|
+
OUTPUT INSERTED.[${tableConfig.resourceIdColumn}]
|
|
114
|
+
VALUES (@resource_type, @json, @test_id)
|
|
115
|
+
`;
|
|
116
|
+
const insertRequest = new mssql_1.Request(globalPool);
|
|
117
|
+
insertRequest.input("resource_type", resource.resourceType);
|
|
118
|
+
insertRequest.input("json", JSON.stringify(resource));
|
|
119
|
+
insertRequest.input("test_id", testId);
|
|
120
|
+
const result = await insertRequest.query(insertSql);
|
|
121
|
+
const insertedId = result.recordset[0]?.[tableConfig.resourceIdColumn];
|
|
122
|
+
if (insertedId) {
|
|
123
|
+
insertedIds.push(insertedId);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
throw new Error(`Failed to insert resource ${resource.id ?? `at index ${i}`}: ${error instanceof Error ? error.message : String(error)}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Store inserted IDs for cleanup (using a Map keyed by testId)
|
|
131
|
+
if (!globalTestData.has(testId)) {
|
|
132
|
+
globalTestData.set(testId, []);
|
|
133
|
+
}
|
|
134
|
+
const testData = globalTestData.get(testId);
|
|
135
|
+
if (testData) {
|
|
136
|
+
testData.push(...insertedIds);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Cleanup test data by removing resources for a specific test.
|
|
141
|
+
* This should be called after each test case.
|
|
142
|
+
*
|
|
143
|
+
* @param testId - Unique test identifier to clean up
|
|
144
|
+
*/
|
|
145
|
+
async function cleanupTestData(testId) {
|
|
146
|
+
if (!globalPool || !isConnected) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const tableConfig = getTableConfig();
|
|
150
|
+
const tableName = `[${tableConfig.schemaName}].[${tableConfig.tableName}]`;
|
|
151
|
+
try {
|
|
152
|
+
// Check if table exists first
|
|
153
|
+
const checkTableSql = `
|
|
154
|
+
SELECT COUNT(*) as table_count
|
|
155
|
+
FROM sys.tables t
|
|
156
|
+
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
157
|
+
WHERE t.name = '${tableConfig.tableName}' AND s.name = '${tableConfig.schemaName}'
|
|
158
|
+
`;
|
|
159
|
+
const checkRequest = new mssql_1.Request(globalPool);
|
|
160
|
+
const checkResult = await checkRequest.query(checkTableSql);
|
|
161
|
+
const tableExists = checkResult.recordset[0]?.table_count > 0;
|
|
162
|
+
if (!tableExists) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Delete rows by test_id
|
|
166
|
+
const deleteRequest = new mssql_1.Request(globalPool);
|
|
167
|
+
deleteRequest.input("test_id", testId);
|
|
168
|
+
await deleteRequest.query(`DELETE FROM ${tableName} WHERE [test_id] = @test_id`);
|
|
169
|
+
// Clean up the tracking data
|
|
170
|
+
globalTestData.delete(testId);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
// Don't silently ignore cleanup failures - they cause subsequent test failures
|
|
174
|
+
throw new Error(`Failed to clean up test data: ${error instanceof Error ? error.message : String(error)}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Clear all data from the test table.
|
|
179
|
+
* This should be called once before running tests to ensure a clean state.
|
|
180
|
+
*/
|
|
181
|
+
async function clearTestTable() {
|
|
182
|
+
if (!globalPool) {
|
|
183
|
+
throw new Error("Database not connected");
|
|
184
|
+
}
|
|
185
|
+
const tableConfig = getTableConfig();
|
|
186
|
+
const tableName = `[${tableConfig.schemaName}].[${tableConfig.tableName}]`;
|
|
187
|
+
try {
|
|
188
|
+
// Check if table exists first
|
|
189
|
+
const checkTableSql = `
|
|
190
|
+
SELECT COUNT(*) as table_count
|
|
191
|
+
FROM sys.tables t
|
|
192
|
+
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
193
|
+
WHERE t.name = '${tableConfig.tableName}' AND s.name = '${tableConfig.schemaName}'
|
|
194
|
+
`;
|
|
195
|
+
const checkRequest = new mssql_1.Request(globalPool);
|
|
196
|
+
const checkResult = await checkRequest.query(checkTableSql);
|
|
197
|
+
const tableExists = checkResult.recordset[0]?.table_count > 0;
|
|
198
|
+
if (!tableExists) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Truncate the table to remove all data
|
|
202
|
+
const truncateRequest = new mssql_1.Request(globalPool);
|
|
203
|
+
await truncateRequest.query(`TRUNCATE TABLE ${tableName}`);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
throw new Error(`Failed to clear test table: ${error instanceof Error ? error.message : String(error)}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Create the FHIR resources table if it doesn't exist.
|
|
211
|
+
*/
|
|
212
|
+
async function createTableIfNotExists() {
|
|
213
|
+
if (!globalPool) {
|
|
214
|
+
throw new Error("Database not connected");
|
|
215
|
+
}
|
|
216
|
+
const tableConfig = getTableConfig();
|
|
217
|
+
const tableName = `[${tableConfig.schemaName}].[${tableConfig.tableName}]`;
|
|
218
|
+
try {
|
|
219
|
+
// Check if table exists
|
|
220
|
+
const checkTableSql = `
|
|
221
|
+
SELECT COUNT(*) as table_count
|
|
222
|
+
FROM sys.tables t
|
|
223
|
+
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
224
|
+
WHERE t.name = '${tableConfig.tableName}' AND s.name = '${tableConfig.schemaName}'
|
|
225
|
+
`;
|
|
226
|
+
const checkRequest = new mssql_1.Request(globalPool);
|
|
227
|
+
const checkResult = await checkRequest.query(checkTableSql);
|
|
228
|
+
const tableExists = checkResult.recordset[0]?.table_count > 0;
|
|
229
|
+
if (tableExists) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Create test table with test_id column for concurrent test isolation
|
|
233
|
+
const createTableSql = `
|
|
234
|
+
CREATE TABLE ${tableName} (
|
|
235
|
+
[${tableConfig.resourceIdColumn}] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
|
|
236
|
+
[resource_type] NVARCHAR(64) NOT NULL,
|
|
237
|
+
[${tableConfig.resourceJsonColumn}] NVARCHAR(MAX) NOT NULL,
|
|
238
|
+
[test_id] NVARCHAR(255) NOT NULL
|
|
239
|
+
)
|
|
240
|
+
`;
|
|
241
|
+
const createRequest = new mssql_1.Request(globalPool);
|
|
242
|
+
await createRequest.query(createTableSql);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
throw new Error(`Failed to create table: ${error instanceof Error ? error.message : String(error)}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get the current database connection pool.
|
|
250
|
+
* Used by test utilities that need direct database access.
|
|
251
|
+
*/
|
|
252
|
+
function getDatabasePool() {
|
|
253
|
+
if (!globalPool || !isConnected) {
|
|
254
|
+
throw new Error("Database not connected. Call setupDatabase() first.");
|
|
255
|
+
}
|
|
256
|
+
return globalPool;
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/tests/utils/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Vitest test generator for SQL-on-FHIR test definitions.
|
|
3
|
+
*
|
|
4
|
+
* Creates Vitest test suites dynamically at runtime without generating physical files.
|
|
5
|
+
* Each SQL-on-FHIR JSON test file becomes a describe block with individual it blocks
|
|
6
|
+
* for each test case. Results are collected for report generation.
|
|
7
|
+
*/
|
|
8
|
+
import type { TestReport } from "./types";
|
|
9
|
+
declare global {
|
|
10
|
+
var testResults: TestReport | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Dynamic test generator that creates Vitest tests at runtime.
|
|
14
|
+
*/
|
|
15
|
+
export declare class DynamicVitestGenerator {
|
|
16
|
+
/**
|
|
17
|
+
* Load and generate tests for a single SQL-on-FHIR test file.
|
|
18
|
+
*/
|
|
19
|
+
generateTestsFromFile(filePath: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Load and generate tests for all JSON files in a directory.
|
|
22
|
+
*/
|
|
23
|
+
generateTestsFromDirectory(directoryPath: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Generate a Vitest test suite for a SQL-on-FHIR test definition.
|
|
26
|
+
*
|
|
27
|
+
* @param testSuite The test suite definition
|
|
28
|
+
* @param suiteName The display name for Vitest (e.g., "basic")
|
|
29
|
+
* @param reportFileName The filename for the test report (e.g., "basic.json")
|
|
30
|
+
*/
|
|
31
|
+
private generateTestSuite;
|
|
32
|
+
/**
|
|
33
|
+
* Generate a single test case within the current describe block.
|
|
34
|
+
*/
|
|
35
|
+
private generateTestCase;
|
|
36
|
+
/**
|
|
37
|
+
* Build hierarchical test name with suite prefix and optional tags.
|
|
38
|
+
*/
|
|
39
|
+
private buildTestName;
|
|
40
|
+
/**
|
|
41
|
+
* Generate a test that expects an error.
|
|
42
|
+
*/
|
|
43
|
+
private generateErrorTest;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a test that expects successful execution.
|
|
46
|
+
*/
|
|
47
|
+
private generateSuccessTest;
|
|
48
|
+
/**
|
|
49
|
+
* Clear test results.
|
|
50
|
+
*/
|
|
51
|
+
clearTestResults(): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create and run dynamic tests for SQL-on-FHIR test definitions.
|
|
55
|
+
* This function should be called from a Vitest test file.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createDynamicTests(testPath: string): DynamicVitestGenerator;
|
|
58
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/tests/utils/generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AAM3D,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC;CACzC;AAED;;GAEG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAW7C;;OAEG;IACH,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAWvD;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAexB;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+C3B;;OAEG;IACH,gBAAgB,IAAI,IAAI;CAKzB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAoB3E"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dynamic Vitest test generator for SQL-on-FHIR test definitions.
|
|
4
|
+
*
|
|
5
|
+
* Creates Vitest test suites dynamically at runtime without generating physical files.
|
|
6
|
+
* Each SQL-on-FHIR JSON test file becomes a describe block with individual it blocks
|
|
7
|
+
* for each test case. Results are collected for report generation.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.DynamicVitestGenerator = void 0;
|
|
11
|
+
exports.createDynamicTests = createDynamicTests;
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
const vitest_1 = require("vitest");
|
|
15
|
+
const parser_1 = require("../../parser");
|
|
16
|
+
const database_js_1 = require("./database.js");
|
|
17
|
+
const sqlOnFhir_1 = require("./sqlOnFhir");
|
|
18
|
+
const testContext_js_1 = require("./testContext.js");
|
|
19
|
+
/**
|
|
20
|
+
* Dynamic test generator that creates Vitest tests at runtime.
|
|
21
|
+
*/
|
|
22
|
+
class DynamicVitestGenerator {
|
|
23
|
+
/**
|
|
24
|
+
* Load and generate tests for a single SQL-on-FHIR test file.
|
|
25
|
+
*/
|
|
26
|
+
generateTestsFromFile(filePath) {
|
|
27
|
+
const testSuiteJson = (0, fs_1.readFileSync)(filePath, "utf8");
|
|
28
|
+
const testSuite = parser_1.ViewDefinitionParser.parseTestSuite(testSuiteJson);
|
|
29
|
+
const suiteName = testSuite.title;
|
|
30
|
+
// Extract filename for report (e.g., "basic.json" from "/path/to/basic.json")
|
|
31
|
+
const fileName = filePath.split("/").pop() ?? filePath;
|
|
32
|
+
this.generateTestSuite(testSuite, suiteName, fileName);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load and generate tests for all JSON files in a directory.
|
|
36
|
+
*/
|
|
37
|
+
generateTestsFromDirectory(directoryPath) {
|
|
38
|
+
const files = (0, fs_1.readdirSync)(directoryPath)
|
|
39
|
+
.filter((file) => file.endsWith(".json"))
|
|
40
|
+
.sort() // Sort to ensure consistent ordering
|
|
41
|
+
.map((file) => (0, path_1.join)(directoryPath, file));
|
|
42
|
+
for (const filePath of files) {
|
|
43
|
+
this.generateTestsFromFile(filePath);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Generate a Vitest test suite for a SQL-on-FHIR test definition.
|
|
48
|
+
*
|
|
49
|
+
* @param testSuite The test suite definition
|
|
50
|
+
* @param suiteName The display name for Vitest (e.g., "basic")
|
|
51
|
+
* @param reportFileName The filename for the test report (e.g., "basic.json")
|
|
52
|
+
*/
|
|
53
|
+
generateTestSuite(testSuite, suiteName, reportFileName) {
|
|
54
|
+
const suiteResults = [];
|
|
55
|
+
(0, vitest_1.describe)(suiteName, () => {
|
|
56
|
+
(0, vitest_1.beforeAll)(async () => {
|
|
57
|
+
await (0, database_js_1.setupDatabase)();
|
|
58
|
+
});
|
|
59
|
+
(0, vitest_1.afterAll)(async () => {
|
|
60
|
+
await (0, database_js_1.cleanupDatabase)();
|
|
61
|
+
// Store results for report generation using the filename as the key
|
|
62
|
+
if (typeof global !== "undefined") {
|
|
63
|
+
global.testResults = global.testResults ?? {};
|
|
64
|
+
global.testResults[reportFileName] = { tests: suiteResults };
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// Note: beforeEach/afterEach are handled per-test for parallel execution
|
|
68
|
+
// Generate individual test cases
|
|
69
|
+
for (const testCase of testSuite.tests) {
|
|
70
|
+
this.generateTestCase(testCase, suiteResults, suiteName, testSuite);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generate a single test case within the current describe block.
|
|
76
|
+
*/
|
|
77
|
+
generateTestCase(testCase, suiteResults, suiteName, testSuite) {
|
|
78
|
+
const testName = this.buildTestName(suiteName, testCase);
|
|
79
|
+
if (testCase.expectError) {
|
|
80
|
+
this.generateErrorTest(testName, testCase, suiteResults, testSuite);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.generateSuccessTest(testName, testCase, suiteResults, testSuite);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build hierarchical test name with suite prefix and optional tags.
|
|
88
|
+
*/
|
|
89
|
+
buildTestName(suiteName, testCase) {
|
|
90
|
+
const formatTag = (tag) => `#${tag}`;
|
|
91
|
+
const tags = testCase.tags
|
|
92
|
+
? ` ${testCase.tags.map(formatTag).join(" ")}`
|
|
93
|
+
: "";
|
|
94
|
+
return `(${suiteName}) ${testCase.title}${tags}`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Generate a test that expects an error.
|
|
98
|
+
*/
|
|
99
|
+
generateErrorTest(testName, testCase, suiteResults, testSuite) {
|
|
100
|
+
vitest_1.it.concurrent(testName, async () => {
|
|
101
|
+
const testId = (0, testContext_js_1.generateTestId)();
|
|
102
|
+
try {
|
|
103
|
+
await (0, database_js_1.setupTestData)(testSuite.resources, testId);
|
|
104
|
+
await (0, sqlOnFhir_1.executeViewDefinition)(testCase.view, testId);
|
|
105
|
+
// If we get here, the test should have failed but didn't
|
|
106
|
+
const errorMessage = "Expected an error but the test passed";
|
|
107
|
+
suiteResults.push({
|
|
108
|
+
name: testCase.title, // Use plain title for report
|
|
109
|
+
result: { passed: false, error: errorMessage },
|
|
110
|
+
});
|
|
111
|
+
vitest_1.expect.fail(errorMessage);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Test passed - we expected an error
|
|
115
|
+
suiteResults.push({
|
|
116
|
+
name: testCase.title, // Use plain title for report
|
|
117
|
+
result: { passed: true },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await (0, database_js_1.cleanupTestData)(testId);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Generate a test that expects successful execution.
|
|
127
|
+
*/
|
|
128
|
+
generateSuccessTest(testName, testCase, suiteResults, testSuite) {
|
|
129
|
+
vitest_1.it.concurrent(testName, async () => {
|
|
130
|
+
const testId = (0, testContext_js_1.generateTestId)();
|
|
131
|
+
try {
|
|
132
|
+
await (0, database_js_1.setupTestData)(testSuite.resources, testId);
|
|
133
|
+
const result = await (0, sqlOnFhir_1.executeViewDefinition)(testCase.view, testId);
|
|
134
|
+
const passed = (0, sqlOnFhir_1.compareResults)(result.results, testCase.expect || [], testCase.expectColumns, result.columns);
|
|
135
|
+
if (!passed) {
|
|
136
|
+
const errorMessage = `Results don't match. Expected: ${JSON.stringify(testCase.expect)}, Actual: ${JSON.stringify(result.results)}`;
|
|
137
|
+
suiteResults.push({
|
|
138
|
+
name: testCase.title, // Use plain title for report
|
|
139
|
+
result: { passed: false, error: errorMessage },
|
|
140
|
+
});
|
|
141
|
+
vitest_1.expect.fail(errorMessage);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
suiteResults.push({
|
|
145
|
+
name: testCase.title, // Use plain title for report
|
|
146
|
+
result: { passed: true },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
(0, vitest_1.expect)(passed).toBe(true);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
153
|
+
suiteResults.push({
|
|
154
|
+
name: testCase.title, // Use plain title for report
|
|
155
|
+
result: { passed: false, error: errorMessage },
|
|
156
|
+
});
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
await (0, database_js_1.cleanupTestData)(testId);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Clear test results.
|
|
166
|
+
*/
|
|
167
|
+
clearTestResults() {
|
|
168
|
+
if (typeof global !== "undefined") {
|
|
169
|
+
global.testResults = {};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.DynamicVitestGenerator = DynamicVitestGenerator;
|
|
174
|
+
/**
|
|
175
|
+
* Create and run dynamic tests for SQL-on-FHIR test definitions.
|
|
176
|
+
* This function should be called from a Vitest test file.
|
|
177
|
+
*/
|
|
178
|
+
function createDynamicTests(testPath) {
|
|
179
|
+
const generator = new DynamicVitestGenerator();
|
|
180
|
+
// Clear any previous results
|
|
181
|
+
generator.clearTestResults();
|
|
182
|
+
// Determine if testPath is a file or directory
|
|
183
|
+
const stat = (0, fs_1.statSync)(testPath);
|
|
184
|
+
if (stat.isDirectory()) {
|
|
185
|
+
generator.generateTestsFromDirectory(testPath);
|
|
186
|
+
}
|
|
187
|
+
else if (stat.isFile() && testPath.endsWith(".json")) {
|
|
188
|
+
generator.generateTestsFromFile(testPath);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
throw new Error(`Invalid test path: ${testPath}. Must be a JSON file or directory containing JSON files.`);
|
|
192
|
+
}
|
|
193
|
+
return generator;
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/tests/utils/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Vitest reporter for SQL-on-FHIR test result collection.
|
|
3
|
+
*
|
|
4
|
+
* Collects test results during Vitest execution and formats them according
|
|
5
|
+
* to the FHIR sql-on-fhir-v2 test report schema. Results are stored globally
|
|
6
|
+
* and can be accessed after test completion for report generation.
|
|
7
|
+
*/
|
|
8
|
+
import type { RunnerTestFile } from "vitest";
|
|
9
|
+
import type { Reporter } from "vitest/reporters";
|
|
10
|
+
export interface SqlOnFhirReporterOptions {
|
|
11
|
+
/** Path to write the test report JSON file */
|
|
12
|
+
outputPath?: string;
|
|
13
|
+
/** Whether to write the report file automatically after tests complete */
|
|
14
|
+
autoWriteReport?: boolean;
|
|
15
|
+
/** Whether to print a summary of test results to console */
|
|
16
|
+
printSummary?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Custom Vitest reporter that collects SQL-on-FHIR test results.
|
|
20
|
+
*/
|
|
21
|
+
declare class SqlOnFhirReporter implements Reporter {
|
|
22
|
+
private readonly options;
|
|
23
|
+
private testReport;
|
|
24
|
+
constructor(options?: SqlOnFhirReporterOptions);
|
|
25
|
+
/**
|
|
26
|
+
* Called when all tests have finished running.
|
|
27
|
+
* @deprecated use onTestRunEnd instead
|
|
28
|
+
*/
|
|
29
|
+
onFinished(files?: RunnerTestFile[], _errors?: unknown[], _coverage?: unknown): void;
|
|
30
|
+
/**
|
|
31
|
+
* Print a summary of test results to the console.
|
|
32
|
+
*/
|
|
33
|
+
private printTestSummary;
|
|
34
|
+
/**
|
|
35
|
+
* Calculate test statistics from Vitest task results.
|
|
36
|
+
*/
|
|
37
|
+
private calculateTestStatistics;
|
|
38
|
+
/**
|
|
39
|
+
* Recursively count test results in a task.
|
|
40
|
+
*/
|
|
41
|
+
private countTestsInTask;
|
|
42
|
+
/**
|
|
43
|
+
* Write the test report to a JSON file.
|
|
44
|
+
*/
|
|
45
|
+
writeReport(outputPath: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Collect test results from Vitest task results as fallback.
|
|
48
|
+
* Groups tests by their source file (e.g., "basic.json", "collection.json").
|
|
49
|
+
*/
|
|
50
|
+
private collectFromVitestTasks;
|
|
51
|
+
/**
|
|
52
|
+
* Collect tests from the parent "SQL on FHIR compliance tests" suite.
|
|
53
|
+
* Processes child suites and groups tests by filename.
|
|
54
|
+
*/
|
|
55
|
+
private collectTestsFromParentSuite;
|
|
56
|
+
/**
|
|
57
|
+
* Collect test results from a test suite.
|
|
58
|
+
*
|
|
59
|
+
* Note: This is a fallback mechanism. The primary test result collection
|
|
60
|
+
* happens in the DynamicVitestGenerator which stores results in global.testResults.
|
|
61
|
+
* This method extracts the plain test title from the formatted test name.
|
|
62
|
+
*
|
|
63
|
+
* @param suite The test suite to collect from
|
|
64
|
+
* @param recursive Whether to recursively collect from nested suites
|
|
65
|
+
*/
|
|
66
|
+
private collectTestsFromSuite;
|
|
67
|
+
/**
|
|
68
|
+
* Extract the plain test title from a formatted test name.
|
|
69
|
+
* Formatted: "(suite) title #tag1 #tag2"
|
|
70
|
+
* Plain: "title"
|
|
71
|
+
*/
|
|
72
|
+
private extractPlainTitle;
|
|
73
|
+
/**
|
|
74
|
+
* Clear the collected test results.
|
|
75
|
+
*/
|
|
76
|
+
clearResults(): void;
|
|
77
|
+
onInit?(_ctx: any): void;
|
|
78
|
+
onUserConsoleLog?(_log: any): void;
|
|
79
|
+
onWatcherStart?(): void;
|
|
80
|
+
onWatcherRerun?(_files: string[], _trigger?: string): void;
|
|
81
|
+
}
|
|
82
|
+
export default SqlOnFhirReporter;
|
|
83
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../../src/tests/utils/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGjD,MAAM,WAAW,wBAAwB;IACvC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,cAAM,iBAAkB,YAAW,QAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,UAAU,CAAkB;gBAExB,OAAO,GAAE,wBAA6B;IASlD;;;OAGG;IACH,UAAU,CACR,KAAK,CAAC,EAAE,cAAc,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,EAAE,EACnB,SAAS,CAAC,EAAE,OAAO,GAClB,IAAI;IAsBP;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA6B/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAarC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAoBnC;;;;;;;;;OASG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,YAAY,IAAI,IAAI;IAQpB,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAKxB,gBAAgB,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAIlC,cAAc,CAAC,IAAI,IAAI;IAIvB,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAI3D;AAGD,eAAe,iBAAiB,CAAC"}
|