subscriptions_test_kit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +22 -0
  4. data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +222 -0
  5. data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +264 -0
  6. data/lib/subscriptions_test_kit/common/notification_conformance_verification.rb +310 -0
  7. data/lib/subscriptions_test_kit/common/subscription_conformance_verification.rb +87 -0
  8. data/lib/subscriptions_test_kit/docs/samples/Subscription_empty.json +37 -0
  9. data/lib/subscriptions_test_kit/docs/samples/Subscription_full-resource.json +37 -0
  10. data/lib/subscriptions_test_kit/docs/samples/Subscription_id-only.json +38 -0
  11. data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_client_suite_description.md +120 -0
  12. data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_server_suite_description.md +170 -0
  13. data/lib/subscriptions_test_kit/endpoints/subscription_create_endpoint.rb +90 -0
  14. data/lib/subscriptions_test_kit/endpoints/subscription_read_endpoint.rb +32 -0
  15. data/lib/subscriptions_test_kit/endpoints/subscription_rest_hook_endpoint.rb +66 -0
  16. data/lib/subscriptions_test_kit/endpoints/subscription_status_endpoint.rb +70 -0
  17. data/lib/subscriptions_test_kit/igs/README.md +21 -0
  18. data/lib/subscriptions_test_kit/jobs/send_subscription_notifications.rb +130 -0
  19. data/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv +136 -0
  20. data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_out_of_scope_requirements.csv +23 -0
  21. data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_requirements.csv +145 -0
  22. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb +140 -0
  23. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/fixtures/capability_statement.json +57 -0
  24. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_payload_verification_test.rb +50 -0
  25. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_verification_test.rb +25 -0
  26. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/processing_attestation_test.rb +38 -0
  27. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/subscription_verification_test.rb +28 -0
  28. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification_group.rb +20 -0
  29. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_test.rb +128 -0
  30. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/event_notification_verification_test.rb +40 -0
  31. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/handshake_notification_verification_test.rb +40 -0
  32. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification_group.rb +16 -0
  33. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow_group.rb +33 -0
  34. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client_suite.rb +66 -0
  35. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/creation_response_conformance_test.rb +51 -0
  36. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/notification_delivery_test.rb +56 -0
  37. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/subscription_conformance_test.rb +72 -0
  38. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_group.rb +24 -0
  39. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification/notification_conformance_test.rb +73 -0
  40. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification_group.rb +19 -0
  41. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_creation.rb +63 -0
  42. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_status_operation.rb +58 -0
  43. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/cs_conformance_test.rb +49 -0
  44. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/topic_discovery_test.rb +106 -0
  45. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement_group.rb +21 -0
  46. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content/empty_conformance_test.rb +63 -0
  47. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content_group.rb +58 -0
  48. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content/full_resource_conformance_test.rb +68 -0
  49. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content_group.rb +58 -0
  50. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content/id_only_conformance_test.rb +66 -0
  51. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content_group.rb +58 -0
  52. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification_group.rb +25 -0
  53. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/handshake_conformance_test.rb +67 -0
  54. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/heartbeat_conformance_test.rb +74 -0
  55. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat_group.rb +19 -0
  56. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation/status_invocation_test.rb +43 -0
  57. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation_group.rb +15 -0
  58. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection/reject_subscriptions_test.rb +181 -0
  59. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection_group.rb +21 -0
  60. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage_group.rb +26 -0
  61. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/workflow_group.rb +27 -0
  62. data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server_suite.rb +79 -0
  63. data/lib/subscriptions_test_kit/tags.rb +10 -0
  64. data/lib/subscriptions_test_kit/urls.rb +37 -0
  65. data/lib/subscriptions_test_kit/version.rb +5 -0
  66. data/lib/subscriptions_test_kit.rb +3 -0
  67. metadata +194 -0
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Client
5
+ class InteractionTest < Inferno::Test
6
+ id :subscriptions_r5_backport_r4_client_interaction
7
+ description %(
8
+ During this test, the client under test will interact with Inferno following the Subscription
9
+ workflow over a `rest-hook` channel. This includes the following steps
10
+ 1. The client under test sends a Subscription request to Inferno
11
+ 2. Inferno sends a handshake notification request to the endpoint specified in the Subscription.
12
+ 3. Inferno sends an event notification request to the endpoint specified in the Subscription.
13
+
14
+ While these steps are taking place and after, Inferno will be waiting for the user to indicate that
15
+ the interaction has completed successfully or failed for some reason. Additionally, the client
16
+ system may make additional requests, such as `$status` checks, while the test is waiting.
17
+ Afterwards, Inferno will no longer respond to requests.
18
+
19
+ To create the handshake and event notifications, Inferno uses the contents of the *Event
20
+ Notification Bundle* input. The provided notification will be modified as appropriate for
21
+ the request Inferno is making:
22
+ - General changes for all notification types
23
+ - update the `subscription` parameter entry reference.
24
+ - update the `status` parameter entry based on the previous interactions.
25
+ - update the `type` parameter entry based on the notification type (e.g., `event-notification` or `handshake`).
26
+ - update the number of notifications sent in the `events-since-subscription-start` parameter entry.
27
+ - `handshake`-specific changes:
28
+ - clear the `events` parameter entry.
29
+ - clear the `errors` parameter entry.
30
+
31
+ While the provided Notification must be conformant to the
32
+ [R4 Topic-Based Subscription Notification Bundle
33
+ profile](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
34
+ for the tests to pass, the tests can run as long as the notification meets the
35
+ following minimal requirements:
36
+ 1. The provided content must be a valid json representation of a FHIR Bundle resource.
37
+ 2. The first instance in the Bundle is a Parameters resource.
38
+ 3. The first Parameters instance has a `subscription` parameter entry.
39
+ )
40
+ title 'Subscription Workflow Interaction'
41
+
42
+ input :access_token,
43
+ title: 'Access Token',
44
+ description: %(
45
+ The bearer token that the client under test will use when making Subscription creation, $status, and other
46
+ requests to Inferno's simulated Subscriptions server.
47
+ )
48
+ input :client_endpoint_access_token,
49
+ optional: true,
50
+ title: 'Client Notification Access Token',
51
+ description: %(
52
+ The bearer token that Inferno will send on requests to the client under test's rest-hook notification endpoint. Not
53
+ needed if the client under test will create a Subscription with an appropriate header value in the
54
+ `channel.header` element. If a value for the `authorization` header is provided in `channel.header`, this
55
+ value will override it.
56
+ )
57
+ input :notification_bundle,
58
+ title: 'Event Notification Bundle',
59
+ type: 'textarea',
60
+ description: %(
61
+ The event notification bundle from which Inferno will derive a handshake notification, an event
62
+ notification to send to the client endpoint, and responses to $status operation requests. The provided
63
+ Bundle must conform to the R4 Topic-Based Subscription Notification Bundle profile.
64
+ )
65
+
66
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@23'
67
+
68
+ run do
69
+ minimally_validate_notification(notification_bundle)
70
+ assert(messages.none? { |m| m[:type] == 'error' }, 'Notification Bundle input is invalid for use by Inferno, see error message(s)')
71
+
72
+ wait(
73
+ identifier: access_token,
74
+ timeout: 600,
75
+ message: %(
76
+ Inferno will wait until the the event notification workflow is complete. The steps in the workflow are:
77
+
78
+ 1. Inferno expects a Subscription POST request at:
79
+
80
+ `#{fhir_subscription_url}`
81
+
82
+ with the Authorization header set to:
83
+
84
+ `Bearer #{access_token}`
85
+
86
+ 2. Inferno will send a handshake notification to the rest-hook endpoint specified in the subscription.
87
+
88
+ 3. After a 5–10 second delay, Inferno will send an event notification to the rest-hook endpoint.
89
+
90
+ At any point while this test is waiting, Inferno will respond to Subscription GET and $status requests.
91
+
92
+ Once the client has received an event notification and has made any additional requests,
93
+ [click here to complete the test](#{resume_pass_url}?test_run_identifier=#{access_token})
94
+
95
+ If at any point something has gone wrong and the client is unable to continue,
96
+ [click here to fail the test](#{resume_fail_url}?test_run_identifier=#{access_token})
97
+
98
+ NOTE: The test must be completed or failed using the links above within 10 minutes. After that,
99
+ attempts to send requests or to complete or fail the tests using the links above
100
+ will result in a *"session not found"* error.
101
+ )
102
+ )
103
+ end
104
+
105
+ # Perform only the verification necessary for the Inferno test to function
106
+ def minimally_validate_notification(notification_bundle)
107
+ assert_valid_json(notification_bundle)
108
+ begin
109
+ bundle = FHIR.from_contents(notification_bundle)
110
+ rescue StandardError
111
+ assert(false, 'Notification bundle input is not a conformant FHIR Bundle')
112
+ end
113
+ assert_resource_type(:bundle, resource: bundle)
114
+ subscription_status = bundle.entry&.first&.resource
115
+ assert(subscription_status.present?, 'Notification bundle input must contain a subscription status entry')
116
+ assert_resource_type(:parameters, resource: subscription_status)
117
+
118
+ # Require the subscription param, just because we need something to later identify the subscription status
119
+ # bundle entry. Note we could just as easily use a different required param, like status or type.
120
+ subscription_param = subscription_status.parameter&.find { |p| p.name == 'subscription' }
121
+ assert(subscription_param.present?, 'Subscription status entry in notification bundle input must contain a'\
122
+ 'subscription parameter')
123
+ rescue Inferno::Exceptions::AssertionException => e
124
+ add_message('error', e.message)
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../common/subscription_simulation_utils'
4
+
5
+ module SubscriptionsTestKit
6
+ module SubscriptionsR5BackportR4Client
7
+ class EventNotificationVerificationTest < Inferno::Test
8
+ include SubscriptionSimulationUtils
9
+
10
+ id :subscriptions_r5_backport_r4_client_event_notification_verification
11
+ title 'Rest-Hook Event Notification Verification'
12
+ description %(
13
+ This test verifies that the client's response to the event notification
14
+ was conformant.
15
+ )
16
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@24',
17
+ 'hl7.fhir.uv.subscriptions_1.1.0@71'
18
+
19
+ run do
20
+ load_tagged_requests(REST_HOOK_EVENT_NOTIFICATION_TAG)
21
+ skip_if(requests.none?, 'Inferno did not send an event notification')
22
+
23
+ # The SendSubscriptionNotifications job saves a nil status if the request fails entirely
24
+ assert(request.status.present?, "Handshake notification request failed with error: #{request.response_body}")
25
+
26
+ assert(request.status.between?(200, 299), "Event notification was not successful, status code #{request.status}")
27
+
28
+ subscription = find_subscription(test_session_id)
29
+ if subscription.present?
30
+ mime_type = subscription&.channel&.payload
31
+ unless ALLOWED_MIME_TYPES.include?(mime_type)
32
+ add_message('warning', %(Subscription specified '#{mime_type}' for `Subscription.channel.payload`, but Inferno
33
+ only supports: #{ALLOWED_MIME_TYPES.map { |type| "'#{type}'" }.join(', ')}.
34
+ Event notification was sent with Content-Type: '#{DEFAULT_MIME_TYPE}'.))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../common/subscription_simulation_utils'
4
+
5
+ module SubscriptionsTestKit
6
+ module SubscriptionsR5BackportR4Client
7
+ class HandshakeNotificationVerificationTest < Inferno::Test
8
+ include SubscriptionSimulationUtils
9
+
10
+ id :subscriptions_r5_backport_r4_client_handshake_notification_verification
11
+ title 'Rest-Hook Handshake Notification Verification'
12
+ description %(
13
+ This test verifies that the client's response to the handshake notification
14
+ was conformant.
15
+ )
16
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@71'
17
+
18
+ run do
19
+ load_tagged_requests(REST_HOOK_HANDSHAKE_NOTIFICATION_TAG)
20
+ skip_if(requests.none?, 'Inferno did not send a handshake notification')
21
+
22
+ # The SendSubscriptionNotifications job saves a nil status if the request fails entirely
23
+ assert(request.status.present?, "Handshake notification request failed with error: #{request.response_body}")
24
+
25
+ assert(request.status.between?(200, 299),
26
+ "Handshake notification was not successful, status code #{request.status}")
27
+
28
+ subscription = find_subscription(test_session_id)
29
+ if subscription.present?
30
+ mime_type = subscription&.channel&.payload
31
+ unless ALLOWED_MIME_TYPES.include?(mime_type)
32
+ add_message('warning', %(Subscription specified '#{mime_type}' for `Subscription.channel.payload`, but Inferno
33
+ only supports: #{ALLOWED_MIME_TYPES.map { |type| "'#{type}'" }.join(', ')}.
34
+ Handshake notification was sent with Content-Type: '#{DEFAULT_MIME_TYPE}'.))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'interaction_verification/handshake_notification_verification_test'
4
+ require_relative 'interaction_verification/event_notification_verification_test'
5
+
6
+ module SubscriptionsTestKit
7
+ module SubscriptionsR5BackportR4Client
8
+ class InteractionVerificationGroup < Inferno::TestGroup
9
+ id :subscriptions_r5_backport_r4_client_interaction_verification
10
+ title 'Rest-Hook Subscription Interaction Verification'
11
+
12
+ test from: :subscriptions_r5_backport_r4_client_handshake_notification_verification
13
+ test from: :subscriptions_r5_backport_r4_client_event_notification_verification
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'workflow/interaction_test'
4
+ require_relative 'workflow/interaction_verification_group'
5
+ require_relative 'workflow/conformance_verification_group'
6
+
7
+ module SubscriptionsTestKit
8
+ module SubscriptionsR5BackportR4Client
9
+ class WorkflowGroup < Inferno::TestGroup
10
+ include URLs
11
+
12
+ id :subscriptions_r5_backport_r4_client_workflow
13
+ title 'Demonstrate the Rest-Hook Subscription Workflow'
14
+ description %(
15
+ Demonstrate the ability of the client to request the
16
+ creation of a FHIR Subscription instance and receive a notification
17
+ for that Subscription. The tester must provide the body of a Notification
18
+ that it expects to receive. Inferno will act as a server,
19
+ waiting for the Subscription creation request and then sending the
20
+ notification. Inferno will then verify that the provided Subscription
21
+ and notification match and that the exchange is conformant.
22
+ )
23
+ run_as_group
24
+
25
+ group 'Rest-Hook Subscription Interaction' do
26
+ test from: :subscriptions_r5_backport_r4_client_interaction
27
+ end
28
+
29
+ group from: :subscriptions_r5_backport_r4_client_interaction_verification
30
+ group from: :subscriptions_r5_backport_r4_client_conformance_verification
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'subscriptions_r5_backport_r4_client/workflow_group'
4
+ require_relative '../endpoints/subscription_create_endpoint'
5
+ require_relative '../endpoints/subscription_read_endpoint'
6
+ require_relative '../endpoints/subscription_status_endpoint'
7
+ require_relative '../version'
8
+
9
+ module SubscriptionsTestKit
10
+ module SubscriptionsR5BackportR4Client
11
+ class SubscriptionsR5BackportR4ClientSuite < Inferno::TestSuite
12
+ id :subscriptions_r5_backport_r4_client
13
+ title 'Subscriptions R5 Backport IG v1.1.0 FHIR R4 Client Test Suite'
14
+ short_title 'Subscriptions R4 Client'
15
+ version VERSION
16
+ description File.read(File.join(__dir__, '..', 'docs', 'subscriptions_r5_backport_r4_client_suite_description.md'))
17
+
18
+ links [
19
+ {
20
+ label: 'Report Issue',
21
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit/issues'
22
+ },
23
+ {
24
+ label: 'Open Source',
25
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit'
26
+ },
27
+ {
28
+ label: 'Download',
29
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit/releases'
30
+ },
31
+ {
32
+ label: 'Implementation Guide',
33
+ url: 'https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/'
34
+ }
35
+ ]
36
+
37
+ # All FHIR validation requests will use this FHIR validator
38
+ fhir_resource_validator do
39
+ igs 'hl7.fhir.uv.subscriptions-backport#1.1.0'
40
+
41
+ exclude_message do |message|
42
+ message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
43
+ end
44
+ end
45
+
46
+ capability_statement = File.read(File.join(__dir__, 'subscriptions_r5_backport_r4_client', 'fixtures', 'capability_statement.json'))
47
+ route(:get, '/fhir/metadata', proc { [200, { 'Content-Type' => 'application/json' }, [capability_statement]] })
48
+
49
+ suite_endpoint :post, FHIR_SUBSCRIPTION_PATH, SubscriptionCreateEndpoint
50
+ suite_endpoint :get, FHIR_SUBSCRIPTION_INSTANCE_PATH, SubscriptionReadEndpoint
51
+ suite_endpoint :post, FHIR_SUBSCRIPTION_INSTANCE_STATUS_PATH, SubscriptionStatusEndpoint
52
+ suite_endpoint :get, FHIR_SUBSCRIPTION_INSTANCE_STATUS_PATH, SubscriptionStatusEndpoint
53
+ suite_endpoint :post, FHIR_SUBSCRIPTION_RESOURCE_STATUS_PATH, SubscriptionStatusEndpoint
54
+
55
+ resume_test_route :get, RESUME_PASS_PATH do |request|
56
+ request.query_parameters['test_run_identifier']
57
+ end
58
+
59
+ resume_test_route :get, RESUME_FAIL_PATH, result: 'fail' do |request|
60
+ request.query_parameters['test_run_identifier']
61
+ end
62
+
63
+ group from: :subscriptions_r5_backport_r4_client_workflow
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,51 @@
1
+ module SubscriptionsTestKit
2
+ module SubscriptionsR5BackportR4Server
3
+ class CreationResponseConformanceTest < Inferno::Test
4
+ id :subscriptions_r5_backport_r4_server_creation_response_conformance
5
+ title 'Verify Subscription Creation Response'
6
+ description %(
7
+ This test ensures that the server responded to the Subscription creation test with the new created Subscription
8
+ resource. If the Subscription's channel type is set to 'rest-hook', the test will ensure that the Subscription's
9
+ status is set to 'requested'.
10
+ )
11
+
12
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@7',
13
+ 'hl7.fhir.uv.subscriptions_1.1.0@25',
14
+ 'hl7.fhir.uv.subscriptions_1.1.0@49',
15
+ 'hl7.fhir.uv.subscriptions_1.1.0@29'
16
+
17
+ def subscription_type
18
+ config.options[:subscription_type]
19
+ end
20
+
21
+ run do
22
+ if subscription_type.present?
23
+ subscription_requests = load_tagged_requests('subscription_creation', subscription_type)
24
+ requests =
25
+ subscription_requests
26
+ .select { |request| request.status == 201 }
27
+ skip_if requests.empty?, 'No successful Subscription creation request was made in the previous test.'
28
+ else
29
+ all_requests = load_tagged_requests('subscription_creation')
30
+ all_subscription_requests =
31
+ all_requests
32
+ .select { |request| request.status == 201 }
33
+ skip_if all_subscription_requests.empty?,
34
+ 'No successful Subscription creation request was made in the previous test.'
35
+ requests = [all_subscription_requests.first]
36
+ end
37
+
38
+ requests.each do |subscription_request|
39
+ assert_valid_json(subscription_request.response_body)
40
+ subscription = FHIR.from_contents(subscription_request.response_body)
41
+ assert subscription.present?, 'Not a FHIR resource'
42
+
43
+ assert_resource_type('Subscription', resource: subscription)
44
+
45
+ assert(subscription.channel.type == 'rest-hook' && subscription.status == 'requested',
46
+ "The Subscription resource should have it's status set to 'requested', was '#{subscription.status}'")
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ require_relative '../subscription_creation'
2
+ require_relative '../../../../urls'
3
+
4
+ module SubscriptionsTestKit
5
+ module SubscriptionsR5BackportR4Server
6
+ class NotificationDeliveryTest < Inferno::Test
7
+ include SubscriptionCreation
8
+ include URLs
9
+
10
+ id :subscriptions_r5_backport_r4_server_notification_delivery
11
+ title 'Send Subscription and Receive Notification Requests from Server'
12
+ description %(
13
+ This test sends a request to create the Subscription resource to the Subscriptions Backport FHIR Server.
14
+ If successful, it then waits for [notification](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/notifications.html#notifications)
15
+ requests of the following types:
16
+ - handshake (required for `rest-hook` notifications)
17
+ - heartbeat (required if `heartbeatPeriod` field is populated in Subscription resource)
18
+ - event-notification
19
+ )
20
+ config options: { accepts_multiple_requests: true }
21
+
22
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@133'
23
+
24
+ input :updated_subscription
25
+ input :access_token,
26
+ title: 'Notification Access Token',
27
+ description: %(
28
+ An access token that the server under test will send to Inferno on notifications
29
+ so that the request gets associated with this test session. The token must be
30
+ provided as a `Bearer` token in the `Authorization` header of HTTP requests
31
+ sent to Inferno.
32
+ )
33
+
34
+ run do
35
+ subscription = JSON.parse(updated_subscription)
36
+ subscription_type = send_subscription(subscription)
37
+
38
+ wait(
39
+ identifier: "notification #{access_token}",
40
+ message: %(
41
+ **Subscription `#{subscription['id']}`: `#{subscription_type}` Notification Test**
42
+
43
+ Send any handshake, heartbeat, and `#{subscription_type}` event-notification requests for the Subscription
44
+ with id `#{subscription['id']}` to:
45
+
46
+ `#{subscription_channel_url}`
47
+
48
+ [Click here](#{resume_pass_url}?token=notification%20#{access_token}) when you have finished submitting
49
+ requests.
50
+
51
+ )
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,72 @@
1
+ require_relative '../../../../common/subscription_conformance_verification'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class SubscriptionConformanceTest < Inferno::Test
6
+ include SubscriptionConformanceVerification
7
+
8
+ id :subscriptions_r5_backport_r4_server_subscription_conformance
9
+ title '[USER INPUT VERIFICATION] Verify Subscription to Send to Server'
10
+ description %(
11
+ The Subscription resource is used to request notifications for a specific client about a specific topic
12
+ Conceptually, a subscription is a concrete request for a single client to receive notifications per a single
13
+ topic. In order to support topic-based subscriptions in R4, this guide defines several extensions for use on the
14
+ [R4 Subscription resource](http://hl7.org/fhir/R4/subscription.html). A list of extensions defined by this guide can
15
+ be found on the [Subscriptions R5 Backport IG's Artifacts page](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/artifacts.html#5).
16
+
17
+ This test accepts a Subscription resource as an input and verifies that it is conformant to the
18
+ [R4/B Topic-Based Subscription profile](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription.html).
19
+
20
+ The Subscription channel should have it's fields populated with the following information:
21
+ - The `endpoint` field must be set to
22
+ `#{Inferno::Application['base_url']}/custom/subscriptions_r5_backport_r4_server/subscription/channel/notification_listener`.
23
+ The test will add the correct url to this field if it is not properly set.
24
+ - The `type` field must be set to `rest-hook`, as the Inferno subscription workflow tests use a `rest-hook`
25
+ subscription channel to receive incoming notifications. The test will add the correct type to this field if it
26
+ is not properly set.
27
+ - The `payload` field must be set to `application/json`, as Inferno will only accept resources in requests with
28
+ this content type.
29
+ - The `header` field must include the `Authorization` header with a Bearer token set to the inputted Inferno
30
+ access token.
31
+ )
32
+
33
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@72',
34
+ 'hl7.fhir.uv.subscriptions_1.1.0@86'
35
+
36
+ input :subscription_resource,
37
+ title: 'Workflow Subscription Resource',
38
+ type: 'textarea',
39
+ description: %(
40
+ A Subscription resource in JSON format that Inferno will send to the server under test
41
+ so that it can demonstrate its ability to perform the Subscription creation and Notification
42
+ response workflow. The instance must be conformant to the R4/B Topic-Based Subscription profile.
43
+ Inferno may modify the Subscription before submission, e.g., to point to Inferno's notification endpoint.
44
+ This input is also used by the unsupported Subscription test as the base on which to add unsupported element
45
+ values to test for server rejection.
46
+ )
47
+ input :access_token,
48
+ title: 'Notification Access Token',
49
+ description: %(
50
+ An access token that the server under test will send to Inferno on notifications
51
+ so that the request gets associated with this test session. The token must be
52
+ provided as a `Bearer` token in the `Authorization` header of HTTP requests
53
+ sent to Inferno.
54
+ )
55
+
56
+ output :updated_subscription, :subscription_topic
57
+
58
+ run do
59
+ omit_if subscription_resource.blank?, 'Did not input a Subscription resource of this type.'
60
+ subscription = subscription_verification(subscription_resource)
61
+ no_error_verification('Subscription resource is not conformant.')
62
+
63
+ assert(subscription['criteria'].present?,
64
+ 'The `criteria` field SHALL be populated and contain the canonical URL for the Subscription Topic.')
65
+ output subscription_topic: subscription['criteria']
66
+
67
+ subscription = server_check_channel(subscription, access_token)
68
+ output updated_subscription: subscription.to_json
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'interaction/subscription_conformance_test'
2
+ require_relative 'interaction/notification_delivery_test'
3
+ require_relative 'interaction/creation_response_conformance_test'
4
+
5
+ module SubscriptionsTestKit
6
+ module SubscriptionsR5BackportR4Server
7
+ class InteractionGroup < Inferno::TestGroup
8
+ id :subscriptions_r5_backport_r4_server_interaction
9
+ title 'Subscription Workflow Interaction'
10
+ description %(
11
+ Verify that the Subscription instance the tester provided is conformant, and then demonstrate the ability of the
12
+ server under test to accept a request for the creation of a FHIR Subscription instance and deliver a notification
13
+ for that Subscription. Inferno will act as a client, creating the Subscription and waiting for a notification
14
+ based on it.
15
+ )
16
+
17
+ run_as_group
18
+
19
+ test from: :subscriptions_r5_backport_r4_server_subscription_conformance
20
+ test from: :subscriptions_r5_backport_r4_server_notification_delivery
21
+ test from: :subscriptions_r5_backport_r4_server_creation_response_conformance
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,73 @@
1
+ require_relative '../../../../common/notification_conformance_verification'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class NotificationConformanceTest < Inferno::Test
6
+ include NotificationConformanceVerification
7
+
8
+ id :subscriptions_r5_backport_r4_server_notification_conformance
9
+ title 'Subscription Notification Verification'
10
+ description %(
11
+ As described in [Topic-Based Subscription Components](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/components.html#subscription-notifications),
12
+ all notifications are enclosed in a Bundle with the type of history. Additionally, the first entry of the bundle
13
+ SHALL be the SubscriptionStatus information, encoded as a Parameters resource using the
14
+ [Backport SubscriptionStatus Profile](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-status-r4.html)
15
+ in FHIR R4.
16
+
17
+ This test takes the received notification bundle and ensures it is conformant to the
18
+ [R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
19
+ profle.
20
+ )
21
+
22
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
23
+ 'hl7.fhir.uv.subscriptions_1.1.0@15',
24
+ 'hl7.fhir.uv.subscriptions_1.1.0@28',
25
+ 'hl7.fhir.uv.subscriptions_1.1.0@69',
26
+ 'hl7.fhir.uv.subscriptions_1.1.0@70',
27
+ 'hl7.fhir.uv.subscriptions_1.1.0@138',
28
+ 'hl7.fhir.uv.subscriptions_1.1.0@139'
29
+
30
+ def subscription_type
31
+ config.options[:subscription_type]
32
+ end
33
+
34
+ run do
35
+ if subscription_type.present?
36
+ requests = load_tagged_requests('subscription_creation', subscription_type)
37
+ subscription_requests =
38
+ requests
39
+ .select { |request| request.status == 201 }
40
+ skip_if subscription_requests.empty?,
41
+ 'No successful Subscription creation request was made in the previous test.'
42
+ else
43
+ all_requests = load_tagged_requests('subscription_creation')
44
+ all_subscription_requests =
45
+ all_requests
46
+ .select { |request| request.status == 201 }
47
+ skip_if all_subscription_requests.empty?,
48
+ 'No successful Subscription creation request was made in the previous test.'
49
+ subscription_requests = [all_subscription_requests.first]
50
+ end
51
+
52
+ subscription_requests.each do |subscription_request|
53
+ assert_valid_json(subscription_request.response_body)
54
+ subscription = JSON.parse(subscription_request.response_body)
55
+
56
+ requests = load_tagged_requests('event-notification', subscription['id'])
57
+ skip_if requests.empty?, 'No event-notification requests were made in a previous test as expected.'
58
+
59
+ requests = requests.uniq(&:request_body)
60
+ requests.each do |request|
61
+ notification_verification(
62
+ request.request_body,
63
+ 'event-notification',
64
+ subscription_id: subscription['id'],
65
+ status: 'active'
66
+ )
67
+ end
68
+ end
69
+ no_error_verification('Received event-notifications are not conformant.')
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'interaction_verification/notification_conformance_test'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class InteractionVerificationGroup < Inferno::TestGroup
6
+ id :subscriptions_r5_backport_r4_server_interaction_verification
7
+ title 'Subscription Workflow Interaction Verification'
8
+ description %(
9
+ Inferno takes the received event-notification Bundle and verifies that it is conformant to the
10
+ [R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
11
+ profle.
12
+ )
13
+
14
+ run_as_group
15
+
16
+ test from: :subscriptions_r5_backport_r4_server_notification_conformance
17
+ end
18
+ end
19
+ end