davinci_pas_test_kit 0.15.2 → 0.16.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 (271) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/g33_br_provider.json +13 -0
  3. data/lib/davinci_pas_test_kit/client/abstract_approval_submit_test.rb +28 -17
  4. data/lib/davinci_pas_test_kit/client/abstract_denial_submit_test.rb +26 -16
  5. data/lib/davinci_pas_test_kit/client/abstract_gather_must_support_test.rb +43 -26
  6. data/lib/davinci_pas_test_kit/client/abstract_modification_submit_test.rb +29 -19
  7. data/lib/davinci_pas_test_kit/client/abstract_response_attest.rb +75 -6
  8. data/lib/davinci_pas_test_kit/client/abstract_subscription_create_test.rb +26 -9
  9. data/lib/davinci_pas_test_kit/client/abstract_subscription_update_delete_test.rb +91 -0
  10. data/lib/davinci_pas_test_kit/client/client_bundle_validation_helper.rb +245 -0
  11. data/lib/davinci_pas_test_kit/client/client_input_descriptions.rb +91 -25
  12. data/lib/davinci_pas_test_kit/client/endpoints/claim_endpoint.rb +108 -68
  13. data/lib/davinci_pas_test_kit/client/endpoints/endpoint_session_identification.rb +24 -0
  14. data/lib/davinci_pas_test_kit/client/endpoints/expired_token.rb +40 -0
  15. data/lib/davinci_pas_test_kit/client/endpoints/subscription_create_endpoint.rb +7 -12
  16. data/lib/davinci_pas_test_kit/client/endpoints/subscription_delete_endpoint.rb +13 -0
  17. data/lib/davinci_pas_test_kit/client/endpoints/subscription_read_endpoint.rb +13 -0
  18. data/lib/davinci_pas_test_kit/client/endpoints/subscription_status_endpoint.rb +15 -20
  19. data/lib/davinci_pas_test_kit/client/endpoints/subscription_update_endpoint.rb +13 -0
  20. data/lib/davinci_pas_test_kit/client/endpoints/token_endpoint.rb +16 -0
  21. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_request_must_support_beneficiary_test.rb +3 -3
  22. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +3 -3
  23. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_request_must_support_beneficiary_test.rb +3 -3
  24. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +3 -3
  25. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
  26. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
  27. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +3 -3
  28. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +3 -3
  29. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/communication_request/client_submit_response_must_support_communication_request_test.rb +3 -3
  30. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_inquire_request_must_support_coverage_test.rb +3 -3
  31. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_submit_request_must_support_coverage_test.rb +3 -3
  32. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/encounter/client_submit_request_must_support_encounter_test.rb +3 -3
  33. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_request_must_support_insurer_test.rb +3 -3
  34. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_response_must_support_insurer_test.rb +3 -3
  35. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_request_must_support_insurer_test.rb +3 -3
  36. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_response_must_support_insurer_test.rb +3 -3
  37. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_must_support_group.rb +1 -1
  38. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_response_must_support_group.rb +9 -31
  39. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_must_support_group.rb +1 -1
  40. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_response_must_support_group.rb +10 -32
  41. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_inquiry_request_bundle/client_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +3 -3
  42. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_inquiry_response_bundle/client_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +3 -3
  43. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_request_bundle/client_submit_request_must_support_pas_request_bundle_test.rb +3 -3
  44. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_response_bundle/client_submit_response_must_support_pas_response_bundle_test.rb +3 -3
  45. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_request_must_support_practitioner_test.rb +3 -3
  46. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +3 -3
  47. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_request_must_support_practitioner_test.rb +3 -3
  48. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_response_must_support_practitioner_test.rb +3 -3
  49. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_request_must_support_practitioner_role_test.rb +3 -3
  50. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +3 -3
  51. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_request_must_support_practitioner_role_test.rb +3 -3
  52. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +3 -3
  53. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_request_must_support_requestor_test.rb +3 -3
  54. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_response_must_support_requestor_test.rb +3 -3
  55. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_request_must_support_requestor_test.rb +3 -3
  56. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_response_must_support_requestor_test.rb +3 -3
  57. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_inquire_request_must_support_subscriber_test.rb +3 -3
  58. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_submit_request_must_support_subscriber_test.rb +3 -3
  59. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +4 -3
  60. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +4 -3
  61. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
  62. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
  63. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +4 -3
  64. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +4 -3
  65. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/communication_request/client_submit_response_must_support_communication_request_test.rb +4 -3
  66. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_inquire_response_must_support_insurer_test.rb +4 -3
  67. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_submit_response_must_support_insurer_test.rb +4 -3
  68. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_must_support_group.rb +8 -6
  69. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_response_must_support_group.rb +9 -31
  70. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_must_support_group.rb +13 -9
  71. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_response_must_support_group.rb +10 -32
  72. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_inquiry_response_bundle/client_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +4 -3
  73. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_response_bundle/client_submit_response_must_support_pas_response_bundle_test.rb +4 -3
  74. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +4 -3
  75. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_submit_response_must_support_practitioner_test.rb +4 -3
  76. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +4 -3
  77. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +4 -3
  78. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_inquire_response_must_support_requestor_test.rb +4 -3
  79. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_submit_response_must_support_requestor_test.rb +4 -3
  80. data/lib/davinci_pas_test_kit/client/jobs/send_pas_subscription_notification.rb +64 -3
  81. data/lib/davinci_pas_test_kit/client/pas_client_subscription_pas_conformance_test.rb +4 -3
  82. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_other_display_test.rb +6 -4
  83. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_smart_display_test.rb +8 -4
  84. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_udap_display_test.rb +9 -4
  85. data/lib/davinci_pas_test_kit/client/registration/abstract_other_auth_attest_test.rb +5 -4
  86. data/lib/davinci_pas_test_kit/client/request_count_gating.rb +14 -0
  87. data/lib/davinci_pas_test_kit/client/response_generator.rb +50 -9
  88. data/lib/davinci_pas_test_kit/client/session_identification.rb +26 -7
  89. data/lib/davinci_pas_test_kit/client/subscription_notification_trigger.rb +80 -0
  90. data/lib/davinci_pas_test_kit/client/subscription_setup_requirement.rb +59 -0
  91. data/lib/davinci_pas_test_kit/client/user_input_response.rb +27 -6
  92. data/lib/davinci_pas_test_kit/client/v2.0.1/client_suite.rb +30 -15
  93. data/lib/davinci_pas_test_kit/client/v2.0.1/must_support/pas_client_must_support_request_profiles_test.rb +2 -2
  94. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_approval_group.rb +8 -7
  95. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_smart_group.rb +4 -4
  96. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_udap_group.rb +4 -4
  97. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_denial_group.rb +8 -7
  98. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_must_support_group.rb +38 -52
  99. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_pended_group.rb +28 -22
  100. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_registration_group.rb +2 -2
  101. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_subscription_setup_group.rb +2 -2
  102. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_workflows_group.rb +2 -2
  103. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +15 -21
  104. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +29 -29
  105. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_pended_submit_test.rb +49 -40
  106. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_request_bundle_validation_test.rb +15 -21
  107. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_response_bundle_validation_test.rb +29 -29
  108. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
  109. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
  110. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_provider_review_attestation_test.rb +45 -0
  111. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_security_attestation_test.rb +42 -0
  112. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_subscription_error_recovery_attestation_test.rb +42 -0
  113. data/lib/davinci_pas_test_kit/client/v2.2.1/client_suite.rb +64 -12
  114. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_failure_submit_test.rb +20 -10
  115. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_outcome_validation_test.rb +11 -5
  116. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_response_validation_test.rb +21 -12
  117. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_submit_test.rb +19 -8
  118. data/lib/davinci_pas_test_kit/client/v2.2.1/must_support/must_support_with_attestation_option.rb +90 -40
  119. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_approval_group.rb +12 -11
  120. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_attestations_group.rb +32 -0
  121. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_smart_group.rb +4 -4
  122. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_udap_group.rb +4 -4
  123. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_claim_updates_group.rb +24 -6
  124. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_denial_group.rb +12 -10
  125. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_modification_group.rb +13 -14
  126. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_must_support_group.rb +55 -59
  127. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_operation_failure_group.rb +8 -5
  128. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_pended_group.rb +53 -41
  129. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_processing_error_group.rb +9 -7
  130. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_registration_group.rb +2 -2
  131. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_setup_group.rb +9 -4
  132. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_update_delete_group.rb +57 -0
  133. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_workflows_group.rb +22 -2
  134. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_create_test.rb +2 -1
  135. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_put_update_pas_conformance_test.rb +49 -0
  136. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_update_delete_test.rb +12 -0
  137. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_referenced_resources_test.rb +5 -6
  138. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_submit_tests.rb +82 -56
  139. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +17 -20
  140. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +59 -27
  141. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_modification_verification_test.rb +0 -3
  142. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_send_notification_test.rb +138 -0
  143. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_submit_test.rb +32 -85
  144. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_request_bundle_validation_test.rb +16 -21
  145. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_response_bundle_validation_test.rb +27 -27
  146. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/task/metadata.yml +0 -4
  147. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/metadata.yml +0 -1
  148. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/task/metadata.yml +0 -4
  149. data/lib/davinci_pas_test_kit/cross_suite/pas_bundle_validation.rb +489 -289
  150. data/lib/davinci_pas_test_kit/cross_suite/pas_constants.rb +7 -0
  151. data/lib/davinci_pas_test_kit/cross_suite/pas_subscription_verification.rb +8 -4
  152. data/lib/davinci_pas_test_kit/cross_suite/referenced_resource_presence_validation.rb +141 -0
  153. data/lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb +13 -11
  154. data/lib/davinci_pas_test_kit/cross_suite/tags.rb +11 -6
  155. data/lib/davinci_pas_test_kit/cross_suite/validator_configuration.rb +16 -0
  156. data/lib/davinci_pas_test_kit/cross_suite/validator_suppressions.rb +4 -0
  157. data/lib/davinci_pas_test_kit/docs/demo/PAS Client Suite Demonstration.postman_collection.json +3 -3
  158. data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +1 -0
  159. data/lib/davinci_pas_test_kit/generator/client_must_support_group_generator.rb +47 -16
  160. data/lib/davinci_pas_test_kit/generator/must_support_target_profiles.rb +17 -0
  161. data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +8 -2
  162. data/lib/davinci_pas_test_kit/generator/profile_metadata.rb +1 -1
  163. data/lib/davinci_pas_test_kit/generator/server_suite_generator.rb +4 -9
  164. data/lib/davinci_pas_test_kit/generator/templates/client_must_support_group.rb.erb +22 -3
  165. data/lib/davinci_pas_test_kit/generator/templates/client_must_support_response_group.rb.erb +7 -16
  166. data/lib/davinci_pas_test_kit/generator/templates/must_support.rb.erb +8 -8
  167. data/lib/davinci_pas_test_kit/generator/templates/server_suite.rb.erb +6 -7
  168. data/lib/davinci_pas_test_kit/generator/use_case_group_generator.rb +5 -5
  169. data/lib/davinci_pas_test_kit/parameters_helper.rb +13 -5
  170. data/lib/davinci_pas_test_kit/pas_notification_conformance_test.rb +2 -2
  171. data/lib/davinci_pas_test_kit/requirements/davinci_pas_test_kit_requirements.csv +14 -7
  172. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v201_requirements_coverage.csv +21 -21
  173. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v221_requirements_coverage.csv +30 -26
  174. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_server_suite_v221_requirements_coverage.csv +12 -6
  175. data/lib/davinci_pas_test_kit/requirements/hl7.fhir.us.davinci-pas_2.2.1_requirements.xlsx +0 -0
  176. data/lib/davinci_pas_test_kit/server/claim_operation_logic.rb +1 -1
  177. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
  178. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
  179. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
  180. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
  181. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
  182. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
  183. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +1 -1
  184. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +1 -1
  185. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
  186. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
  187. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
  188. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
  189. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
  190. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
  191. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
  192. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
  193. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_inquiry_request_bundle/server_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +1 -1
  194. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_inquiry_response_bundle/server_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +1 -1
  195. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_request_bundle/server_submit_request_must_support_pas_request_bundle_test.rb +1 -1
  196. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_response_bundle/server_submit_response_must_support_pas_response_bundle_test.rb +1 -1
  197. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_approval_use_case_group.rb +3 -3
  198. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_denial_use_case_group.rb +3 -3
  199. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_pended_use_case_group.rb +6 -6
  200. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
  201. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
  202. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
  203. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
  204. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
  205. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
  206. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
  207. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
  208. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
  209. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
  210. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
  211. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
  212. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/server_suite.rb +6 -7
  213. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
  214. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
  215. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_inquire_response_must_support_task_test.rb +1 -1
  216. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_submit_response_must_support_task_test.rb +1 -1
  217. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
  218. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
  219. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
  220. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
  221. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
  222. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
  223. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +1 -1
  224. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +1 -1
  225. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
  226. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
  227. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
  228. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
  229. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
  230. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
  231. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
  232. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
  233. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_inquiry_request_bundle/server_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +1 -1
  234. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_inquiry_response_bundle/server_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +1 -1
  235. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_request_bundle/server_submit_request_must_support_pas_request_bundle_test.rb +1 -1
  236. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_response_bundle/server_submit_response_must_support_pas_response_bundle_test.rb +1 -1
  237. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_approval_use_case_group.rb +3 -3
  238. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_denial_use_case_group.rb +3 -3
  239. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_pended_use_case_group.rb +4 -4
  240. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
  241. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
  242. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
  243. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
  244. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
  245. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
  246. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
  247. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
  248. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
  249. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
  250. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
  251. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
  252. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/server_suite.rb +6 -7
  253. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
  254. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
  255. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_inquire_response_must_support_task_test.rb +1 -1
  256. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_submit_response_must_support_task_test.rb +1 -1
  257. data/lib/davinci_pas_test_kit/server/pas_claim_response_decision_test.rb +2 -2
  258. data/lib/davinci_pas_test_kit/server/server_request_bundle_validation_test.rb +4 -6
  259. data/lib/davinci_pas_test_kit/server/server_response_bundle_validation_test.rb +4 -6
  260. data/lib/davinci_pas_test_kit/server/v2.0.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
  261. data/lib/davinci_pas_test_kit/server/v2.0.1/pas_server_subscription_setup.rb +1 -1
  262. data/lib/davinci_pas_test_kit/server/v2.2.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
  263. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_claim_updates_group.rb +1 -1
  264. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_subscription_setup.rb +1 -1
  265. data/lib/davinci_pas_test_kit/version.rb +2 -2
  266. metadata +31 -13
  267. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_inquire_response_must_support_task_test.rb +0 -45
  268. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_submit_response_must_support_task_test.rb +0 -45
  269. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_inquire_response_must_support_task_test.rb +0 -55
  270. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_submit_response_must_support_task_test.rb +0 -55
  271. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_error_handling_group.rb +0 -20
@@ -0,0 +1,14 @@
1
+ module DaVinciPASTestKit
2
+ # Shared predicates for the no_requests_ok/multiple_requests_ok config options, used to gate
3
+ # on how many tagged requests were found by AbstractResponseAttest's run block and by
4
+ # ClientBundleValidationHelper#check_request_count.
5
+ module RequestCountGating
6
+ def no_requests_ok?
7
+ config.options[:no_requests_ok]
8
+ end
9
+
10
+ def multiple_requests_ok?
11
+ config.options[:multiple_requests_ok]
12
+ end
13
+ end
14
+ end
@@ -4,6 +4,11 @@ module DaVinciPASTestKit
4
4
  module ResponseGenerator
5
5
  include ParametersHelper
6
6
 
7
+ # Extensions on elements of the request Claim that Inferno copies into the ClaimResponse it generates
8
+ # are kept only if they are published by HL7 (e.g., the PAS identifier extensions), since Inferno,
9
+ # acting as the payer, doesn't send custom extensions - see NO_CUSTOM_EXTENSIONS_VALIDATOR.
10
+ HL7_EXTENSION_URL_PREFIX = 'http://hl7.org/fhir/'.freeze
11
+
7
12
  def mock_id_only_notification_bundle(submit_response, subscription_reference, subscription_topic,
8
13
  ig_version = 'v2.0.1')
9
14
  notification_timestamp = Time.now.utc
@@ -240,14 +245,14 @@ module DaVinciPASTestKit
240
245
  else
241
246
  "http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claiminquiryresponse|#{ig_version.delete('v')}"
242
247
  end),
243
- identifier: claim.identifier,
244
- type: claim.type,
248
+ identifier: copy_without_custom_extensions(claim.identifier),
249
+ type: copy_without_custom_extensions(claim.type),
245
250
  status: claim.status,
246
251
  use: claim.use,
247
- patient: absolute_reference(claim.patient, request_bundle.entry, root_url),
252
+ patient: copy_without_custom_extensions(absolute_reference(claim.patient, request_bundle.entry, root_url)),
248
253
  created: timestamp.iso8601,
249
- insurer: absolute_reference(claim.insurer, request_bundle.entry, root_url),
250
- requestor: absolute_reference(claim.provider, request_bundle.entry, root_url),
254
+ insurer: copy_without_custom_extensions(absolute_reference(claim.insurer, request_bundle.entry, root_url)),
255
+ requestor: copy_without_custom_extensions(absolute_reference(claim.provider, request_bundle.entry, root_url)),
251
256
  request: claim_full_url.present? ? FHIR::Reference.new(reference: claim_full_url) : nil,
252
257
  # v2.2.1 removed 'queued' from ClaimResponseOutcome ValueSet; pended status is
253
258
  # conveyed via item.extension:reviewActionCode instead.
@@ -303,13 +308,41 @@ module DaVinciPASTestKit
303
308
  claim_response
304
309
  end
305
310
 
311
+ # @param element [FHIR::Model, Array<FHIR::Model>, nil] an element of the request Claim.
312
+ # @return a copy of the element without extensions (at any depth) that aren't published by HL7.
313
+ def copy_without_custom_extensions(element)
314
+ return element.map { |child| copy_without_custom_extensions(child) } if element.is_a?(Array)
315
+ return element if element.nil?
316
+
317
+ element.class.new(without_custom_extensions(element.to_hash))
318
+ end
319
+
320
+ # Kept extensions are left whole, since complex extensions' sub-extensions use relative urls.
321
+ def without_custom_extensions(value)
322
+ case value
323
+ when Hash
324
+ value.each_with_object({}) do |(key, child), result|
325
+ if %w[extension modifierExtension].include?(key)
326
+ kept = child.select { |extension| extension['url'].to_s.start_with?(HL7_EXTENSION_URL_PREFIX) }
327
+ result[key] = kept if kept.present?
328
+ else
329
+ result[key] = without_custom_extensions(child)
330
+ end
331
+ end
332
+ when Array
333
+ value.map { |child| without_custom_extensions(child) }
334
+ else
335
+ value
336
+ end
337
+ end
338
+
306
339
  # Pairs each modified item (already marked A6 above) with a ClaimResponse.addItem, referenced by
307
340
  # the same itemSequence, conveying what the payer authorized (marked A1, 'Certified in total').
308
341
  def add_modified_items(claim_response, claim)
309
342
  claim_response.addItem = claim.item.map do |item|
310
343
  FHIR::ClaimResponse::AddItem.new(
311
344
  itemSequence: [item.sequence],
312
- productOrService: item.productOrService,
345
+ productOrService: copy_without_custom_extensions(item.productOrService),
313
346
  adjudication: [
314
347
  FHIR::ClaimResponse::Item::Adjudication.new(
315
348
  extension: [
@@ -466,6 +499,8 @@ module DaVinciPASTestKit
466
499
  if attr.to_s == 'request' && resource.respond_to?(:resourceType) && resource.resourceType == 'ClaimResponse'
467
500
  next
468
501
  end
502
+ # JSON keys without a matching attribute, e.g., the `_gender` holding a primitive's extensions
503
+ next unless resource.respond_to?(attr.to_sym)
469
504
 
470
505
  value = resource.send(attr.to_sym)
471
506
  if value.is_a?(FHIR::Reference) && value.reference.present?
@@ -502,10 +537,16 @@ module DaVinciPASTestKit
502
537
  url.sub(%r{/[^/]*/[^/]*(/)?\z}, '')
503
538
  end
504
539
 
505
- def claim_response_full_url_from_submit_response_bundle(submit_response_bundle)
506
- submit_response_bundle = submit_response_bundle.parameter[0] if submit_response_bundle.is_a?(FHIR::Parameters)
540
+ # Finds the Bundle.entry for the ClaimResponse in a $submit response, which may be wrapped in a
541
+ # FHIR::Parameters resource (v2.2.1). Returns nil if there is no response bundle or no such entry.
542
+ def claim_response_entry_from_response_bundle(response_bundle)
543
+ response_bundle = response_bundle.parameter[0]&.resource if response_bundle.is_a?(FHIR::Parameters)
507
544
 
508
- claim_response_entry = submit_response_bundle&.entry&.find { |e| e&.resource&.resourceType == 'ClaimResponse' }
545
+ response_bundle&.entry&.find { |e| e&.resource&.resourceType == 'ClaimResponse' }
546
+ end
547
+
548
+ def claim_response_full_url_from_submit_response_bundle(submit_response_bundle)
549
+ claim_response_entry = claim_response_entry_from_response_bundle(submit_response_bundle)
509
550
 
510
551
  if claim_response_entry.present?
511
552
  return claim_response_entry.fullUrl unless claim_response_entry.fullUrl.blank?
@@ -1,7 +1,14 @@
1
1
  require 'udap_security_test_kit'
2
+ require_relative 'pas_client_options'
2
3
 
3
4
  module DaVinciPASTestKit
4
5
  module SessionIdentification
6
+ # Wait identifiers:
7
+ # - A wait during which the client sends requests to Inferno (including waits that also offer a
8
+ # "click here when done" link) must use session_wait_identifier, since Inferno's endpoints find
9
+ # the waiting test from the client id or session URL path on the request.
10
+ # - A wait that only the tester (e.g., an attestation) or an Inferno job continues must use a fresh
11
+ # SecureRandom.uuid, so that a stale link from an earlier wait in the session can't resume it.
5
12
  def session_wait_identifier(client_id, session_url_path)
6
13
  # look at test config and determine the wait identifier to use
7
14
  # at somepoint this would be an inferno type, for now, just two options
@@ -31,14 +38,26 @@ module DaVinciPASTestKit
31
38
  end
32
39
  end
33
40
 
34
- # interpret the bearer token structure to determine the wait identifer
35
- # - if structured like a token returned by the simulated Auth server, return the client URI
36
- # - otherwise, use the raw token (provided token)
37
- def bearer_token_to_wait_identifier(token)
38
- client_id = UDAPSecurityTestKit::MockUDAPServer.issued_token_to_client_id(token)
39
- return client_id if client_id.present?
41
+ def auth_description_for_wait(client_id)
42
+ case suite_options[:client_type]
43
+ when PASClientOptions::OTHER_AUTH
44
+ 'No authentication with Inferno is required. Requests will be associated ' \
45
+ 'with this session based on the endpoint alone.'
46
+ when PASClientOptions::SMART_BACKEND_SERVICES_CONFIDENTIAL_ASYMMETRIC
47
+ authenticated_auth_description_for_wait(client_id, 'SMART Backend Services')
48
+ when PASClientOptions::UDAP_CLIENT_CREDENTIALS
49
+ authenticated_auth_description_for_wait(client_id, 'UDAP B2B Client Credentials')
50
+ end
51
+ end
40
52
 
41
- token
53
+ def authenticated_auth_description_for_wait(client_id, type)
54
+ "Requests must be authenticated by first obtaining a #{type} " \
55
+ 'access token using' \
56
+ "\n\n- Token endpoint: `#{token_url}`" \
57
+ "\n- Client Id: `#{client_id}`\n\n" \
58
+ 'Only requests that include an obtained access token as a bearer token ' \
59
+ 'in the Authorization header of the HTTP request will be recognized as ' \
60
+ 'associated with this session and return successful responses.'
42
61
  end
43
62
  end
44
63
  end
@@ -0,0 +1,80 @@
1
+ require_relative 'response_generator'
2
+ require_relative 'jobs/send_pas_subscription_notification'
3
+
4
+ module DaVinciPASTestKit
5
+ # Starts the job that sends a Subscription notification to the client after a pended $submit response.
6
+ # The notification is the tester-provided one (updated to be current) when there is one, or a mocked
7
+ # notification based on the response and the client's Subscription otherwise.
8
+ #
9
+ # The module does not know how to reach the tester's inputs or the requests made earlier in the session,
10
+ # because that differs between the classes that use it (suite endpoints and Inferno tests). Including
11
+ # classes provide them through the helper methods below, which raise NotImplementedError here.
12
+ #
13
+ # Helper methods the including class must provide:
14
+ # - notification_test_run_id, notification_test_session_id, notification_result_id: identify the test run,
15
+ # session and the waiting result that the job checks on and records the notification request on. The test
16
+ # run and result ids may be nil when the including class cannot know them yet (an Inferno test that has
17
+ # not started waiting), in which case the job looks them up.
18
+ # - notification_bearer_token: the access token to send with the notification, from the tester's inputs
19
+ # - tester_notification_bundle: the tester-provided notification Bundle JSON, or nil
20
+ # - client_subscription_json: the Subscription the client created, as parsed JSON (so that primitive
21
+ # extensions are kept), from the earlier successful Subscription create request. nil if there is none.
22
+ # - test_run_identifier: the token that identifies the waiting test to resume
23
+ # - suite_id and ig_version: the suite that the job should send the notification for, and its IG version
24
+ # - fhir_subscription_url: the base URL of the Subscription endpoint (provided by ClientURLs)
25
+ module SubscriptionNotificationTrigger
26
+ include ResponseGenerator
27
+
28
+ HELPERS = %i[notification_test_run_id notification_test_session_id notification_result_id
29
+ notification_bearer_token tester_notification_bundle client_subscription_json].freeze
30
+ HELPERS.each do |helper|
31
+ define_method(helper) do
32
+ raise NotImplementedError, "#{self.class} must implement ##{helper} to use SubscriptionNotificationTrigger"
33
+ end
34
+ end
35
+
36
+ # With resume_test true, the job ends the wait identified by test_run_identifier once it has sent the
37
+ # notification, for use by an Inferno test that waits for the notification to be sent.
38
+ def start_notification_job(response_bundle_json, decision, generated_claim_response_uuid, resume_test: false)
39
+ notification_contents = notification_json(response_bundle_json, decision, generated_claim_response_uuid)
40
+
41
+ Inferno::Jobs.perform(Jobs::SendPASSubscriptionNotification, notification_test_run_id,
42
+ notification_test_session_id, notification_result_id, notification_bearer_token,
43
+ notification_contents, test_run_identifier, suite_id, ig_version, resume_test)
44
+ end
45
+
46
+ private
47
+
48
+ def notification_json(response_bundle_json, decision, generated_claim_response_uuid)
49
+ user_inputted_notification_json = tester_notification_bundle
50
+
51
+ if user_inputted_notification_json.present?
52
+ update_tester_provided_notification(user_inputted_notification_json, generated_claim_response_uuid)
53
+ else
54
+ generate_notification(response_bundle_json, decision)
55
+ end
56
+ end
57
+
58
+ def generate_notification(response_bundle_json, decision)
59
+ subscription = client_subscription_json
60
+ subscription_reference = "#{fhir_subscription_url}/#{subscription['id']}"
61
+ subscription_topic = subscription['criteria']
62
+
63
+ if find_subscription_content_type(subscription) == 'full-resource'
64
+ mock_full_resource_notification_bundle(response_bundle_json, subscription_reference, subscription_topic,
65
+ decision, ig_version)
66
+ else # assume id-only since empty not allowed - if asked for empty, other failures will occur
67
+ mock_id_only_notification_bundle(response_bundle_json, subscription_reference, subscription_topic,
68
+ ig_version)
69
+ end
70
+ end
71
+
72
+ def find_subscription_content_type(subscription)
73
+ content_ext = subscription.dig('channel', '_payload', 'extension')
74
+ &.find do |ext|
75
+ ext['url'] == 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content'
76
+ end
77
+ content_ext&.dig('valueCode')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,59 @@
1
+ module DaVinciPASTestKit
2
+ # Shared guard for client tests that need the client's Subscription Setup to have completed
3
+ # before they can proceed - either because they need the created Subscription itself (e.g. to
4
+ # generate a notification against it, or to update or delete it) or just need to know one exists
5
+ # before continuing with the pended scenario.
6
+ module SubscriptionSetupRequirement
7
+ PENDED_SCENARIO_SKIP_MESSAGE = %(
8
+ This test cannot proceed because no Subscription exists to receive notifications
9
+ for pended claims. Run the _Subscription Setup_ tests to provide a Subscription
10
+ for use in delivering notifications before re-running the pended scenario tests.
11
+ ).freeze
12
+
13
+ PENDED_SCENARIO_MODIFIED_SUBSCRIPTION_SKIP_MESSAGE = %(
14
+ This test cannot proceed because the PAS client submitted update or delete requests for its
15
+ Subscription during the _Subscription Update and Deletion_ tests. Re-run the _Subscription Setup_
16
+ tests to create a new Subscription for use in delivering notifications before re-running the
17
+ pended scenario tests.
18
+ ).freeze
19
+
20
+ UPDATE_DELETE_SKIP_MESSAGE = %(
21
+ This test cannot proceed because no Subscription exists to update or delete. Run the
22
+ _Subscription Setup_ tests to create a Subscription before re-running this test.
23
+ ).freeze
24
+
25
+ # Skips the test unless a successful (201) Subscription-create request was made during this
26
+ # session.
27
+ # @param skip_message [String] explanation shown when the test is skipped.
28
+ # @return [Hash] the created Subscription as returned to the client, parsed from the response body.
29
+ def require_created_subscription(skip_message: PENDED_SCENARIO_SKIP_MESSAGE)
30
+ subscription_request = load_tagged_requests(SUBSCRIPTION_CREATE_TAG).find { |req| req.status == 201 }
31
+ skip_if subscription_request.blank?, skip_message
32
+ JSON.parse(subscription_request.response_body)
33
+ end
34
+
35
+ # Like require_created_subscription, but also skips if the client has successfully updated or
36
+ # deleted the created Subscription. Notifications are generated from the Subscription as created,
37
+ # so the pended scenario must not run against one the client has since changed or removed.
38
+ # Rejected update and delete requests leave the Subscription unchanged and so are ignored.
39
+ # @return [Hash] the created Subscription as returned to the client, parsed from the response body.
40
+ def require_unmodified_subscription
41
+ subscription = require_created_subscription
42
+ # Only update and delete requests are tagged with the Subscription id, which is new for each create
43
+ skip_if load_tagged_requests(subscription['id']).any? { |req| subscription_change_succeeded?(req) },
44
+ PENDED_SCENARIO_MODIFIED_SUBSCRIPTION_SKIP_MESSAGE
45
+ subscription
46
+ end
47
+
48
+ private
49
+
50
+ # Successful updates respond with 200 and successful deletes with a 2xx status
51
+ def subscription_change_succeeded?(request)
52
+ if request.tags.include?(SUBSCRIPTION_DELETE_TAG)
53
+ request.status.between?(200, 299)
54
+ else
55
+ request.status == 200
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,5 @@
1
+ require_relative '../cross_suite/response_selection_utils'
2
+
1
3
  module DaVinciPASTestKit
2
4
  module UserInputResponse
3
5
  # Raised when a tester-provided response input is present but cannot be used. The
@@ -25,9 +27,9 @@ module DaVinciPASTestKit
25
27
 
26
28
  # Returns the tester-provided response candidates for the must support workflow
27
29
  # as a list of parsed JSON hashes. The input value may be a single entry or a
28
- # JSON array of entries, where each entry is either a bare FHIR Bundle or a
29
- # wrapper object holding the response Bundle under "bundle" alongside optional
30
- # selection "criteria".
30
+ # JSON array of entries, where each entry is either a bare FHIR Bundle or Parameters
31
+ # or a wrapper object holding the response resource under "bundle" alongside optional
32
+ # selection "criteria" - see ResponseSelectionUtils.
31
33
  # Returns nil if the input has no value and raises InvalidInputError if the value
32
34
  # is present but unusable. The configurable (the waiting test) supplies the input
33
35
  # title so that the error names the input as the tester sees it.
@@ -41,8 +43,8 @@ module DaVinciPASTestKit
41
43
  invalid_index = candidates.index { |candidate| !valid_candidate?(candidate) }
42
44
  if invalid_index.present?
43
45
  raise InvalidInputError,
44
- "Entry #{invalid_index + 1} of the '#{input_title(configurable, input_name)}' input is neither " \
45
- 'a FHIR Bundle nor a wrapper object with a FHIR Bundle in the "bundle" key.'
46
+ "Entry #{invalid_index + 1} of the '#{input_title(configurable, input_name)}' input is not " \
47
+ 'a FHIR Bundle or Parameters resource, or a wrapper object with one in the "bundle" key.'
46
48
  end
47
49
 
48
50
  candidates
@@ -59,7 +61,8 @@ module DaVinciPASTestKit
59
61
  def self.valid_candidate?(candidate)
60
62
  return false unless candidate.is_a?(Hash)
61
63
 
62
- candidate['resourceType'] == 'Bundle' || candidate['bundle'].is_a?(Hash)
64
+ ResponseSelectionUtils::RESPONSE_RESOURCE_TYPES.include?(candidate['resourceType']) ||
65
+ candidate[ResponseSelectionUtils::BUNDLE_KEY].is_a?(Hash)
63
66
  end
64
67
 
65
68
  def user_inputted_response?(input_key)
@@ -70,6 +73,24 @@ module DaVinciPASTestKit
70
73
  UserInputResponse.input_title(self, input_key)
71
74
  end
72
75
 
76
+ def response_description_for_wait(user_input, user_input_title, operation)
77
+ if user_input
78
+ <<~DESCRIPTION.strip
79
+ Inferno will respond to `#{operation}` requests with the content provided in the
80
+ '**#{user_input_title}**' input, with `{{...}}` fhirpath expressions replaced with
81
+ their value when evaluated against the request and timestamps and resources references
82
+ updated to be current and consistent. See the ["Response Instantiation" section](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#response-instantiation)
83
+ of the Da Vinci PAS Test Kit wiki for details on these updates.
84
+ DESCRIPTION
85
+ else
86
+ <<~DESCRIPTION.strip
87
+ Inferno will respond to `#{operation}` requests with a mocked response based on the request.
88
+ See the ["Mocked Responses" section](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#mocked-responses)
89
+ of the Da Vinci PAS Test Kit wiki for details on the mocked response.
90
+ DESCRIPTION
91
+ end
92
+ end
93
+
73
94
  module ClassMethods
74
95
  def submit_respond_with(key)
75
96
  config options: { submit_respond_with: key }
@@ -1,11 +1,13 @@
1
1
  require 'subscriptions_test_kit'
2
2
  require 'udap_security_test_kit'
3
3
  require 'smart_app_launch_test_kit'
4
+ require_relative '../../cross_suite/validator_configuration'
4
5
  require_relative '../../cross_suite/validator_suppressions'
5
6
  require_relative '../../cross_suite/tags'
6
7
  require_relative '../endpoints/claim_endpoint'
7
8
  require_relative '../endpoints/token_endpoint'
8
9
  require_relative '../endpoints/subscription_create_endpoint'
10
+ require_relative '../endpoints/subscription_read_endpoint'
9
11
  require_relative '../endpoints/subscription_status_endpoint'
10
12
  require_relative '../pas_client_options'
11
13
  require_relative 'pas_client_workflows_group'
@@ -22,33 +24,33 @@ module DaVinciPASTestKit
22
24
  id :davinci_pas_client_suite_v201
23
25
  title 'Da Vinci PAS Client Suite v2.0.1'
24
26
  description %(
25
- The Da Vinci PAS Test Kit Client Suite validates the conformance of client
26
- systems to the STU 2 version of the HL7® FHIR®
27
+ The Da Vinci PAS Test Kit Client Suite validates the conformance of PAS clients
28
+ to the STU 2 version of the HL7® FHIR®
27
29
  [Da Vinci Prior Authorization Support Implementation Guide](https://hl7.org/fhir/us/davinci-pas/STU2/).
28
30
 
29
31
  These tests are a **DRAFT** intended to allow PAS client implementers to perform
30
- preliminary checks of their clients against PAS IG requirements and [provide
32
+ preliminary checks of their PAS clients against PAS IG requirements and [provide
31
33
  feedback](https://github.com/inferno-framework/davinci-pas-test-kit/issues)
32
34
  on the tests. Future versions of these tests may validate other
33
35
  requirements and may change the test validation logic.
34
36
 
35
37
  The best place to get started is the [Client Testing
36
38
  Walkthrough](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Client-Instructions-v2.0.1),
37
- which provides a step-by-step guide for running the tests against a client and provides
39
+ which provides a step-by-step guide for running the tests against a PAS client and provides
38
40
  an example client implemented in Postman. Visit the [Client Testing
39
41
  Details](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Client-Details)
40
42
  documentation for information about technical implementation and known limitations of these tests.
41
43
 
42
- In this test suite, Inferno simulates a PAS server for the client under test to
43
- interact with. The client will be expected to initiate requests to the server
44
+ In this test suite, Inferno simulates a PAS server for the PAS client to
45
+ interact with. The PAS client will be expected to initiate requests to the server
44
46
  and demonstrate its ability to react to the returned responses. Over the course
45
47
  of these interactions, Inferno will seek to observe conformant handling of PAS
46
48
  requirements, including:
47
- - The ability of the client to initiate a prior authorization submission and react to
49
+ - The ability of the PAS client to initiate a prior authorization submission and react to
48
50
  - The approval of the request
49
51
  - The denial of the request
50
52
  - The pending of the request and a subsequent notification that a final decision was made
51
- - The ability of the client to provide data covering the full scope of required by PAS, including
53
+ - The ability of the PAS client to provide data covering the full scope of required by PAS, including
52
54
  - The ability to send prior auth requests and inquiries with all PAS
53
55
  profiles and all must support elements on those profiles
54
56
  - The ability to handle responses that contain all PAS profiles and all must support elements on those
@@ -93,16 +95,29 @@ module DaVinciPASTestKit
93
95
  )
94
96
 
95
97
  fhir_resource_validator do
96
- igs 'hl7.fhir.us.davinci-pas#2.0.1'
98
+ igs(*V201_VALIDATOR_IGS)
97
99
 
98
100
  exclude_message do |message|
99
- # Messages expected of the form `<ResourceType>: <FHIRPath>: <message>`
100
- # We strip `<ResourceType>: <FHIRPath>: ` for the sake of matching
101
- V201_SUPPRESSED_MESSAGES.match?(message.message.sub(/\A\S+: \S+: /, ''))
101
+ V201_SUPPRESSED_MESSAGES.match?(message.message.sub(VALIDATOR_MESSAGE_LOCATION_PREFIX, ''))
102
102
  end
103
103
 
104
104
  validation_context do
105
- snomedCT '731000124108'
105
+ snomedCT SNOMED_CT_US_EDITION
106
+ end
107
+ end
108
+
109
+ # Used to verify responses sent by Inferno, which may be tester-provided, to
110
+ # ensure they don't contain extensions not defined in the PAS IG or its dependencies.
111
+ fhir_resource_validator NO_CUSTOM_EXTENSIONS_VALIDATOR do
112
+ igs(*V201_VALIDATOR_IGS)
113
+
114
+ exclude_message do |message|
115
+ V201_SUPPRESSED_MESSAGES.match?(message.message.sub(VALIDATOR_MESSAGE_LOCATION_PREFIX, ''))
116
+ end
117
+
118
+ validation_context do
119
+ snomedCT SNOMED_CT_US_EDITION
120
+ extensions [] # no extensions not in the spec
106
121
  end
107
122
  end
108
123
 
@@ -140,8 +155,8 @@ module DaVinciPASTestKit
140
155
  suite_endpoint :post, SESSION_INQUIRE_PATH, ClaimEndpoint
141
156
  suite_endpoint :post, FHIR_SUBSCRIPTION_PATH, SubscriptionCreateEndpoint
142
157
  suite_endpoint :post, SESSION_FHIR_SUBSCRIPTION_PATH, SubscriptionCreateEndpoint
143
- suite_endpoint :get, FHIR_SUBSCRIPTION_INSTANCE_PATH, SubscriptionsTestKit::SubscriptionReadEndpoint
144
- suite_endpoint :get, SESSION_FHIR_SUBSCRIPTION_INSTANCE_PATH, SubscriptionsTestKit::SubscriptionReadEndpoint
158
+ suite_endpoint :get, FHIR_SUBSCRIPTION_INSTANCE_PATH, SubscriptionReadEndpoint
159
+ suite_endpoint :get, SESSION_FHIR_SUBSCRIPTION_INSTANCE_PATH, SubscriptionReadEndpoint
145
160
  suite_endpoint :post, FHIR_SUBSCRIPTION_INSTANCE_STATUS_PATH, SubscriptionStatusEndpoint
146
161
  suite_endpoint :post, SESSION_FHIR_SUBSCRIPTION_INSTANCE_STATUS_PATH, SubscriptionStatusEndpoint
147
162
  suite_endpoint :get, FHIR_SUBSCRIPTION_INSTANCE_STATUS_PATH, SubscriptionStatusEndpoint
@@ -18,7 +18,7 @@ module DaVinciPASTestKit
18
18
  * PAS Device Request
19
19
  * PAS Nutrition Order
20
20
 
21
- System are allowed to support only the request profiles that fit their use cases. However,
21
+ PAS clients are allowed to support only the request profiles that fit their use cases. However,
22
22
  they must support at least one of them (because `Claim.item.extension:requestedService` is a
23
23
  must support element) and for any request profiles they support, they must be able to
24
24
  populate all of the defined must support elements.
@@ -27,7 +27,7 @@ module DaVinciPASTestKit
27
27
  profile listed above. Then for each profile observed, it checks for the presence of
28
28
  each must support element defined in that profile.
29
29
 
30
- The test will look through the instances included in submissions made by the client
30
+ The test will look through the instances included in submissions made by the PAS client
31
31
  for the following must support elements:
32
32
 
33
33
  ### PAS Medication Request
@@ -8,10 +8,10 @@ module DaVinciPASTestKit
8
8
  module DaVinciPASV201
9
9
  class PASClientApprovalGroup < Inferno::TestGroup
10
10
  id :pas_client_v201_approval_group
11
- title 'Approval Workflow'
11
+ title 'Approval Response'
12
12
  description %(
13
- During these tests, the client will initiate a prior authorization
14
- request and show it can respond appropriately to an 'approved' decision.
13
+ During these tests, the PAS client will initiate a prior authorization
14
+ request and show it can react appropriately to an 'approved' decision.
15
15
  )
16
16
  run_as_group
17
17
 
@@ -24,16 +24,17 @@ module DaVinciPASTestKit
24
24
  test from: :pas_client_v201_response_bundle_validation_test,
25
25
  config: { options: { workflow_tag: APPROVAL_WORKFLOW_TAG } }
26
26
  test from: :pas_client_v201_response_attest,
27
- title: 'Check that the client registers the request as approved (Attestation)',
27
+ title: 'Check that the PAS client registers the request as approved',
28
28
  description: %(
29
- This test provides the tester an opportunity to observe their client following
29
+ During this test, the tester will observe the PAS client following
30
30
  the receipt of the approved response and attest that users are able to determine
31
31
  that the response has been approved.
32
32
  ),
33
33
  config: { options: {
34
34
  workflow_tag: APPROVAL_WORKFLOW_TAG,
35
- attest_message: "I attest that the client system displays the submitted claim as 'approved' meaning " \
36
- 'that the user can proceed with ordering or providing the requested service.'
35
+ attest_message: 'I attest that the PAS client did not error when handling the `$submit` ' \
36
+ "response and displays the submitted claim as 'approved' meaning that the " \
37
+ 'user can proceed with ordering or providing the requested service.'
37
38
  } }
38
39
  end
39
40
  end
@@ -7,13 +7,13 @@ module DaVinciPASTestKit
7
7
  id :pas_client_v201_auth_smart
8
8
  title 'Review Authentication Interactions'
9
9
  description %(
10
- During these tests, Inferno will verify that the client interacted with Inferno's
10
+ During these tests, Inferno will verify that the PAS client interacted with Inferno's
11
11
  simulated SMART authorization server in a conformant manner when requesting access tokens
12
- and that the client under test was able to use provided access tokens to make PAS
12
+ and that the PAS client was able to use provided access tokens to make PAS
13
13
  requests.
14
14
 
15
- Before running these tests, execute the tests for at least one "PAS workflows" sub-group
16
- so that the client will request an access token and use it on a PAS request.
15
+ Before running these tests, execute the tests for at least one "PAS Scenarios" sub-group
16
+ so that the PAS client will request an access token and use it on a PAS request.
17
17
  )
18
18
  run_as_group
19
19
 
@@ -7,13 +7,13 @@ module DaVinciPASTestKit
7
7
  id :pas_client_v201_auth_udap
8
8
  title 'Review UDAP Authentication Interactions'
9
9
  description %(
10
- During these tests, Inferno will verify that the client interacted with Inferno's
10
+ During these tests, Inferno will verify that the PAS client interacted with Inferno's
11
11
  simulated UDAP authorization server in a conformant manner when requesting access tokens
12
- and that the client under test was able to use provided access tokens to make PAS
12
+ and that the PAS client was able to use provided access tokens to make PAS
13
13
  requests.
14
14
 
15
- Before running these tests, execute the tests for at least one "PAS workflows" sub-group
16
- so that the client will request an access token and use it on a PAS request.
15
+ Before running these tests, execute the tests for at least one "PAS Scenarios" sub-group
16
+ so that the PAS client will request an access token and use it on a PAS request.
17
17
  )
18
18
  run_as_group
19
19
 
@@ -11,10 +11,10 @@ module DaVinciPASTestKit
11
11
  include UserInputResponse
12
12
 
13
13
  id :pas_client_v201_denial_group
14
- title 'Denial Workflow'
14
+ title 'Denial Response'
15
15
  description %(
16
- During these tests, the client will initiate a prior authorization
17
- request and show it can respond appropriately to a 'denied' decision.
16
+ During these tests, the PAS client will initiate a prior authorization
17
+ request and show it can react appropriately to a 'denied' decision.
18
18
  )
19
19
  run_as_group
20
20
 
@@ -30,17 +30,18 @@ module DaVinciPASTestKit
30
30
  test from: :pas_client_v201_response_bundle_validation_test,
31
31
  config: { options: { workflow_tag: DENIAL_WORKFLOW_TAG } }
32
32
  test from: :pas_client_v201_response_attest,
33
- title: 'Check that the client registers the request as denied (Attestation)',
33
+ title: 'Check that the PAS client registers the request as denied',
34
34
  description: %(
35
- This test provides the tester an opportunity to observe their client following
35
+ During this test, the tester will observe the PAS client following
36
36
  the receipt of the denied response and attest that users are able to determine
37
37
  that the response has been denied.
38
38
  ),
39
39
  config: { options: {
40
40
  workflow_tag: DENIAL_WORKFLOW_TAG,
41
- attest_message: "I attest that the client system displays the submitted claim as 'denied', meaning " \
41
+ attest_message: 'I attest that the PAS client did not error when handling the `$submit` ' \
42
+ "response and displays the submitted claim as 'denied', meaning " \
42
43
  'that the user cannot proceed with ordering or providing the requested service without ' \
43
- 'making adjustments and submitting for further approval.'
44
+ 'making adjustments and submitting for further review.'
44
45
  } }
45
46
  end
46
47
  end