us_core_test_kit 0.8.0 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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