us_core_test_kit 0.8.0 → 0.8.2

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/us_core_test_kit/custom_groups/granted_granular_scopes_test.rb +15 -3
  3. data/lib/us_core_test_kit/generated/v6.1.0/metadata.yml +3 -12
  4. data/lib/us_core_test_kit/generated/v6.1.0/practitioner/metadata.yml +2 -6
  5. data/lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_address_test.rb +32 -0
  6. data/lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_must_support_test.rb +0 -6
  7. data/lib/us_core_test_kit/generated/v6.1.0/practitioner_group.rb +2 -0
  8. data/lib/us_core_test_kit/generated/v6.1.0/smokingstatus/metadata.yml +1 -6
  9. data/lib/us_core_test_kit/generated/v6.1.0/smokingstatus/smokingstatus_must_support_test.rb +1 -1
  10. data/lib/us_core_test_kit/generated/v6.1.0/us_core_test_suite.rb +5 -1
  11. data/lib/us_core_test_kit/generated/v7.0.0/metadata.yml +2 -6
  12. data/lib/us_core_test_kit/generated/v7.0.0/practitioner/metadata.yml +2 -6
  13. data/lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_address_test.rb +32 -0
  14. data/lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_must_support_test.rb +0 -6
  15. data/lib/us_core_test_kit/generated/v7.0.0/practitioner_group.rb +2 -0
  16. data/lib/us_core_test_kit/generator/group_generator.rb +1 -2
  17. data/lib/us_core_test_kit/generator/must_support_metadata_extractor_us_core_6.rb +15 -0
  18. data/lib/us_core_test_kit/generator/must_support_metadata_extractor_us_core_7.rb +4 -1
  19. data/lib/us_core_test_kit/generator/practitioner_address_test_generator.rb +68 -0
  20. data/lib/us_core_test_kit/generator/suite_generator.rb +10 -1
  21. data/lib/us_core_test_kit/generator.rb +6 -0
  22. data/lib/us_core_test_kit/granular_scope_search_test.rb +3 -1
  23. data/lib/us_core_test_kit/must_support_test.rb +25 -22
  24. data/lib/us_core_test_kit/practitioner_address_test.rb +85 -0
  25. data/lib/us_core_test_kit/reference_resolution_test.rb +31 -23
  26. data/lib/us_core_test_kit/search_test.rb +11 -8
  27. data/lib/us_core_test_kit/version.rb +1 -1
  28. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0646308cfd9f7fae1d17b4b4b9c3f1cb3d09b1c6cfd9a649104beb0a65077672'
4
- data.tar.gz: bd6a3a0fa4427eed31e61d93da2b327bb43eaccf9accf5146fb089601a34a22e
3
+ metadata.gz: a96c6f3f861e76af7890dece571af5e3c4ca97a8250438807218ac2affe33fce
4
+ data.tar.gz: 5b005b8775b3855768365acdc237ce371501187102672fbc5058d0214a18dc5f
5
5
  SHA512:
6
- metadata.gz: bceab9b2ccb933f2af3931d342e7b8a86b4c5c258c2f57187d6bffe7c6856916a1d4db4b58878fcd549d3b8354fbacde2191ab6b0062bc361acb988a7fa2938a
7
- data.tar.gz: 031b914039a12f0263230605c6256a57864e4f0780db9379626a207f100adf824bffe03f32f99a55c751e8bced04de27043c1e12237d68c269bd85a9ea4358bb
6
+ metadata.gz: b210de56a48140207534ad50251d849da40023352e34d71b0e4d73d05a307ec02e5c2c04a81e6b40120246ab50e6e68ff8f138b54134c1c46c94906b453ec36a
7
+ data.tar.gz: e43c0f334ee18d8b7861328890ed0bc791bc4ef3175d439fafb37b0ecda10222b4e5e5100fd00307ce3f92abaaed35450845b556d6dc3e81e79530fea37328dd
@@ -13,18 +13,30 @@ module USCoreTestKit
13
13
  .options[:required_scopes]
14
14
  .map { |scope| scope[scope.index('/') + 1, scope.length] }
15
15
 
16
+ required_granular_regexes =
17
+ required_granular_scopes.flat_map do |scope|
18
+ [
19
+ Regexp.new(Regexp.quote(scope).gsub(".rs", ".r?s")),
20
+ Regexp.new(Regexp.quote(scope).gsub(".rs", ".rs?"))
21
+ ]
22
+ end
23
+
16
24
  received_granular_scopes =
17
25
  received_scopes
18
26
  .split(' ')
19
27
  .select { |scope| scope.include? '?' }
20
28
  .map { |scope| scope[scope.index('/') + 1, scope.length] }
21
29
 
22
- missing_scopes = required_granular_scopes - received_granular_scopes
30
+ missing_scopes =
31
+ required_granular_regexes
32
+ .reject do |required_scope|
33
+ received_granular_scopes.any? { |received_scope| received_scope.match?(required_scope) }
34
+ end
23
35
 
24
- wrapped_missing_scopes = missing_scopes.map { |scope| "`#{scope}`" }
36
+ wrapped_missing_scopes = missing_scopes.map { |scope| "`#{scope.source}`" }
25
37
 
26
38
  assert missing_scopes.empty?,
27
- "The following granular scopes were not granted: #{wrapped_missing_scopes.to_sentence}"
39
+ "Granular scopes matching the following were not matched: #{wrapped_missing_scopes.to_sentence}"
28
40
 
29
41
  granular_scope_resource_types =
30
42
  required_granular_scopes
@@ -7111,12 +7111,6 @@
7111
7111
  :path: ''
7112
7112
  :code: social-history
7113
7113
  :system: http://terminology.hl7.org/CodeSystem/observation-category
7114
- - :slice_id: Observation.effective[x]:effectiveDateTime
7115
- :slice_name: effectiveDateTime
7116
- :path: effective[x]
7117
- :discriminator:
7118
- :type: type
7119
- :code: DateTime
7120
7114
  :elements:
7121
7115
  - :path: status
7122
7116
  - :path: category
@@ -7128,6 +7122,7 @@
7128
7122
  - http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient
7129
7123
  - :path: valueCodeableConcept
7130
7124
  :original_path: value[x]
7125
+ - :path: effective[x]
7131
7126
  :mandatory_elements:
7132
7127
  - Observation.status
7133
7128
  - Observation.category
@@ -10732,12 +10727,6 @@
10732
10727
  - :path: telecom
10733
10728
  - :path: telecom.system
10734
10729
  - :path: telecom.value
10735
- - :path: address
10736
- - :path: address.line
10737
- - :path: address.city
10738
- - :path: address.state
10739
- - :path: address.postalCode
10740
- - :path: address.country
10741
10730
  :mandatory_elements:
10742
10731
  - Practitioner.identifier
10743
10732
  - Practitioner.identifier.system
@@ -10794,6 +10783,8 @@
10794
10783
  :file_name: practitioner_validation_test.rb
10795
10784
  - :id: us_core_v610_practitioner_must_support_test
10796
10785
  :file_name: practitioner_must_support_test.rb
10786
+ - :id: us_core_v610_practitioner_address_test
10787
+ :file_name: practitioner_address_test.rb
10797
10788
  :id: us_core_v610_practitioner
10798
10789
  :file_name: practitioner_group.rb
10799
10790
  :delayed_references: []
@@ -100,12 +100,6 @@
100
100
  - :path: telecom
101
101
  - :path: telecom.system
102
102
  - :path: telecom.value
103
- - :path: address
104
- - :path: address.line
105
- - :path: address.city
106
- - :path: address.state
107
- - :path: address.postalCode
108
- - :path: address.country
109
103
  :mandatory_elements:
110
104
  - Practitioner.identifier
111
105
  - Practitioner.identifier.system
@@ -162,6 +156,8 @@
162
156
  :file_name: practitioner_validation_test.rb
163
157
  - :id: us_core_v610_practitioner_must_support_test
164
158
  :file_name: practitioner_must_support_test.rb
159
+ - :id: us_core_v610_practitioner_address_test
160
+ :file_name: practitioner_address_test.rb
165
161
  :id: us_core_v610_practitioner
166
162
  :file_name: practitioner_group.rb
167
163
  :delayed_references: []
@@ -0,0 +1,32 @@
1
+ require_relative '../../../practitioner_address_test'
2
+
3
+ module USCoreTestKit
4
+ module USCoreV610
5
+ class PractitionerAddressTest < Inferno::Test
6
+ include USCoreTestKit::PractitionerAddressTest
7
+
8
+ title 'Server support either Practitioner.address or PractitionerRole'
9
+ description %(
10
+ US Core Responders SHALL support either US Core PractitionerRole Profile or
11
+ these data elements in US Core Practitioner Profile
12
+
13
+ * Practitioner.address
14
+ * Practitioner.address.city
15
+ * Practitioner.address.country
16
+ * Practitioner.address.line
17
+ * Practitioner.address.postalCode
18
+ * Practitioner.address.state
19
+ )
20
+
21
+ id :us_core_v610_practitioner_address_test
22
+
23
+ def self.metadata
24
+ @metadata ||= Generator::GroupMetadata.new(YAML.load_file(File.join(__dir__, 'metadata.yml'), aliases: true))
25
+ end
26
+
27
+ run do
28
+ verify_practitioner_address
29
+ end
30
+ end
31
+ end
32
+ end
@@ -12,12 +12,6 @@ module USCoreTestKit
12
12
  Statement. This test will look through the Practitioner resources
13
13
  found previously for the following must support elements:
14
14
 
15
- * Practitioner.address
16
- * Practitioner.address.city
17
- * Practitioner.address.country
18
- * Practitioner.address.line
19
- * Practitioner.address.postalCode
20
- * Practitioner.address.state
21
15
  * Practitioner.identifier
22
16
  * Practitioner.identifier.system
23
17
  * Practitioner.identifier.value
@@ -4,6 +4,7 @@ require_relative 'practitioner/practitioner_name_search_test'
4
4
  require_relative 'practitioner/practitioner_identifier_search_test'
5
5
  require_relative 'practitioner/practitioner_validation_test'
6
6
  require_relative 'practitioner/practitioner_must_support_test'
7
+ require_relative 'practitioner/practitioner_address_test'
7
8
 
8
9
  module USCoreTestKit
9
10
  module USCoreV610
@@ -82,6 +83,7 @@ read succeeds.
82
83
  test from: :us_core_v610_practitioner_identifier_search_test
83
84
  test from: :us_core_v610_practitioner_validation_test
84
85
  test from: :us_core_v610_practitioner_must_support_test
86
+ test from: :us_core_v610_practitioner_address_test
85
87
  end
86
88
  end
87
89
  end
@@ -144,12 +144,6 @@
144
144
  :path: ''
145
145
  :code: social-history
146
146
  :system: http://terminology.hl7.org/CodeSystem/observation-category
147
- - :slice_id: Observation.effective[x]:effectiveDateTime
148
- :slice_name: effectiveDateTime
149
- :path: effective[x]
150
- :discriminator:
151
- :type: type
152
- :code: DateTime
153
147
  :elements:
154
148
  - :path: status
155
149
  - :path: category
@@ -161,6 +155,7 @@
161
155
  - http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient
162
156
  - :path: valueCodeableConcept
163
157
  :original_path: value[x]
158
+ - :path: effective[x]
164
159
  :mandatory_elements:
165
160
  - Observation.status
166
161
  - Observation.category
@@ -15,7 +15,7 @@ module USCoreTestKit
15
15
  * Observation.category
16
16
  * Observation.category:SocialHistory
17
17
  * Observation.code
18
- * Observation.effective[x]:effectiveDateTime
18
+ * Observation.effective[x]
19
19
  * Observation.status
20
20
  * Observation.subject
21
21
  * Observation.valueCodeableConcept
@@ -88,7 +88,11 @@ module USCoreTestKit
88
88
  %r{Observation.component\[\d+\].value.ofType\(Quantity\): The code provided \(http://unitsofmeasure.org#L/min\) was not found in the value set 'Vital Signs Units'} # Known issue with the Pulse Oximetry Profile
89
89
  ].freeze
90
90
 
91
- VERSION_SPECIFIC_MESSAGE_FILTERS = [].freeze
91
+ VERSION_SPECIFIC_MESSAGE_FILTERS = [
92
+ %r{Observation\.effective\.ofType\(Period\):.*http://hl7.org/fhir/us/core/StructureDefinition/us-core-smokingstatus},
93
+ %r{Observation: Slice 'Observation\.effective\[x\]:effectiveDateTime':.*http://hl7.org/fhir/us/core/StructureDefinition/us-core-smokingstatus},
94
+ %r{Observation\.effective\.ofType\(Period\).*This element is not allowed by the profile http://hl7.org/fhir/StructureDefinition/dateTime}
95
+ ].freeze
92
96
 
93
97
  def self.metadata
94
98
  @metadata ||= YAML.load_file(File.join(__dir__, 'metadata.yml'), aliases: true)[:groups].map do |raw_metadata|
@@ -12533,12 +12533,6 @@
12533
12533
  - :path: telecom
12534
12534
  - :path: telecom.system
12535
12535
  - :path: telecom.value
12536
- - :path: address
12537
- - :path: address.line
12538
- - :path: address.city
12539
- - :path: address.state
12540
- - :path: address.postalCode
12541
- - :path: address.country
12542
12536
  :mandatory_elements:
12543
12537
  - Practitioner.identifier
12544
12538
  - Practitioner.identifier.system
@@ -12595,6 +12589,8 @@
12595
12589
  :file_name: practitioner_validation_test.rb
12596
12590
  - :id: us_core_v700_practitioner_must_support_test
12597
12591
  :file_name: practitioner_must_support_test.rb
12592
+ - :id: us_core_v700_practitioner_address_test
12593
+ :file_name: practitioner_address_test.rb
12598
12594
  :id: us_core_v700_practitioner
12599
12595
  :file_name: practitioner_group.rb
12600
12596
  :delayed_references: []
@@ -100,12 +100,6 @@
100
100
  - :path: telecom
101
101
  - :path: telecom.system
102
102
  - :path: telecom.value
103
- - :path: address
104
- - :path: address.line
105
- - :path: address.city
106
- - :path: address.state
107
- - :path: address.postalCode
108
- - :path: address.country
109
103
  :mandatory_elements:
110
104
  - Practitioner.identifier
111
105
  - Practitioner.identifier.system
@@ -162,6 +156,8 @@
162
156
  :file_name: practitioner_validation_test.rb
163
157
  - :id: us_core_v700_practitioner_must_support_test
164
158
  :file_name: practitioner_must_support_test.rb
159
+ - :id: us_core_v700_practitioner_address_test
160
+ :file_name: practitioner_address_test.rb
165
161
  :id: us_core_v700_practitioner
166
162
  :file_name: practitioner_group.rb
167
163
  :delayed_references: []
@@ -0,0 +1,32 @@
1
+ require_relative '../../../practitioner_address_test'
2
+
3
+ module USCoreTestKit
4
+ module USCoreV700
5
+ class PractitionerAddressTest < Inferno::Test
6
+ include USCoreTestKit::PractitionerAddressTest
7
+
8
+ title 'Server support either Practitioner.address or PractitionerRole'
9
+ description %(
10
+ US Core Responders SHALL support either US Core PractitionerRole Profile or
11
+ these data elements in US Core Practitioner Profile
12
+
13
+ * Practitioner.address
14
+ * Practitioner.address.city
15
+ * Practitioner.address.country
16
+ * Practitioner.address.line
17
+ * Practitioner.address.postalCode
18
+ * Practitioner.address.state
19
+ )
20
+
21
+ id :us_core_v700_practitioner_address_test
22
+
23
+ def self.metadata
24
+ @metadata ||= Generator::GroupMetadata.new(YAML.load_file(File.join(__dir__, 'metadata.yml'), aliases: true))
25
+ end
26
+
27
+ run do
28
+ verify_practitioner_address
29
+ end
30
+ end
31
+ end
32
+ end
@@ -12,12 +12,6 @@ module USCoreTestKit
12
12
  Statement. This test will look through the Practitioner resources
13
13
  found previously for the following must support elements:
14
14
 
15
- * Practitioner.address
16
- * Practitioner.address.city
17
- * Practitioner.address.country
18
- * Practitioner.address.line
19
- * Practitioner.address.postalCode
20
- * Practitioner.address.state
21
15
  * Practitioner.identifier
22
16
  * Practitioner.identifier.system
23
17
  * Practitioner.identifier.value
@@ -4,6 +4,7 @@ require_relative 'practitioner/practitioner_identifier_search_test'
4
4
  require_relative 'practitioner/practitioner_name_search_test'
5
5
  require_relative 'practitioner/practitioner_validation_test'
6
6
  require_relative 'practitioner/practitioner_must_support_test'
7
+ require_relative 'practitioner/practitioner_address_test'
7
8
 
8
9
  module USCoreTestKit
9
10
  module USCoreV700
@@ -82,6 +83,7 @@ read succeeds.
82
83
  test from: :us_core_v700_practitioner_name_search_test
83
84
  test from: :us_core_v700_practitioner_validation_test
84
85
  test from: :us_core_v700_practitioner_must_support_test
86
+ test from: :us_core_v700_practitioner_address_test
85
87
  end
86
88
  end
87
89
  end
@@ -110,8 +110,7 @@ module USCoreTestKit
110
110
  def add_special_tests
111
111
  return if group_metadata.reformatted_version == 'v311'
112
112
 
113
- case group_metadata.resource
114
- when 'DocumentReference'
113
+ if group_metadata.resource == 'DocumentReference'
115
114
  group_metadata.add_test(
116
115
  id: 'us_core_v400_document_reference_custodian_test',
117
116
  file_name: '../../custom_groups/v4.0.0/document_reference_custodian_test.rb'
@@ -27,6 +27,8 @@ module USCoreTestKit
27
27
  def handle_special_cases
28
28
  add_must_support_choices
29
29
  add_patient_uscdi_elements
30
+ update_smoking_status_effective
31
+ remove_practitioner_address
30
32
  end
31
33
 
32
34
  def add_must_support_choices
@@ -79,8 +81,21 @@ module USCoreTestKit
79
81
  element[:path] = 'deceasedDateTime'
80
82
  end
81
83
  end
84
+ end
85
+
86
+ # US Core v6.1.0 Patch FHIR-43355, US Core Smoking Status Observation Profile may be supported
87
+ # either Observation.effectiveDateTime or Observation.effectivePeriod data element
88
+ def update_smoking_status_effective
89
+ return unless profile.id == 'us-core-smokingstatus'
90
+
91
+ must_supports[:slices].delete_if { |slice| slice[:slice_id] == 'Observation.effective[x]:effectiveDateTime' }
92
+ must_supports[:elements] << { path: 'effective[x]' }
93
+ end
82
94
 
95
+ def remove_practitioner_address
96
+ return unless profile.type == 'Practitioner'
83
97
 
98
+ must_supports[:elements].delete_if { |element| element[:path].start_with?('address') }
84
99
  end
85
100
  end
86
101
  end
@@ -17,11 +17,14 @@ module USCoreTestKit
17
17
  end
18
18
 
19
19
  def handle_special_cases
20
- us_core_6_extractor.handle_special_cases
20
+ us_core_6_extractor.add_patient_uscdi_elements
21
21
  add_must_support_choices
22
+ us_core_6_extractor.remove_practitioner_address
22
23
  end
23
24
 
24
25
  def add_must_support_choices
26
+ us_core_6_extractor.add_must_support_choices
27
+
25
28
  more_choices = []
26
29
 
27
30
  case profile.type
@@ -0,0 +1,68 @@
1
+ module USCoreTestKit
2
+ class Generator
3
+ class PractitionerAddressTestGenerator
4
+ class << self
5
+ def generate(ig_metadata, base_output_dir)
6
+ ig_metadata.groups
7
+ .reject { |group| SpecialCases.exclude_group? group }
8
+ .each { |group| new(group, base_output_dir).generate }
9
+ end
10
+ end
11
+
12
+ attr_accessor :group_metadata, :base_output_dir
13
+
14
+ def initialize(group_metadata, base_output_dir)
15
+ self.group_metadata = group_metadata
16
+ self.base_output_dir = base_output_dir
17
+ end
18
+
19
+ def template
20
+ @template ||= File.read(File.join(__dir__, 'templates', 'practitioner_address_test.rb.erb'))
21
+ end
22
+
23
+ def output
24
+ @output ||= ERB.new(template).result(binding)
25
+ end
26
+
27
+ def base_output_file_name
28
+ "#{class_name.underscore}.rb"
29
+ end
30
+
31
+ def output_file_directory
32
+ File.join(base_output_dir, profile_identifier)
33
+ end
34
+
35
+ def output_file_name
36
+ File.join(output_file_directory, base_output_file_name)
37
+ end
38
+
39
+ def profile_identifier
40
+ Naming.snake_case_for_profile(group_metadata)
41
+ end
42
+
43
+ def test_id
44
+ "us_core_#{group_metadata.reformatted_version}_practitioner_address_test"
45
+ end
46
+
47
+ def class_name
48
+ "PractitionerAddressTest"
49
+ end
50
+
51
+ def module_name
52
+ "USCore#{group_metadata.reformatted_version.upcase}"
53
+ end
54
+
55
+ def generate
56
+ return unless group_metadata.resource == 'Practitioner' && group_metadata.version[1].to_i > 5
57
+
58
+ FileUtils.mkdir_p(output_file_directory)
59
+ File.open(output_file_name, 'w') { |f| f.write(output) }
60
+
61
+ group_metadata.add_test(
62
+ id: test_id,
63
+ file_name: base_output_file_name
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
@@ -18,7 +18,16 @@ module USCoreTestKit
18
18
  end
19
19
 
20
20
  def version_specific_message_filters
21
- []
21
+ case ig_metadata.reformatted_version
22
+ when 'v610'
23
+ [
24
+ %r{Observation\.effective\.ofType\(Period\):.*http://hl7.org/fhir/us/core/StructureDefinition/us-core-smokingstatus},
25
+ %r{Observation: Slice 'Observation\.effective\[x\]:effectiveDateTime':.*http://hl7.org/fhir/us/core/StructureDefinition/us-core-smokingstatus},
26
+ %r{Observation\.effective\.ofType\(Period\).*This element is not allowed by the profile http://hl7.org/fhir/StructureDefinition/dateTime}
27
+ ]
28
+ else
29
+ []
30
+ end
22
31
  end
23
32
 
24
33
  def template
@@ -15,6 +15,7 @@ require_relative 'generator/reference_resolution_test_generator'
15
15
  require_relative 'generator/search_test_generator'
16
16
  require_relative 'generator/suite_generator'
17
17
  require_relative 'generator/validation_test_generator'
18
+ require_relative 'generator/practitioner_address_test_generator'
18
19
 
19
20
  module USCoreTestKit
20
21
  class Generator
@@ -44,6 +45,7 @@ module USCoreTestKit
44
45
  generate_validation_tests
45
46
  generate_must_support_tests
46
47
  generate_reference_resolution_tests
48
+ generate_practitioner_address_tests
47
49
 
48
50
  generate_granular_scope_tests
49
51
 
@@ -120,6 +122,10 @@ module USCoreTestKit
120
122
  GranularScopeGroupGenerator.generate(ig_metadata, base_output_dir)
121
123
  end
122
124
 
125
+ def generate_practitioner_address_tests
126
+ PractitionerAddressTestGenerator.generate(ig_metadata, base_output_dir)
127
+ end
128
+
123
129
  def generate_suites
124
130
  SuiteGenerator.generate(ig_metadata, base_output_dir)
125
131
  end
@@ -28,7 +28,7 @@ module USCoreTestKit
28
28
  if request.status != 200
29
29
  []
30
30
  else
31
- fetch_all_bundled_resources
31
+ fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
32
32
  end
33
33
 
34
34
  mismatched_ids = mismatched_resource_ids(found_resources)
@@ -78,6 +78,7 @@ module USCoreTestKit
78
78
 
79
79
  def expected_resource_ids(resources)
80
80
  resources
81
+ .select { |resource| resource.resourceType == resource_type }
81
82
  .select do |resource|
82
83
  granular_scope_search_params.any? do |param|
83
84
  resource_matches_param?(resource, param[:name], param[:value])
@@ -88,6 +89,7 @@ module USCoreTestKit
88
89
 
89
90
  def mismatched_resource_ids(resources)
90
91
  resources
92
+ .select { |resource| resource.resourceType == resource_type }
91
93
  .reject do |resource|
92
94
  granular_scope_search_params.any? do |param|
93
95
  resource_matches_param?(resource, param[:name], param[:value])
@@ -107,33 +107,36 @@ module USCoreTestKit
107
107
  end
108
108
 
109
109
  def missing_elements(resources = [])
110
- @missing_elements ||=
111
- must_support_elements.select do |element_definition|
112
- resources.none? do |resource|
113
- path = element_definition[:path]
114
- ms_extension_urls = must_support_extensions.select { |ex| ex[:path] == "#{path}.extension" }
115
- .map { |ex| ex[:url] }
116
-
117
- value_found = find_a_value_at(resource, path) do |value|
118
- if value.instance_of?(USCoreTestKit::PrimitiveType) && ms_extension_urls.present?
119
- urls = value.extension&.map(&:url)
120
- has_ms_extension = (urls & ms_extension_urls).present?
121
- end
110
+ @missing_elements ||= find_missing_elements(resources, must_support_elements)
111
+ @missing_elements
112
+ end
122
113
 
123
- unless has_ms_extension
124
- value = value.value if value.instance_of?(USCoreTestKit::PrimitiveType)
125
- value_without_extensions =
126
- value.respond_to?(:to_hash) ? value.to_hash.reject { |key, _| key == 'extension' } : value
127
- end
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
128
126
 
129
- (has_ms_extension || value_without_extensions.present? || value_without_extensions == false) &&
130
- (element_definition[:fixed_value].blank? || value == element_definition[:fixed_value])
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
131
  end
132
- # Note that false.present? => false, which is why we need to add this extra check
133
- value_found.present? || value_found == false
132
+
133
+ (has_ms_extension || value_without_extensions.present? || value_without_extensions == false) &&
134
+ (element_definition[:fixed_value].blank? || value == element_definition[:fixed_value])
134
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
135
138
  end
136
- @missing_elements
139
+ end
137
140
  end
138
141
 
139
142
  def must_support_slices
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module USCoreTestKit
4
+ module PractitionerAddressTest
5
+ include SearchTest
6
+ include ReferenceResolutionTest
7
+ include MustSupportTest
8
+
9
+ MUST_SUPPORT_ELEMENTS = [
10
+ { path: 'address' },
11
+ { path: 'address.line' },
12
+ { path: 'address.city' },
13
+ { path: 'address.state' },
14
+ { path: 'address.postalCode' },
15
+ { path: 'address.country' }
16
+ ].freeze
17
+
18
+ def resource_type
19
+ 'Practitioner'
20
+ end
21
+
22
+ def scratch_resources
23
+ scratch[:practitioner_resource] ||= {}
24
+ end
25
+
26
+ def verify_practitioner_address
27
+ references = scratch.dig(:references, 'Practitioner')
28
+ assert references.any?, 'No Pracitioner references found.'
29
+
30
+ @missing_elements = MUST_SUPPORT_ELEMENTS
31
+ practitioners = []
32
+
33
+ references.each do |reference|
34
+ resolved_resource = resolve_reference(reference)
35
+
36
+ if resolved_resource.nil? ||
37
+ resolved_resource.resourceType != resource_type ||
38
+ resolved_resource.id != reference.reference_id
39
+ next
40
+ end
41
+
42
+ practitioners << resolved_resource
43
+
44
+ some_missing_elements = find_missing_elements([resolved_resource], MUST_SUPPORT_ELEMENTS)
45
+ @missing_elements &= some_missing_elements
46
+
47
+ break if @missing_elements.empty?
48
+ end
49
+
50
+ missing_elements_string = @missing_elements.map { |element| missing_element_string(element) }
51
+ support_practitioner_role = false
52
+
53
+ if @missing_elements.any?
54
+ resource_type = 'PractitionerRole'
55
+ support_practitioner_role = practitioners.any? do |practitioner|
56
+ search_params = { practitioner: practitioner.id }
57
+
58
+ search_and_check_response(search_params, resource_type)
59
+
60
+ practitioner_roles = fetch_all_bundled_resources(resource_type:)
61
+ .select { |resource| resource.resourceType == resource_type }
62
+
63
+ next false if practitioner_roles.empty?
64
+ next true if config.options[:skip_practitioner_role_validation]
65
+
66
+ target_profile_with_version =
67
+ "http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitionerrole|#{metadata.profile_version}"
68
+
69
+ practitioner_roles.any? { |pr| resource_is_valid_with_target_profile?(pr, target_profile_with_version) }
70
+ end
71
+ end
72
+
73
+ missing_must_support_message = "Could not find US Core PractitionerRole Profile resources and " \
74
+ "these MustSupport elements #{missing_elements_string.join(', ')} " \
75
+ "in US Core Practitioner Profile resources. " \
76
+ "Please use patients with more information."
77
+
78
+ assert (support_practitioner_role || @missing_elements.blank?), missing_must_support_message
79
+ end
80
+
81
+ def get_practitioner_ids(references)
82
+ references.map { |reference| reference.reference&.split('/')&.last }.compact.uniq
83
+ end
84
+ end
85
+ end
@@ -119,36 +119,17 @@ module USCoreTestKit
119
119
  return resource.contained.any? do |contained_resource|
120
120
  contained_resource&.id == reference.reference_id &&
121
121
  resource_is_valid_with_target_profile?(contained_resource, target_profile)
122
- end
122
+ end
123
123
  end
124
124
 
125
125
  reference_type = reference.resource_type
126
126
  reference_id = reference.reference_id
127
127
 
128
- resolved_resource =
129
- begin
130
- if reference.relative?
131
- begin
132
- reference.resource_class
133
- rescue NameError
134
- return false
135
- end
128
+ resolved_resource = resolve_reference(reference)
136
129
 
137
- fhir_read(reference_type, reference_id)&.resource
138
- else
139
- if reference.base_uri.chomp('/') == fhir_client.instance_variable_get(:@base_service_url).chomp('/')
140
- fhir_read(reference_type, reference_id)&.resource
141
- else
142
- get(reference.reference)&.resource
143
- end
144
- end
145
- rescue StandardError => e
146
- Inferno::Application['logger'].error("Unable to resolve reference #{reference.reference}")
147
- Inferno::Application['logger'].error(e.full_message)
148
- return false
149
- end
130
+ return false if resolved_resource.nil?
150
131
 
151
- return false unless resolved_resource&.resourceType == reference_type && resolved_resource&.id == reference_id
132
+ return false unless resolved_resource.resourceType == reference_type && resolved_resource.id == reference_id
152
133
 
153
134
  return false unless resource_is_valid_with_target_profile?(resolved_resource, target_profile)
154
135
 
@@ -156,6 +137,33 @@ module USCoreTestKit
156
137
  true
157
138
  end
158
139
 
140
+ def resolve_reference(reference)
141
+ reference_type = reference.resource_type
142
+ reference_id = reference.reference_id
143
+
144
+ begin
145
+ if reference.relative?
146
+ begin
147
+ reference.resource_class
148
+ rescue NameError
149
+ return nil
150
+ end
151
+
152
+ fhir_read(reference_type, reference_id)&.resource
153
+ else
154
+ if reference.base_uri.chomp('/') == fhir_client.instance_variable_get(:@base_service_url).chomp('/')
155
+ fhir_read(reference_type, reference_id)&.resource
156
+ else
157
+ get(reference.reference)&.resource
158
+ end
159
+ end
160
+ rescue StandardError => e
161
+ Inferno::Application['logger'].error("Unable to resolve reference #{reference.reference}")
162
+ Inferno::Application['logger'].error(e.full_message)
163
+ return nil
164
+ end
165
+ end
166
+
159
167
  def resource_is_valid_with_target_profile?(resource, target_profile)
160
168
  return true if target_profile.blank?
161
169
 
@@ -737,16 +737,19 @@ module USCoreTestKit
737
737
 
738
738
  paths.each do |path|
739
739
  type = metadata.search_definitions[search_param_name.to_sym][:type]
740
- values_found =
741
- resolve_path(resource, path)
742
- .map do |value|
743
- if value.is_a? FHIR::Reference
744
- value.reference
745
- else
746
- value
747
- end
740
+
741
+ resolve_path(resource, path).each do |value|
742
+ values_found <<
743
+ if value.is_a? FHIR::Reference
744
+ value.reference
745
+ elsif value.is_a? USCoreTestKit::PrimitiveType
746
+ value.value
747
+ else
748
+ value
749
+ end
748
750
  end
749
751
 
752
+ values_found.compact!
750
753
  match_found =
751
754
  case type
752
755
  when 'Period', 'date', 'instant', 'dateTime'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USCoreTestKit
4
- VERSION = '0.8.0'
4
+ VERSION = '0.8.2'
5
5
  end
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.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen MacVicar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-01 00:00:00.000000000 Z
11
+ date: 2024-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -1739,6 +1739,7 @@ files:
1739
1739
  - lib/us_core_test_kit/generated/v6.1.0/pediatric_weight_for_height/pediatric_weight_for_height_validation_test.rb
1740
1740
  - lib/us_core_test_kit/generated/v6.1.0/pediatric_weight_for_height_group.rb
1741
1741
  - lib/us_core_test_kit/generated/v6.1.0/practitioner/metadata.yml
1742
+ - lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_address_test.rb
1742
1743
  - lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_id_search_test.rb
1743
1744
  - lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_identifier_search_test.rb
1744
1745
  - lib/us_core_test_kit/generated/v6.1.0/practitioner/practitioner_must_support_test.rb
@@ -2359,6 +2360,7 @@ files:
2359
2360
  - lib/us_core_test_kit/generated/v7.0.0/pediatric_weight_for_height/pediatric_weight_for_height_validation_test.rb
2360
2361
  - lib/us_core_test_kit/generated/v7.0.0/pediatric_weight_for_height_group.rb
2361
2362
  - lib/us_core_test_kit/generated/v7.0.0/practitioner/metadata.yml
2363
+ - lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_address_test.rb
2362
2364
  - lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_id_search_test.rb
2363
2365
  - lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_identifier_search_test.rb
2364
2366
  - lib/us_core_test_kit/generated/v7.0.0/practitioner/practitioner_must_support_test.rb
@@ -2522,6 +2524,7 @@ files:
2522
2524
  - lib/us_core_test_kit/generator/must_support_metadata_extractor_us_core_7.rb
2523
2525
  - lib/us_core_test_kit/generator/must_support_test_generator.rb
2524
2526
  - lib/us_core_test_kit/generator/naming.rb
2527
+ - lib/us_core_test_kit/generator/practitioner_address_test_generator.rb
2525
2528
  - lib/us_core_test_kit/generator/provenance_revinclude_search_test_generator.rb
2526
2529
  - lib/us_core_test_kit/generator/read_test_generator.rb
2527
2530
  - lib/us_core_test_kit/generator/reference_resolution_test_generator.rb
@@ -2558,6 +2561,7 @@ files:
2558
2561
  - lib/us_core_test_kit/igs/us_core_700/ValueSet-SmokingStatusType.json
2559
2562
  - lib/us_core_test_kit/igs/us_core_700/ValueSet-servicerequest-category.json
2560
2563
  - lib/us_core_test_kit/must_support_test.rb
2564
+ - lib/us_core_test_kit/practitioner_address_test.rb
2561
2565
  - lib/us_core_test_kit/primitive_type.rb
2562
2566
  - lib/us_core_test_kit/provenance_validator.rb
2563
2567
  - lib/us_core_test_kit/read_test.rb