us_quality_core_test_kit 0.1.1 → 0.1.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/NOTICE.md +12 -0
  3. data/config/presets/{localhost_preset.json → inferno_reference_server_preset.json.erb} +2 -2
  4. data/lib/us_quality_core_test_kit/client/generator/example_client_generator.rb +0 -1
  5. data/lib/us_quality_core_test_kit/client/generator/tags_generator.rb +0 -1
  6. data/lib/us_quality_core_test_kit/client/server_proxy.rb +2 -6
  7. data/lib/us_quality_core_test_kit/date_search_validation.rb +122 -0
  8. data/lib/us_quality_core_test_kit/fhir_resource_navigation.rb +9 -0
  9. data/lib/us_quality_core_test_kit/generated/v0.5.0/devicenotrequested/devicenotrequested_validation_test.rb +3 -0
  10. data/lib/us_quality_core_test_kit/generated/v0.5.0/devicerequest/devicerequest_validation_test.rb +3 -0
  11. data/lib/us_quality_core_test_kit/generated/v0.5.0/patient/patient_validation_test.rb +4 -0
  12. data/lib/us_quality_core_test_kit/generated/v0.5.0/us_quality_core_test_suite.rb +1 -2
  13. data/lib/us_quality_core_test_kit/generator/group_generator.rb +69 -3
  14. data/lib/us_quality_core_test_kit/generator/group_metadata.rb +100 -4
  15. data/lib/us_quality_core_test_kit/generator/group_metadata_extractor.rb +184 -8
  16. data/lib/us_quality_core_test_kit/generator/ig_loader.rb +47 -3
  17. data/lib/us_quality_core_test_kit/generator/ig_metadata.rb +51 -2
  18. data/lib/us_quality_core_test_kit/generator/ig_metadata_extractor.rb +25 -6
  19. data/lib/us_quality_core_test_kit/generator/ig_resources.rb +27 -3
  20. data/lib/us_quality_core_test_kit/generator/must_support_metadata_extractor.rb +366 -9
  21. data/lib/us_quality_core_test_kit/generator/must_support_test_generator.rb +54 -3
  22. data/lib/us_quality_core_test_kit/generator/provenance_revinclude_search_test_generator.rb +149 -3
  23. data/lib/us_quality_core_test_kit/generator/read_test_generator.rb +54 -3
  24. data/lib/us_quality_core_test_kit/generator/reference_resolution_test_generator.rb +57 -3
  25. data/lib/us_quality_core_test_kit/generator/search_definition_metadata_extractor.rb +181 -5
  26. data/lib/us_quality_core_test_kit/generator/search_metadata_extractor.rb +61 -3
  27. data/lib/us_quality_core_test_kit/generator/search_test_generator.rb +186 -3
  28. data/lib/us_quality_core_test_kit/generator/suite_generator.rb +35 -8
  29. data/lib/us_quality_core_test_kit/generator/terminology_binding_metadata_extractor.rb +107 -3
  30. data/lib/us_quality_core_test_kit/generator/validation_test_generator.rb +83 -4
  31. data/lib/us_quality_core_test_kit/generator/value_extractor.rb +147 -3
  32. data/lib/us_quality_core_test_kit/must_support_test.rb +15 -3
  33. data/lib/us_quality_core_test_kit/primitive_type.rb +7 -0
  34. data/lib/us_quality_core_test_kit/read_test.rb +99 -4
  35. data/lib/us_quality_core_test_kit/reference_resolution_test.rb +164 -3
  36. data/lib/us_quality_core_test_kit/resource_search_param_checker.rb +138 -0
  37. data/lib/us_quality_core_test_kit/search_test.rb +681 -46
  38. data/lib/us_quality_core_test_kit/search_test_properties.rb +53 -3
  39. data/lib/us_quality_core_test_kit/validation_test.rb +51 -4
  40. data/lib/us_quality_core_test_kit/version.rb +2 -2
  41. data/lib/us_quality_core_test_kit/well_known_code_systems.rb +23 -0
  42. metadata +8 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d71c2e36b7ed3be04801523be2585090953365e9716279aab8cbb46dab077a6
4
- data.tar.gz: 885e8a05af4bdfd964cb1656221ebd309b196e2be36b1fc4404e2a9c5a2069b3
3
+ metadata.gz: '0297423f25d4655d95c5d963fb2363bdef89197c13c082b63ee2bc339a9780fe'
4
+ data.tar.gz: 614f8a0f368729af2383e877bff720b9784ece107bef849cf887966dec2e73e0
5
5
  SHA512:
6
- metadata.gz: 6bd30d52b1610e68728f93052002061195b2cc284b61c2fb99e356fce30c4477d749efeee3e757538cdd928e29befb329b146fb77d38a94f938bcabe7bad3099
7
- data.tar.gz: acc81efae38e987ad357ea1fecdbec236454819e8ac3187e1a078401f30713e9be10a4a3798fc9d74c01d0d5716b057f9682d86f096d9741a1ed3a970f5f091b
6
+ metadata.gz: 10673556b891c029d3c94779d7439412f633dcc9c6dfe033fce3deeb64da61e1d29a96f953cdaf8dd8338db314eb7f6217d9b1518d356d702dd397b8daaf34e9
7
+ data.tar.gz: 8c8e669cebe8ff4a3b1fcb49ed3023c32f7546b27116ad21c965beb716017cc488694cb6ca225f1f17380cd7bb31f13ffa6273a777647de75ebb9790b57a2a5e
data/NOTICE.md CHANGED
@@ -11,3 +11,15 @@ For further information, please contact The MITRE Corporation, Contracts Managem
11
11
  Approved for Public Release; Distribution Unlimited. Public Release Case Number: 25-3234
12
12
 
13
13
  ### <p align='center'>**ⓒ2026 The MITRE Corporation.**</p>
14
+
15
+ Portions of this software include code from the US Core Test Kit.
16
+
17
+ That software was produced for the U. S. Government under Contract Number 75FCMC18D0047, and is subject to Federal Acquisition Regulation Clause 52.227-14, Rights in Data-General.
18
+
19
+ No other use other than that granted to the U. S. Government, or to those acting on behalf of the U. S. Government under that Clause is authorized without the express written permission of The MITRE Corporation.
20
+
21
+ To the extent necessary MITRE hereby grants express written permission to use, reproduce, distribute, modify, and otherwise leverage this software to the extent permitted by the Apache 2.0 license.
22
+
23
+ For further information, please contact The MITRE Corporation, Contracts Management Office, 7515 Colshire Drive, McLean, VA 22102-7539, (703) 983-6000.
24
+
25
+ ### <p align='center'>**ⓒ2024 The MITRE Corporation.**</p>
@@ -1,5 +1,5 @@
1
1
  {
2
- "title": "Localhost Server",
2
+ "title": "Inferno Reference Server",
3
3
  "id": null,
4
4
  "test_suite_id": "us_quality_core_v050",
5
5
  "inputs": [
@@ -8,7 +8,7 @@
8
8
  "type": "text",
9
9
  "title": "FHIR Endpoint",
10
10
  "description": "URL of the FHIR endpoint",
11
- "value": "http://localhost:8080/reference-server/r4"
11
+ "value": "<%= ENV.fetch('FHIR_REFERENCE_SERVER', 'https://inferno.healthit.gov/reference-server/r4') %>"
12
12
  },
13
13
  {
14
14
  "name": "smart_auth_info",
@@ -126,7 +126,6 @@ module USQualityCoreTestKit
126
126
  end
127
127
  end
128
128
 
129
- # rubocop:disable Metrics/ClassLength
130
129
  class ExampleClientGenerator
131
130
  class << self
132
131
  def generate(ig_metadata, base_output_dir)
@@ -35,7 +35,6 @@ module USQualityCoreTestKit
35
35
 
36
36
  def groups
37
37
  ig_metadata.ordered_groups
38
- .reject { |group| USCoreTestKit::Generator::SpecialCases.exclude_group? group }
39
38
  end
40
39
 
41
40
  def resources
@@ -58,12 +58,8 @@ module USQualityCoreTestKit
58
58
 
59
59
  def replace_bundle_urls(bundle)
60
60
  reference_server_base = ENV.fetch('FHIR_REFERENCE_SERVER')
61
- bundle&.link&.map! { |link| { relation: link.relation, url: link.url.gsub(reference_server_base, new_link) } }
62
- bundle&.entry&.map! do |bundled_resource|
63
- { fullUrl: bundled_resource.fullUrl.gsub(reference_server_base, new_link),
64
- resource: bundled_resource.resource,
65
- search: bundled_resource.search }
66
- end
61
+ bundle&.link&.each { |link| link.url = link.url.gsub(reference_server_base, new_link) }
62
+ bundle&.entry&.each { |entry| entry.fullUrl = entry.fullUrl.gsub(reference_server_base, new_link) }
67
63
  bundle
68
64
  end
69
65
 
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module USQualityCoreTestKit
4
+ module DateSearchValidation
5
+ def get_fhir_datetime_range(datetime)
6
+ range = { start: DateTime.xmlschema(datetime), end: nil }
7
+ range[:end] =
8
+ case datetime
9
+ when /^\d{4}$/ # YYYY
10
+ range[:start].next_year - 1.seconds
11
+ when /^\d{4}-\d{2}$/ # YYYY-MM
12
+ range[:start].next_month - 1.seconds
13
+ when /^\d{4}-\d{2}-\d{2}$/ # YYYY-MM-DD
14
+ range[:start].next_day - 1.seconds
15
+ else # YYYY-MM-DDThh:mm:ss+zz:zz
16
+ range[:start]
17
+ end
18
+ range
19
+ end
20
+
21
+ def get_fhir_period_range(period)
22
+ range = { start: nil, end: nil }
23
+ range[:start] = DateTime.xmlschema(period.start) unless period.start.nil?
24
+ return range if period.end.nil?
25
+
26
+ period_end_beginning = DateTime.xmlschema(period.end)
27
+ range[:end] =
28
+ case period.end
29
+ when /^\d{4}$/ # YYYY
30
+ period_end_beginning.next_year - 1.seconds
31
+ when /^\d{4}-\d{2}$/ # YYYY-MM
32
+ period_end_beginning.next_month - 1.seconds
33
+ when /^\d{4}-\d{2}-\d{2}$/ # YYYY-MM-DD
34
+ period_end_beginning.next_day - 1.seconds
35
+ else # YYYY-MM-DDThh:mm:ss+zz:zz
36
+ period_end_beginning
37
+ end
38
+ range
39
+ end
40
+
41
+ def fhir_date_comparer(search_range, target_range, comparator, extend_start: false, extend_end: false)
42
+ # Implicitly, a missing lower boundary is "less than" any actual date. A missing upper boundary is "greater than" any actual date.
43
+ case comparator
44
+ when 'eq' # the range of the search value fully contains the range of the target value
45
+ !target_range[:start].nil? && !target_range[:end].nil? && search_range[:start] <= target_range[:start] && search_range[:end] >= target_range[:end]
46
+ when 'ne' # the range of the search value does not fully contain the range of the target value
47
+ target_range[:start].nil? || target_range[:end].nil? || search_range[:start] > target_range[:start] || search_range[:end] < target_range[:end]
48
+ when 'gt' # the range above the search value intersects (i.e. overlaps) with the range of the target value
49
+ target_range[:end].nil? || search_range[:end] < target_range[:end] || (search_range[:end] < (target_range[:end] + 1) && extend_end)
50
+ when 'lt' # the range below the search value intersects (i.e. overlaps) with the range of the target value
51
+ target_range[:start].nil? || search_range[:start] > target_range[:start] || (search_range[:start] > (target_range[:start] - 1) && extend_start)
52
+ when 'ge'
53
+ fhir_date_comparer(search_range, target_range, 'gt', extend_start:, extend_end:) || fhir_date_comparer(search_range, target_range, 'eq')
54
+ when 'le'
55
+ fhir_date_comparer(search_range, target_range, 'lt', extend_start:, extend_end:) || fhir_date_comparer(search_range, target_range, 'eq')
56
+ when 'sa' # the range above the search value contains the range of the target value
57
+ !target_range[:start].nil? && search_range[:end] < target_range[:start]
58
+ when 'eb' # the range below the search value contains the range of the target value
59
+ !target_range[:end].nil? && search_range[:start] > target_range[:end]
60
+ when 'ap' # the range of the search value overlaps with the range of the target value
61
+ if target_range[:start].nil? || target_range[:end].nil?
62
+ (target_range[:start].nil? && search_range[:start] < target_range[:end]) ||
63
+ (target_range[:end].nil? && search_range[:end] > target_range[:start])
64
+ else
65
+ (search_range[:start] >= target_range[:start] && search_range[:start] <= target_range[:end]) ||
66
+ (search_range[:end] >= target_range[:start] && search_range[:end] <= target_range[:end])
67
+ end
68
+ end
69
+ end
70
+
71
+ def validate_date_search(search_value, target_value)
72
+ if target_value.instance_of? FHIR::Period
73
+ validate_period_search(search_value, target_value)
74
+ else
75
+ validate_datetime_search(search_value, target_value)
76
+ end
77
+ end
78
+
79
+ def validate_datetime_search(search_value, target_value)
80
+ comparator = search_value[0..1]
81
+ if %w[eq ge gt le lt ne sa eb ap].include? comparator
82
+ search_value = search_value[2..]
83
+ else
84
+ comparator = 'eq'
85
+ end
86
+ search_is_date = date?(search_value)
87
+ target_is_date = date?(target_value)
88
+ search_range = get_fhir_datetime_range(search_value)
89
+ target_range = get_fhir_datetime_range(target_value)
90
+ fhir_date_comparer(
91
+ search_range,
92
+ target_range,
93
+ comparator,
94
+ extend_start: !search_is_date && target_is_date,
95
+ extend_end: !search_is_date && target_is_date
96
+ )
97
+ end
98
+
99
+ def validate_period_search(search_value, target_value)
100
+ comparator = search_value[0..1]
101
+ if %w[eq ge gt le lt ne sa eb ap].include? comparator
102
+ search_value = search_value[2..]
103
+ else
104
+ comparator = 'eq'
105
+ end
106
+ search_is_date = date?(search_value)
107
+ search_range = get_fhir_datetime_range(search_value)
108
+ target_range = get_fhir_period_range(target_value)
109
+ fhir_date_comparer(
110
+ search_range,
111
+ target_range,
112
+ comparator,
113
+ extend_start: !search_is_date && date?(target_value.start),
114
+ extend_end: !search_is_date && date?(target_value.end)
115
+ )
116
+ end
117
+
118
+ def date?(value)
119
+ /^\d{4}(-\d{2})?(-\d{2})?$/.match?(value) # YYYY or YYYY-MM or YYYY-MM-DD
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'primitive_type'
4
+
5
+ module USQualityCoreTestKit
6
+ # This functionality has been moved to Inferno Core, but this reference is
7
+ # retained to avoid a breaking change.
8
+ FHIRResourceNavigation = Inferno::DSL::FHIRResourceNavigation
9
+ end
@@ -20,6 +20,9 @@ bindings will fail if none of their codings have a code/system belonging
20
20
  to the bound ValueSet. Quantity, Coding, and code element bindings will
21
21
  fail if their code/system are not found in the valueset.
22
22
 
23
+ Note: This test ignores a known validator slicing resolution message for
24
+ `DeviceRequest.modifierExtension`.
25
+
23
26
  )
24
27
 
25
28
  output :dar_code_found, :dar_extension_found
@@ -20,6 +20,9 @@ bindings will fail if none of their codings have a code/system belonging
20
20
  to the bound ValueSet. Quantity, Coding, and code element bindings will
21
21
  fail if their code/system are not found in the valueset.
22
22
 
23
+ Note: This test ignores a known validator slicing resolution message for
24
+ `DeviceRequest.modifierExtension`.
25
+
23
26
  )
24
27
 
25
28
  output :dar_code_found, :dar_extension_found
@@ -20,6 +20,10 @@ bindings will fail if none of their codings have a code/system belonging
20
20
  to the bound ValueSet. Quantity, Coding, and code element bindings will
21
21
  fail if their code/system are not found in the valueset.
22
22
 
23
+ Note: This test ignores validator messages for `Patient.extension`. This is a workaround for
24
+ a known validator package interaction where CQL can load US Core 7 definitions into the
25
+ validator session even though US Quality Core 0.5.0 is based on US Core 6.1.0.
26
+
23
27
  )
24
28
 
25
29
  output :dar_code_found, :dar_extension_found
@@ -98,8 +98,7 @@ module USQualityCoreTestKit
98
98
 
99
99
 
100
100
  VERSION_SPECIFIC_MESSAGE_FILTERS = [
101
- %r{Patient.*Patient\.extension\[\d+\]\[url='http://hl7\.org/fhir/us/core/StructureDefinition/us-core-(race|ethnicity|tribal-affiliation)\|\d+\.\d+(?:\.\d+)?'\]:\s*The extension URL must not contain a version\.},
102
- %r{Patient.*Patient\.extension\[\d+\]\.url:\s*Value is 'http://hl7\.org/fhir/us/core/StructureDefinition/us-core-(race|ethnicity|tribal-affiliation)\|\d+\.\d+(?:\.\d+)?'\s*but is fixed to 'http://hl7\.org/fhir/us/core/StructureDefinition/us-core-(race|ethnicity|tribal-affiliation)'\s*in the profile http://hl7\.org/fhir/us/core/StructureDefinition/us-core-(race|ethnicity|tribal-affiliation)\|\d+\.\d+(?:\.\d+)?#Extension\.url},
101
+ %r{\bPatient\.extension},
103
102
  %r{DeviceRequest.*DeviceRequest\.modifierExtension\[\d+\]:\s*Slicing cannot be evaluated:\s*Unable to resolve profile CanonicalType\[http://hl7\.org/fhir/5\.0/StructureDefinition/extension-DeviceRequest\.doNotPerform\]}
104
103
  ].freeze
105
104
 
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'us_core_test_kit/generator/group_generator'
4
-
5
3
  require_relative 'naming'
6
4
  require_relative 'special_cases'
7
5
 
8
6
  module USQualityCoreTestKit
9
7
  class Generator
10
- class GroupGenerator < USCoreTestKit::Generator::GroupGenerator
8
+ class GroupGenerator
11
9
  class << self
12
10
  def generate(ig_metadata, base_output_dir)
13
11
  ig_metadata.ordered_groups
@@ -16,10 +14,29 @@ module USQualityCoreTestKit
16
14
  end
17
15
  end
18
16
 
17
+ attr_accessor :group_metadata, :base_output_dir
18
+
19
+ def initialize(group_metadata, base_output_dir)
20
+ self.group_metadata = group_metadata
21
+ self.base_output_dir = base_output_dir
22
+ end
23
+
19
24
  def template
20
25
  @template ||= File.read(File.join(__dir__, 'templates', 'group.rb.erb'))
21
26
  end
22
27
 
28
+ def output
29
+ @output ||= ERB.new(template, trim_mode: '-').result(binding)
30
+ end
31
+
32
+ def base_output_file_name
33
+ "#{class_name.underscore}.rb"
34
+ end
35
+
36
+ def base_metadata_file_name
37
+ 'metadata.yml'
38
+ end
39
+
23
40
  def class_name
24
41
  "#{Naming.upper_camel_case_for_profile(group_metadata)}Group"
25
42
  end
@@ -28,6 +45,22 @@ module USQualityCoreTestKit
28
45
  "USQualityCore#{group_metadata.reformatted_version.upcase}"
29
46
  end
30
47
 
48
+ def title
49
+ group_metadata.title
50
+ end
51
+
52
+ def short_description
53
+ group_metadata.short_description
54
+ end
55
+
56
+ def output_file_name
57
+ File.join(base_output_dir, base_output_file_name)
58
+ end
59
+
60
+ def metadata_file_name
61
+ File.join(base_output_dir, profile_identifier, base_metadata_file_name)
62
+ end
63
+
31
64
  def profile_identifier
32
65
  Naming.snake_case_for_profile(group_metadata)
33
66
  end
@@ -36,16 +69,49 @@ module USQualityCoreTestKit
36
69
  "us_quality_core_#{group_metadata.reformatted_version}_#{profile_identifier}"
37
70
  end
38
71
 
72
+ def resource_type
73
+ group_metadata.resource
74
+ end
75
+
39
76
  def search_validation_resource_type
40
77
  "#{resource_type} resources"
41
78
  end
42
79
 
80
+ def profile_name
81
+ group_metadata.profile_name
82
+ end
83
+
84
+ def profile_url
85
+ group_metadata.profile_url
86
+ end
87
+
43
88
  def optional?
44
89
  SpecialCases::OPTIONAL_RESOURCES.include?(resource_type) || group_metadata.optional_profile?
45
90
  end
46
91
 
92
+ def generate
93
+ add_special_tests
94
+ File.write(output_file_name, output)
95
+ group_metadata.id = group_id
96
+ group_metadata.file_name = base_output_file_name
97
+ File.write(metadata_file_name, YAML.dump(group_metadata.to_hash))
98
+ end
99
+
47
100
  def add_special_tests; end
48
101
 
102
+ def test_id_list
103
+ @test_id_list ||=
104
+ group_metadata.tests.map { |test| test[:id] }
105
+ end
106
+
107
+ def test_file_list
108
+ @test_file_list ||=
109
+ group_metadata.tests.map do |test|
110
+ name_without_suffix = test[:file_name].delete_suffix('.rb')
111
+ name_without_suffix.start_with?('..') ? name_without_suffix : "#{profile_identifier}/#{name_without_suffix}"
112
+ end
113
+ end
114
+
49
115
  def required_searches
50
116
  group_metadata.searches.select { |search| search[:expectation] == 'SHALL' }
51
117
  end
@@ -2,14 +2,110 @@
2
2
 
3
3
  require_relative 'special_cases'
4
4
 
5
- require 'us_core_test_kit/generator/group_metadata'
6
-
7
5
  module USQualityCoreTestKit
8
6
  class Generator
9
- class GroupMetadata < USCoreTestKit::Generator::GroupMetadata
7
+ class GroupMetadata
8
+ ATTRIBUTES = %i[
9
+ name
10
+ class_name
11
+ version
12
+ reformatted_version
13
+ resource
14
+ profile_url
15
+ profile_name
16
+ profile_version
17
+ title
18
+ short_description
19
+ is_delayed
20
+ interactions
21
+ operations
22
+ searches
23
+ search_definitions
24
+ include_params
25
+ revincludes
26
+ required_concepts
27
+ must_supports
28
+ mandatory_elements
29
+ bindings
30
+ references
31
+ tests
32
+ granular_scope_tests
33
+ id
34
+ file_name
35
+ delayed_references
36
+ resource_conformance_expectation
37
+ ].freeze
38
+
39
+ ATTRIBUTES.each { |name| attr_accessor name }
40
+
41
+ def initialize(metadata)
42
+ metadata.each do |key, value|
43
+ raise "Unknown attribute #{key}" unless ATTRIBUTES.include? key
44
+
45
+ instance_variable_set(:"@#{key}", value)
46
+ end
47
+ end
48
+
49
+ def exclude_search_tests?
50
+ delayed? && !searchable_delayed_resource?
51
+ end
52
+
53
+ def non_uscdi_resource?
54
+ SpecialCases::NON_USCDI_RESOURCES.key?(resource) && SpecialCases::NON_USCDI_RESOURCES[resource].include?(reformatted_version)
55
+ end
56
+
57
+ def optional_profile?
58
+ SpecialCases::OPTIONAL_PROFILES.key?(profile_url) && SpecialCases::OPTIONAL_PROFILES[profile_url].include?(reformatted_version)
59
+ end
60
+
61
+ def searchable_delayed_resource?
62
+ SpecialCases::SEARCHABLE_DELAYED_RESOURCES.key?(resource) && SpecialCases::SEARCHABLE_DELAYED_RESOURCES[resource].include?(reformatted_version)
63
+ end
64
+
65
+ def add_test(id:, file_name:)
66
+ self.tests ||= []
67
+
68
+ test_metadata = {
69
+ id: id,
70
+ file_name: file_name
71
+ }
72
+
73
+ if delayed? && id.include?('read')
74
+ self.tests.unshift(test_metadata)
75
+ else
76
+ self.tests << test_metadata
77
+ end
78
+ end
79
+
80
+ def add_granular_scope_test(id:, file_name:)
81
+ self.granular_scope_tests ||= []
82
+
83
+ self.granular_scope_tests << {
84
+ id:,
85
+ file_name:
86
+ }
87
+ end
88
+
89
+ def to_hash
90
+ ATTRIBUTES.each_with_object({}) { |key, hash| hash[key] = send(key) unless send(key).nil? }
91
+ end
92
+
93
+ def add_delayed_references(delayed_profiles, ig_resources)
94
+ self.delayed_references =
95
+ references
96
+ .select { |reference| (reference[:profiles] & delayed_profiles).present? }
97
+ .map do |reference|
98
+ profile_urls = (reference[:profiles] & delayed_profiles)
99
+ delayed_resources = profile_urls.map { |url| ig_resources.resource_for_profile(url) }
100
+ {
101
+ path: reference[:path].gsub("#{resource}.", ''),
102
+ resources: delayed_resources
103
+ }
104
+ end
105
+ end
106
+
10
107
  def delayed?
11
108
  # rubocop:disable Naming/MemoizedInstanceVariableName
12
- # @is_delayed is used in USCoreTestKit::Generator::GroupMetadata
13
109
  @is_delayed ||= if resource == 'Patient'
14
110
  false
15
111
  else