davinci_us_drug_formulary_test_kit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/capability_statement/conformance_support_test.rb +41 -0
  4. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/capability_statement/fhir_version_test.rb +15 -0
  5. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/capability_statement/instantiate_test.rb +19 -0
  6. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/capability_statement/json_support_test.rb +40 -0
  7. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/capability_statement/profile_support_test.rb +39 -0
  8. data/lib/davinci_us_drug_formulary_test_kit/custom_groups/v2.0.1/capability_statement_group.rb +78 -0
  9. data/lib/davinci_us_drug_formulary_test_kit/date_search_validation.rb +121 -0
  10. data/lib/davinci_us_drug_formulary_test_kit/fhir_resource_navigation.rb +155 -0
  11. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_code_search_test.rb +54 -0
  12. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_drug_tier_search_test.rb +43 -0
  13. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_formulary_include_search_test.rb +40 -0
  14. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_formulary_search_test.rb +43 -0
  15. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_id_search_test.rb +42 -0
  16. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_lastupdated_search_test.rb +42 -0
  17. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_must_support_test.rb +46 -0
  18. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_period_search_test.rb +42 -0
  19. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_pharmacy_benefit_type_search_test.rb +43 -0
  20. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_read_test.rb +26 -0
  21. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_reference_resolution_test.rb +40 -0
  22. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_status_search_test.rb +42 -0
  23. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_subject_include_search_test.rb +40 -0
  24. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_subject_search_test.rb +43 -0
  25. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/basic_validation_test.rb +39 -0
  26. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic/metadata.yml +292 -0
  27. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/basic_group.rb +107 -0
  28. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_coverage_area_search_test.rb +45 -0
  29. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_coverage_type_search_test.rb +45 -0
  30. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_formulary_coverage_search_test.rb +45 -0
  31. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_id_search_test.rb +42 -0
  32. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_identifier_search_test.rb +43 -0
  33. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_lastupdated_search_test.rb +42 -0
  34. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_must_support_test.rb +42 -0
  35. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_name_search_test.rb +42 -0
  36. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_period_search_test.rb +42 -0
  37. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_read_test.rb +26 -0
  38. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_status_search_test.rb +53 -0
  39. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_type_search_test.rb +43 -0
  40. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/formulary_validation_test.rb +39 -0
  41. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary/metadata.yml +278 -0
  42. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/formulary_group.rb +104 -0
  43. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_address_city_search_test.rb +44 -0
  44. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_address_postalcode_search_test.rb +44 -0
  45. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_address_search_test.rb +42 -0
  46. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_address_state_search_test.rb +44 -0
  47. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_id_search_test.rb +56 -0
  48. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_lastupdated_search_test.rb +44 -0
  49. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_must_support_test.rb +37 -0
  50. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_read_test.rb +26 -0
  51. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/location_validation_test.rb +39 -0
  52. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location/metadata.yml +177 -0
  53. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/location_group.rb +92 -0
  54. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_code_search_test.rb +43 -0
  55. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_doseform_search_test.rb +45 -0
  56. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_drug_name_search_test.rb +44 -0
  57. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_id_search_test.rb +42 -0
  58. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_lastupdated_search_test.rb +42 -0
  59. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_must_support_test.rb +47 -0
  60. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_read_test.rb +26 -0
  61. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_status_search_test.rb +53 -0
  62. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/medication_knowledge_validation_test.rb +39 -0
  63. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge/metadata.yml +214 -0
  64. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/medication_knowledge_group.rb +91 -0
  65. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/metadata.yml +1192 -0
  66. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/metadata.yml +371 -0
  67. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_coverage_area_search_test.rb +43 -0
  68. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_coverage_type_search_test.rb +43 -0
  69. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_formulary_coverage_include_search_test.rb +40 -0
  70. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_formulary_coverage_search_test.rb +43 -0
  71. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_id_search_test.rb +42 -0
  72. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_identifier_search_test.rb +43 -0
  73. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_lastupdated_search_test.rb +42 -0
  74. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_must_support_test.rb +66 -0
  75. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_name_search_test.rb +42 -0
  76. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_period_search_test.rb +42 -0
  77. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_read_test.rb +26 -0
  78. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_reference_resolution_test.rb +40 -0
  79. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_status_search_test.rb +53 -0
  80. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_type_search_test.rb +43 -0
  81. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan/payer_insurance_plan_validation_test.rb +39 -0
  82. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/payer_insurance_plan_group.rb +108 -0
  83. data/lib/davinci_us_drug_formulary_test_kit/generated/v2.0.1/usdf_test_suite.rb +114 -0
  84. data/lib/davinci_us_drug_formulary_test_kit/generator/group_generator.rb +181 -0
  85. data/lib/davinci_us_drug_formulary_test_kit/generator/group_metadata.rb +79 -0
  86. data/lib/davinci_us_drug_formulary_test_kit/generator/group_metadata_extractor.rb +329 -0
  87. data/lib/davinci_us_drug_formulary_test_kit/generator/ig_loader.rb +77 -0
  88. data/lib/davinci_us_drug_formulary_test_kit/generator/ig_metadata.rb +33 -0
  89. data/lib/davinci_us_drug_formulary_test_kit/generator/ig_metadata_extractor.rb +40 -0
  90. data/lib/davinci_us_drug_formulary_test_kit/generator/ig_resources.rb +60 -0
  91. data/lib/davinci_us_drug_formulary_test_kit/generator/include_search_test_generator.rb +68 -0
  92. data/lib/davinci_us_drug_formulary_test_kit/generator/must_support_metadata_extractor.rb +384 -0
  93. data/lib/davinci_us_drug_formulary_test_kit/generator/must_support_test_generator.rb +117 -0
  94. data/lib/davinci_us_drug_formulary_test_kit/generator/naming.rb +28 -0
  95. data/lib/davinci_us_drug_formulary_test_kit/generator/read_test_generator.rb +92 -0
  96. data/lib/davinci_us_drug_formulary_test_kit/generator/reference_resolution_test_generator.rb +91 -0
  97. data/lib/davinci_us_drug_formulary_test_kit/generator/search_definition_metadata_extractor.rb +187 -0
  98. data/lib/davinci_us_drug_formulary_test_kit/generator/search_metadata_extractor.rb +59 -0
  99. data/lib/davinci_us_drug_formulary_test_kit/generator/search_test_generator.rb +270 -0
  100. data/lib/davinci_us_drug_formulary_test_kit/generator/suite_generator.rb +94 -0
  101. data/lib/davinci_us_drug_formulary_test_kit/generator/terminology_binding_metadata_extractor.rb +116 -0
  102. data/lib/davinci_us_drug_formulary_test_kit/generator/validation_test_generator.rb +102 -0
  103. data/lib/davinci_us_drug_formulary_test_kit/generator/value_extractor.rb +113 -0
  104. data/lib/davinci_us_drug_formulary_test_kit/generator.rb +94 -0
  105. data/lib/davinci_us_drug_formulary_test_kit/igs/package/r4_search-parameters.json +65408 -0
  106. data/lib/davinci_us_drug_formulary_test_kit/igs/package.tgz +0 -0
  107. data/lib/davinci_us_drug_formulary_test_kit/must_support_test.rb +224 -0
  108. data/lib/davinci_us_drug_formulary_test_kit/read_test.rb +62 -0
  109. data/lib/davinci_us_drug_formulary_test_kit/reference_resolution_test.rb +174 -0
  110. data/lib/davinci_us_drug_formulary_test_kit/request_logger.rb +46 -0
  111. data/lib/davinci_us_drug_formulary_test_kit/search_test.rb +767 -0
  112. data/lib/davinci_us_drug_formulary_test_kit/search_test_properties.rb +58 -0
  113. data/lib/davinci_us_drug_formulary_test_kit/validation_test.rb +56 -0
  114. data/lib/davinci_us_drug_formulary_test_kit/version.rb +5 -0
  115. data/lib/davinci_us_drug_formulary_test_kit.rb +1 -0
  116. metadata +245 -0
@@ -0,0 +1,94 @@
1
+ require_relative 'naming'
2
+
3
+ module DaVinciUSDrugFormularyTestKit
4
+ class Generator
5
+ class SuiteGenerator
6
+ class << self
7
+ def generate(ig_metadata, base_output_dir)
8
+ new(ig_metadata, base_output_dir).generate
9
+ end
10
+ end
11
+
12
+ attr_accessor :ig_metadata, :base_output_dir
13
+
14
+ def initialize(ig_metadata, base_output_dir)
15
+ self.ig_metadata = ig_metadata
16
+ self.base_output_dir = base_output_dir
17
+ end
18
+
19
+ def version_specific_message_filters
20
+ []
21
+ end
22
+
23
+ def template
24
+ @template ||= File.read(File.join(__dir__, 'templates', 'suite.rb.erb'))
25
+ end
26
+
27
+ def output
28
+ @output ||= ERB.new(template).result(binding)
29
+ end
30
+
31
+ def base_output_file_name
32
+ 'usdf_test_suite.rb'
33
+ end
34
+
35
+ def class_name
36
+ 'USDFTestSuite'
37
+ end
38
+
39
+ def module_name
40
+ "USDF#{ig_metadata.reformatted_version.upcase}"
41
+ end
42
+
43
+ def output_file_name
44
+ File.join(base_output_dir, base_output_file_name)
45
+ end
46
+
47
+ def suite_id
48
+ "davinci_us_drug_formulary_#{ig_metadata.reformatted_version}"
49
+ end
50
+
51
+ def title
52
+ "Da Vinci US Drug Formulary #{ig_metadata.ig_version}"
53
+ end
54
+
55
+ def short_title
56
+ "US Drug Formulary #{ig_metadata.ig_version}"
57
+ end
58
+
59
+ def validator_env_name
60
+ "#{ig_metadata.reformatted_version.upcase}_VALIDATOR_URL"
61
+ end
62
+
63
+ def ig_link
64
+ 'https://hl7.org/fhir/us/davinci-drug-formulary/STU2.0.1/'
65
+ end
66
+
67
+ def generate
68
+ File.write(output_file_name, output)
69
+ end
70
+
71
+ def groups
72
+ ig_metadata.ordered_groups
73
+ end
74
+
75
+ def group_id_list
76
+ @group_id_list ||=
77
+ groups.map(&:id)
78
+ end
79
+
80
+ def group_file_list
81
+ @group_file_list ||=
82
+ groups.map { |group| group.file_name.delete_suffix('.rb') }
83
+ end
84
+
85
+ def capability_statement_file_name
86
+ "../../custom_groups/#{ig_metadata.ig_version}/capability_statement_group"
87
+ end
88
+
89
+ def capability_statement_group_id
90
+ "usdf_#{ig_metadata.reformatted_version}_capability_statement"
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,116 @@
1
+ module DaVinciUSDrugFormularyTestKit
2
+ class Generator
3
+ class TerminologyBindingMetadataExtractor
4
+ attr_accessor :profile_elements, :ig_resources, :resource
5
+
6
+ def initialize(profile_elements, ig_resources, resource)
7
+ self.profile_elements = profile_elements
8
+ self.ig_resources = ig_resources
9
+ self.resource = resource
10
+ end
11
+
12
+ def terminology_bindings
13
+ (element_terminology_bindings + extension_terminology_bindings).compact
14
+ # add_terminology_bindings_from_extensions
15
+ # profile_elements.select { |element| element.type&.first&.code == 'Extension' }
16
+ # .each { |extension| add_terminology_bindings_from_extension(extension) }
17
+ end
18
+
19
+ def element_has_fixed_value?(element)
20
+ case element.type.first.code
21
+ when 'Quantity'
22
+ code = profile_elements.find { |e| e.path == "#{element.path}.code" }
23
+ system = profile_elements.find { |e| e.path == "#{element.path}.system" }
24
+ code&.fixedCode || system&.fixedUri
25
+ when 'code'
26
+ element.fixedCode.present?
27
+ end
28
+ end
29
+
30
+ def element_has_optional_binding_slice?(element)
31
+ element.sliceName.present? && element.min.zero?
32
+ end
33
+
34
+ def profile_elements_with_bindings
35
+ profile_elements
36
+ .select { |element| element.binding.present? && element.binding.strength == 'required' }
37
+ .reject { |element| element_has_fixed_value?(element) || element_has_optional_binding_slice?(element) }
38
+ end
39
+
40
+ def element_terminology_bindings
41
+ profile_elements_with_bindings.map do |element|
42
+ binding = {
43
+ type: element.type.first.code,
44
+ strength: element.binding.strength,
45
+ # Goal.target.detail has an unbound binding
46
+ system: element.binding.valueSet&.split('|')&.first,
47
+ path: element.path.gsub('[x]', '').gsub("#{resource}.", '')
48
+ }
49
+
50
+ binding[:required_binding_slice] = true if element.sliceName.present? && element.min.positive?
51
+
52
+ binding
53
+ end
54
+ end
55
+
56
+ def extension_profile_elements
57
+ profile_elements
58
+ .select { |element| element.type&.first&.code == 'Extension' }
59
+ .select { |element| extension_profile_url(element).present? }
60
+ end
61
+
62
+ def extension_profile_url(extension)
63
+ extension.type.first.profile&.first
64
+ end
65
+
66
+ def extension_terminology_bindings
67
+ extension_profile_elements
68
+ .flat_map do |extension_profile_element|
69
+ url = extension_profile_url(extension_profile_element)
70
+ extension = ig_resources.profile_by_url(url)
71
+
72
+ # TODO: Temporaray fix for extension defined out of US Core. FI-1623
73
+ next if extension.nil?
74
+
75
+ elements = extension.snapshot.element
76
+ elements_with_bindings = elements.select do |element|
77
+ element.binding.present? && !element.id.include?('Extension.extension')
78
+ end
79
+
80
+ elements_with_bindings.map do |element|
81
+ {
82
+ type: element.type.first.code,
83
+ strength: element.binding.strength,
84
+ system: element.binding.valueSet&.split('|')&.first,
85
+ path: element.path.gsub('[x]', '').gsub('Extension.', ''),
86
+ extensions: [url]
87
+ }
88
+ end + nested_extension_terminology_bindings(elements, url)
89
+ end
90
+ end
91
+
92
+ def nested_extension_terminology_bindings(elements, extension_url)
93
+ nested_extensions = elements.select { |element| element.path == 'Extension.extension' }
94
+ nested_extensions.flat_map do |nested_extension|
95
+ nested_extension_element = elements.find { |element| element.id == "#{nested_extension.id}.url" }
96
+ next unless nested_extension_element.present?
97
+
98
+ nested_extension_url = nested_extension_element.fixedUri
99
+ nested_elements_with_bindings = elements.select do |element|
100
+ element.id.include?(nested_extension.id) && element.binding.present?
101
+ end
102
+
103
+ nested_elements_with_bindings.map do |element|
104
+ {
105
+ type: element.type.first.code,
106
+ strength: element.binding.strength,
107
+ system: element.binding.valueSet&.split('|')&.first,
108
+ path: element.path.gsub('[x]', '').gsub('Extension.extension.', ''),
109
+ extensions: [extension_url, nested_extension_url]
110
+ }
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,102 @@
1
+ require_relative 'naming'
2
+ module DaVinciUSDrugFormularyTestKit
3
+ class Generator
4
+ class ValidationTestGenerator
5
+ class << self
6
+ def generate(ig_metadata, base_output_dir)
7
+ ig_metadata.groups
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', 'validation.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, directory_name)
33
+ end
34
+
35
+ def output_file_name
36
+ File.join(output_file_directory, base_output_file_name)
37
+ end
38
+
39
+ def directory_name
40
+ Naming.snake_case_for_profile(group_metadata)
41
+ end
42
+
43
+ def profile_identifier
44
+ Naming.snake_case_for_profile(group_metadata)
45
+ end
46
+
47
+ def profile_url
48
+ group_metadata.profile_url
49
+ end
50
+
51
+ def profile_name
52
+ group_metadata.profile_name
53
+ end
54
+
55
+ def profile_version
56
+ group_metadata.profile_version
57
+ end
58
+
59
+ def test_id
60
+ "usdf_#{group_metadata.reformatted_version}_#{profile_identifier}_validation_test"
61
+ end
62
+
63
+ def class_name
64
+ "#{Naming.upper_camel_case_for_profile(group_metadata)}ValidationTest"
65
+ end
66
+
67
+ def module_name
68
+ "DaVinciUSDrugFormulary#{group_metadata.reformatted_version.upcase}"
69
+ end
70
+
71
+ def resource_type
72
+ group_metadata.resource
73
+ end
74
+
75
+ def description
76
+ <<~DESCRIPTION
77
+ This test verifies resources returned from the first search conform to
78
+ the [#{profile_name} profile](#{profile_url}).
79
+
80
+ Systems must demonstrate at least one valid example in order to pass this test.
81
+ It verifies the presence of mandatory elements and that elements with
82
+ required bindings contain appropriate values. CodeableConcept element
83
+ bindings will fail if none of their codings have a code/system belonging
84
+ to the bound ValueSet. Quantity, Coding, and code element bindings will
85
+ fail if their code/system are not found in the valueset.
86
+ DESCRIPTION
87
+ end
88
+
89
+ def generate
90
+ FileUtils.mkdir_p(output_file_directory)
91
+ File.write(output_file_name, output)
92
+
93
+ test_metadata = {
94
+ id: test_id,
95
+ file_name: base_output_file_name
96
+ }
97
+
98
+ group_metadata.add_test(**test_metadata)
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,113 @@
1
+ module DaVinciUSDrugFormularyTestKit
2
+ class Generator
3
+ class ValueExactor
4
+ attr_accessor :ig_resources, :resource, :profile_elements
5
+
6
+ def initialize(ig_resources, resource, profile_elements)
7
+ self.ig_resources = ig_resources
8
+ self.resource = resource
9
+ self.profile_elements = profile_elements
10
+ end
11
+
12
+ def values_from_slicing(profile_element, type)
13
+ (
14
+ values_from_fixed_codes(profile_element, type) +
15
+ values_from_pattern_coding(profile_element, type) +
16
+ values_from_pattern_codeable_concept(profile_element, type)
17
+ ).uniq
18
+ end
19
+
20
+ def values_from_required_binding(profile_element)
21
+ return [] unless profile_element&.max == '*'
22
+
23
+ profile_elements
24
+ .select do |element|
25
+ element.path == profile_element.path && element.binding&.strength == 'required'
26
+ end
27
+ .map { |element| values_from_value_set_binding(element) }
28
+ .flatten.compact
29
+ end
30
+
31
+ def values_from_fixed_codes(profile_element, type)
32
+ return [] unless type == 'CodeableConcept'
33
+
34
+ profile_elements
35
+ .select do |element|
36
+ element.path == "#{profile_element.path}.coding.code" && element.fixedCode.present?
37
+ end
38
+ .map(&:fixedCode)
39
+ end
40
+
41
+ def values_from_pattern_coding(profile_element, type)
42
+ return [] unless type == 'CodeableConcept'
43
+
44
+ profile_elements
45
+ .select do |element|
46
+ element.path == "#{profile_element.path}.coding" && element.patternCoding.present?
47
+ end
48
+ .map { |element| element.patternCoding.code }
49
+ end
50
+
51
+ def values_from_pattern_codeable_concept(profile_element, type)
52
+ return [] unless type == 'CodeableConcept'
53
+
54
+ profile_elements
55
+ .select do |element|
56
+ element.path == profile_element.path && element.patternCodeableConcept.present? && element.min.positive?
57
+ end
58
+ .map { |element| element.patternCodeableConcept.coding.first.code }
59
+ end
60
+
61
+ def value_set_binding(the_element)
62
+ the_element&.binding
63
+ end
64
+
65
+ def value_set(the_element)
66
+ ig_resources.value_set_by_url(value_set_binding(the_element)&.valueSet)
67
+ end
68
+
69
+ def bound_systems(the_element)
70
+ bound_systems_from_valueset(value_set(the_element))
71
+ end
72
+
73
+ def bound_systems_from_valueset(value_set)
74
+ value_set&.compose&.include&.map do |include|
75
+ if include.concept.present?
76
+ include
77
+ elsif include.system.present? && include.filter&.empty? # Cannot process intensional value set with filters
78
+ ig_resources.code_system_by_url(include.system)
79
+ elsif include.valueSet.present?
80
+ include.valueSet.map do |vs|
81
+ a_value_set = ig_resources.value_set_by_url(vs)
82
+ bound_systems_from_valueset(a_value_set)
83
+ end
84
+ end
85
+ end&.flatten&.compact
86
+ end
87
+
88
+ def values_from_value_set_binding(the_element)
89
+ bound_systems = bound_systems(the_element)
90
+
91
+ return [] if bound_systems.blank?
92
+
93
+ bound_systems.flat_map { |system| system.concept.map(&:code) }.uniq
94
+ end
95
+
96
+ def fhir_metadata(current_path)
97
+ FHIR.const_get(resource)::METADATA[current_path]
98
+ end
99
+
100
+ def values_from_resource_metadata(paths)
101
+ values = []
102
+
103
+ paths.each do |current_path|
104
+ current_metadata = fhir_metadata(current_path)
105
+
106
+ values += current_metadata['valid_codes'].values.flatten if current_metadata&.dig('valid_codes').present?
107
+ end
108
+
109
+ values
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,94 @@
1
+ require 'fhir_models'
2
+ require 'inferno/ext/fhir_models'
3
+
4
+ require_relative 'generator/ig_loader'
5
+ require_relative 'generator/ig_metadata_extractor'
6
+ require_relative 'generator/group_generator'
7
+ require_relative 'generator/must_support_test_generator'
8
+ require_relative 'generator/read_test_generator'
9
+ require_relative 'generator/reference_resolution_test_generator'
10
+ require_relative 'generator/search_test_generator'
11
+ require_relative 'generator/suite_generator'
12
+ require_relative 'generator/validation_test_generator'
13
+ require_relative 'generator/include_search_test_generator'
14
+
15
+ module DaVinciUSDrugFormularyTestKit
16
+ class Generator
17
+ def self.generate
18
+ ig_packages = Dir.glob(File.join(Dir.pwd, 'lib', 'davinci_us_drug_formulary_test_kit', 'igs', '*.tgz'))
19
+
20
+ ig_packages.each do |ig_package|
21
+ new(ig_package).generate
22
+ end
23
+ end
24
+
25
+ attr_accessor :ig_resources, :ig_metadata, :ig_file_name
26
+
27
+ def initialize(ig_file_name)
28
+ self.ig_file_name = ig_file_name
29
+ end
30
+
31
+ def generate
32
+ load_ig_package
33
+ extract_metadata
34
+ generate_search_tests
35
+ generate_read_tests
36
+ generate_include_search_tests
37
+ generate_validation_tests
38
+ generate_must_support_tests
39
+ generate_reference_resolution_tests
40
+
41
+ generate_groups
42
+
43
+ generate_suites
44
+ end
45
+
46
+ def extract_metadata
47
+ self.ig_metadata = IGMetadataExtractor.new(ig_resources).extract
48
+
49
+ FileUtils.mkdir_p(base_output_dir)
50
+ File.write(File.join(base_output_dir, 'metadata.yml'), YAML.dump(ig_metadata.to_hash))
51
+ end
52
+
53
+ def base_output_dir
54
+ File.join(__dir__, 'generated', ig_metadata.ig_version)
55
+ end
56
+
57
+ def load_ig_package
58
+ FHIR.logger = Logger.new('/dev/null')
59
+ self.ig_resources = IGLoader.new(ig_file_name).load
60
+ end
61
+
62
+ def generate_reference_resolution_tests
63
+ ReferenceResolutionTestGenerator.generate(ig_metadata, base_output_dir)
64
+ end
65
+
66
+ def generate_must_support_tests
67
+ MustSupportTestGenerator.generate(ig_metadata, base_output_dir)
68
+ end
69
+
70
+ def generate_validation_tests
71
+ ValidationTestGenerator.generate(ig_metadata, base_output_dir)
72
+ end
73
+
74
+ def generate_read_tests
75
+ ReadTestGenerator.generate(ig_metadata, base_output_dir)
76
+ end
77
+
78
+ def generate_search_tests
79
+ SearchTestGenerator.generate(ig_metadata, base_output_dir)
80
+ end
81
+
82
+ def generate_include_search_tests
83
+ IncludeSearchTestGenerator.generate(ig_metadata, base_output_dir)
84
+ end
85
+
86
+ def generate_groups
87
+ GroupGenerator.generate(ig_metadata, base_output_dir)
88
+ end
89
+
90
+ def generate_suites
91
+ SuiteGenerator.generate(ig_metadata, base_output_dir)
92
+ end
93
+ end
94
+ end