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,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