subscriptions_test_kit 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,63 @@
|
|
1
|
+
module SubscriptionsTestKit
|
2
|
+
module SubscriptionsR5BackportR4Server
|
3
|
+
module SubscriptionCreation
|
4
|
+
def no_error_verification(message)
|
5
|
+
assert messages.none? { |msg| msg[:type] == 'error' }, message
|
6
|
+
end
|
7
|
+
|
8
|
+
def json_parse(json)
|
9
|
+
JSON.parse(json)
|
10
|
+
rescue JSON::ParserError
|
11
|
+
add_message('error', "#{request_number}Invalid JSON.")
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_new_subscription_value(subscription, field_path)
|
16
|
+
field_path.reduce(subscription) { |obj, path| obj[path] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_unsupported_subscription(subscription, unsupported_type, field_paths, subscription_field_old_values)
|
20
|
+
fhir_operation('/Subscription', body: subscription)
|
21
|
+
|
22
|
+
return if request.status != 201
|
23
|
+
|
24
|
+
new_subscription = json_parse(request.response_body)
|
25
|
+
return unless new_subscription
|
26
|
+
|
27
|
+
altered_field = false
|
28
|
+
field_paths.each_with_index do |field_path, index|
|
29
|
+
subscription_field_new_value = get_new_subscription_value(new_subscription, field_path)
|
30
|
+
if subscription_field_new_value != subscription_field_old_values[index]
|
31
|
+
altered_field = true
|
32
|
+
break
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
return if altered_field
|
37
|
+
|
38
|
+
add_message('error', %(
|
39
|
+
Sending a Subscription with #{unsupported_type} should be rejected, or the Subscription should be
|
40
|
+
altered to fix the unsupported value.))
|
41
|
+
end
|
42
|
+
|
43
|
+
def subscription_payload_type(subscription)
|
44
|
+
return unless subscription['channel']['_payload']
|
45
|
+
|
46
|
+
payload_extension = subscription['channel']['_payload']['extension'].find do |ext|
|
47
|
+
ext['url'].ends_with?('/backport-payload-content')
|
48
|
+
end
|
49
|
+
payload_extension['valueCode']
|
50
|
+
end
|
51
|
+
|
52
|
+
def send_subscription(subscription)
|
53
|
+
tags = ['subscription_creation']
|
54
|
+
payload_type = subscription_payload_type(subscription)
|
55
|
+
tags.append(payload_type) if payload_type.present?
|
56
|
+
|
57
|
+
fhir_operation('/Subscription', body: subscription, tags:)
|
58
|
+
assert_response_status(201)
|
59
|
+
payload_type
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module SubscriptionsTestKit
|
2
|
+
module SubscriptionsR5BackportR4Server
|
3
|
+
module SubscriptionStatusOperation
|
4
|
+
def no_error_verification(message)
|
5
|
+
assert messages.none? { |msg| msg[:type] == 'error' }, message
|
6
|
+
end
|
7
|
+
|
8
|
+
def find_elem(resource_array, param_name)
|
9
|
+
resource_array.find do |param|
|
10
|
+
param.name == param_name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute_subscription_status_operation(subscription_id)
|
15
|
+
fhir_operation("Subscription/#{subscription_id}/$status", operation_method: :get)
|
16
|
+
assert_response_status(200)
|
17
|
+
assert_resource_type('Bundle')
|
18
|
+
|
19
|
+
unless resource.type == 'searchset'
|
20
|
+
add_message('error', "Bundle returned from $status operation should be type 'searchset', was #{resource.type}")
|
21
|
+
end
|
22
|
+
|
23
|
+
assert_valid_resource
|
24
|
+
|
25
|
+
resource.entry
|
26
|
+
end
|
27
|
+
|
28
|
+
def subscription_ref_found?(entry, subscription_id)
|
29
|
+
subscription_param = find_elem(entry.resource.parameter, 'subscription')
|
30
|
+
subscription_ref = subscription_param.valueReference.reference
|
31
|
+
return false if subscription_ref.blank?
|
32
|
+
|
33
|
+
subscription_ref.split('/').last == subscription_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def perform_subscription_status_test(subscription_id, status = nil)
|
37
|
+
bundle_entries = execute_subscription_status_operation(subscription_id)
|
38
|
+
subscription_status_entry = bundle_entries.find do |entry|
|
39
|
+
entry.resource.resourceType == 'Parameters' && subscription_ref_found?(entry, subscription_id)
|
40
|
+
end
|
41
|
+
assert(subscription_status_entry,
|
42
|
+
"No Subscription status with id #{subscription_id} returned from $status operation")
|
43
|
+
|
44
|
+
subscription_status_resource = subscription_status_entry.resource
|
45
|
+
assert_valid_resource(resource: subscription_status_resource,
|
46
|
+
profile_url: 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription-status-r4')
|
47
|
+
|
48
|
+
subscription_status = find_elem(subscription_status_resource.parameter, 'status')
|
49
|
+
|
50
|
+
return unless status.present?
|
51
|
+
|
52
|
+
assert(subscription_status.valueCode == status, %(
|
53
|
+
The Subscription resource should have it's `status` set to #{status}, was
|
54
|
+
`#{subscription_status.valueCode}`))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module SubscriptionsTestKit
|
2
|
+
module SubscriptionsR5BackportR4Server
|
3
|
+
class CSConformanceTest < Inferno::Test
|
4
|
+
id :subscriptions_r5_backport_r4_server_cs_conformance
|
5
|
+
title 'Capability Statement Conformance Verification'
|
6
|
+
description %(
|
7
|
+
This test attempts to retreive the server's Capability Statement in order to verify that it
|
8
|
+
declares support for the Backport Subscription Profile by including its official URL in the server's
|
9
|
+
CapabilityStatement.rest.resource.supportedProfile element: http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription
|
10
|
+
)
|
11
|
+
|
12
|
+
verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@52',
|
13
|
+
'hl7.fhir.uv.subscriptions_1.1.0@114',
|
14
|
+
'hl7.fhir.uv.subscriptions_1.1.0@120'
|
15
|
+
|
16
|
+
def subscription_profile_url
|
17
|
+
'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription'
|
18
|
+
end
|
19
|
+
|
20
|
+
run do
|
21
|
+
fhir_get_capability_statement
|
22
|
+
assert_response_status(200)
|
23
|
+
assert_resource_type(:capability_statement)
|
24
|
+
assert_valid_resource
|
25
|
+
|
26
|
+
scratch[:capability_statement] ||= resource
|
27
|
+
|
28
|
+
assert(resource.rest.present?, 'Capability Statement missing the `rest` field')
|
29
|
+
rest_server = resource.rest.find { |elem| elem.mode == 'server' }
|
30
|
+
assert(rest_server.present?, "Capability Statement missing entry in `rest` with a `mode` set to 'server'")
|
31
|
+
|
32
|
+
rest_subscription = rest_server.resource.find { |elem| elem.type == 'Subscription' }
|
33
|
+
assert(rest_subscription.present?, 'Capability Statement missing `Subscription` resource in `rest` field')
|
34
|
+
|
35
|
+
assert(rest_subscription.supportedProfile.present?,
|
36
|
+
'Capability Statement missing the `supportedProfile` field in `Subscription` resource')
|
37
|
+
|
38
|
+
subscription_profile_present = rest_subscription.supportedProfile.any? do |profile|
|
39
|
+
profile == subscription_profile_url
|
40
|
+
end
|
41
|
+
unless subscription_profile_present
|
42
|
+
add_message('warning', %(
|
43
|
+
Subscription resource should declare support for the Backport Subscription Profile by including its
|
44
|
+
official URL))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative '../../../../common/subscription_conformance_verification'
|
2
|
+
|
3
|
+
module SubscriptionsTestKit
|
4
|
+
module SubscriptionsR5BackportR4Server
|
5
|
+
class TopicDiscoveryTest < Inferno::Test
|
6
|
+
include SubscriptionConformanceVerification
|
7
|
+
|
8
|
+
id :subscriptions_r5_backport_r4_server_topic_discovery
|
9
|
+
title 'Attempt topic discovery'
|
10
|
+
description %(
|
11
|
+
This test attempts to perform topic discovery with the server. In order to allow for [discovery of supported
|
12
|
+
subscription topics in R4](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/components.html#subscription-topics-in-r4),
|
13
|
+
the Subscriptions Backport IG defines the CapabilityStatement [SubscriptionTopic Canonical extension](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-capabilitystatement-subscriptiontopic-canonical.html).
|
14
|
+
The extension allows server implementers to advertise the canonical URLs of topics available to clients and
|
15
|
+
allows clients to see the list of supported topics on a server.
|
16
|
+
|
17
|
+
The extension is expected to appear, if supported, on the Subscription resource entry. Note that servers are NOT
|
18
|
+
required to advertise supported topics via this extension, so this test it optional. Supported topics can also
|
19
|
+
be advertised, for example, by the CapabilityStatement.instantiates or CapabilityStatement.implementationGuide
|
20
|
+
elements of a CapabilityStatement, as defined by another Implementation Guide. Finally, FHIR R4 servers MAY
|
21
|
+
choose to leave topic discovery completely out-of-band and part of other steps, such as registration or
|
22
|
+
integration.
|
23
|
+
|
24
|
+
In order to claim conformance with this IG for R4, a server SHOULD support topic discovery
|
25
|
+
via the CapabilityStatement SubscriptionTopic Canonical extension.
|
26
|
+
)
|
27
|
+
|
28
|
+
verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@2',
|
29
|
+
'hl7.fhir.uv.subscriptions_1.1.0@48'
|
30
|
+
|
31
|
+
optional
|
32
|
+
|
33
|
+
def backport_subscription_server_url
|
34
|
+
'http://hl7.org/fhir/uv/subscriptions-backport/CapabilityStatement/backport-subscription-server-r4'
|
35
|
+
end
|
36
|
+
|
37
|
+
def subscription_profile_url
|
38
|
+
'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription'
|
39
|
+
end
|
40
|
+
|
41
|
+
def capability_statement_subscriptiontopic_extension
|
42
|
+
'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/capabilitystatement-subscriptiontopic-canonical'
|
43
|
+
end
|
44
|
+
|
45
|
+
def scratch_resource
|
46
|
+
scratch[:capability_statement] ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
run do
|
50
|
+
resource = scratch_resource
|
51
|
+
|
52
|
+
skip_if resource.blank?, 'No Capability Statement received in previous test'
|
53
|
+
|
54
|
+
assert(resource.rest.present?, 'Capability Statement missing the `rest` field')
|
55
|
+
rest_server = resource.rest.find { |elem| elem.mode == 'server' }
|
56
|
+
assert(rest_server.present?, "Capability Statement missing entry in `rest` with a `mode` set to 'server'")
|
57
|
+
|
58
|
+
rest_subscription = rest_server.resource.find { |elem| elem.type == 'Subscription' }
|
59
|
+
assert(rest_subscription.present?, 'Capability Statement missing `Subscription` resource in `rest` field')
|
60
|
+
|
61
|
+
assert(rest_subscription.extension.present?,
|
62
|
+
'Capability Statement missing the `extension` field on the Subscription resource')
|
63
|
+
subscription_topic_extension = rest_subscription.extension.select do |elem|
|
64
|
+
elem.url == capability_statement_subscriptiontopic_extension
|
65
|
+
end
|
66
|
+
assert(subscription_topic_extension.any?, %(
|
67
|
+
The server SHOULD support topic discovery via the CapabilityStatement SubscriptionTopic Canonical
|
68
|
+
extension))
|
69
|
+
|
70
|
+
subscription_requests = load_tagged_requests('subscription_creation')
|
71
|
+
|
72
|
+
if subscription_requests.any?
|
73
|
+
subscription_topics =
|
74
|
+
subscription_requests
|
75
|
+
.select { |request| request.status == 201 }
|
76
|
+
.uniq(&:response_body)
|
77
|
+
.map { |request| JSON.parse(request.response_body) }
|
78
|
+
.map { |subscription| subscription['criteria'] }
|
79
|
+
.uniq
|
80
|
+
|
81
|
+
if subscription_topics.any?
|
82
|
+
subscription_topics.each do |subscription_topic|
|
83
|
+
next if subscription_topic_extension.any? { |elem| elem.valueCanonical == subscription_topic }
|
84
|
+
|
85
|
+
add_message('error', %(
|
86
|
+
The SubscriptionTopic Canonical extension should include the Subscription Topic URLs found in
|
87
|
+
Subscription.criteria: #{subscription_topic}))
|
88
|
+
end
|
89
|
+
else
|
90
|
+
add_message('warning', %(
|
91
|
+
Subscriptions missing criteria field containing a Subscription topic URL. Could not verify any
|
92
|
+
topics found in the SubscriptionTopic Canonical extension))
|
93
|
+
end
|
94
|
+
|
95
|
+
no_error_verification(
|
96
|
+
"Subscription.criteria value(s) not found in Capability Statement's SubscriptionTopic Canonical extension"
|
97
|
+
)
|
98
|
+
else
|
99
|
+
add_message('warning', %(
|
100
|
+
No Subscription requests have been made in previous tests. Run the Subscription workflow tests first in order
|
101
|
+
to verify topics found in the SubscriptionTopic Canonical extension))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'capability_statement/cs_conformance_test'
|
2
|
+
require_relative 'capability_statement/topic_discovery_test'
|
3
|
+
|
4
|
+
module SubscriptionsTestKit
|
5
|
+
module SubscriptionsR5BackportR4Server
|
6
|
+
class CapabilityStatementGroup < Inferno::TestGroup
|
7
|
+
id :subscriptions_r5_backport_r4_server_capability_statement
|
8
|
+
title 'Capability Statement Verification'
|
9
|
+
description %(
|
10
|
+
Verify the Backport Subscriptions Server has a conformant Capability Statement and that it declares support for the
|
11
|
+
Backport Subscription Profile on the Subscription resource in the rest field. Then the group will verify if the
|
12
|
+
server supports topic discovert via the Capability Statement, which is an optional requirement.
|
13
|
+
)
|
14
|
+
|
15
|
+
run_as_group
|
16
|
+
|
17
|
+
test from: :subscriptions_r5_backport_r4_server_cs_conformance
|
18
|
+
test from: :subscriptions_r5_backport_r4_server_topic_discovery
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative '../../../../../common/notification_conformance_verification'
|
2
|
+
|
3
|
+
module SubscriptionsTestKit
|
4
|
+
module SubscriptionsR5BackportR4Server
|
5
|
+
class EmptyConformanceTest < Inferno::Test
|
6
|
+
include NotificationConformanceVerification
|
7
|
+
|
8
|
+
id :subscriptions_r5_backport_r4_server_empty_conformance
|
9
|
+
title 'Subscription Empty Notification Verification'
|
10
|
+
description %(
|
11
|
+
This test takes the received empty notification bundle and ensures it is conformant to the
|
12
|
+
[R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
|
13
|
+
profle and to the requirements listed for empty notifications.
|
14
|
+
|
15
|
+
With the content type of empty, no information about the resources involved in triggering the notification is
|
16
|
+
available via the subscription channel. When populating the SubscriptionStatus.notificationEvent structure for a
|
17
|
+
notification with an empty payload, a server SHALL NOT include references to resources
|
18
|
+
(e.g., SubscriptionStatus.notificationEvent.focus and SubscriptionStatus.notificationEvent.additionalContext
|
19
|
+
SHALL NOT be present).
|
20
|
+
|
21
|
+
When the content type is empty, notification bundles SHALL not contain Bundle.entry
|
22
|
+
elements other than the SubscriptionStatus for the notification.
|
23
|
+
)
|
24
|
+
|
25
|
+
verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
|
26
|
+
'hl7.fhir.uv.subscriptions_1.1.0@15',
|
27
|
+
'hl7.fhir.uv.subscriptions_1.1.0@28',
|
28
|
+
'hl7.fhir.uv.subscriptions_1.1.0@69',
|
29
|
+
'hl7.fhir.uv.subscriptions_1.1.0@70',
|
30
|
+
'hl7.fhir.uv.subscriptions_1.1.0@38',
|
31
|
+
'hl7.fhir.uv.subscriptions_1.1.0@39',
|
32
|
+
'hl7.fhir.uv.subscriptions_1.1.0@35',
|
33
|
+
'hl7.fhir.uv.subscriptions_1.1.0@67',
|
34
|
+
'hl7.fhir.uv.subscriptions_1.1.0@51',
|
35
|
+
'hl7.fhir.uv.subscriptions_1.1.0@53',
|
36
|
+
'hl7.fhir.uv.subscriptions_1.1.0@65',
|
37
|
+
'hl7.fhir.uv.subscriptions_1.1.0@99',
|
38
|
+
'hl7.fhir.uv.subscriptions_1.1.0@138',
|
39
|
+
'hl7.fhir.uv.subscriptions_1.1.0@139'
|
40
|
+
|
41
|
+
run do
|
42
|
+
subscription_requests = load_tagged_requests('subscription_creation', 'empty')
|
43
|
+
omit_if subscription_requests.empty?, 'No Subscriptions sent with notification payload type of `empty`'
|
44
|
+
|
45
|
+
subscription_requests.each do |subscription_request|
|
46
|
+
assert_valid_json(subscription_request.response_body)
|
47
|
+
subscription = JSON.parse(subscription_request.response_body)
|
48
|
+
|
49
|
+
requests = load_tagged_requests('event-notification', subscription['id'])
|
50
|
+
skip_if requests.empty?, 'No event-notification requests were made in a previous test as expected.'
|
51
|
+
|
52
|
+
requests = requests.uniq(&:request_body)
|
53
|
+
|
54
|
+
requests.each do |request|
|
55
|
+
empty_event_notification_verification(request.request_body)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
no_error_verification('Received empty notification-events are not conformant.')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../../common/interaction_group'
|
2
|
+
require_relative '../../common/interaction_verification_group'
|
3
|
+
require_relative 'empty_content/empty_conformance_test'
|
4
|
+
|
5
|
+
module SubscriptionsTestKit
|
6
|
+
module SubscriptionsR5BackportR4Server
|
7
|
+
class EmptyContentGroup < Inferno::TestGroup
|
8
|
+
id :subscriptions_r5_backport_r4_server_empty_content
|
9
|
+
title 'Empty Notification Verification'
|
10
|
+
description %(
|
11
|
+
Verify that the received Notifications are conformant to the
|
12
|
+
[R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
|
13
|
+
profile, including additional requirements around the `empty` content type ([example empty
|
14
|
+
Subscription](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_empty.json)).
|
15
|
+
)
|
16
|
+
run_as_group
|
17
|
+
optional
|
18
|
+
|
19
|
+
input_order :url, :credentials, :access_token, :empty_subscription_resource
|
20
|
+
|
21
|
+
group from: :subscriptions_r5_backport_r4_server_interaction do
|
22
|
+
id :subscriptions_r5_backport_r4_server_empty_content_interaction
|
23
|
+
optional
|
24
|
+
|
25
|
+
config(
|
26
|
+
options: { subscription_type: 'empty' },
|
27
|
+
inputs: {
|
28
|
+
subscription_resource: {
|
29
|
+
name: :empty_subscription_resource,
|
30
|
+
title: 'Empty Notification Subscription Resource',
|
31
|
+
type: 'textarea',
|
32
|
+
description: %(
|
33
|
+
A Subscription resource in JSON format that Inferno will send to the server under test
|
34
|
+
so that it can demonstrate its ability to send an empty Notification.
|
35
|
+
The instance must be conformant to the R4/B Topic-Based Subscription profile.
|
36
|
+
Inferno may modify the Subscription before submission, e.g., to point to Inferno's notification endpoint.
|
37
|
+
),
|
38
|
+
optional: true
|
39
|
+
},
|
40
|
+
updated_subscription: { name: :empty_updated_subscription }
|
41
|
+
},
|
42
|
+
outputs: {
|
43
|
+
updated_subscription: { name: :empty_updated_subscription }
|
44
|
+
}
|
45
|
+
)
|
46
|
+
end
|
47
|
+
group from: :subscriptions_r5_backport_r4_server_interaction_verification do
|
48
|
+
id :subscriptions_r5_backport_r4_server_empty_content_interaction_verification
|
49
|
+
optional
|
50
|
+
|
51
|
+
config(
|
52
|
+
options: { subscription_type: 'empty' }
|
53
|
+
)
|
54
|
+
test from: :subscriptions_r5_backport_r4_server_empty_conformance
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative '../../../../../common/notification_conformance_verification'
|
2
|
+
|
3
|
+
module SubscriptionsTestKit
|
4
|
+
module SubscriptionsR5BackportR4Server
|
5
|
+
class FullResourceConformanceTest < Inferno::Test
|
6
|
+
include NotificationConformanceVerification
|
7
|
+
|
8
|
+
id :subscriptions_r5_backport_r4_server_full_resource_conformance
|
9
|
+
title 'Subscription Full-Resource Notification Verification'
|
10
|
+
description %(
|
11
|
+
This test takes the received notification bundle and ensures it is conformant to the
|
12
|
+
[R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
|
13
|
+
profle.
|
14
|
+
|
15
|
+
With the content type of full-resource, the resources involved in triggering the notification are included in the
|
16
|
+
notification bundle.
|
17
|
+
|
18
|
+
When the content type is full-resource, notification bundles SHALL include references to the
|
19
|
+
appropriate focus resources in the SubscriptionStatus.notificationEvent.focus element.
|
20
|
+
|
21
|
+
Notification bundles for full-resource subscriptions SHALL contain, in addition to the SubscriptionStatus, at
|
22
|
+
least one Bundle.entry for each resource relevant to the notification.
|
23
|
+
|
24
|
+
Each Bundle.entry for a full-resource notification SHALL contain a relevant resource in the
|
25
|
+
entry.resource element. If a server cannot include the resource contents due to an issue with a specific
|
26
|
+
notification, the server SHALL populate the entry.request and/or entry.response elements.
|
27
|
+
)
|
28
|
+
|
29
|
+
verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
|
30
|
+
'hl7.fhir.uv.subscriptions_1.1.0@15',
|
31
|
+
'hl7.fhir.uv.subscriptions_1.1.0@28',
|
32
|
+
'hl7.fhir.uv.subscriptions_1.1.0@69',
|
33
|
+
'hl7.fhir.uv.subscriptions_1.1.0@70',
|
34
|
+
'hl7.fhir.uv.subscriptions_1.1.0@43',
|
35
|
+
'hl7.fhir.uv.subscriptions_1.1.0@44',
|
36
|
+
'hl7.fhir.uv.subscriptions_1.1.0@45',
|
37
|
+
'hl7.fhir.uv.subscriptions_1.1.0@35',
|
38
|
+
'hl7.fhir.uv.subscriptions_1.1.0@67',
|
39
|
+
'hl7.fhir.uv.subscriptions_1.1.0@51',
|
40
|
+
'hl7.fhir.uv.subscriptions_1.1.0@53',
|
41
|
+
'hl7.fhir.uv.subscriptions_1.1.0@65',
|
42
|
+
'hl7.fhir.uv.subscriptions_1.1.0@101',
|
43
|
+
'hl7.fhir.uv.subscriptions_1.1.0@138',
|
44
|
+
'hl7.fhir.uv.subscriptions_1.1.0@139'
|
45
|
+
|
46
|
+
run do
|
47
|
+
subscription_requests = load_tagged_requests('subscription_creation', 'full-resource')
|
48
|
+
omit_if subscription_requests.empty?, 'No Subscriptions sent with notification payload type of `full-resource`'
|
49
|
+
|
50
|
+
subscription_requests.each do |subscription_request|
|
51
|
+
assert_valid_json(subscription_request.response_body)
|
52
|
+
subscription = JSON.parse(subscription_request.response_body)
|
53
|
+
|
54
|
+
requests = load_tagged_requests('event-notification', subscription['id'])
|
55
|
+
skip_if requests.empty?, 'No event-notification requests were made in a previous test as expected.'
|
56
|
+
|
57
|
+
criteria_resource_type = subscription_criteria(subscription)
|
58
|
+
requests = requests.uniq(&:request_body)
|
59
|
+
|
60
|
+
requests.each do |request|
|
61
|
+
full_resource_event_notification_verification(request.request_body, criteria_resource_type)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
no_error_verification('Received notification-events are not conformant.')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../../common/interaction_group'
|
2
|
+
require_relative '../../common/interaction_verification_group'
|
3
|
+
require_relative 'full_resource_content/full_resource_conformance_test'
|
4
|
+
|
5
|
+
module SubscriptionsTestKit
|
6
|
+
module SubscriptionsR5BackportR4Server
|
7
|
+
class FullResourceContentGroup < Inferno::TestGroup
|
8
|
+
id :subscriptions_r5_backport_r4_server_full_resource_content
|
9
|
+
title 'Full Resource Notification Verification'
|
10
|
+
description %(
|
11
|
+
Verify that the received Notifications are conformant to the
|
12
|
+
[R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
|
13
|
+
profile, including additional requirements around the `full-resource` content type ([example full-resource
|
14
|
+
Subscription](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_full-resource.json)).
|
15
|
+
)
|
16
|
+
run_as_group
|
17
|
+
optional
|
18
|
+
|
19
|
+
input_order :url, :credentials, :access_token, :full_resource_subscription_resource
|
20
|
+
|
21
|
+
group from: :subscriptions_r5_backport_r4_server_interaction do
|
22
|
+
id :subscriptions_r5_backport_r4_server_full_resource_content_interaction
|
23
|
+
optional
|
24
|
+
|
25
|
+
config(
|
26
|
+
options: { subscription_type: 'full-resource' },
|
27
|
+
inputs: {
|
28
|
+
subscription_resource: {
|
29
|
+
name: :full_resource_subscription_resource,
|
30
|
+
title: 'Full-Resource Notification Subscription Resource',
|
31
|
+
type: 'textarea',
|
32
|
+
description: %(
|
33
|
+
A Subscription resource in JSON format that Inferno will send to the server under test
|
34
|
+
so that it can demonstrate its ability to send a full-resource Notification.
|
35
|
+
The instance must be conformant to the R4/B Topic-Based Subscription profile.
|
36
|
+
Inferno may modify the Subscription before submission, e.g., to point to Inferno's notification endpoint.
|
37
|
+
),
|
38
|
+
optional: true
|
39
|
+
},
|
40
|
+
updated_subscription: { name: :full_resource_updated_subscription }
|
41
|
+
},
|
42
|
+
outputs: {
|
43
|
+
updated_subscription: { name: :full_resource_updated_subscription }
|
44
|
+
}
|
45
|
+
)
|
46
|
+
end
|
47
|
+
group from: :subscriptions_r5_backport_r4_server_interaction_verification do
|
48
|
+
id :subscriptions_r5_backport_r4_server_full_resource_content_interaction_verification
|
49
|
+
optional
|
50
|
+
|
51
|
+
config(
|
52
|
+
options: { subscription_type: 'full-resource' }
|
53
|
+
)
|
54
|
+
test from: :subscriptions_r5_backport_r4_server_full_resource_conformance
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative '../../../../../common/notification_conformance_verification'
|
2
|
+
|
3
|
+
module SubscriptionsTestKit
|
4
|
+
module SubscriptionsR5BackportR4Server
|
5
|
+
class IdOnlyConformanceTest < Inferno::Test
|
6
|
+
include NotificationConformanceVerification
|
7
|
+
|
8
|
+
id :subscriptions_r5_backport_r4_server_id_only_conformance
|
9
|
+
title 'Subscription Id-Only Notification Verification'
|
10
|
+
description %(
|
11
|
+
This test takes the received notification bundle and ensures it is conformant to the
|
12
|
+
[R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
|
13
|
+
profle.
|
14
|
+
|
15
|
+
With the content type of id-only, the resources involved in triggering the notification are only available
|
16
|
+
through other channels, but notifications include URLs which can be used to access those resources.
|
17
|
+
|
18
|
+
When the content type is id-only, notification bundles SHALL include references to the appropriate focus resources
|
19
|
+
in the SubscriptionStatus.notificationEvent.focus element.
|
20
|
+
|
21
|
+
Additionally, notification bundles MAY contain, in addition to the SubscriptionStatus used to convey status
|
22
|
+
information, at least one Bundle.entry for each resource relevant to the notification.
|
23
|
+
|
24
|
+
Each Bundle.entry for id-only notification SHALL contain a relevant resource URL in the fullUrl and request
|
25
|
+
elements, as is required for history bundles.
|
26
|
+
)
|
27
|
+
|
28
|
+
verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
|
29
|
+
'hl7.fhir.uv.subscriptions_1.1.0@15',
|
30
|
+
'hl7.fhir.uv.subscriptions_1.1.0@28',
|
31
|
+
'hl7.fhir.uv.subscriptions_1.1.0@69',
|
32
|
+
'hl7.fhir.uv.subscriptions_1.1.0@70',
|
33
|
+
'hl7.fhir.uv.subscriptions_1.1.0@40',
|
34
|
+
'hl7.fhir.uv.subscriptions_1.1.0@42',
|
35
|
+
'hl7.fhir.uv.subscriptions_1.1.0@35',
|
36
|
+
'hl7.fhir.uv.subscriptions_1.1.0@67',
|
37
|
+
'hl7.fhir.uv.subscriptions_1.1.0@51',
|
38
|
+
'hl7.fhir.uv.subscriptions_1.1.0@53',
|
39
|
+
'hl7.fhir.uv.subscriptions_1.1.0@65',
|
40
|
+
'hl7.fhir.uv.subscriptions_1.1.0@100',
|
41
|
+
'hl7.fhir.uv.subscriptions_1.1.0@138',
|
42
|
+
'hl7.fhir.uv.subscriptions_1.1.0@139'
|
43
|
+
|
44
|
+
run do
|
45
|
+
subscription_requests = load_tagged_requests('subscription_creation', 'id-only')
|
46
|
+
omit_if subscription_requests.empty?, 'No Subscriptions sent with notification payload type of `id-only`'
|
47
|
+
|
48
|
+
subscription_requests.each do |subscription_request|
|
49
|
+
assert_valid_json(subscription_request.response_body)
|
50
|
+
subscription = JSON.parse(subscription_request.response_body)
|
51
|
+
|
52
|
+
requests = load_tagged_requests('event-notification', subscription['id'])
|
53
|
+
skip_if requests.empty?, 'No event-notification requests were made in a previous test as expected.'
|
54
|
+
|
55
|
+
criteria_resource_type = subscription_criteria(subscription)
|
56
|
+
requests = requests.uniq(&:request_body)
|
57
|
+
|
58
|
+
requests.each do |request|
|
59
|
+
id_only_event_notification_verification(request.request_body, criteria_resource_type)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
no_error_verification('Received notification-events are not conformant.')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|