davinci_pas_test_kit 0.15.1 → 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 (334) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/g33_br_provider.json +13 -0
  3. data/config/presets/pas_client_example.json +2 -2
  4. data/config/presets/pas_client_v201_run_against_pas_server.json +2 -2
  5. data/config/presets/pas_client_v221_run_against_pas_server.json +3 -3
  6. data/config/presets/pas_ri.json +6 -6
  7. data/config/presets/pas_server_v201_run_against_pas_client.json.erb +6 -6
  8. data/config/presets/pas_server_v221_run_against_pas_client.json.erb +10 -10
  9. data/lib/davinci_pas_test_kit/client/abstract_approval_submit_test.rb +28 -17
  10. data/lib/davinci_pas_test_kit/client/abstract_denial_submit_test.rb +26 -16
  11. data/lib/davinci_pas_test_kit/client/abstract_gather_must_support_test.rb +45 -74
  12. data/lib/davinci_pas_test_kit/client/abstract_modification_submit_test.rb +29 -19
  13. data/lib/davinci_pas_test_kit/client/abstract_response_attest.rb +75 -6
  14. data/lib/davinci_pas_test_kit/client/abstract_subscription_create_test.rb +26 -9
  15. data/lib/davinci_pas_test_kit/client/abstract_subscription_update_delete_test.rb +91 -0
  16. data/lib/davinci_pas_test_kit/client/client_bundle_validation_helper.rb +245 -0
  17. data/lib/davinci_pas_test_kit/client/client_input_descriptions.rb +96 -1
  18. data/lib/davinci_pas_test_kit/client/endpoints/claim_endpoint.rb +128 -72
  19. data/lib/davinci_pas_test_kit/client/endpoints/endpoint_session_identification.rb +24 -0
  20. data/lib/davinci_pas_test_kit/client/endpoints/expired_token.rb +40 -0
  21. data/lib/davinci_pas_test_kit/client/endpoints/subscription_create_endpoint.rb +7 -12
  22. data/lib/davinci_pas_test_kit/client/endpoints/subscription_delete_endpoint.rb +13 -0
  23. data/lib/davinci_pas_test_kit/client/endpoints/subscription_read_endpoint.rb +13 -0
  24. data/lib/davinci_pas_test_kit/client/endpoints/subscription_status_endpoint.rb +15 -20
  25. data/lib/davinci_pas_test_kit/client/endpoints/subscription_update_endpoint.rb +13 -0
  26. data/lib/davinci_pas_test_kit/client/endpoints/token_endpoint.rb +16 -0
  27. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_request_must_support_beneficiary_test.rb +3 -3
  28. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +3 -3
  29. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_request_must_support_beneficiary_test.rb +3 -3
  30. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +3 -3
  31. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
  32. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
  33. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +3 -3
  34. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +3 -3
  35. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/communication_request/client_submit_response_must_support_communication_request_test.rb +3 -3
  36. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_inquire_request_must_support_coverage_test.rb +3 -3
  37. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_submit_request_must_support_coverage_test.rb +3 -3
  38. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/encounter/client_submit_request_must_support_encounter_test.rb +3 -3
  39. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_request_must_support_insurer_test.rb +3 -3
  40. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_response_must_support_insurer_test.rb +3 -3
  41. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_request_must_support_insurer_test.rb +3 -3
  42. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_response_must_support_insurer_test.rb +3 -3
  43. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_must_support_group.rb +1 -1
  44. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_response_must_support_group.rb +9 -31
  45. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_must_support_group.rb +1 -1
  46. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_response_must_support_group.rb +10 -32
  47. 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
  48. 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
  49. 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
  50. 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
  51. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_request_must_support_practitioner_test.rb +3 -3
  52. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +3 -3
  53. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_request_must_support_practitioner_test.rb +3 -3
  54. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_response_must_support_practitioner_test.rb +3 -3
  55. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_request_must_support_practitioner_role_test.rb +3 -3
  56. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +3 -3
  57. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_request_must_support_practitioner_role_test.rb +3 -3
  58. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +3 -3
  59. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_request_must_support_requestor_test.rb +3 -3
  60. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_response_must_support_requestor_test.rb +3 -3
  61. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_request_must_support_requestor_test.rb +3 -3
  62. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_response_must_support_requestor_test.rb +3 -3
  63. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_inquire_request_must_support_subscriber_test.rb +3 -3
  64. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_submit_request_must_support_subscriber_test.rb +3 -3
  65. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +4 -3
  66. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +4 -3
  67. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
  68. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
  69. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +4 -3
  70. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +4 -3
  71. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/communication_request/client_submit_response_must_support_communication_request_test.rb +4 -3
  72. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_inquire_response_must_support_insurer_test.rb +4 -3
  73. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_submit_response_must_support_insurer_test.rb +4 -3
  74. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_must_support_group.rb +8 -6
  75. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_response_must_support_group.rb +9 -31
  76. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_must_support_group.rb +13 -9
  77. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_response_must_support_group.rb +10 -32
  78. 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
  79. 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
  80. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +4 -3
  81. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_submit_response_must_support_practitioner_test.rb +4 -3
  82. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +4 -3
  83. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +4 -3
  84. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_inquire_response_must_support_requestor_test.rb +4 -3
  85. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_submit_response_must_support_requestor_test.rb +4 -3
  86. data/lib/davinci_pas_test_kit/client/jobs/send_pas_subscription_notification.rb +64 -3
  87. data/lib/davinci_pas_test_kit/client/pas_client_subscription_pas_conformance_test.rb +4 -3
  88. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_other_display_test.rb +6 -4
  89. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_smart_display_test.rb +8 -4
  90. data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_udap_display_test.rb +9 -4
  91. data/lib/davinci_pas_test_kit/client/registration/abstract_other_auth_attest_test.rb +5 -4
  92. data/lib/davinci_pas_test_kit/client/request_count_gating.rb +14 -0
  93. data/lib/davinci_pas_test_kit/client/response_generator.rb +50 -9
  94. data/lib/davinci_pas_test_kit/client/session_identification.rb +26 -7
  95. data/lib/davinci_pas_test_kit/client/subscription_notification_trigger.rb +80 -0
  96. data/lib/davinci_pas_test_kit/client/subscription_setup_requirement.rb +59 -0
  97. data/lib/davinci_pas_test_kit/client/user_input_response.rb +50 -10
  98. data/lib/davinci_pas_test_kit/client/v2.0.1/client_suite.rb +30 -15
  99. data/lib/davinci_pas_test_kit/client/v2.0.1/must_support/pas_client_must_support_request_profiles_test.rb +2 -2
  100. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_approval_group.rb +8 -7
  101. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_smart_group.rb +4 -4
  102. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_udap_group.rb +4 -4
  103. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_denial_group.rb +8 -7
  104. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_must_support_group.rb +38 -52
  105. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_pended_group.rb +28 -22
  106. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_registration_group.rb +2 -2
  107. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_subscription_setup_group.rb +2 -2
  108. data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_workflows_group.rb +2 -2
  109. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +15 -21
  110. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +29 -29
  111. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_pended_submit_test.rb +49 -40
  112. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_request_bundle_validation_test.rb +15 -21
  113. data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_response_bundle_validation_test.rb +29 -29
  114. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
  115. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
  116. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_provider_review_attestation_test.rb +45 -0
  117. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_security_attestation_test.rb +42 -0
  118. data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_subscription_error_recovery_attestation_test.rb +42 -0
  119. data/lib/davinci_pas_test_kit/client/v2.2.1/client_suite.rb +64 -12
  120. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_failure_submit_test.rb +20 -10
  121. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_outcome_validation_test.rb +11 -5
  122. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_response_validation_test.rb +21 -12
  123. data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_submit_test.rb +19 -8
  124. data/lib/davinci_pas_test_kit/client/v2.2.1/must_support/must_support_with_attestation_option.rb +90 -40
  125. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_approval_group.rb +12 -11
  126. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_attestations_group.rb +32 -0
  127. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_smart_group.rb +4 -4
  128. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_udap_group.rb +4 -4
  129. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_claim_updates_group.rb +24 -6
  130. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_denial_group.rb +12 -10
  131. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_modification_group.rb +13 -14
  132. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_must_support_group.rb +55 -59
  133. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_operation_failure_group.rb +8 -5
  134. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_pended_group.rb +53 -41
  135. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_processing_error_group.rb +9 -7
  136. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_registration_group.rb +2 -2
  137. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_setup_group.rb +9 -4
  138. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_update_delete_group.rb +57 -0
  139. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_workflows_group.rb +22 -2
  140. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_create_test.rb +2 -1
  141. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_put_update_pas_conformance_test.rb +49 -0
  142. data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_update_delete_test.rb +12 -0
  143. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_referenced_resources_test.rb +5 -6
  144. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_submit_tests.rb +82 -56
  145. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +17 -20
  146. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +59 -27
  147. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_modification_verification_test.rb +0 -3
  148. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_send_notification_test.rb +138 -0
  149. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_submit_test.rb +32 -85
  150. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_request_bundle_validation_test.rb +16 -21
  151. data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_response_bundle_validation_test.rb +27 -27
  152. data/lib/davinci_pas_test_kit/cross_suite/fhirpath_utils.rb +13 -3
  153. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/beneficiary/metadata.yml +4 -0
  154. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/claim_inquiry/metadata.yml +15 -0
  155. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/claim_update/metadata.yml +17 -0
  156. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/claiminquiryresponse/metadata.yml +15 -0
  157. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/claimresponse/metadata.yml +15 -0
  158. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/communication_request/metadata.yml +4 -0
  159. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/coverage/metadata.yml +1 -0
  160. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/device_request/metadata.yml +2 -0
  161. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/encounter/metadata.yml +3 -0
  162. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/insurer/metadata.yml +1 -0
  163. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/medication_request/metadata.yml +2 -0
  164. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/metadata.yml +143 -0
  165. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/nutrition_order/metadata.yml +2 -0
  166. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/pas_inquiry_request_bundle/metadata.yml +2 -0
  167. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/pas_inquiry_response_bundle/metadata.yml +2 -0
  168. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/pas_request_bundle/metadata.yml +2 -0
  169. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/pas_response_bundle/metadata.yml +2 -0
  170. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/practitioner/metadata.yml +1 -0
  171. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/practitioner_role/metadata.yml +1 -0
  172. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/requestor/metadata.yml +1 -0
  173. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/service_request/metadata.yml +3 -0
  174. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/subscriber/metadata.yml +4 -0
  175. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/task/metadata.yml +1 -4
  176. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/beneficiary/metadata.yml +1 -0
  177. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/claim_inquiry/metadata.yml +23 -0
  178. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/claim_update/metadata.yml +31 -0
  179. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/claiminquiryresponse/metadata.yml +42 -0
  180. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/claimresponse/metadata.yml +42 -0
  181. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/communication_request/metadata.yml +4 -0
  182. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/coverage/metadata.yml +1 -0
  183. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/device_request/metadata.yml +2 -0
  184. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/encounter/metadata.yml +3 -0
  185. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/insurer/metadata.yml +1 -0
  186. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/medication_request/metadata.yml +2 -0
  187. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/metadata.yml +265 -1
  188. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/nutrition_order/metadata.yml +2 -0
  189. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/pas_inquiry_request_bundle/metadata.yml +2 -0
  190. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/pas_inquiry_response_bundle/metadata.yml +2 -0
  191. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/pas_request_bundle/metadata.yml +2 -0
  192. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/pas_response_bundle/metadata.yml +2 -0
  193. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/practitioner/metadata.yml +1 -0
  194. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/practitioner_role/metadata.yml +1 -0
  195. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/requestor/metadata.yml +1 -0
  196. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/service_request/metadata.yml +3 -0
  197. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/subscriber/metadata.yml +1 -0
  198. data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/task/metadata.yml +4 -4
  199. data/lib/davinci_pas_test_kit/cross_suite/pas_bundle_validation.rb +570 -312
  200. data/lib/davinci_pas_test_kit/cross_suite/pas_constants.rb +13 -0
  201. data/lib/davinci_pas_test_kit/cross_suite/pas_datatype_constraints.rb +166 -0
  202. data/lib/davinci_pas_test_kit/cross_suite/pas_subscription_verification.rb +8 -4
  203. data/lib/davinci_pas_test_kit/cross_suite/referenced_resource_presence_validation.rb +141 -0
  204. data/lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb +39 -21
  205. data/lib/davinci_pas_test_kit/cross_suite/tags.rb +11 -6
  206. data/lib/davinci_pas_test_kit/cross_suite/validator_configuration.rb +16 -0
  207. data/lib/davinci_pas_test_kit/cross_suite/validator_suppressions.rb +210 -146
  208. data/lib/davinci_pas_test_kit/docs/demo/PAS Client Suite Demonstration.postman_collection.json +7 -7
  209. data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +1 -0
  210. data/lib/davinci_pas_test_kit/generator/client_must_support_group_generator.rb +47 -16
  211. data/lib/davinci_pas_test_kit/generator/must_support_target_profiles.rb +17 -0
  212. data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +14 -2
  213. data/lib/davinci_pas_test_kit/generator/pas_must_support_metadata_extractor.rb +1 -2
  214. data/lib/davinci_pas_test_kit/generator/profile_metadata.rb +1 -1
  215. data/lib/davinci_pas_test_kit/generator/server_must_support_group_generator.rb +23 -0
  216. data/lib/davinci_pas_test_kit/generator/server_suite_generator.rb +8 -7
  217. data/lib/davinci_pas_test_kit/generator/templates/client_must_support_group.rb.erb +22 -3
  218. data/lib/davinci_pas_test_kit/generator/templates/client_must_support_response_group.rb.erb +7 -16
  219. data/lib/davinci_pas_test_kit/generator/templates/must_support.rb.erb +11 -10
  220. data/lib/davinci_pas_test_kit/generator/templates/server_must_support_group.rb.erb +22 -0
  221. data/lib/davinci_pas_test_kit/generator/templates/server_suite.rb.erb +9 -11
  222. data/lib/davinci_pas_test_kit/generator/templates/use_case_group.rb.erb +3 -0
  223. data/lib/davinci_pas_test_kit/generator/use_case_group_generator.rb +19 -13
  224. data/lib/davinci_pas_test_kit/parameters_helper.rb +13 -5
  225. data/lib/davinci_pas_test_kit/pas_notification_conformance_test.rb +2 -2
  226. data/lib/davinci_pas_test_kit/requirements/davinci_pas_test_kit_requirements.csv +14 -7
  227. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v201_requirements_coverage.csv +21 -21
  228. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v221_requirements_coverage.csv +30 -26
  229. data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_server_suite_v221_requirements_coverage.csv +39 -33
  230. data/lib/davinci_pas_test_kit/requirements/hl7.fhir.us.davinci-pas_2.2.1_requirements.xlsx +0 -0
  231. data/lib/davinci_pas_test_kit/server/claim_operation_logic.rb +1 -1
  232. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
  233. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
  234. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
  235. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
  236. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
  237. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
  238. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +1 -1
  239. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +1 -1
  240. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
  241. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
  242. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
  243. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
  244. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
  245. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
  246. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
  247. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
  248. 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
  249. 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
  250. 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
  251. 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
  252. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_approval_use_case_group.rb +4 -3
  253. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_denial_use_case_group.rb +4 -3
  254. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_pended_use_case_group.rb +7 -6
  255. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
  256. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
  257. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
  258. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
  259. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
  260. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
  261. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
  262. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
  263. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
  264. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
  265. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
  266. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
  267. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/server_suite.rb +9 -11
  268. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
  269. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
  270. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_inquire_response_must_support_task_test.rb +1 -1
  271. data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_submit_response_must_support_task_test.rb +1 -1
  272. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
  273. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
  274. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
  275. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
  276. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
  277. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
  278. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +3 -1
  279. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +3 -1
  280. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
  281. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
  282. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
  283. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
  284. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
  285. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
  286. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
  287. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
  288. 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
  289. 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
  290. 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
  291. 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
  292. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_approval_use_case_group.rb +5 -3
  293. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_denial_use_case_group.rb +5 -3
  294. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_must_support_group.rb +12 -0
  295. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_pended_use_case_group.rb +9 -4
  296. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
  297. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
  298. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
  299. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
  300. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
  301. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
  302. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
  303. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
  304. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
  305. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
  306. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
  307. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
  308. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/server_suite.rb +9 -11
  309. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
  310. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
  311. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_inquire_response_must_support_task_test.rb +1 -1
  312. data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_submit_response_must_support_task_test.rb +1 -1
  313. data/lib/davinci_pas_test_kit/server/pas_claim_response_decision_test.rb +2 -2
  314. data/lib/davinci_pas_test_kit/server/server_request_bundle_validation_test.rb +4 -6
  315. data/lib/davinci_pas_test_kit/server/server_response_bundle_validation_test.rb +17 -10
  316. data/lib/davinci_pas_test_kit/server/v2.0.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
  317. data/lib/davinci_pas_test_kit/server/v2.0.1/pas_server_subscription_setup.rb +1 -1
  318. data/lib/davinci_pas_test_kit/server/v2.2.1/claim_inquiry/server_claim_inquiry_response_tests.rb +89 -0
  319. data/lib/davinci_pas_test_kit/server/v2.2.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
  320. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_error_group.rb +2 -0
  321. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_claim_inquiry_responses_group.rb +17 -0
  322. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_claim_updates_group.rb +1 -1
  323. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_no_custom_extensions_test.rb +241 -0
  324. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_subscription_capability_statement_test.rb +40 -0
  325. data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_subscription_setup.rb +15 -10
  326. data/lib/davinci_pas_test_kit/server/v2.2.1/server_replaced_pa_inquire_reference_input_test.rb +63 -0
  327. data/lib/davinci_pas_test_kit/server/v2.2.1/server_replaced_pa_inquire_reference_test.rb +109 -0
  328. data/lib/davinci_pas_test_kit/version.rb +2 -2
  329. metadata +38 -13
  330. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_inquire_response_must_support_task_test.rb +0 -45
  331. data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_submit_response_must_support_task_test.rb +0 -45
  332. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_inquire_response_must_support_task_test.rb +0 -55
  333. data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_submit_response_must_support_task_test.rb +0 -55
  334. data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_error_handling_group.rb +0 -20
@@ -7,11 +7,11 @@ module DaVinciPASTestKit
7
7
  title 'All must support elements for profile PAS PractitionerRole are observed on $submit responses'
8
8
  description %(
9
9
 
10
- PAS client systems are required to be able to receive all
11
- must support elements on instances of all profiles included in
10
+ PAS clients are required to be able to receive all
11
+ must support elements on instances of all profiles included in `$submit`
12
12
  responses, including instances of the PAS PractitionerRole Profile.
13
13
  This test checks all identified instances of the PAS PractitionerRole
14
- Profile on responses sent to the client to ensure that the following
14
+ Profile on responses sent to the PAS client to ensure that the following
15
15
  must support elements are observed:
16
16
 
17
17
  * PractitionerRole.code
@@ -24,6 +24,7 @@ module DaVinciPASTestKit
24
24
  * PractitionerRole.telecom.system
25
25
  * PractitionerRole.telecom.value
26
26
  )
27
+ verifies_requirements 'hl7.fhir.us.davinci-pas_2.2.1@hrex-conf-2'
27
28
 
28
29
  config(
29
30
  options: {
@@ -7,11 +7,11 @@ module DaVinciPASTestKit
7
7
  title 'All must support elements for profile PAS Requestor Organization are observed on $inquire responses'
8
8
  description %(
9
9
 
10
- PAS client systems are required to be able to receive all
11
- must support elements on instances of all profiles included in
10
+ PAS clients are required to be able to receive all
11
+ must support elements on instances of all profiles included in `$inquire`
12
12
  responses, including instances of the PAS Requestor Organization Profile.
13
13
  This test checks all identified instances of the PAS Requestor Organization
14
- Profile on responses sent to the client to ensure that the following
14
+ Profile on responses sent to the PAS client to ensure that the following
15
15
  must support elements are observed:
16
16
 
17
17
  * Organization.active
@@ -34,6 +34,7 @@ module DaVinciPASTestKit
34
34
  * Organization.telecom.value
35
35
  * Organization.type
36
36
  )
37
+ verifies_requirements 'hl7.fhir.us.davinci-pas_2.2.1@hrex-conf-2'
37
38
 
38
39
  config(
39
40
  options: {
@@ -7,11 +7,11 @@ module DaVinciPASTestKit
7
7
  title 'All must support elements for profile PAS Requestor Organization are observed on $submit responses'
8
8
  description %(
9
9
 
10
- PAS client systems are required to be able to receive all
11
- must support elements on instances of all profiles included in
10
+ PAS clients are required to be able to receive all
11
+ must support elements on instances of all profiles included in `$submit`
12
12
  responses, including instances of the PAS Requestor Organization Profile.
13
13
  This test checks all identified instances of the PAS Requestor Organization
14
- Profile on responses sent to the client to ensure that the following
14
+ Profile on responses sent to the PAS client to ensure that the following
15
15
  must support elements are observed:
16
16
 
17
17
  * Organization.active
@@ -34,6 +34,7 @@ module DaVinciPASTestKit
34
34
  * Organization.telecom.value
35
35
  * Organization.type
36
36
  )
37
+ verifies_requirements 'hl7.fhir.us.davinci-pas_2.2.1@hrex-conf-2'
37
38
 
38
39
  config(
39
40
  options: {
@@ -20,8 +20,18 @@ module DaVinciPASTestKit
20
20
 
21
21
  sidekiq_options retry: false
22
22
 
23
+ # How long an Inferno test that starts this job waits for it to send the notification. The job polls for
24
+ # the test to start waiting for up to this long, since there is no point sending once the wait has timed out.
25
+ TEST_WAIT_TIMEOUT_SECONDS = 300
26
+ TEST_WAITING_POLL_INTERVAL_SECONDS = 0.5
27
+
28
+ # test_run_id and result_id may be nil when the job is started by an Inferno test, which does not know
29
+ # them until it is waiting. They are then looked up from the test session once the test waits.
30
+ # When resume_test_after_notification is true, the job ends the wait with the resume_token after
31
+ # sending the notification (or fails it if the job errors).
32
+ # Sidekiq job arguments are positional, so the boolean cannot be a keyword argument
23
33
  def perform(test_run_id, test_session_id, result_id, notification_bearer_token, notification_json, resume_token,
24
- notification_suite_id, ig_version = 'v2.0.1')
34
+ notification_suite_id, ig_version = 'v2.0.1', resume_test_after_notification = false) # rubocop:disable Style/OptionalBooleanParameter
25
35
  @test_run_id = test_run_id
26
36
  @test_session_id = test_session_id
27
37
  @result_id = result_id
@@ -30,8 +40,17 @@ module DaVinciPASTestKit
30
40
  @resume_token = resume_token
31
41
  @notification_suite_id = notification_suite_id
32
42
  @ig_version = ig_version
43
+ @resume_test_after_notification = resume_test_after_notification
33
44
 
34
45
  await_subscription_creation # NOTE: currently must exist - see PASClientPendedSubmitTest
46
+ if @result_id.nil? && !test_starts_waiting?
47
+ # the test can't be resumed because it isn't waiting, so just explain why no notification was sent
48
+ Inferno::Application['logger'].error(
49
+ "Subscription notification not sent: no test started waiting on '#{@resume_token}' " \
50
+ "within #{TEST_WAIT_TIMEOUT_SECONDS} seconds."
51
+ )
52
+ return
53
+ end
35
54
  sleep 1
36
55
  return unless test_still_waiting?
37
56
 
@@ -39,6 +58,12 @@ module DaVinciPASTestKit
39
58
  return unless test_still_waiting?
40
59
 
41
60
  send_event_notification
61
+ resume_test(RESUME_PASS_PATH) if @resume_test_after_notification
62
+ rescue StandardError => e
63
+ raise unless @resume_test_after_notification
64
+
65
+ Inferno::Application['logger'].error("Sending the subscription notification failed: #{e.message}")
66
+ resume_test(RESUME_FAIL_PATH)
42
67
  end
43
68
 
44
69
  def requests_repo
@@ -94,8 +119,44 @@ module DaVinciPASTestKit
94
119
  @subscription_full_url ||= "#{fhir_subscription_url}/#{subscription.id}"
95
120
  end
96
121
 
122
+ def test_runs_repo
123
+ @test_runs_repo ||= Inferno::Repositories::TestRuns.new
124
+ end
125
+
126
+ # @resume_token is the same identifier the test's own wait() call registers (and that
127
+ # resume_test later ends the wait with), so this is an exact match on the waiting test
128
+ # run - not a guess at "the most recent run for this session", which could pick up an
129
+ # unrelated run if the tester has more than one for the same session.
130
+ def test_run_id
131
+ @test_run_id ||= test_runs_repo.find_latest_waiting_by_identifier(@resume_token)&.id
132
+ end
133
+
134
+ def waiting_result
135
+ results_repo.find_waiting_result(test_run_id:)
136
+ end
137
+
138
+ def result_id
139
+ @result_id ||= waiting_result&.id
140
+ end
141
+
97
142
  def test_still_waiting?
98
- results_repo.find_waiting_result(test_run_id: @test_run_id)
143
+ waiting_result.present?
144
+ end
145
+
146
+ # Inferno tests start the job before they begin waiting, so poll until the test is waiting, giving up
147
+ # once the test's own wait would have timed out.
148
+ # @return [Boolean] whether the test is waiting
149
+ def test_starts_waiting?
150
+ (TEST_WAIT_TIMEOUT_SECONDS / TEST_WAITING_POLL_INTERVAL_SECONDS).to_i.times do
151
+ return true if test_still_waiting?
152
+
153
+ sleep TEST_WAITING_POLL_INTERVAL_SECONDS
154
+ end
155
+ test_still_waiting?
156
+ end
157
+
158
+ def resume_test(path)
159
+ test_suite_connection.get(path.delete_prefix('/'), { token: @resume_token })
99
160
  end
100
161
 
101
162
  def await_subscription_creation
@@ -130,7 +191,7 @@ module DaVinciPASTestKit
130
191
  request_body: response.env.request_body,
131
192
  response_body: response.env.response_body,
132
193
  test_session_id: @test_session_id,
133
- result_id: @result_id,
194
+ result_id:,
134
195
  request_headers: inferno_request_headers,
135
196
  response_headers: inferno_response_headers,
136
197
  tags:
@@ -9,14 +9,15 @@ module DaVinciPASTestKit
9
9
  id :pas_client_subscription_pas_conformance_test
10
10
  title 'Subscription creation request has the correct structure and content'
11
11
  description %(
12
- This test verifies that the Subscription created by the client under test
12
+ This test verifies that the Subscription created by the PAS client
13
13
  is conformant to PAS requirements on the Subscription, including
14
14
  - The use of the [PAS-defined Subscription
15
15
  Topic](https://hl7.org/fhir/us/davinci-pas/STU2/SubscriptionTopic-PASSubscriptionTopic.html), and
16
- - Inclusion of filter criteria for the client's organization.
16
+ - Inclusion of filter criteria for the PAS client's organization.
17
17
  )
18
18
 
19
- verifies_requirements 'hl7.fhir.us.davinci-pas_2.2.1@spec-62'
19
+ verifies_requirements 'hl7.fhir.us.davinci-pas_2.2.1@spec-62', 'hl7.fhir.uv.subscriptions_1.1.0@64',
20
+ 'hl7.fhir.uv.subscriptions_1.1.0@96', 'hl7.fhir.uv.subscriptions_1.1.0@116'
20
21
 
21
22
  def ig_version
22
23
  config.options[:ig_version]
@@ -3,9 +3,11 @@ module DaVinciPASTestKit
3
3
  id :pas_client_reg_config_other_display
4
4
  title 'PAS client registers Inferno as a PAS server'
5
5
  description %(
6
- This test provides all the information needed for testers to configure
7
- the client under test to communicate with Inferno's simulated PAS server
8
- using dedicated endpoints.
6
+ During this test, Inferno will wait while the tester configures the PAS client
7
+ to communicate with Inferno's simulated PAS server using dedicated
8
+ endpoints. The "User Action Required" dialog that appears during the test
9
+ will provide all the information needed for testers to configure the PAS client,
10
+ including the FHIR base URL.
9
11
  )
10
12
  attestation
11
13
 
@@ -37,7 +39,7 @@ module DaVinciPASTestKit
37
39
  FHIR Base URL: `#{session_fhir_base_url(wait_identifier)}`
38
40
 
39
41
  [Click here](#{confirmation_url}) once you have configured
40
- the client to connect to Inferno at the above endpoints.
42
+ the PAS client to send PAS requests to Inferno at the above endpoint.
41
43
  )
42
44
  )
43
45
  end
@@ -3,9 +3,12 @@ module DaVinciPASTestKit
3
3
  id :pas_client_reg_config_smart_display
4
4
  title 'PAS client registers Inferno as a PAS server'
5
5
  description %(
6
- This test provides all the information needed for testers to configure
7
- the client under test to communicate with Inferno's simulated PAS server
8
- including SMART endpoints to obtain access tokens.
6
+ During this test, Inferno will wait while the tester configures the PAS client
7
+ to communicate with Inferno's simulated PAS server using
8
+ endpoints authenticated using SMART Backend Services. The "User Action Required"
9
+ dialog that appears during the test will provide all the information needed
10
+ for testers to configure the PAS client, including the FHIR base URL, the
11
+ token endpoint, and the PAS client's assigned client id.
9
12
  )
10
13
  attestation
11
14
 
@@ -29,7 +32,8 @@ module DaVinciPASTestKit
29
32
  - Token endpoint: `#{token_url}`
30
33
 
31
34
  [Click here](#{confirmation_url}) once you have configured
32
- the client to connect to Inferno at the above endpoints.
35
+ the PAS client to authenticate with Inferno and send PAS requests
36
+ to Inferno at the above endpoint.
33
37
  )
34
38
  )
35
39
  end
@@ -3,9 +3,13 @@ module DaVinciPASTestKit
3
3
  id :pas_client_reg_config_udap_display
4
4
  title 'PAS client registers Inferno as a PAS server'
5
5
  description %(
6
- This test provides all the information needed for testers to configure
7
- the client under test to communicate with Inferno's simulated PAS server
8
- including UDAP endpoints to obtain access tokens.
6
+ During this test, Inferno will wait while the tester configures the PAS client
7
+ to communicate with Inferno's simulated PAS server using
8
+ endpoints authenticated using the UDAP Client Credentials flow.
9
+ The "User Action Required" dialog that appears during the test will provide
10
+ all the information needed for testers to configure the PAS client,
11
+ including the FHIR base URL, the token endpoint, and the
12
+ assigned client id.
9
13
  )
10
14
  attestation
11
15
 
@@ -29,7 +33,8 @@ module DaVinciPASTestKit
29
33
  - Token endpoint: `#{token_url}`
30
34
 
31
35
  [Click here](#{confirmation_url}) once you have configured
32
- the client to connect to Inferno at the above endpoints.
36
+ the PAS client to authenticate with Inferno and send PAS requests
37
+ to Inferno at the above endpoint.
33
38
  )
34
39
  )
35
40
  end
@@ -3,8 +3,8 @@ module DaVinciPASTestKit
3
3
  id :pas_client_reg_other_auth_attest
4
4
  title 'PAS client supports a non-standard approach for authenticating with the PAS server'
5
5
  description %(
6
- Since a standard auth approach was not chosen for this session, this test provides testers with an
7
- opportunity to attest to their client's ability to authenticate itself to a server
6
+ Since a standard auth approach was not chosen for this session, this test asks testers
7
+ to attest to the PAS client's ability to authenticate itself to a server
8
8
  using a method that this Inferno test suite does not support, such as mutual authentication
9
9
  TLS.
10
10
  )
@@ -14,7 +14,8 @@ module DaVinciPASTestKit
14
14
  output :attest_false_url
15
15
 
16
16
  run do
17
- identifier = test_session_id
17
+ # only the tester continues this wait, so use a fresh random identifier - see SessionIdentification
18
+ identifier = SecureRandom.uuid
18
19
  attest_true_url = "#{resume_pass_url}?token=#{identifier}"
19
20
  output(attest_true_url:)
20
21
  attest_false_url = "#{resume_fail_url}?token=#{identifier}"
@@ -25,7 +26,7 @@ module DaVinciPASTestKit
25
26
  message: %(
26
27
  **Other Authentication Attestation**:
27
28
 
28
- I attest that the client system can authenticate itself with a PAS server using
29
+ I attest that the PAS client can authenticate itself with a PAS server using
29
30
  a mechanism other than the SMART Backend Services or UDAP B2B client credentials
30
31
  flows.
31
32
 
@@ -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