subscriptions_test_kit 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +22 -0
- data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +222 -0
- data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +264 -0
- data/lib/subscriptions_test_kit/common/notification_conformance_verification.rb +310 -0
- data/lib/subscriptions_test_kit/common/subscription_conformance_verification.rb +87 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_empty.json +37 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_full-resource.json +37 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_id-only.json +38 -0
- data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_client_suite_description.md +120 -0
- data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_server_suite_description.md +170 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_create_endpoint.rb +90 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_read_endpoint.rb +32 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_rest_hook_endpoint.rb +66 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_status_endpoint.rb +70 -0
- data/lib/subscriptions_test_kit/igs/README.md +21 -0
- data/lib/subscriptions_test_kit/jobs/send_subscription_notifications.rb +130 -0
- data/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv +136 -0
- data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_out_of_scope_requirements.csv +23 -0
- data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_requirements.csv +145 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb +140 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/fixtures/capability_statement.json +57 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_payload_verification_test.rb +50 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_verification_test.rb +25 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/processing_attestation_test.rb +38 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/subscription_verification_test.rb +28 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification_group.rb +20 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_test.rb +128 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/event_notification_verification_test.rb +40 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/handshake_notification_verification_test.rb +40 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification_group.rb +16 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow_group.rb +33 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client_suite.rb +66 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/creation_response_conformance_test.rb +51 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/notification_delivery_test.rb +56 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/subscription_conformance_test.rb +72 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_group.rb +24 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification/notification_conformance_test.rb +73 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification_group.rb +19 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_creation.rb +63 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_status_operation.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/cs_conformance_test.rb +49 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/topic_discovery_test.rb +106 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement_group.rb +21 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content/empty_conformance_test.rb +63 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content/full_resource_conformance_test.rb +68 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content/id_only_conformance_test.rb +66 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification_group.rb +25 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/handshake_conformance_test.rb +67 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/heartbeat_conformance_test.rb +74 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat_group.rb +19 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation/status_invocation_test.rb +43 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation_group.rb +15 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection/reject_subscriptions_test.rb +181 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection_group.rb +21 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage_group.rb +26 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/workflow_group.rb +27 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server_suite.rb +79 -0
- data/lib/subscriptions_test_kit/tags.rb +10 -0
- data/lib/subscriptions_test_kit/urls.rb +37 -0
- data/lib/subscriptions_test_kit/version.rb +5 -0
- data/lib/subscriptions_test_kit.rb +3 -0
- 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
|