us_core_test_kit 0.11.0 → 0.11.1
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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19c0ab03440b94688b25fff04431c7ca891b45ff474517595a6657203cde5b98
|
4
|
+
data.tar.gz: b13607fd2d36f35ea718cb2984677506bee66c7cd11946b9da65553d624fe8d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0f264d4c176cff39da75e135dacab88009349bd60083fdb9aea59d227de321461b6207d9ebceb03ff17fcb3f2d3294e2c1e60cca5c4e7e327c96cd255360b73
|
7
|
+
data.tar.gz: 47c6d483549723b3a76f62b5838c5e80428f85345d21d0dbed372f366b98c6d63dca6bcc076a76c9469cab00ccc51a777d1b032a9b24c260d11f3288f20ae782
|
@@ -22,7 +22,7 @@ module USCoreTestKit
|
|
22
22
|
"No #{resource_type} reads found"
|
23
23
|
previous_resources_for_reads = previous_request_resources.values.flatten
|
24
24
|
|
25
|
-
resource_specific_granular_scope_search_params.each do |scope|
|
25
|
+
resource_specific_granular_scope_search_params.each do |scope|
|
26
26
|
current_scope = granular_scopes.find {|granular| granular.include?(scope[:name]) && granular.include?(scope[:value])}
|
27
27
|
|
28
28
|
resource_matching_scope = previous_resources_for_reads.find do |prev_resource|
|
@@ -37,19 +37,26 @@ module USCoreTestKit
|
|
37
37
|
end
|
38
38
|
|
39
39
|
nonmatching_resource = previous_resources_for_reads.find do |prev_resource|
|
40
|
-
resource_specific_granular_scope_search_params.none? do |scope|
|
40
|
+
resource_specific_granular_scope_search_params.none? do |scope|
|
41
41
|
resource_matches_param?(prev_resource, scope[:name], scope[:value])
|
42
42
|
end
|
43
43
|
end
|
44
44
|
if nonmatching_resource
|
45
45
|
fhir_read resource_type, nonmatching_resource.id
|
46
46
|
assert (response && response[:status]) != 200, "Server incorrectly responded with a successful status, read should fail due to scopes."
|
47
|
-
|
47
|
+
|
48
|
+
begin
|
49
|
+
res = resource
|
50
|
+
rescue NoMethodError
|
51
|
+
res = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
assert (!res || res.resourceType == 'OperationOutcome'), "Read shall fail due to scopes. Server shall return 4xx status code with an optional OperationOutcome payload."
|
48
55
|
else
|
49
56
|
info "Unable to find a resource that does not match scopes."
|
50
57
|
end
|
51
58
|
end
|
52
|
-
|
59
|
+
|
53
60
|
def load_previous_requests
|
54
61
|
params = metadata.searches.first[:names]
|
55
62
|
search_params_as_hash = params.each_with_object({}) do |name, hash|
|
@@ -14,221 +14,7 @@ module USCoreTestKit
|
|
14
14
|
def perform_must_support_test(resources)
|
15
15
|
skip_if resources.blank?, "No #{resource_type} resources were found"
|
16
16
|
|
17
|
-
|
18
|
-
missing_slices(resources)
|
19
|
-
missing_extensions(resources)
|
20
|
-
|
21
|
-
handle_must_support_choices if metadata.must_supports[:choices].present?
|
22
|
-
|
23
|
-
if (missing_elements + missing_slices + missing_extensions).length.zero?
|
24
|
-
pass
|
25
|
-
end
|
26
|
-
skip "Could not find #{missing_must_support_strings.join(', ')} in the #{resources.length} " \
|
27
|
-
"provided #{resource_type} resource(s)"
|
28
|
-
end
|
29
|
-
|
30
|
-
def handle_must_support_choices
|
31
|
-
missing_elements.delete_if do |element|
|
32
|
-
choices = metadata.must_supports[:choices].find { |choice| choice[:paths]&.include?(element[:path]) }
|
33
|
-
is_any_choice_supported?(choices)
|
34
|
-
end
|
35
|
-
|
36
|
-
missing_extensions.delete_if do |extension|
|
37
|
-
choices = metadata.must_supports[:choices].find { |choice| choice[:extension_ids]&.include?(extension[:id]) }
|
38
|
-
is_any_choice_supported?(choices)
|
39
|
-
end
|
40
|
-
|
41
|
-
missing_slices.delete_if do |slice|
|
42
|
-
choices = metadata.must_supports[:choices].find { |choice| choice[:slice_names]&.include?(slice[:name]) }
|
43
|
-
is_any_choice_supported?(choices)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def is_any_choice_supported? (choices)
|
48
|
-
choices.present? &&
|
49
|
-
(
|
50
|
-
choices[:paths]&.any? { |path| missing_elements.none? { |element| element[:path] == path } } ||
|
51
|
-
choices[:extension_ids]&.any? { |extension_id| missing_extensions.none? { |extension| extension[:id] == extension_id} } ||
|
52
|
-
choices[:slice_names]&.any? { |slice_name| missing_slices.none? { |slice| slice[:name] == slice_name} }
|
53
|
-
)
|
54
|
-
end
|
55
|
-
|
56
|
-
def missing_must_support_strings
|
57
|
-
missing_elements.map { |element_definition| missing_element_string(element_definition) } +
|
58
|
-
missing_slices.map { |slice_definition| slice_definition[:slice_id] } +
|
59
|
-
missing_extensions.map { |extension_definition| extension_definition[:id] }
|
60
|
-
end
|
61
|
-
|
62
|
-
def missing_element_string(element_definition)
|
63
|
-
if element_definition[:fixed_value].present?
|
64
|
-
"#{element_definition[:path]}:#{element_definition[:fixed_value]}"
|
65
|
-
else
|
66
|
-
element_definition[:path]
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def exclude_uscdi_only_test?
|
71
|
-
config.options[:exclude_uscdi_only_test] == true
|
72
|
-
end
|
73
|
-
|
74
|
-
def must_support_extensions
|
75
|
-
if exclude_uscdi_only_test?
|
76
|
-
metadata.must_supports[:extensions].reject{ |extension| extension[:uscdi_only] }
|
77
|
-
else
|
78
|
-
metadata.must_supports[:extensions]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def missing_extensions(resources = [])
|
83
|
-
@missing_extensions ||=
|
84
|
-
must_support_extensions.select do |extension_definition|
|
85
|
-
resources.none? do |resource|
|
86
|
-
path = extension_definition[:path]
|
87
|
-
|
88
|
-
if path == 'extension'
|
89
|
-
resource.extension.any? { |extension| extension.url == extension_definition[:url] }
|
90
|
-
else
|
91
|
-
extension = find_a_value_at(resource, path) do |el|
|
92
|
-
el.url == extension_definition[:url]
|
93
|
-
end
|
94
|
-
|
95
|
-
extension.present?
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def must_support_elements
|
102
|
-
if exclude_uscdi_only_test?
|
103
|
-
metadata.must_supports[:elements].reject{ |element| element[:uscdi_only] }
|
104
|
-
else
|
105
|
-
metadata.must_supports[:elements]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def missing_elements(resources = [])
|
110
|
-
@missing_elements ||= find_missing_elements(resources, must_support_elements)
|
111
|
-
@missing_elements
|
112
|
-
end
|
113
|
-
|
114
|
-
def find_missing_elements(resources, must_support_elements)
|
115
|
-
must_support_elements.select do |element_definition|
|
116
|
-
resources.none? do |resource|
|
117
|
-
path = element_definition[:path]
|
118
|
-
ms_extension_urls = must_support_extensions.select { |ex| ex[:path] == "#{path}.extension" }
|
119
|
-
.map { |ex| ex[:url] }
|
120
|
-
|
121
|
-
value_found = find_a_value_at(resource, path) do |value|
|
122
|
-
if value.instance_of?(USCoreTestKit::PrimitiveType) && ms_extension_urls.present?
|
123
|
-
urls = value.extension&.map(&:url)
|
124
|
-
has_ms_extension = (urls & ms_extension_urls).present?
|
125
|
-
end
|
126
|
-
|
127
|
-
unless has_ms_extension
|
128
|
-
value = value.value if value.instance_of?(USCoreTestKit::PrimitiveType)
|
129
|
-
value_without_extensions =
|
130
|
-
value.respond_to?(:to_hash) ? value.to_hash.reject { |key, _| key == 'extension' } : value
|
131
|
-
end
|
132
|
-
|
133
|
-
(has_ms_extension || value_without_extensions.present? || value_without_extensions == false) &&
|
134
|
-
(element_definition[:fixed_value].blank? || value == element_definition[:fixed_value])
|
135
|
-
end
|
136
|
-
# Note that false.present? => false, which is why we need to add this extra check
|
137
|
-
value_found.present? || value_found == false
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def must_support_slices
|
143
|
-
if exclude_uscdi_only_test?
|
144
|
-
metadata.must_supports[:slices].reject{ |slice| slice[:uscdi_only] }
|
145
|
-
else
|
146
|
-
metadata.must_supports[:slices]
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def missing_slices(resources = [])
|
151
|
-
@missing_slices ||=
|
152
|
-
must_support_slices.select do |slice|
|
153
|
-
resources.none? do |resource|
|
154
|
-
path = slice[:path] # .delete_suffix('[x]')
|
155
|
-
find_slice(resource, path, slice[:discriminator]).present?
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def find_slice(resource, path, discriminator)
|
161
|
-
find_a_value_at(resource, path) do |element|
|
162
|
-
case discriminator[:type]
|
163
|
-
when 'patternCodeableConcept'
|
164
|
-
coding_path = discriminator[:path].present? ? "#{discriminator[:path]}.coding" : 'coding'
|
165
|
-
find_a_value_at(element, coding_path) do |coding|
|
166
|
-
coding.code == discriminator[:code] && coding.system == discriminator[:system]
|
167
|
-
end
|
168
|
-
when 'patternCoding'
|
169
|
-
coding_path = discriminator[:path].present? ? discriminator[:path] : ''
|
170
|
-
find_a_value_at(element, coding_path) do |coding|
|
171
|
-
coding.code == discriminator[:code] && coding.system == discriminator[:system]
|
172
|
-
end
|
173
|
-
when 'patternIdentifier'
|
174
|
-
find_a_value_at(element, discriminator[:path]) { |identifier| identifier.system == discriminator[:system] }
|
175
|
-
when 'value'
|
176
|
-
values = discriminator[:values].map { |value| value.merge(path: value[:path].split('.')) }
|
177
|
-
find_slice_by_values(element, values)
|
178
|
-
when 'type'
|
179
|
-
case discriminator[:code]
|
180
|
-
when 'Date'
|
181
|
-
begin
|
182
|
-
Date.parse(element)
|
183
|
-
rescue ArgumentError
|
184
|
-
false
|
185
|
-
end
|
186
|
-
when 'DateTime'
|
187
|
-
begin
|
188
|
-
DateTime.parse(element)
|
189
|
-
rescue ArgumentError
|
190
|
-
false
|
191
|
-
end
|
192
|
-
when 'String'
|
193
|
-
element.is_a? String
|
194
|
-
else
|
195
|
-
element.is_a? FHIR.const_get(discriminator[:code])
|
196
|
-
end
|
197
|
-
when 'requiredBinding'
|
198
|
-
coding_path = discriminator[:path].present? ? "#{discriminator[:path]}.coding" : 'coding'
|
199
|
-
|
200
|
-
find_a_value_at(element, coding_path) do |coding|
|
201
|
-
discriminator[:values].any? { |value| value[:system] == coding.system && value[:code] == coding.code }
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def find_slice_by_values(element, value_definitions)
|
208
|
-
path_prefixes = value_definitions.map { |value_definition| value_definition[:path].first }.uniq
|
209
|
-
Array.wrap(element).find do |el|
|
210
|
-
path_prefixes.all? do |path_prefix|
|
211
|
-
value_definitions_for_path =
|
212
|
-
value_definitions
|
213
|
-
.select { |value_definition| value_definition[:path].first == path_prefix }
|
214
|
-
.each { |value_definition| value_definition[:path].shift }
|
215
|
-
|
216
|
-
find_a_value_at(el, path_prefix) do |el_found|
|
217
|
-
child_element_value_definitions, current_element_value_definitions =
|
218
|
-
value_definitions_for_path.partition { |value_definition| value_definition[:path].present? }
|
219
|
-
|
220
|
-
current_element_values_match =
|
221
|
-
current_element_value_definitions
|
222
|
-
.all? { |value_definition| value_definition[:value] == el_found }
|
223
|
-
|
224
|
-
child_element_values_match =
|
225
|
-
child_element_value_definitions.present? ?
|
226
|
-
find_slice_by_values(el_found, child_element_value_definitions) : true
|
227
|
-
|
228
|
-
current_element_values_match && child_element_values_match
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
17
|
+
skip { assert_must_support_elements_present(resources, nil, metadata:) }
|
232
18
|
end
|
233
19
|
end
|
234
20
|
end
|
@@ -25,7 +25,7 @@ module USCoreTestKit
|
|
25
25
|
|
26
26
|
def verify_practitioner_address
|
27
27
|
references = scratch.dig(:references, 'Practitioner')
|
28
|
-
assert references.any?, 'No
|
28
|
+
assert references.any?, 'No Practitioner references found.'
|
29
29
|
|
30
30
|
@missing_elements = MUST_SUPPORT_ELEMENTS
|
31
31
|
practitioners = []
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: us_core_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen MacVicar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inferno_core
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.6.
|
19
|
+
version: 0.6.8
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.6.
|
26
|
+
version: 0.6.8
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: smart_app_launch_test_kit
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.6.
|
33
|
+
version: 0.6.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.6.
|
40
|
+
version: 0.6.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: tls_test_kit
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|