davinci_dtr_test_kit 0.16.0 → 0.16.1

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/full_ehr_postman_dinner_order_example.json.erb +41 -0
  3. data/config/presets/full_ehr_postman_respiratory_device_example.json +1 -1
  4. data/config/presets/smart_app_postman_dinner_order_example.json +8 -1
  5. data/config/presets/smart_app_postman_respiratory_device_example.json +1 -1
  6. data/lib/davinci_dtr_test_kit/certs/InfernoCA.key +52 -0
  7. data/lib/davinci_dtr_test_kit/certs/InfernoCA.pem +35 -0
  8. data/lib/davinci_dtr_test_kit/certs/TestKit.pem +32 -0
  9. data/lib/davinci_dtr_test_kit/certs/TestKitPrivateKey.key +28 -0
  10. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_custom_next_question_response_validation_test.rb +95 -0
  11. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_full_ehr_custom_adaptive_request_test.rb +87 -0
  12. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_full_ehr_custom_adaptive_workflow_group.rb +136 -0
  13. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_smart_app_custom_adaptive_request_test.rb +171 -0
  14. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_smart_app_custom_adaptive_workflow_group.rb +146 -0
  15. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_next_question_retrieval_group.rb +3 -3
  16. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_full_ehr_adaptive_dinner_workflow_group.rb +21 -11
  17. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_full_ehr_adaptive_initial_retrieval_group.rb +6 -6
  18. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_smart_app_adaptive_dinner_workflow_group.rb +5 -5
  19. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_smart_app_adaptive_initial_retrieval_group.rb +5 -5
  20. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire}/dtr_adaptive_next_question_request_test.rb +9 -24
  21. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire}/dtr_adaptive_next_question_request_validation_test.rb +36 -17
  22. data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/dtr_adaptive_response_validation_test.rb +130 -0
  23. data/lib/davinci_dtr_test_kit/client_groups/auth/dtr_client_payer_auth_smart_group.rb +29 -0
  24. data/lib/davinci_dtr_test_kit/client_groups/auth/dtr_client_payer_auth_udap_group.rb +29 -0
  25. data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_full_ehr_custom_static_workflow_group.rb +15 -14
  26. data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_smart_app_custom_static_workflow_group.rb +5 -5
  27. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_static_dinner_workflow_group.rb +14 -10
  28. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_static_dinner_workflow_group.rb +1 -1
  29. data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → full_ehr}/dtr_full_ehr_adaptive_request_test.rb +11 -14
  30. data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_package_request_test.rb +9 -17
  31. data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_correctness_test.rb +10 -1
  32. data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_store_attestation_test.rb +3 -3
  33. data/lib/davinci_dtr_test_kit/client_groups/light_ehr/fhir_context_references_test.rb +4 -5
  34. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_full_ehr_ms_questionnaire_package_request_test.rb +75 -0
  35. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_full_ehr_questionnaire_must_support_group.rb +85 -0
  36. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_must_support_attestation_test.rb +39 -0
  37. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_questionnaire_must_support_test.rb +42 -0
  38. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_smart_app_ms_questionnaire_package_request_test.rb +148 -0
  39. data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_smart_app_questionnaire_must_support_group.rb +85 -0
  40. data/lib/davinci_dtr_test_kit/client_groups/must_support/questionnaire_must_support_elements.rb +55 -0
  41. data/lib/davinci_dtr_test_kit/client_groups/payer_registration/configuration_display_smart_test.rb +35 -0
  42. data/lib/davinci_dtr_test_kit/client_groups/payer_registration/configuration_display_udap_test.rb +35 -0
  43. data/lib/davinci_dtr_test_kit/client_groups/payer_registration/dtr_client_registration_group.rb +48 -0
  44. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_custom_questionnaire_expressions_test.rb +36 -0
  45. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_custom_questionnaire_extensions_test.rb +32 -0
  46. data/lib/davinci_dtr_test_kit/client_groups/{custom_static → shared}/dtr_custom_questionnaire_libraries_test.rb +7 -2
  47. data/lib/davinci_dtr_test_kit/client_groups/{custom_static → shared}/dtr_custom_questionnaire_package_validation_test.rb +6 -2
  48. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb +6 -2
  49. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_prepopulation_test.rb +7 -1
  50. data/lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_questionnaire_response_correctness_test.rb +4 -3
  51. data/lib/davinci_dtr_test_kit/descriptions.rb +8 -0
  52. data/lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md +145 -78
  53. data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +4 -3
  54. data/lib/davinci_dtr_test_kit/dtr_client_options.rb +13 -0
  55. data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +47 -7
  56. data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +33 -21
  57. data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +7 -4
  58. data/lib/davinci_dtr_test_kit/endpoints/mock_ehr.rb +1 -1
  59. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +20 -1
  60. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +21 -1
  61. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_endpoint.rb +29 -4
  62. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_endpoint.rb +1 -1
  63. data/lib/davinci_dtr_test_kit/endpoints/mock_udap_smart_server/token_endpoint.rb +36 -0
  64. data/lib/davinci_dtr_test_kit/requirements/davinci-dtr-test-kit_out_of_scope_requirements.csv +6 -5
  65. data/lib/davinci_dtr_test_kit/requirements/davinci-dtr-test-kit_requirements.csv +10 -9
  66. data/lib/davinci_dtr_test_kit/requirements/generated/davinci-dtr-test-kit_requirements_coverage.csv +21 -21
  67. data/lib/davinci_dtr_test_kit/urls.rb +21 -4
  68. data/lib/davinci_dtr_test_kit/version.rb +2 -2
  69. metadata +59 -21
  70. data/config/presets/full_ehr_postman_dinner_order_example_postman.json +0 -19
  71. data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_custom_questionnaire_expressions_test.rb +0 -22
  72. data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_custom_questionnaire_extensions_test.rb +0 -19
  73. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_response_validation_test.rb +0 -68
  74. /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_completion_group.rb +0 -0
  75. /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_followup_questions_group.rb +0 -0
  76. /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → smart_app}/dtr_smart_app_adaptive_request_test.rb +0 -0
@@ -1,14 +1,15 @@
1
- require_relative '../../tags'
1
+ require_relative '../../../tags'
2
2
  require_relative 'dtr_full_ehr_adaptive_initial_retrieval_group'
3
- require_relative '../full_ehr/dtr_full_ehr_prepopulation_attestation_test'
4
- require_relative '../full_ehr/dtr_full_ehr_prepopulation_override_attestation_test'
3
+ require_relative '../../full_ehr/dtr_full_ehr_prepopulation_attestation_test'
4
+ require_relative '../../full_ehr/dtr_full_ehr_prepopulation_override_attestation_test'
5
5
  require_relative 'dtr_adaptive_followup_questions_group'
6
6
  require_relative 'dtr_adaptive_completion_group'
7
+ require_relative '../../full_ehr/dtr_full_ehr_store_attestation_test'
7
8
 
8
9
  module DaVinciDTRTestKit
9
10
  class DTRFullEHRAdaptiveDinnerWorkflowGroup < Inferno::TestGroup
10
11
  id :dtr_full_ehr_adaptive_dinner_workflow
11
- title 'Adaptive Questionnaire Workflow'
12
+ title 'Dinner Order Adaptive Questionnaire Workflow'
12
13
  description %(
13
14
  This test validates that a DTR Full EHR client can perform a full DTR Adaptive Questionnaire workflow
14
15
  using a mocked questionnaire requesting what a patient wants for dinner. The client system must
@@ -67,12 +68,21 @@ module DaVinciDTRTestKit
67
68
  }
68
69
  }
69
70
 
70
- group from: :dtr_adaptive_completion,
71
- config: {
72
- options: {
73
- accepts_multiple_requests: true,
74
- next_tag: "completion_#{CLIENT_NEXT_TAG}"
75
- }
76
- }
71
+ group from: :dtr_adaptive_completion do
72
+ config(
73
+ options: {
74
+ accepts_multiple_requests: true,
75
+ next_tag: "completion_#{CLIENT_NEXT_TAG}"
76
+ }
77
+ )
78
+ group do
79
+ title 'Attestation: QuestionnaireResponse Completion and Storage'
80
+ description %(
81
+ The tester will attest to the completion of the questionnaire such that the results are stored for later use.
82
+ )
83
+
84
+ test from: :dtr_full_ehr_store_attest
85
+ end
86
+ end
77
87
  end
78
88
  end
@@ -1,9 +1,9 @@
1
- require_relative '../../tags'
2
- require_relative '../full_ehr/dtr_full_ehr_launch_attestation_test'
3
- require_relative 'dtr_full_ehr_adaptive_request_test'
4
- require_relative '../shared/dtr_questionnaire_package_request_validation_test'
5
- require_relative 'dtr_adaptive_next_question_request_validation_test'
6
- require_relative 'dtr_adaptive_response_validation_test'
1
+ require_relative '../../../tags'
2
+ require_relative '../../full_ehr/dtr_full_ehr_launch_attestation_test'
3
+ require_relative '../../full_ehr/dtr_full_ehr_adaptive_request_test'
4
+ require_relative '../../shared/dtr_questionnaire_package_request_validation_test'
5
+ require_relative '../dtr_adaptive_next_question_request_validation_test'
6
+ require_relative '../dtr_adaptive_response_validation_test'
7
7
 
8
8
  module DaVinciDTRTestKit
9
9
  class DTRFullEHRAdaptiveInitialRetrievalGroup < Inferno::TestGroup
@@ -1,15 +1,15 @@
1
- require_relative '../../tags'
1
+ require_relative '../../../tags'
2
2
  require_relative 'dtr_smart_app_adaptive_initial_retrieval_group'
3
- require_relative '../smart_app/dtr_smart_app_prepopulation_attestation_test'
4
- require_relative '../smart_app/dtr_smart_app_prepopulation_override_attestation_test'
3
+ require_relative '../../smart_app/dtr_smart_app_prepopulation_attestation_test'
4
+ require_relative '../../smart_app/dtr_smart_app_prepopulation_override_attestation_test'
5
5
  require_relative 'dtr_adaptive_followup_questions_group'
6
6
  require_relative 'dtr_adaptive_completion_group'
7
- require_relative '../shared/dtr_questionnaire_response_prepopulation_test'
7
+ require_relative '../../shared/dtr_questionnaire_response_prepopulation_test'
8
8
 
9
9
  module DaVinciDTRTestKit
10
10
  class DTRSmartAppAdaptiveDinnerWorkflowGroup < Inferno::TestGroup
11
11
  id :dtr_smart_app_adaptive_dinner_workflow
12
- title 'Adaptive Questionnaire Workflow'
12
+ title 'Dinner Order Adaptive Questionnaire Workflow'
13
13
  description %(
14
14
  This test validates that a DTR SMART App client can perform a full DTR Adaptive Questionnaire workflow
15
15
  using a mocked questionnaire requesting what a patient wants for dinner. The client system must
@@ -1,8 +1,8 @@
1
- require_relative '../../tags'
2
- require_relative 'dtr_smart_app_adaptive_request_test'
3
- require_relative '../shared/dtr_questionnaire_package_request_validation_test'
4
- require_relative 'dtr_adaptive_next_question_request_validation_test'
5
- require_relative 'dtr_adaptive_response_validation_test'
1
+ require_relative '../../../tags'
2
+ require_relative '../../smart_app/dtr_smart_app_adaptive_request_test'
3
+ require_relative '../../shared/dtr_questionnaire_package_request_validation_test'
4
+ require_relative '../dtr_adaptive_next_question_request_validation_test'
5
+ require_relative '../dtr_adaptive_response_validation_test'
6
6
 
7
7
  module DaVinciDTRTestKit
8
8
  class DTRSmartAppAdaptiveInitialRetrievalGroup < Inferno::TestGroup
@@ -1,3 +1,4 @@
1
+ require_relative '../../descriptions'
1
2
  require_relative '../../urls'
2
3
 
3
4
  module DaVinciDTRTestKit
@@ -14,19 +15,12 @@ module DaVinciDTRTestKit
14
15
  )
15
16
  verifies_requirements 'hl7.fhir.us.davinci-dtr_2.0.1@264'
16
17
 
17
- input :access_token
18
-
19
- def example_client_jwt_payload_part
20
- Base64.strict_encode64({ inferno_client_id: access_token }.to_json).delete('=')
21
- end
22
-
23
- def request_identification
24
- if config.options[:smart_app]
25
- "eyJhbGciOiJub25lIn0.#{example_client_jwt_payload_part}"
26
- else
27
- access_token
28
- end
29
- end
18
+ input :client_id,
19
+ title: 'Client Id',
20
+ type: 'text',
21
+ optional: true,
22
+ locked: true,
23
+ description: INPUT_CLIENT_ID_LOCKED
30
24
 
31
25
  def cont_test_description
32
26
  <<~DESCRIPTION
@@ -34,7 +28,7 @@ module DaVinciDTRTestKit
34
28
 
35
29
  When the DTR application has finished loading the Questionnaire,
36
30
  including any clinical data requests to support pre-population,
37
- [Click here](#{resume_pass_url}?token=#{access_token}) to continue.
31
+ [Click here](#{resume_pass_url}?token=#{client_id}) to continue.
38
32
  DESCRIPTION
39
33
  end
40
34
 
@@ -67,7 +61,7 @@ module DaVinciDTRTestKit
67
61
 
68
62
  run do
69
63
  wait(
70
- identifier: access_token,
64
+ identifier: client_id,
71
65
  message: <<~MESSAGE
72
66
  ### #{next_question_prompt_title}
73
67
 
@@ -77,15 +71,6 @@ module DaVinciDTRTestKit
77
71
 
78
72
  #{prompt_cont}
79
73
 
80
- ### Request Identification
81
-
82
- In order to identify requests for this session, Inferno will look for
83
- an `Authorization` header with value:
84
-
85
- ```
86
- Bearer #{request_identification}
87
- ```
88
-
89
74
  #{cont_test_description if config.options[:accepts_multiple_requests]}
90
75
  MESSAGE
91
76
  )
@@ -24,6 +24,9 @@ module DaVinciDTRTestKit
24
24
  If it is a Parameters resource, it must contain one parameter named `questionnaire-response`
25
25
  with a `resource` attribute set to a FHIR QuestionnaireResponse instance, as specified above.
26
26
 
27
+ This test may process multiple resources, labeling messages with the corresponding tested resources
28
+ in the order that they were received.
29
+
27
30
  The QuestionnaireResponse resource's structure and conformance will be validated
28
31
  in the following test ('Adaptive QuestionnaireResponse is valid').
29
32
  )
@@ -39,25 +42,41 @@ module DaVinciDTRTestKit
39
42
  config.options[:next_tag]
40
43
  end
41
44
 
45
+ def perform_requests_validation
46
+ requests.each_with_index do |r, index|
47
+ if r.url != next_url
48
+ add_message('warning',
49
+ "Request #{index} made to wrong URL: #{r.url}. Should instead be to #{next_url}")
50
+ end
51
+ assert_valid_json(r.request_body)
52
+ input_params = FHIR.from_contents(r.request_body)
53
+ assert input_params.present?, 'Request does not contain a recognized FHIR object'
54
+ assert_valid_resource_type(input_params)
55
+
56
+ if input_params.is_a?(FHIR::Parameters)
57
+ questionnaire_response_params = input_params.parameter.select do |param|
58
+ param.name == 'questionnaire-response'
59
+ end
60
+ qr_params_count = questionnaire_response_params.length
61
+ assert qr_params_count == 1,
62
+ "Input parameter must contain one `parameter:questionnaire-response` slice. Found #{qr_params_count}"
63
+
64
+ questionnaire_response = questionnaire_response_params.first.resource
65
+ assert_resource_type(:questionnaire_response, resource: questionnaire_response)
66
+ end
67
+ rescue Inferno::Exceptions::AssertionException => e
68
+ add_message('error', "Request #{index}: #{e.message}")
69
+ next
70
+ end
71
+ end
72
+
42
73
  run do
43
74
  load_tagged_requests next_request_tag
44
- skip_if request.blank?, 'A $next-question request must be made prior to running this test'
45
-
46
- assert request.url == next_url, "Request made to wrong URL: #{request.url}. Should instead be to #{next_url}"
47
- assert_valid_json(request.request_body)
48
- input_params = FHIR.from_contents(request.request_body)
49
- assert input_params.present?, 'Request does not contain a recognized FHIR object'
50
- assert_valid_resource_type(input_params)
51
-
52
- if input_params.is_a?(FHIR::Parameters)
53
- questionnaire_response_params = input_params.parameter.select { |param| param.name == 'questionnaire-response' }
54
- qr_params_count = questionnaire_response_params.length
55
- assert qr_params_count == 1,
56
- "Input parameter must contain one `parameter:questionnaire-response` slice. Found #{qr_params_count}"
57
-
58
- questionnaire_response = questionnaire_response_params.first.resource
59
- assert_resource_type(:questionnaire_response, resource: questionnaire_response)
60
- end
75
+ skip_if requests.blank?, 'A $next-question request must be made prior to running this test'
76
+
77
+ perform_requests_validation
78
+
79
+ assert messages.none? { |m| m[:type] == 'error' }, 'next-quest request(s) not comformant'
61
80
  end
62
81
  end
63
82
  end
@@ -0,0 +1,130 @@
1
+ require_relative '../../urls'
2
+ require_relative '../../dtr_questionnaire_response_validation'
3
+
4
+ module DaVinciDTRTestKit
5
+ class DTRAdaptiveResponseValidationTest < Inferno::Test
6
+ include URLs
7
+ include DTRQuestionnaireResponseValidation
8
+
9
+ id :dtr_adaptive_response_validation
10
+ title 'Adaptive QuestionnaireResponse is valid'
11
+ description %(
12
+ This test validates the conformance of the Adaptive QuestionnaireResponse to the
13
+ [SDCQuestionnaireResponseAdapt](http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse-adapt)
14
+ structure. It verifies the presence of mandatory elements and that elements
15
+ with required bindings contain appropriate values.
16
+
17
+ It also ensures that all required questions are answered, and that the `origin.source`
18
+ extension is correct for each answer:
19
+ - `PBD.1` (Last Name) and `LOC.1` (Location): `auto`
20
+ - `PBD.2` (First Name): `override`
21
+ - `3` (all nested dinner questions): `manual`
22
+
23
+ Note: For the initial next-question request, only the conformance to the profile is checked
24
+ since neither the QuestionnaireResponse nor the contained Questionnaire will have any items,
25
+ as no questions are yet known.
26
+ )
27
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.0.1@38', 'hl7.fhir.us.davinci-dtr_2.0.1@210',
28
+ 'hl7.fhir.us.davinci-dtr_2.0.1@264'
29
+
30
+ def profile_url
31
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse-adapt'
32
+ end
33
+
34
+ def next_request_tag
35
+ config.options[:next_tag]
36
+ end
37
+
38
+ def perform_questionnaire_reponses_validation(custom_questionnaires) # rubocop:disable Metrics/CyclomaticComplexity
39
+ requests.each_with_index do |r, index|
40
+ if r.url != next_url
41
+ add_message('warning',
42
+ "Request #{index} made to wrong URL: #{r.url}. Should instead be to #{next_url}")
43
+ end
44
+
45
+ assert_valid_json(r.request_body)
46
+ input_params = FHIR.from_contents(r.request_body)
47
+ assert input_params.present?, 'Request does not contain a recognized FHIR object'
48
+
49
+ qr = nil
50
+ if input_params.is_a?(FHIR::QuestionnaireResponse)
51
+ qr = input_params
52
+ elsif input_params.is_a?(FHIR::Parameters)
53
+ qr = input_params.parameter&.find do |param|
54
+ param.name == 'questionnaire-response'
55
+ end&.resource
56
+ end
57
+
58
+ assert qr.present?, 'QuestionnaireResponse resource not provided.'
59
+ verify_basic_conformance(qr.to_json, profile_url)
60
+
61
+ questionnaire = qr.contained.find { |res| res.resourceType == 'Questionnaire' }
62
+ assert questionnaire, 'QuestionnaireResponse does not contained a Questionnaire'
63
+
64
+ scratch[:contained_questionnaires] ||= []
65
+ scratch[:contained_questionnaires] << questionnaire
66
+
67
+ verify_contained_questionnaire(questionnaire, index, custom_questionnaires)
68
+ check_missing_origin_sources(qr, index) if index == requests.length - 1
69
+
70
+ expected_overrides = next_request_tag&.include?('custom') ? [] : ['PBD.2']
71
+ check_origin_sources(questionnaire.item, qr.item, expected_overrides:, index:)
72
+
73
+ required_link_ids = extract_required_link_ids(questionnaire.item)
74
+ check_answer_presence(qr.item, required_link_ids, index)
75
+ rescue Inferno::Exceptions::AssertionException => e
76
+ prefix = e.message.include?('Workflow not') ? '' : "Request #{index}: "
77
+ add_message('error', "#{prefix}#{e.message}")
78
+ next
79
+ end
80
+ end
81
+
82
+ def verify_contained_questionnaire(questionnaire, index, custom_questionnaires)
83
+ return unless next_request_tag&.include?('custom')
84
+ return unless index.positive? && custom_questionnaires.present?
85
+
86
+ expected_questionnaire = custom_questionnaires[index - 1]
87
+ return unless expected_questionnaire
88
+
89
+ actual_items = questionnaire.to_hash['item']
90
+ expected_items = expected_questionnaire['item']
91
+
92
+ assert actual_items == expected_items, %(
93
+ Invalid QuestionnaireResponse: the contained Questionnaire `item` does not match the expected content.
94
+ **Expected**: #{expected_items.inspect}
95
+ **Received**: #{actual_items.inspect}
96
+ )
97
+ end
98
+
99
+ def verify_workflow_completion(custom_questionnaires)
100
+ return unless next_request_tag&.include?('custom')
101
+
102
+ assert requests.length > custom_questionnaires.length, %(
103
+ Workflow not completed: expected #{custom_questionnaires.length + 1} next-question requests,
104
+ but received #{requests.length}.
105
+ )
106
+ end
107
+
108
+ run do
109
+ load_tagged_requests next_request_tag
110
+ skip_if requests.blank?, 'A $next-question request must be made prior to running this test'
111
+
112
+ custom_questionnaires = []
113
+ if next_request_tag&.include?('custom')
114
+ begin
115
+ custom_questionnaires = [JSON.parse(custom_next_question_questionnaires)].flatten
116
+ rescue JSON::ParserError
117
+ add_message(
118
+ 'error',
119
+ 'Workflow not completed: the provided questionnaires input for next-question requests is not valid JSON'
120
+ )
121
+ end
122
+ end
123
+
124
+ perform_questionnaire_reponses_validation(custom_questionnaires)
125
+ verify_workflow_completion(custom_questionnaires)
126
+
127
+ assert(messages.none? { |m| m[:type] == 'error' }, 'QuestionnaireResponse is not correct, see error message(s)')
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,29 @@
1
+ require 'smart_app_launch_test_kit'
2
+ require_relative '../../tags'
3
+
4
+ module DaVinciDTRTestKit
5
+ class DTRClientPayerAuthSMARTGroup < Inferno::TestGroup
6
+ id :dtr_client_payer_auth_smart
7
+ title 'Review Authentication Interactions'
8
+ description %(
9
+ During these tests, Inferno will verify that the client interacted with Inferno's
10
+ simulated SMART authorization server in a conformant manner when requesting access tokens
11
+ and that the client under test was able to use provided access tokens to make DTR
12
+ requests.
13
+
14
+ Before running these tests, perform at least one DTR workflow group so that the client
15
+ will request an access token and use it on a DTR request.
16
+ )
17
+ run_as_group
18
+
19
+ # smart auth verification
20
+ test from: :smart_client_token_request_bsca_verification,
21
+ config: {
22
+ options: { endpoint_suite_id: :dtr_full_ehr }
23
+ }
24
+ test from: :smart_client_token_use_verification,
25
+ config: {
26
+ options: { access_request_tags: [QUESTIONNAIRE_PACKAGE_TAG, CLIENT_NEXT_TAG] }
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'udap_security_test_kit'
2
+ require_relative '../../tags'
3
+
4
+ module DaVinciDTRTestKit
5
+ class DTRClientPayerAuthUDAPGroup < Inferno::TestGroup
6
+ id :dtr_client_payer_auth_udap
7
+ title 'Review Authentication Interactions'
8
+ description %(
9
+ During these tests, Inferno will verify that the client interacted with Inferno's
10
+ simulated UDAP authorization server in a conformant manner when requesting access tokens
11
+ and that the client under test was able to use provided access tokens to make DTR
12
+ requests.
13
+
14
+ Before running these tests, perform at least one DTR workflow group so that the client
15
+ will request an access token and use it on a DTR request.
16
+ )
17
+ run_as_group
18
+
19
+ # udap auth verification
20
+ test from: :udap_client_token_request_cc_verification,
21
+ config: {
22
+ options: { endpoint_suite_id: :dtr_full_ehr }
23
+ }
24
+ test from: :udap_client_token_use_verification,
25
+ config: {
26
+ options: { access_request_tags: [QUESTIONNAIRE_PACKAGE_TAG, CLIENT_NEXT_TAG] }
27
+ }
28
+ end
29
+ end
@@ -1,7 +1,7 @@
1
- require_relative 'dtr_custom_questionnaire_package_validation_test'
2
- require_relative 'dtr_custom_questionnaire_libraries_test'
3
- require_relative 'dtr_custom_questionnaire_extensions_test'
4
- require_relative 'dtr_custom_questionnaire_expressions_test'
1
+ require_relative '../shared/dtr_custom_questionnaire_package_validation_test'
2
+ require_relative '../shared/dtr_custom_questionnaire_libraries_test'
3
+ require_relative '../shared/dtr_custom_questionnaire_extensions_test'
4
+ require_relative '../shared/dtr_custom_questionnaire_expressions_test'
5
5
  require_relative '../full_ehr/dtr_full_ehr_launch_attestation_test'
6
6
  require_relative '../full_ehr/dtr_full_ehr_questionnaire_package_request_test'
7
7
  require_relative '../shared/dtr_questionnaire_package_request_validation_test'
@@ -29,6 +29,8 @@ module DaVinciDTRTestKit
29
29
  )
30
30
  verifies_requirements 'hl7.fhir.us.davinci-dtr_2.0.1@35', 'hl7.fhir.us.davinci-dtr_2.0.1@208'
31
31
 
32
+ input_order :custom_questionnaire_package_response, :static_custom_questionnaire_response
33
+
32
34
  group do
33
35
  id :dtr_full_ehr_custom_static_retrieval
34
36
  title 'Retrieving the Static Questionnaire'
@@ -46,7 +48,7 @@ module DaVinciDTRTestKit
46
48
  )
47
49
  run_as_group
48
50
 
49
- input_order :access_token, :custom_questionnaire_package_response
51
+ input_order :custom_questionnaire_package_response
50
52
 
51
53
  # Test 0: attest to launch
52
54
  test from: :dtr_full_ehr_launch_attest,
@@ -55,7 +57,13 @@ module DaVinciDTRTestKit
55
57
  title: 'Launch DTR (Attestation)'
56
58
  # Test 1: wait for the $questionnaire-package request
57
59
  test from: :dtr_full_ehr_qp_request do
58
- input :custom_questionnaire_package_response
60
+ input :custom_questionnaire_package_response,
61
+ title: 'Custom Questionnaire Package Response JSON',
62
+ description: %(
63
+ Provide a JSON FHIR Bundle containing a custom questionnaire for Inferno to use as a response to
64
+ the $questionnaire-package request.
65
+ ),
66
+ optional: false
59
67
  end
60
68
  # Test 2: validate the $questionnaire-package body
61
69
  test from: :dtr_qp_request_validation
@@ -89,17 +97,10 @@ module DaVinciDTRTestKit
89
97
  end
90
98
 
91
99
  group from: :dtr_full_ehr_saving_qr do
92
- input :custom_questionnaire_package_response,
93
- title: 'Custom Questionnaire Package Response JSON',
94
- description: %(
95
- A JSON PackageBundle may be provided here to replace Inferno's response to the
96
- $questionnaire-package request.
97
- ),
98
- type: 'textarea'
99
-
100
100
  config(
101
101
  inputs: {
102
102
  questionnaire_response: {
103
+ name: 'static_custom_questionnaire_response',
103
104
  description: "The QuestionnaireResponse as exported from the EHR after completion of the Questionnaire.
104
105
  IMPORTANT: If you have not yet run the 'Filling Out the Static Questionnaire' group, leave this blank
105
106
  until you have done so. Then, run just the 'Saving the QuestionnaireResponse' group and populate
@@ -1,7 +1,7 @@
1
- require_relative 'dtr_custom_questionnaire_package_validation_test'
2
- require_relative 'dtr_custom_questionnaire_libraries_test'
3
- require_relative 'dtr_custom_questionnaire_extensions_test'
4
- require_relative 'dtr_custom_questionnaire_expressions_test'
1
+ require_relative '../shared/dtr_custom_questionnaire_package_validation_test'
2
+ require_relative '../shared/dtr_custom_questionnaire_libraries_test'
3
+ require_relative '../shared/dtr_custom_questionnaire_extensions_test'
4
+ require_relative '../shared/dtr_custom_questionnaire_expressions_test'
5
5
  require_relative '../smart_app/dtr_smart_app_questionnaire_package_request_test'
6
6
  require_relative '../shared/dtr_questionnaire_package_request_validation_test'
7
7
  require_relative '../shared/dtr_prepopulation_attestation_test'
@@ -68,7 +68,7 @@ module DaVinciDTRTestKit
68
68
  title 'Filling Out the Static Questionnaire'
69
69
  description %(
70
70
  The tester will interact with the questionnaire within their client system
71
- such that pre-population steps are taken, the qustionnaire is rendered, and
71
+ such that pre-population steps are taken, the questionnaire is rendered, and
72
72
  they are able to fill it out. The tester will attest that questionnaire pre-population
73
73
  and rendering directives were followed.
74
74
  )
@@ -61,16 +61,20 @@ module DaVinciDTRTestKit
61
61
  test from: :dtr_static_dinner_enabled_questions_attest
62
62
  end
63
63
 
64
- group from: :dtr_full_ehr_saving_qr,
65
- config: {
66
- inputs: {
67
- questionnaire_response: {
68
- description: "The QuestionnaireResponse as exported from the EHR after completion of the Questionnaire.
69
- IMPORTANT: If you have not yet run the 'Filling Out the Static Questionnaire' group, leave this blank
70
- until you have done so. Then, run just the 'Saving the QuestionnaireResponse' group and populate
71
- this input."
72
- }
73
- }
64
+ group from: :dtr_full_ehr_saving_qr do
65
+ config(
66
+ inputs: {
67
+ questionnaire_response: {
68
+ name: 'static_dinner_questionnaire_response',
69
+ description: "The QuestionnaireResponse as exported from the EHR after completion of the Questionnaire.
70
+ IMPORTANT: If you have not yet run the 'Filling Out the Static Questionnaire' group, leave this blank
71
+ until you have done so. Then, run just the 'Saving the QuestionnaireResponse' group and populate
72
+ this input."
74
73
  }
74
+ }
75
+ )
76
+ # custom qp input not used - Inferno-defined questionnaire
77
+ children[2].inputs.delete(:custom_questionnaire_package_response)
78
+ end
75
79
  end
76
80
  end
@@ -46,7 +46,7 @@ module DaVinciDTRTestKit
46
46
  title 'Filling Out the Static Questionnaire'
47
47
  description %(
48
48
  The tester will interact with the questionnaire within their client system
49
- such that pre-population steps are taken, the qustionnaire is rendered, and
49
+ such that pre-population steps are taken, the questionnaire is rendered, and
50
50
  they are able to fill it out. Inferno will check that appropriate interactions
51
51
  with the server occur and the tester will attest that questionnaire pre-population
52
52
  and rendering directives were followed.
@@ -1,3 +1,4 @@
1
+ require_relative '../../descriptions'
1
2
  require_relative '../../urls'
2
3
 
3
4
  module DaVinciDTRTestKit
@@ -20,17 +21,22 @@ module DaVinciDTRTestKit
20
21
  'hl7.fhir.us.davinci-dtr_2.0.1@264'
21
22
 
22
23
  config options: { accepts_multiple_requests: true }
23
- input :access_token
24
+ input :client_id,
25
+ title: 'Client Id',
26
+ type: 'text',
27
+ optional: true,
28
+ locked: true,
29
+ description: INPUT_CLIENT_ID_LOCKED
24
30
 
25
31
  run do
26
32
  wait(
27
- identifier: access_token,
33
+ identifier: client_id,
28
34
  message: %(
29
35
  ### Adaptive Questionnaire Retrieval
30
36
 
31
37
  1. **Questionnaire Package Request**:
32
38
  - Invoke the `$questionnaire-package` operation by sending a POST request to the following
33
- endpoint to retrieve the adaptive questionnaire package:
39
+ endpoint to retrieve the adaptive questionnaire package:
34
40
 
35
41
  `#{questionnaire_package_url}`.
36
42
 
@@ -38,7 +44,7 @@ module DaVinciDTRTestKit
38
44
 
39
45
  2. **Initial Next Question Request**:
40
46
  - After receiving the questionnaire package, invoke the `$next-question` operation by sending
41
- a POST request to the following endpoint to retrieve the first set of questions:
47
+ a POST request to the following endpoint to retrieve the first set of questions:
42
48
 
43
49
  `#{next_url}`.
44
50
 
@@ -46,18 +52,9 @@ module DaVinciDTRTestKit
46
52
 
47
53
  Inferno will wait for both of these requests to be made.
48
54
 
49
- ### Request Identification
50
-
51
- In order to identify requests for this session, Inferno will look for
52
- an `Authorization` header with value:
53
-
54
- ```
55
- Bearer #{access_token}
56
- ```
57
-
58
55
  ### Continuing the Tests
59
56
 
60
- When both requests have been made, [Click here](#{resume_pass_url}?token=#{access_token}) to continue.
57
+ When both requests have been made, [Click here](#{resume_pass_url}?token=#{client_id}) to continue.
61
58
  )
62
59
  )
63
60
  end