davinci_pas_test_kit 0.9.0

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 (168) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/davinci_pas_test_kit/client_suite.rb +289 -0
  4. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/claim_status/pas_claim_status_test.rb +109 -0
  5. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_response_attest.rb +39 -0
  6. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_test.rb +38 -0
  7. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_response_attest.rb +38 -0
  8. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_test.rb +43 -0
  9. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_must_support_test.rb +51 -0
  10. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_response_attest.rb +39 -0
  11. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_inquire_test.rb +35 -0
  12. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_response_attest.rb +39 -0
  13. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_test.rb +43 -0
  14. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_submit_must_support_test.rb +57 -0
  15. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_request_test.rb +31 -0
  16. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_validation_test.rb +18 -0
  17. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/nonconformant_pas_bundle.json +16 -0
  18. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_inquiry_error_test.rb +38 -0
  19. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_submission_error_test.rb +56 -0
  20. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/device_request_metadata.yml +112 -0
  21. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/medication_request_metadata.yml +183 -0
  22. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/nutrition_order_metadata.yml +109 -0
  23. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_client_must_support_requirement_test.rb +117 -0
  24. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/pas_server_must_support_requirement_test.rb +116 -0
  25. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/service_request_metadata.yml +148 -0
  26. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_approval_group.rb +26 -0
  27. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_authentication_group.rb +49 -0
  28. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_denial_group.rb +41 -0
  29. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_pended_group.rb +56 -0
  30. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_error_group.rb +20 -0
  31. data/lib/davinci_pas_test_kit/ext/inferno_core/record_response_route.rb +98 -0
  32. data/lib/davinci_pas_test_kit/ext/inferno_core/request.rb +19 -0
  33. data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +18 -0
  34. data/lib/davinci_pas_test_kit/fhir_resource_navigation.rb +72 -0
  35. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_inquiry_request_beneficiary_must_support_test.rb +75 -0
  36. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/client_submit_request_beneficiary_must_support_test.rb +75 -0
  37. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/metadata.yml +162 -0
  38. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_request_beneficiary_must_support_test.rb +75 -0
  39. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_inquiry_response_beneficiary_must_support_test.rb +75 -0
  40. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_request_beneficiary_must_support_test.rb +75 -0
  41. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/server_submit_response_beneficiary_must_support_test.rb +75 -0
  42. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/claim_operation_test.rb +67 -0
  43. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/metadata.yml +577 -0
  44. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/claim_inquiry_operation_test.rb +57 -0
  45. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/client_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
  46. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/metadata.yml +516 -0
  47. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/server_inquiry_request_claim_inquiry_must_support_test.rb +95 -0
  48. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/client_submit_request_claim_update_must_support_test.rb +102 -0
  49. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/metadata.yml +591 -0
  50. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/server_submit_request_claim_update_must_support_test.rb +102 -0
  51. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/metadata.yml +311 -0
  52. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/server_inquiry_response_claiminquiryresponse_must_support_test.rb +73 -0
  53. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/metadata.yml +318 -0
  54. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/server_submit_response_claimresponse_must_support_test.rb +75 -0
  55. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_denial_pas_response_bundle_validation_test.rb +53 -0
  56. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pas_request_bundle_validation_test.rb +55 -0
  57. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_inquiry_request_bundle_validation_test.rb +55 -0
  58. data/lib/davinci_pas_test_kit/generated/v2.0.1/client_tests/client_pended_pas_response_bundle_validation_test.rb +53 -0
  59. data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/metadata.yml +130 -0
  60. data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/server_submit_response_communication_request_must_support_test.rb +58 -0
  61. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_inquiry_request_coverage_must_support_test.rb +55 -0
  62. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/client_submit_request_coverage_must_support_test.rb +55 -0
  63. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/metadata.yml +111 -0
  64. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_inquiry_request_coverage_must_support_test.rb +55 -0
  65. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/server_submit_request_coverage_must_support_test.rb +55 -0
  66. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/client_submit_request_device_request_must_support_test.rb +51 -0
  67. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/metadata.yml +112 -0
  68. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/server_submit_request_device_request_must_support_test.rb +51 -0
  69. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/client_submit_request_encounter_must_support_test.rb +67 -0
  70. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/metadata.yml +213 -0
  71. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/server_submit_request_encounter_must_support_test.rb +67 -0
  72. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_inquiry_request_insurer_must_support_test.rb +60 -0
  73. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/client_submit_request_insurer_must_support_test.rb +60 -0
  74. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/metadata.yml +104 -0
  75. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_request_insurer_must_support_test.rb +60 -0
  76. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_inquiry_response_insurer_must_support_test.rb +60 -0
  77. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_request_insurer_must_support_test.rb +60 -0
  78. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/server_submit_response_insurer_must_support_test.rb +60 -0
  79. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/client_submit_request_medication_request_must_support_test.rb +61 -0
  80. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/metadata.yml +183 -0
  81. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/server_submit_request_medication_request_must_support_test.rb +61 -0
  82. data/lib/davinci_pas_test_kit/generated/v2.0.1/metadata.yml +5253 -0
  83. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/client_submit_request_nutrition_order_must_support_test.rb +53 -0
  84. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/metadata.yml +109 -0
  85. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/server_submit_request_nutrition_order_must_support_test.rb +53 -0
  86. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_inquiry_must_support_use_case_group.rb +51 -0
  87. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_client_submit_must_support_use_case_group.rb +61 -0
  88. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/client_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
  89. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/metadata.yml +77 -0
  90. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_inquiry_request_pas_inquiry_request_bundle_must_support_test.rb +53 -0
  91. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_pas_inquiry_request_bundle_validation_test.rb +83 -0
  92. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/metadata.yml +67 -0
  93. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_inquiry_response_pas_inquiry_response_bundle_must_support_test.rb +52 -0
  94. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_pas_inquiry_response_bundle_validation_test.rb +80 -0
  95. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/client_submit_request_pas_request_bundle_must_support_test.rb +53 -0
  96. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/metadata.yml +77 -0
  97. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_pas_request_bundle_validation_test.rb +83 -0
  98. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_submit_request_pas_request_bundle_must_support_test.rb +53 -0
  99. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/metadata.yml +71 -0
  100. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_pas_response_bundle_validation_test.rb +80 -0
  101. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_submit_response_pas_response_bundle_must_support_test.rb +52 -0
  102. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_approval_use_case_group.rb +59 -0
  103. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_denial_use_case_group.rb +59 -0
  104. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_must_support_use_case_group.rb +265 -0
  105. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_pended_use_case_group.rb +84 -0
  106. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_inquiry_request_practitioner_must_support_test.rb +53 -0
  107. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/client_submit_request_practitioner_must_support_test.rb +53 -0
  108. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/metadata.yml +74 -0
  109. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_request_practitioner_must_support_test.rb +53 -0
  110. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_inquiry_response_practitioner_must_support_test.rb +53 -0
  111. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_request_practitioner_must_support_test.rb +53 -0
  112. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/server_submit_response_practitioner_must_support_test.rb +53 -0
  113. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_inquiry_request_practitioner_role_must_support_test.rb +49 -0
  114. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/client_submit_request_practitioner_role_must_support_test.rb +49 -0
  115. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/metadata.yml +81 -0
  116. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_request_practitioner_role_must_support_test.rb +49 -0
  117. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_inquiry_response_practitioner_role_must_support_test.rb +49 -0
  118. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_request_practitioner_role_must_support_test.rb +49 -0
  119. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/server_submit_response_practitioner_role_must_support_test.rb +49 -0
  120. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_inquiry_request_requestor_must_support_test.rb +63 -0
  121. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/client_submit_request_requestor_must_support_test.rb +63 -0
  122. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/metadata.yml +107 -0
  123. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_request_requestor_must_support_test.rb +63 -0
  124. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_inquiry_response_requestor_must_support_test.rb +63 -0
  125. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_request_requestor_must_support_test.rb +63 -0
  126. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/server_submit_response_requestor_must_support_test.rb +63 -0
  127. data/lib/davinci_pas_test_kit/generated/v2.0.1/resource_list.rb +54 -0
  128. data/lib/davinci_pas_test_kit/generated/v2.0.1/server_suite.rb +236 -0
  129. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/client_submit_request_service_request_must_support_test.rb +53 -0
  130. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/metadata.yml +148 -0
  131. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/server_submit_request_service_request_must_support_test.rb +53 -0
  132. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_inquiry_request_subscriber_must_support_test.rb +74 -0
  133. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/client_submit_request_subscriber_must_support_test.rb +74 -0
  134. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/metadata.yml +159 -0
  135. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_inquiry_request_subscriber_must_support_test.rb +74 -0
  136. data/lib/davinci_pas_test_kit/generated/v2.0.1/subscriber/server_submit_request_subscriber_must_support_test.rb +74 -0
  137. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/metadata.yml +192 -0
  138. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_inquiry_response_task_must_support_test.rb +61 -0
  139. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/server_submit_response_task_must_support_test.rb +61 -0
  140. data/lib/davinci_pas_test_kit/generator/group_generator.rb +440 -0
  141. data/lib/davinci_pas_test_kit/generator/group_metadata.rb +73 -0
  142. data/lib/davinci_pas_test_kit/generator/group_metadata_extractor.rb +244 -0
  143. data/lib/davinci_pas_test_kit/generator/ig_loader.rb +78 -0
  144. data/lib/davinci_pas_test_kit/generator/ig_metadata.rb +66 -0
  145. data/lib/davinci_pas_test_kit/generator/ig_metadata_extractor.rb +54 -0
  146. data/lib/davinci_pas_test_kit/generator/ig_resources.rb +74 -0
  147. data/lib/davinci_pas_test_kit/generator/must_support_check_profiles.rb +86 -0
  148. data/lib/davinci_pas_test_kit/generator/must_support_metadata_extractor.rb +327 -0
  149. data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +155 -0
  150. data/lib/davinci_pas_test_kit/generator/naming.rb +50 -0
  151. data/lib/davinci_pas_test_kit/generator/operation_test_generator.rb +136 -0
  152. data/lib/davinci_pas_test_kit/generator/resource_list_generator.rb +59 -0
  153. data/lib/davinci_pas_test_kit/generator/suite_generator.rb +94 -0
  154. data/lib/davinci_pas_test_kit/generator/terminology_binding_metadata_extractor.rb +108 -0
  155. data/lib/davinci_pas_test_kit/generator/validation_test_generator.rb +181 -0
  156. data/lib/davinci_pas_test_kit/generator/value_extractor.rb +48 -0
  157. data/lib/davinci_pas_test_kit/generator.rb +80 -0
  158. data/lib/davinci_pas_test_kit/mock_server.rb +189 -0
  159. data/lib/davinci_pas_test_kit/must_support_test.rb +267 -0
  160. data/lib/davinci_pas_test_kit/pas_bundle_validation.rb +568 -0
  161. data/lib/davinci_pas_test_kit/tags.rb +7 -0
  162. data/lib/davinci_pas_test_kit/urls.rb +39 -0
  163. data/lib/davinci_pas_test_kit/user_input_response.rb +32 -0
  164. data/lib/davinci_pas_test_kit/validation_test.rb +58 -0
  165. data/lib/davinci_pas_test_kit/validator_suppressions.rb +143 -0
  166. data/lib/davinci_pas_test_kit/version.rb +5 -0
  167. data/lib/davinci_pas_test_kit.rb +2 -0
  168. metadata +281 -0
@@ -0,0 +1,59 @@
1
+ module DaVinciPASTestKit
2
+ class Generator
3
+ class ResourceListGenerator
4
+ class << self
5
+ def generate(ig_metadata, base_output_dir)
6
+ @ig_metadata = ig_metadata
7
+
8
+ FileUtils.mkdir_p(base_output_dir)
9
+ File.write(File.join(base_output_dir, base_output_file_name), output)
10
+ end
11
+
12
+ def resource_list
13
+ @ig_metadata.groups.map(&:title).uniq
14
+ end
15
+
16
+ def resource_supported_profiles
17
+ dict = {}
18
+ @ig_metadata.groups.each do |group|
19
+ dict[group.resource] ||= []
20
+ dict[group.resource] << group.profile_url
21
+ end
22
+ dict
23
+ end
24
+
25
+ def resource_list_string
26
+ resource_list.map { |resource| " '#{resource}'" }.join(",\n")
27
+ end
28
+
29
+ def module_name
30
+ "PAS#{@ig_metadata.reformatted_version.upcase}"
31
+ end
32
+
33
+ def read_interaction(group_metadata)
34
+ group_metadata.interactions.find { |interaction| interaction[:code] == 'read' } || {}
35
+ end
36
+
37
+ def submit_operation(group_metadata)
38
+ group_metadata.operations.find { |operation| operation[:code] == '$submit' } || {}
39
+ end
40
+
41
+ def inquiry_operation(group_metadata)
42
+ group_metadata.operations.find { |operation| operation[:code] == '$inquire' } || {}
43
+ end
44
+
45
+ def template
46
+ @template ||= File.read(File.join(__dir__, 'templates', 'resource_list.rb.erb'))
47
+ end
48
+
49
+ def output
50
+ ERB.new(template).result(binding)
51
+ end
52
+
53
+ def base_output_file_name
54
+ 'resource_list.rb'
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,94 @@
1
+ require_relative 'naming'
2
+
3
+ module DaVinciPASTestKit
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 template
20
+ @template ||= File.read(File.join(__dir__, 'templates', 'suite.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
+ 'server_suite.rb'
29
+ end
30
+
31
+ def class_name
32
+ 'ServerSuite'
33
+ end
34
+
35
+ def module_name
36
+ "DaVinciPAS#{ig_metadata.reformatted_version.upcase}"
37
+ end
38
+
39
+ def output_file_name
40
+ File.join(base_output_dir, base_output_file_name)
41
+ end
42
+
43
+ def suite_id
44
+ "davinci_pas_server_suite_#{ig_metadata.reformatted_version}"
45
+ end
46
+
47
+ def title
48
+ "Da Vinci PAS Server Suite #{ig_metadata.ig_version}"
49
+ end
50
+
51
+ def ig_link
52
+ case ig_metadata.ig_version
53
+ when 'v2.0.1'
54
+ 'https://hl7.org/fhir/us/davinci-pas/STU2/'
55
+ else
56
+ 'https://hl7.org/fhir/us/davinci-pas/history.html'
57
+ end
58
+ end
59
+
60
+ def generate
61
+ File.write(output_file_name, output)
62
+ end
63
+
64
+ def groups
65
+ ig_metadata.use_case_groups
66
+ end
67
+
68
+ def group_id_list
69
+ @group_id_list ||= groups.map { |group| group[:id] }
70
+ .reject { |id| id.include?('client') }
71
+ .reject { |id| id.include?('must_support') }
72
+ end
73
+
74
+ def group_file_list
75
+ @group_file_list ||= groups.map { |group| group[:file_name].delete_suffix('.rb') }
76
+ .reject { |name| name.include?('client') }
77
+ end
78
+
79
+ def error_group_file_name
80
+ "../../custom_groups/#{ig_metadata.ig_version}/pas_error_group"
81
+ end
82
+
83
+ def error_group_id
84
+ "pas_#{ig_metadata.reformatted_version}_error_group"
85
+ end
86
+
87
+ def must_support_group_id
88
+ @must_support_group_id ||= groups.map { |group| group[:id] }
89
+ .reject { |id| id.include?('client') }
90
+ .find { |id| id.include?('must_support') }
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,108 @@
1
+ module DaVinciPASTestKit
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 profile_elements_with_bindings
31
+ profile_elements
32
+ .select { |element| element.binding.present? }
33
+ .reject { |element| element_has_fixed_value? element }
34
+ end
35
+
36
+ def element_terminology_bindings
37
+ profile_elements_with_bindings.map do |element|
38
+ {
39
+ type: element.type.first.code,
40
+ strength: element.binding.strength,
41
+ # Goal.target.detail has an unbound binding
42
+ system: element.binding.valueSet&.split('|')&.first,
43
+ path: element.path.gsub('[x]', '').gsub("#{resource}.", '')
44
+ }
45
+ end
46
+ end
47
+
48
+ def extension_profile_elements
49
+ profile_elements
50
+ .select { |element| element.type&.first&.code == 'Extension' }
51
+ .select { |element| extension_profile_url(element).present? }
52
+ end
53
+
54
+ def extension_profile_url(extension)
55
+ extension.type.first.profile&.first
56
+ end
57
+
58
+ def extension_terminology_bindings
59
+ extension_profile_elements
60
+ .flat_map do |extension_profile_element|
61
+ url = extension_profile_url(extension_profile_element)
62
+ extension = ig_resources.profile_by_url(url)
63
+
64
+ # TODO: Temporaray fix for extension defined out of US Core. FI-1623
65
+ next if extension.nil?
66
+
67
+ elements = extension.snapshot.element
68
+ elements_with_bindings = elements.select do |element|
69
+ element.binding.present? && !element.id.include?('Extension.extension')
70
+ end
71
+
72
+ elements_with_bindings.map do |element|
73
+ {
74
+ type: element.type.first.code,
75
+ strength: element.binding.strength,
76
+ system: element.binding.valueSet&.split('|')&.first,
77
+ path: element.path.gsub('[x]', '').gsub('Extension.', ''),
78
+ extensions: [url]
79
+ }
80
+ end + nested_extension_terminology_bindings(elements, url)
81
+ end
82
+ end
83
+
84
+ def nested_extension_terminology_bindings(elements, extension_url)
85
+ nested_extensions = elements.select { |element| element.path == 'Extension.extension' }
86
+ nested_extensions.flat_map do |nested_extension|
87
+ nested_extension_element = elements.find { |element| element.id == "#{nested_extension.id}.url" }
88
+ next unless nested_extension_element.present?
89
+
90
+ nested_extension_url = nested_extension_element.fixedUri
91
+ nested_elements_with_bindings = elements.select do |element|
92
+ element.id.include?(nested_extension.id) && element.binding.present?
93
+ end
94
+
95
+ nested_elements_with_bindings.map do |element|
96
+ {
97
+ type: element.type.first.code,
98
+ strength: element.binding.strength,
99
+ system: element.binding.valueSet&.split('|')&.first,
100
+ path: element.path.gsub('[x]', '').gsub('Extension.extension.', ''),
101
+ extensions: [extension_url, nested_extension_url]
102
+ }
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,181 @@
1
+ require 'pry'
2
+ require_relative 'naming'
3
+
4
+ module DaVinciPASTestKit
5
+ class Generator
6
+ class ValidationTestGenerator
7
+ class << self
8
+ def generate(ig_metadata, base_output_dir)
9
+ ['server', 'client'].each do |system|
10
+ if system == 'server'
11
+ ig_metadata.bundle_groups.each do |group|
12
+ new(group, system, base_output_dir:).generate
13
+ end
14
+ else
15
+ ig_metadata.bundle_groups.each do |group|
16
+ case group.profile_name
17
+ when 'PAS Request Bundle'
18
+ new(group, system, base_output_dir:).generate
19
+ when 'PAS Inquiry Request Bundle'
20
+ new(group, system, 'pended_inquiry', base_output_dir:).generate
21
+ when 'PAS Response Bundle'
22
+ ['denial', 'pended'].each do |workflow|
23
+ new(group, system, workflow, base_output_dir:).generate
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ attr_accessor :group_metadata, :medication_request_metadata, :base_output_dir, :system, :workflow
33
+
34
+ def initialize(group_metadata, system, workflow = nil, medication_request_metadata = nil, base_output_dir:)
35
+ self.group_metadata = group_metadata
36
+ self.system = system
37
+ self.workflow = workflow
38
+ self.medication_request_metadata = medication_request_metadata
39
+ self.base_output_dir = base_output_dir
40
+ end
41
+
42
+ def template
43
+ temp = system == 'server' ? 'validation.rb.erb' : 'validation_client.rb.erb'
44
+ @template ||= File.read(File.join(__dir__, 'templates', temp))
45
+ end
46
+
47
+ def output
48
+ @output ||= ERB.new(template).result(binding)
49
+ end
50
+
51
+ def base_output_file_name
52
+ "#{class_name.underscore}.rb"
53
+ end
54
+
55
+ def output_file_directory
56
+ File.join(base_output_dir, directory_name)
57
+ end
58
+
59
+ def output_file_name
60
+ File.join(output_file_directory, base_output_file_name)
61
+ end
62
+
63
+ def directory_name
64
+ return 'client_tests' if system == 'client'
65
+
66
+ Naming.snake_case_for_profile(medication_request_metadata || group_metadata)
67
+ end
68
+
69
+ def profile_identifier
70
+ Naming.snake_case_for_profile(group_metadata)
71
+ end
72
+
73
+ def profile_url
74
+ group_metadata.profile_url
75
+ end
76
+
77
+ def profile_name
78
+ group_metadata.profile_name
79
+ end
80
+
81
+ def profile_version
82
+ group_metadata.profile_version
83
+ end
84
+
85
+ def formatted_workflow
86
+ workflow.to_s.split('_').first.to_s
87
+ end
88
+
89
+ def test_id
90
+ pref = "pas_#{system}_#{group_metadata.reformatted_version}_#{formatted_workflow}".delete_suffix('_')
91
+ "#{pref}_#{profile_identifier}_validation_test"
92
+ end
93
+
94
+ def class_name
95
+ pref = "#{system.capitalize}#{formatted_workflow.camelize}"
96
+ "#{pref}#{Naming.upper_camel_case_for_profile(group_metadata)}ValidationTest"
97
+ end
98
+
99
+ def module_name
100
+ "DaVinciPAS#{group_metadata.reformatted_version.upcase}"
101
+ end
102
+
103
+ def resource_type
104
+ group_metadata.resource
105
+ end
106
+
107
+ def conformance_expectation
108
+ read_interaction[:expectation]
109
+ end
110
+
111
+ def skip_if_empty
112
+ # Return true if a system must demonstrate at least one example of the resource type.
113
+ # This drives omit vs. skip result statuses in this test.
114
+ resource_type != 'Medication'
115
+ end
116
+
117
+ def request_type
118
+ Naming.request_type_for_bundle_or_claim[profile_name]
119
+ end
120
+
121
+ def generate
122
+ FileUtils.mkdir_p(output_file_directory)
123
+ File.write(output_file_name, output)
124
+
125
+ test_metadata = {
126
+ id: test_id,
127
+ file_name: base_output_file_name
128
+ }
129
+ group_metadata.add_test(**test_metadata)
130
+ end
131
+
132
+ def title
133
+ pref = user_input? ? '[USER INPUT VALIDATION] ' : ''
134
+ "#{pref}#{group_metadata.title} is valid"
135
+ end
136
+
137
+ def user_input?
138
+ (system == 'server' && request_type.include?('request')) ||
139
+ (system == 'client' && request_type.include?('response'))
140
+ end
141
+
142
+ def description
143
+ <<~DESCRIPTION
144
+ #{system == 'server' ? description_intro_server : description_intro_client}
145
+ It verifies the presence of mandatory elements and that elements with
146
+ required bindings contain appropriate values. CodeableConcept element
147
+ bindings will fail if none of their codings have a code/system belonging
148
+ to the bound ValueSet. Quantity, Coding, and code element bindings will
149
+ fail if their code/system are not found in the valueset.
150
+
151
+ Note that because X12 value sets are not public, elements bound to value
152
+ sets containing X12 codes are not validated.
153
+ DESCRIPTION
154
+ end
155
+
156
+ def description_intro_server
157
+ <<~GENERIC_INTRO
158
+ This test validates the conformity of the
159
+ #{request_type.include?('request') ? 'user input' : "server's response"} to the
160
+ [#{profile_name}](#{profile_url}) structure#{request_type.include?('request') ? ', ensuring subsequent tests can accurately simulate content.' : '.'}
161
+ It also checks that other conformance requirements defined in the [PAS Formal
162
+ Specification](https://hl7.org/fhir/us/davinci-pas/STU2/specification.html),
163
+ such as the presence of all referenced instances within the bundle and the
164
+ conformance of those instances to the appropriate profiles, are met.
165
+ GENERIC_INTRO
166
+ end
167
+
168
+ def description_intro_client
169
+ <<~GENERIC_INTRO
170
+ This test validates the conformity of the
171
+ #{request_type.include?('response') ? 'user input' : "client's request"} to the
172
+ [#{profile_name}](#{profile_url}) structure.
173
+ It also checks that other conformance requirements defined in the [PAS Formal
174
+ Specification](https://hl7.org/fhir/us/davinci-pas/STU2/specification.html),
175
+ such as the presence of all referenced instances within the bundle and the
176
+ conformance of those instances to the appropriate profiles, are met.
177
+ GENERIC_INTRO
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,48 @@
1
+ module DaVinciPASTestKit
2
+ class Generator
3
+ class ValueExactor
4
+ attr_accessor :ig_resources, :resource
5
+
6
+ def initialize(ig_resources, resource)
7
+ self.ig_resources = ig_resources
8
+ self.resource = resource
9
+ end
10
+
11
+ def value_set_binding(the_element)
12
+ the_element&.binding
13
+ end
14
+
15
+ def value_set(the_element)
16
+ ig_resources.value_set_by_url(value_set_binding(the_element)&.valueSet)
17
+ end
18
+
19
+ def bound_systems(the_element)
20
+ value_set(the_element)&.compose&.include&.reject { |code| code.concept.nil? }
21
+ end
22
+
23
+ def values_from_value_set_binding(the_element)
24
+ bound_systems = bound_systems(the_element)
25
+
26
+ return [] if bound_systems.blank?
27
+
28
+ bound_systems.flat_map { |system| system.concept.map(&:code) }.uniq
29
+ end
30
+
31
+ def fhir_metadata(current_path)
32
+ FHIR.const_get(resource)::METADATA[current_path]
33
+ end
34
+
35
+ def values_from_resource_metadata(paths)
36
+ values = []
37
+
38
+ paths.each do |current_path|
39
+ current_metadata = fhir_metadata(current_path)
40
+
41
+ values += current_metadata['valid_codes'].values.flatten if current_metadata&.dig('valid_codes').present?
42
+ end
43
+
44
+ values
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,80 @@
1
+ require 'inferno/ext/fhir_models'
2
+
3
+ require_relative 'generator/ig_loader'
4
+ require_relative 'generator/ig_metadata_extractor'
5
+ require_relative 'generator/resource_list_generator'
6
+ require_relative 'generator/validation_test_generator'
7
+ require_relative 'generator/operation_test_generator'
8
+ require_relative 'generator/group_generator'
9
+ require_relative 'generator/suite_generator'
10
+ require_relative 'generator/must_support_test_generator'
11
+
12
+ module DaVinciPASTestKit
13
+ class Generator
14
+ def self.generate
15
+ ig_packages = Dir.glob(File.join(Dir.pwd, 'lib', 'davinci_pas_test_kit', 'igs', '*.tgz'))
16
+
17
+ ig_packages.each do |ig_package|
18
+ new(ig_package).generate
19
+ end
20
+ end
21
+
22
+ attr_accessor :ig_resources, :ig_metadata, :ig_file_name
23
+
24
+ def initialize(ig_file_name)
25
+ self.ig_file_name = ig_file_name
26
+ end
27
+
28
+ def generate
29
+ puts "Generating tests for IG #{File.basename(ig_file_name)}"
30
+ load_ig_package
31
+ extract_metadata
32
+ generate_resource_list
33
+ generate_validation_tests
34
+ generate_operation_tests
35
+ generate_must_support_tests
36
+ generate_groups
37
+ generate_suites
38
+ end
39
+
40
+ def load_ig_package
41
+ FHIR.logger = Logger.new('/dev/null')
42
+ self.ig_resources = IGLoader.new(ig_file_name).load
43
+ end
44
+
45
+ def extract_metadata
46
+ self.ig_metadata = IGMetadataExtractor.new(ig_resources).extract
47
+
48
+ FileUtils.mkdir_p(base_output_dir)
49
+ File.write(File.join(base_output_dir, 'metadata.yml'), YAML.dump(ig_metadata.to_hash))
50
+ end
51
+
52
+ def base_output_dir
53
+ File.join(__dir__, 'generated', ig_metadata.ig_version)
54
+ end
55
+
56
+ def generate_resource_list
57
+ ResourceListGenerator.generate(ig_metadata, base_output_dir)
58
+ end
59
+
60
+ def generate_validation_tests
61
+ ValidationTestGenerator.generate(ig_metadata, base_output_dir)
62
+ end
63
+
64
+ def generate_operation_tests
65
+ OperationTestGenerator.generate(ig_metadata, base_output_dir)
66
+ end
67
+
68
+ def generate_groups
69
+ GroupGenerator.generate(ig_metadata, base_output_dir)
70
+ end
71
+
72
+ def generate_suites
73
+ SuiteGenerator.generate(ig_metadata, base_output_dir)
74
+ end
75
+
76
+ def generate_must_support_tests
77
+ MustSupportTestGenerator.generate(ig_metadata, base_output_dir)
78
+ end
79
+ end
80
+ end