auscvdrisk_inferno 0.1.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.
@@ -0,0 +1,433 @@
1
+ require_relative '../helpers'
2
+
3
+ module AusCVDRisk
4
+ module PrePopulation
5
+ class Observations < Inferno::TestGroup
6
+ include AusCVDRisk::Helpers
7
+
8
+ title 'Pre-population: Observations'
9
+ id :prepop_observations
10
+
11
+ test do
12
+ optional
13
+ title 'Server declares support for Observation patient search parameter'
14
+
15
+ run do
16
+ fhir_get_capability_statement
17
+
18
+ assert_response_status(200)
19
+ assert_resource_type(:capability_statement)
20
+ capability_statement = resource
21
+
22
+ resource_type = 'Observation'
23
+ parameter_name = 'patient'
24
+
25
+ if check_search_parameter_support(capability_statement, resource_type, parameter_name)
26
+ pass "Server declares support for Observation search parameter: #{parameter_name}"
27
+ else
28
+ assert false, "Server does not declare support for required Observation search parameter: #{parameter_name}"
29
+ end
30
+ end
31
+ end
32
+
33
+ test do
34
+ optional
35
+ title 'Server declares support for Observation code search parameter'
36
+
37
+ run do
38
+ fhir_get_capability_statement
39
+
40
+ assert_response_status(200)
41
+ assert_resource_type(:capability_statement)
42
+ capability_statement = resource
43
+
44
+ resource_type = 'Observation'
45
+ parameter_name = 'code'
46
+
47
+ if check_search_parameter_support(capability_statement, resource_type, parameter_name)
48
+ pass "Server declares support for Observation search parameter: #{parameter_name}"
49
+ else
50
+ assert false, "Server does not declare support for required Observation search parameter: #{parameter_name}"
51
+ end
52
+ end
53
+ end
54
+
55
+ test do
56
+ optional
57
+ title 'Server declares support for Observation status search parameter'
58
+
59
+ run do
60
+ fhir_get_capability_statement
61
+
62
+ assert_response_status(200)
63
+ assert_resource_type(:capability_statement)
64
+ capability_statement = resource
65
+
66
+ resource_type = 'Observation'
67
+ parameter_name = 'status'
68
+
69
+ if check_search_parameter_support(capability_statement, resource_type, parameter_name)
70
+ pass "Server declares support for Observation search parameter: #{parameter_name}"
71
+ else
72
+ assert false, "Server does not declare support for required Observation search parameter: #{parameter_name}"
73
+ end
74
+ end
75
+ end
76
+
77
+ test do
78
+ optional
79
+ title 'Server declares support for Observation _count search parameter'
80
+
81
+ run do
82
+ fhir_get_capability_statement
83
+
84
+ assert_response_status(200)
85
+ assert_resource_type(:capability_statement)
86
+ capability_statement = resource
87
+
88
+ resource_type = 'Observation'
89
+ parameter_name = '_count'
90
+
91
+ # Check for Observation resource specifically
92
+ if check_search_parameter_support(capability_statement, resource_type, parameter_name)
93
+ pass "Server declares support for Observation search parameter: #{parameter_name}"
94
+ end
95
+
96
+ # Check for global search parameters
97
+ if check_global_search_parameter_support(capability_statement, parameter_name)
98
+ pass "Server declares global support for _count search parameter"
99
+ else
100
+ assert false, "Server does not declare support for search parameter: #{parameter_name}"
101
+ end
102
+ end
103
+ end
104
+
105
+ test do
106
+ optional
107
+ title 'Server declares support for Observation _sort search parameter'
108
+
109
+ run do
110
+ fhir_get_capability_statement
111
+
112
+ assert_response_status(200)
113
+ assert_resource_type(:capability_statement)
114
+ capability_statement = resource
115
+
116
+ resource_type = 'Observation'
117
+ parameter_name = '_sort'
118
+
119
+ # Check for Observation resource specifically
120
+ if check_search_parameter_support(capability_statement, resource_type, parameter_name)
121
+ pass "Server declares support for Observation search parameter: #{parameter_name}"
122
+ end
123
+
124
+ # Check for global search parameters
125
+ if check_global_search_parameter_support(capability_statement, parameter_name)
126
+ pass "Server declares global support for _count search parameter"
127
+ else
128
+ assert false, "Server does not declare support for search parameter: #{parameter_name}"
129
+ end
130
+ end
131
+ end
132
+
133
+ test do
134
+ optional
135
+ title 'Server declares support for Observation combined search parameters'
136
+
137
+ run do
138
+ fhir_get_capability_statement
139
+
140
+ assert_response_status(200)
141
+ assert_resource_type(:capability_statement)
142
+ capability_statement = resource
143
+
144
+ resource_type = 'Observation'
145
+ required_params = %w[patient code status _count _sort]
146
+ combined_params = 'patient+code+status+_count+_sort'
147
+
148
+ if check_search_combination_support(capability_statement, resource_type, required_params)
149
+ pass "Server declares support for combined Observation search parameters: #{combined_params}"
150
+ else
151
+ assert false, "Server does not declare support for combined Observation search parameters: #{combined_params}"
152
+ end
153
+ end
154
+ end
155
+
156
+ test do
157
+ optional
158
+ title 'Observation search with patient parameter is successful'
159
+
160
+ input :patient_id,
161
+ title: 'Patient ID',
162
+ description: 'ID of a patient resource on the server'
163
+
164
+ run do
165
+ skip_if patient_id.blank?, 'No patient ID provided'
166
+
167
+ search_params = "patient=#{patient_id}"
168
+
169
+ fhir_search(:observation, params: { patient: patient_id })
170
+
171
+ assert_response_status(200)
172
+ bundle = JSON.parse(response[:body])
173
+ verify_search_parameters_in_self_link(bundle, search_params)
174
+ pass 'Successfully searched for Observations with patient parameter'
175
+ end
176
+ end
177
+
178
+ test do
179
+ optional
180
+ title 'Observation search with code parameter is successful'
181
+
182
+ input :patient_id,
183
+ title: 'Patient ID',
184
+ description: 'ID of a patient resource on the server'
185
+
186
+ run do
187
+ skip_if patient_id.blank?, 'No patient ID provided'
188
+
189
+ # Using LOINC code for total cholesterol as an example
190
+ code = 'http://loinc.org|2093-3'
191
+ search_params = "code=#{code}&patient=#{patient_id}"
192
+
193
+ fhir_search(:observation, params: {
194
+ code: code,
195
+ patient: patient_id
196
+ })
197
+
198
+ assert_response_status(200)
199
+ bundle = JSON.parse(response[:body])
200
+ verify_search_parameters_in_self_link(bundle, search_params)
201
+ pass 'Successfully searched for Observations with code parameter'
202
+ end
203
+ end
204
+
205
+ test do
206
+ optional
207
+ title 'Observation search with status parameter is successful'
208
+
209
+ input :patient_id,
210
+ title: 'Patient ID',
211
+ description: 'ID of a patient resource on the server'
212
+
213
+ run do
214
+ skip_if patient_id.blank?, 'No patient ID provided'
215
+
216
+ status = 'final,amended,corrected'
217
+ search_params = "status=#{status}&patient=#{patient_id}"
218
+
219
+ fhir_search(:observation, params: {
220
+ status: status,
221
+ patient: patient_id
222
+ })
223
+
224
+ assert_response_status(200)
225
+ bundle = JSON.parse(response[:body])
226
+ verify_search_parameters_in_self_link(bundle, search_params)
227
+ pass 'Successfully searched for Observations with status parameter'
228
+ end
229
+ end
230
+
231
+ test do
232
+ optional
233
+ title 'Observation search with _count parameter is successful'
234
+
235
+ input :patient_id,
236
+ title: 'Patient ID',
237
+ description: 'ID of a patient resource on the server'
238
+
239
+ run do
240
+ skip_if patient_id.blank?, 'No patient ID provided'
241
+
242
+ count = 5
243
+ search_params = "_count=#{count}&patient=#{patient_id}"
244
+
245
+ fhir_search(:observation, params: {
246
+ _count: count,
247
+ patient: patient_id
248
+ })
249
+
250
+ assert_response_status(200)
251
+ bundle = JSON.parse(response[:body])
252
+ verify_search_parameters_in_self_link(bundle, search_params)
253
+
254
+ # Verify that no more than _count resources are returned
255
+ if bundle['entry']
256
+ assert bundle['entry'].length <= count, "Server returned more than #{count} resources despite _count parameter"
257
+ end
258
+
259
+ pass 'Successfully searched for Observations with _count parameter'
260
+ end
261
+ end
262
+
263
+ test do
264
+ optional
265
+ title 'Observation search with _sort parameter is successful'
266
+
267
+ input :patient_id,
268
+ title: 'Patient ID',
269
+ description: 'ID of a patient resource on the server'
270
+
271
+ run do
272
+ skip_if patient_id.blank?, 'No patient ID provided'
273
+
274
+ sort = '-date'
275
+ search_params = "_sort=#{sort}&patient=#{patient_id}"
276
+
277
+ fhir_search(:observation, params: {
278
+ _sort: sort,
279
+ patient: patient_id
280
+ })
281
+
282
+ assert_response_status(200)
283
+ bundle = JSON.parse(response[:body])
284
+ verify_search_parameters_in_self_link(bundle, search_params)
285
+
286
+ # Check if entries are sorted by date in descending order
287
+ if bundle['entry'] && bundle['entry'].length > 1
288
+ dates = bundle['entry'].map do |entry|
289
+ next unless entry['resource']['resourceType'] == 'Observation'
290
+ entry['resource']['effectiveDateTime'] ||
291
+ (entry['resource']['effectivePeriod'] && entry['resource']['effectivePeriod']['start']) ||
292
+ entry['resource']['issued']
293
+ end.compact
294
+
295
+ if dates.length > 1
296
+ is_sorted = dates.each_cons(2).all? { |a, b| a >= b }
297
+ assert is_sorted, 'Observations are not properly sorted by date in descending order'
298
+ end
299
+ end
300
+
301
+ pass 'Successfully searched for Observations with _sort parameter'
302
+ end
303
+ end
304
+
305
+ test do
306
+ optional
307
+ title 'Observation search with combined parameters is successful'
308
+
309
+ input :patient_id,
310
+ title: 'Patient ID',
311
+ description: 'ID of a patient resource on the server'
312
+
313
+ run do
314
+ skip_if patient_id.blank?, 'No patient ID provided'
315
+
316
+ # Using LOINC code for total cholesterol as an example
317
+ code = 'http://loinc.org|2093-3'
318
+ status = 'final'
319
+ count = 5
320
+ sort = '-date'
321
+
322
+ search_params = "code=#{code}&status=#{status}&_count=#{count}&_sort=#{sort}&patient=#{patient_id}"
323
+
324
+ fhir_search(:observation, params: {
325
+ code: code,
326
+ status: status,
327
+ _count: count,
328
+ _sort: sort,
329
+ patient: patient_id
330
+ })
331
+
332
+ assert_response_status(200)
333
+ bundle = JSON.parse(response[:body])
334
+ verify_search_parameters_in_self_link(bundle, search_params)
335
+
336
+ # Verify that no more than _count resources are returned
337
+ if bundle['entry']
338
+ assert bundle['entry'].length <= count, "Server returned more than #{count} resources despite _count parameter"
339
+
340
+ # Check if entries are sorted by date in descending order
341
+ if bundle['entry'].length > 1
342
+ dates = bundle['entry'].map do |entry|
343
+ next unless entry['resource']['resourceType'] == 'Observation'
344
+ entry['resource']['effectiveDateTime'] ||
345
+ (entry['resource']['effectivePeriod'] && entry['resource']['effectivePeriod']['start']) ||
346
+ entry['resource']['issued']
347
+ end.compact
348
+
349
+ if dates.length > 1
350
+ is_sorted = dates.each_cons(2).all? { |a, b| a >= b }
351
+ assert is_sorted, 'Observations are not properly sorted by date in descending order'
352
+ end
353
+ end
354
+ end
355
+
356
+ pass 'Successfully searched for Observations with combined parameters'
357
+ end
358
+ end
359
+
360
+ test do
361
+ optional
362
+ title 'Server declares support for CVD Risk Sitting Blood Pressure profile '
363
+
364
+ run do
365
+ fhir_get_capability_statement
366
+
367
+ assert_response_status(200)
368
+ assert_resource_type(:capability_statement)
369
+ capability_statement = resource
370
+
371
+ resource_type = 'Observation'
372
+ profile_url = 'https://www.cvdcheck.org.au/fhir/StructureDefinition/CVDRiskSittingBloodPressure'
373
+
374
+ has_profile = check_capability_statement_for_profile(capability_statement, resource_type, profile_url)
375
+
376
+ if has_profile
377
+ pass "Server declares support for CVD Risk Sitting Blood Pressure profile"
378
+ else
379
+ assert false, "CapabilityStatement does not declare support for CVD Risk Sitting Blood Pressure profile, but this is a SHOULD requirement"
380
+ end
381
+ end
382
+ end
383
+
384
+ test do
385
+ optional
386
+ title 'Server declares support for AU Core Smoking Status profile '
387
+
388
+ run do
389
+ fhir_get_capability_statement
390
+
391
+ assert_response_status(200)
392
+ assert_resource_type(:capability_statement)
393
+ capability_statement = resource
394
+
395
+ resource_type = 'Observation'
396
+ profile_url = 'http://hl7.org.au/fhir/core/StructureDefinition/au-core-smokingstatus'
397
+
398
+ has_profile = check_capability_statement_for_profile(capability_statement, resource_type, profile_url)
399
+
400
+ if has_profile
401
+ pass "Server declares support for AU Core Smoking Status profile"
402
+ else
403
+ assert false, "CapabilityStatement does not declare support for AU Core Smoking Status profile, but this is a SHOULD requirement"
404
+ end
405
+ end
406
+ end
407
+
408
+ test do
409
+ optional
410
+ title 'Server declares support for AU Core Pathology Result profile '
411
+
412
+ run do
413
+ fhir_get_capability_statement
414
+
415
+ assert_response_status(200)
416
+ assert_resource_type(:capability_statement)
417
+ capability_statement = resource
418
+
419
+ resource_type = 'Observation'
420
+ profile_url = 'http://hl7.org.au/fhir/core/StructureDefinition/au-core-diagnosticresult-path'
421
+
422
+ has_profile = check_capability_statement_for_profile(capability_statement, resource_type, profile_url)
423
+
424
+ if has_profile
425
+ pass "Server declares support for AU Core Pathology Result profile"
426
+ else
427
+ assert false, "CapabilityStatement does not declare support for AU Core Pathology Result profile, but this is a SHOULD requirement"
428
+ end
429
+ end
430
+ end
431
+ end
432
+ end
433
+ end
@@ -0,0 +1,57 @@
1
+ require_relative 'metadata'
2
+ require_relative 'context'
3
+ require_relative 'prepop/demographics'
4
+ require_relative 'prepop/diagnoses'
5
+ require_relative 'prepop/medications'
6
+ require_relative 'prepop/observations'
7
+ require_relative 'write_back'
8
+
9
+ module AusCVDRisk
10
+ class Suite < Inferno::TestSuite
11
+ id :auscvdrisk_server
12
+ title 'Aus CVD Risk-i Server Test Suite'
13
+ description <<~DESCRIPTION
14
+ Tests conformance against the requirements for implementing a FHIR service that supports the
15
+ Aus CVD Risk-i Calculator application.
16
+ DESCRIPTION
17
+
18
+ # These inputs will be available to all tests in this suite
19
+ input :url,
20
+ title: 'FHIR Server Base Url'
21
+
22
+ input :credentials,
23
+ title: 'OAuth Credentials',
24
+ type: :oauth_credentials,
25
+ optional: true
26
+
27
+ input :patient_id
28
+
29
+ # All FHIR requests in this suite will use this FHIR client
30
+ fhir_client do
31
+ url :url
32
+ oauth_credentials :credentials if credentials.present?
33
+ headers 'Prefer' => 'handling=strict'
34
+ end
35
+
36
+ # All FHIR validation requests will use this FHIR validator
37
+ fhir_resource_validator do
38
+ igs 'hl7.fhir.au.core#1.0.0', 'igs/auscvdrisk-Iteration3.tgz'
39
+
40
+ cli_context do
41
+ txServer 'https://tx.dev.hl7.org.au/fhir'
42
+ snomedCT '32506021000036107'
43
+ end
44
+
45
+ exclude_message do |message|
46
+ message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
47
+ end
48
+ end
49
+
50
+ group from: :context
51
+ group from: :prepop_demographics
52
+ group from: :prepop_diagnoses
53
+ group from: :prepop_medications
54
+ group from: :prepop_observations
55
+ group from: :write_back
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ module AusCVDRisk
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,89 @@
1
+ require_relative 'helpers'
2
+
3
+ module AusCVDRisk
4
+ class WriteBack < Inferno::TestGroup
5
+ include AusCVDRisk::Helpers
6
+
7
+ title 'Result write-back'
8
+ id :write_back
9
+
10
+ test do
11
+ optional
12
+ title 'Server declares support for CVD Risk Result profile '
13
+
14
+ run do
15
+ fhir_get_capability_statement
16
+
17
+ assert_response_status(200)
18
+ assert_resource_type(:capability_statement)
19
+ capability_statement = resource
20
+
21
+ resource_type = 'Observation'
22
+ profile_url = 'https://www.cvdcheck.org.au/fhir/StructureDefinition/CVDRiskResult'
23
+
24
+ has_profile = check_capability_statement_for_profile(capability_statement, resource_type, profile_url)
25
+
26
+ assert has_profile, "CapabilityStatement does not declare support for CVD Risk Result profile"
27
+ end
28
+ end
29
+
30
+ test do
31
+ optional
32
+ title 'Server supports creating CVD Risk Result resources'
33
+
34
+ input :patient_id,
35
+ title: 'Patient ID',
36
+ description: 'ID of a patient resource on the server'
37
+
38
+ run do
39
+ skip_if patient_id.blank?, 'No patient ID provided'
40
+
41
+ # Create a minimal CVD Risk Result resource
42
+ cvd_risk_result = FHIR::Observation.new(
43
+ status: 'final',
44
+ code: {
45
+ coding: [
46
+ {
47
+ system: 'http://loinc.org',
48
+ code: '79423-0',
49
+ display: 'Cardiovascular disease 5 year risk score'
50
+ }
51
+ ],
52
+ text: 'CVD Risk Score'
53
+ },
54
+ subject: {
55
+ reference: "Patient/#{patient_id}"
56
+ },
57
+ valueQuantity: {
58
+ value: 10.5,
59
+ unit: '%',
60
+ system: 'http://unitsofmeasure.org',
61
+ code: '%'
62
+ },
63
+ effectiveDateTime: Time.now.strftime('%Y-%m-%dT%H:%M:%S%:z'),
64
+ meta: {
65
+ profile: ['https://www.cvdcheck.org.au/fhir/StructureDefinition/CVDRiskResult']
66
+ }
67
+ )
68
+
69
+ fhir_create(cvd_risk_result)
70
+
71
+ # Check if creation was successful (201) or already exists (200)
72
+ assert [200, 201].include?(response[:status]),
73
+ "Expected response status to be 200 or 201, but was #{response[:status]}"
74
+
75
+ # If we got a 201 Created, verify we can read the resource back
76
+ if response[:status] == 201
77
+ # Extract the ID from the Location header or the resource
78
+ created_id = resource&.id
79
+ assert created_id.present?, 'Created resource does not have an ID'
80
+
81
+ # Try to read the created resource
82
+ fhir_read(:observation, created_id)
83
+ assert_response_status(200)
84
+ assert_resource_type(:observation)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
data/lib/auscvdrisk.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative 'auscvdrisk/suite'
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auscvdrisk_inferno
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Australian e-Health Research Centre, CSIRO
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: inferno_core
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.6.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.6.2
26
+ executables: []
27
+ extensions: []
28
+ extra_rdoc_files: []
29
+ files:
30
+ - lib/auscvdrisk.rb
31
+ - lib/auscvdrisk/context.rb
32
+ - lib/auscvdrisk/helpers.rb
33
+ - lib/auscvdrisk/igs/.keep
34
+ - lib/auscvdrisk/igs/README.md
35
+ - lib/auscvdrisk/igs/auscvdrisk-Iteration3.tgz
36
+ - lib/auscvdrisk/igs/put_ig_package_dot_tgz_here
37
+ - lib/auscvdrisk/metadata.rb
38
+ - lib/auscvdrisk/prepop/demographics.rb
39
+ - lib/auscvdrisk/prepop/diagnoses.rb
40
+ - lib/auscvdrisk/prepop/medications.rb
41
+ - lib/auscvdrisk/prepop/observations.rb
42
+ - lib/auscvdrisk/suite.rb
43
+ - lib/auscvdrisk/version.rb
44
+ - lib/auscvdrisk/write_back.rb
45
+ licenses: []
46
+ metadata:
47
+ inferno_test_kit: 'true'
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 3.3.6
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.6.7
63
+ specification_version: 4
64
+ summary: Aus CVD Risk-i Test Kit
65
+ test_files: []