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.
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,58 @@
1
+ require_relative '../../common/interaction_group'
2
+ require_relative '../../common/interaction_verification_group'
3
+ require_relative 'id_only_content/id_only_conformance_test'
4
+
5
+ module SubscriptionsTestKit
6
+ module SubscriptionsR5BackportR4Server
7
+ class IdOnlyContentGroup < Inferno::TestGroup
8
+ id :subscriptions_r5_backport_r4_server_id_only_content
9
+ title 'Id Only 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 `id-only` content type ([example id-only
14
+ Subscription](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_id-only.json)).
15
+ )
16
+ run_as_group
17
+ optional
18
+
19
+ input_order :url, :credentials, :access_token, :id_only_subscription_resource
20
+
21
+ group from: :subscriptions_r5_backport_r4_server_interaction do
22
+ id :subscriptions_r5_backport_r4_server_id_only_content_interaction
23
+ optional
24
+
25
+ config(
26
+ options: { subscription_type: 'id-only' },
27
+ inputs: {
28
+ subscription_resource: {
29
+ name: :id_only_subscription_resource,
30
+ title: 'Id-Only 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 id-only 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: :id_only_updated_subscription }
41
+ },
42
+ outputs: {
43
+ updated_subscription: { name: :id_only_updated_subscription }
44
+ }
45
+ )
46
+ end
47
+ group from: :subscriptions_r5_backport_r4_server_interaction_verification do
48
+ id :subscriptions_r5_backport_r4_server_id_only_content_interaction_verification
49
+ optional
50
+
51
+ config(
52
+ options: { subscription_type: 'id-only' }
53
+ )
54
+ test from: :subscriptions_r5_backport_r4_server_id_only_conformance
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'event_notification/empty_content_group'
2
+ require_relative 'event_notification/full_resource_content_group'
3
+ require_relative 'event_notification/id_only_content_group'
4
+
5
+ module SubscriptionsTestKit
6
+ module SubscriptionsR5BackportR4Server
7
+ class EventNotificationGroup < Inferno::TestGroup
8
+ id :subscriptions_r5_backport_r4_server_event_notification
9
+ title 'Backport Subscription 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 content type. This group contains tests for the three options
14
+ available when specifying the contents of a Notification: empty, id-only, and full-resource.
15
+ )
16
+
17
+ input_order :url, :credentials, :access_token, :empty_subscription_resource,
18
+ :id_only_subscription_resource, :full_resource_subscription_resource
19
+
20
+ group from: :subscriptions_r5_backport_r4_server_empty_content
21
+ group from: :subscriptions_r5_backport_r4_server_id_only_content
22
+ group from: :subscriptions_r5_backport_r4_server_full_resource_content
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../../../../common/notification_conformance_verification'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class HandshakeConformanceTest < Inferno::Test
6
+ include NotificationConformanceVerification
7
+
8
+ id :subscriptions_r5_backport_r4_server_handshake_conformance
9
+ title 'Subscription Handshake Verification'
10
+ description %(
11
+ When a Subscription is created for a REST Hook channel type, the server SHALL set initial status to requested,
12
+ pending verification of the nominated endpoint URL. The Server will then send a handshake bundle to the endpoint.
13
+ After a successful handshake notification has been sent and accepted, the server SHALL update the status to
14
+ active. This test verifies that the incoming handshake request is a conformant
15
+ [R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html).
16
+ )
17
+
18
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
19
+ 'hl7.fhir.uv.subscriptions_1.1.0@15',
20
+ 'hl7.fhir.uv.subscriptions_1.1.0@28',
21
+ 'hl7.fhir.uv.subscriptions_1.1.0@69',
22
+ 'hl7.fhir.uv.subscriptions_1.1.0@70',
23
+ 'hl7.fhir.uv.subscriptions_1.1.0@24',
24
+ 'hl7.fhir.uv.subscriptions_1.1.0@25',
25
+ 'hl7.fhir.uv.subscriptions_1.1.0@138',
26
+ 'hl7.fhir.uv.subscriptions_1.1.0@139'
27
+
28
+ run do
29
+ subscription_requests = load_tagged_requests('subscription_creation')
30
+ skip_if(subscription_requests.empty?, %(
31
+ No Subscription creation requests were made in previous tests. Must run Subscription Workflow tests first in
32
+ order to run this test.))
33
+
34
+ subscription_request_ids =
35
+ subscription_requests
36
+ .select { |request| request.status == 201 }
37
+ .uniq(&:response_body)
38
+ .map { |request| JSON.parse(request.response_body) }
39
+ .select { |subscription| subscription['channel']['type'] == 'rest-hook' }
40
+ .map { |subscription| subscription['id'] }
41
+
42
+ requests = load_tagged_requests('handshake')
43
+ if requests.empty?
44
+ omit_if subscription_request_ids.empty?, 'No handshake requests were required or received in a previous tests.'
45
+ assert(subscription_request_ids.empty?,
46
+ 'Handshake requests are required if a Subscription channel type is `rest-hook`')
47
+ end
48
+
49
+ requests = requests.uniq(&:request_body)
50
+
51
+ requests.each do |request|
52
+ tags = request.tags.dup
53
+ tags -= ['handshake']
54
+ subscription_id = tags.first
55
+
56
+ subscription_request_ids.delete(subscription_id)
57
+
58
+ notification_verification(request.request_body, 'handshake', subscription_id:, status: 'requested')
59
+ end
60
+
61
+ no_error_verification('Received handshakes are not conformant.')
62
+ assert(subscription_request_ids.empty?,
63
+ 'Did not receive a handshake notification for some `rest-hook` subscriptions')
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../../../../common/notification_conformance_verification'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class HeartbeatConformanceTest < Inferno::Test
6
+ include NotificationConformanceVerification
7
+
8
+ id :subscriptions_r5_backport_r4_server_heartbeat_conformance
9
+ title 'Subscription Heartbeat Verification'
10
+ description %(
11
+ When a Subscription is created for a REST Hook channel type, the server Server may send notifications of type
12
+ heartbeat at any time. This test verifies that the incoming heartbeat request is a conformant
13
+ [R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html).
14
+ )
15
+
16
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@14',
17
+ 'hl7.fhir.uv.subscriptions_1.1.0@15',
18
+ 'hl7.fhir.uv.subscriptions_1.1.0@28',
19
+ 'hl7.fhir.uv.subscriptions_1.1.0@69',
20
+ 'hl7.fhir.uv.subscriptions_1.1.0@70',
21
+ 'hl7.fhir.uv.subscriptions_1.1.0@138',
22
+ 'hl7.fhir.uv.subscriptions_1.1.0@139',
23
+ 'hl7.fhir.uv.subscriptions_1.1.0@93',
24
+ 'hl7.fhir.uv.subscriptions_1.1.0@94'
25
+
26
+ def heartbeat_period?(subscription_extensions)
27
+ return false if subscription_extensions.blank?
28
+
29
+ heartbeat = subscription_extensions.find { |extension| extension['url'].ends_with?('/backport-heartbeat-period') }
30
+
31
+ return false if heartbeat.blank?
32
+
33
+ heartbeat['valueUnsignedInt'].present?
34
+ end
35
+
36
+ run do
37
+ subscription_requests = load_tagged_requests('subscription_creation')
38
+ skip_if(subscription_requests.empty?, %(
39
+ No Subscription creation requests were made in previous tests. Must run Subscription Workflow tests first in
40
+ order to run this test.))
41
+
42
+ subscription_request_ids =
43
+ subscription_requests
44
+ .select { |request| request.status == 201 }
45
+ .uniq(&:response_body)
46
+ .map { |request| JSON.parse(request.response_body) }
47
+ .select { |subscription| heartbeat_period?(subscription['channel']['extension']) }
48
+ .map { |subscription| subscription['id'] }
49
+
50
+ requests = load_tagged_requests('heartbeat')
51
+ if requests.empty?
52
+ omit_if subscription_request_ids.empty?, 'No heartbeat requests requested or received in previous tests.'
53
+ assert(subscription_request_ids.empty?, %(
54
+ No Heartbeat notifications received when heartbeat was requested by the subscriber (`heartbeatPeriod` is
55
+ populated)))
56
+ end
57
+
58
+ requests = requests.uniq(&:request_body)
59
+
60
+ requests.each do |request|
61
+ tags = request.tags.dup
62
+ tags -= ['heartbeat']
63
+ subscription_id = tags.first
64
+
65
+ assert(subscription_request_ids.include?(subscription_id),
66
+ 'If `heartbeatPeriod` field is not present in the Subscription, heartbeat should not be sent.')
67
+
68
+ notification_verification(request.request_body, 'heartbeat', subscription_id:)
69
+ no_error_verification('Received heartbeats are not conformant.')
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'handshake_heartbeat/handshake_conformance_test'
2
+ require_relative 'handshake_heartbeat/heartbeat_conformance_test'
3
+
4
+ module SubscriptionsTestKit
5
+ module SubscriptionsR5BackportR4Server
6
+ class HandshakeHeartbeatGroup < Inferno::TestGroup
7
+ id :subscriptions_r5_backport_r4_server_handshake_heartbeat
8
+ title 'Backport Subscription Handshake and Heartbeat Notification Verification'
9
+ description %(
10
+ Verify that the any received Handshake or Heartbeat Notifications are conformant to the
11
+ [R4 Topic-Based Subscription Notification Bundle](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html)
12
+ profile.
13
+ )
14
+
15
+ test from: :subscriptions_r5_backport_r4_server_handshake_conformance
16
+ test from: :subscriptions_r5_backport_r4_server_heartbeat_conformance
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../../common/subscription_status_operation'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class StatusInvocationTest < Inferno::Test
6
+ include SubscriptionStatusOperation
7
+
8
+ id :subscriptions_r5_backport_r4_server_status_invocation
9
+ title 'Server supports subscription $status operation'
10
+ description %(
11
+ In order to claim conformance with this guide, a server: SHALL support the [$status operation](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/OperationDefinition-backport-subscription-status.html)
12
+ on the Subscription resource. This operation is used to return the current status information about one or more
13
+ topic-based Subscriptions in R4. The operation returns a bundle containing one or more subscription status
14
+ resources, one per Subscription being queried. The Bundle type is "searchset". The status of the Subscription
15
+ should be set to 'active' after a successful handshake with the rest-hook endpoint.
16
+
17
+ This test ensures the server supports the $status operation by performing the operation and ensuring it receives a
18
+ valid response.
19
+ )
20
+
21
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@20',
22
+ 'hl7.fhir.uv.subscriptions_1.1.0@30',
23
+ 'hl7.fhir.uv.subscriptions_1.1.0@47'
24
+
25
+ run do
26
+ subscription_requests = load_tagged_requests('subscription_creation')
27
+ success_subscription_requests =
28
+ subscription_requests
29
+ .select { |request| request.status == 201 }
30
+ skip_if success_subscription_requests.empty?, %(
31
+ No successful Subscription creation requests were made in previous tests. Must run Subscription Workflow tests
32
+ first in order to run this test.
33
+ )
34
+
35
+ subscription = JSON.parse(success_subscription_requests.first.response_body)
36
+ subscription_id = subscription['id']
37
+
38
+ perform_subscription_status_test(subscription_id)
39
+ no_error_verification('Subscription status response was not conformant.')
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'status_operation/status_invocation_test'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class StatusOperationGroup < Inferno::TestGroup
6
+ id :subscriptions_r5_backport_r4_server_status_operation
7
+ title 'Subscription $status Operation Verification'
8
+ description %(
9
+ This test group verifies that the Backport Subscriptions Server supports the $status operation.
10
+ )
11
+
12
+ test from: :subscriptions_r5_backport_r4_server_status_invocation
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,181 @@
1
+ require_relative '../../common/subscription_creation'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class RejectSubscriptionsTest < Inferno::Test
6
+ include SubscriptionCreation
7
+
8
+ id :subscriptions_r5_backport_r4_server_reject_subscriptions
9
+ title 'Server Handles Unsupported Subscriptions'
10
+ description %(
11
+ When processing a request for a Subscription a server SHOULD verify that the Subscription is supported and does not
12
+ contain any information not implemented by the server. If the Subscription is no supported, the server should reject
13
+ the Subscription create request, or it should attempt to adjust the Subscription. This test checks that the server
14
+ correctly rejects or adjusts the Subscription in the following cases:
15
+
16
+ - The Subscription contains cross-version extension
17
+ - The Subscription contains a Subscription Topic not implemented by the server
18
+ - The Subscription contains a filtering criteria not implemented by the server
19
+ - The Subscription contains channel type not implemented by the server
20
+ - The Subscription contains an unsupported channel endpoint
21
+ - The Subscription contains a payload type not implemented by the server
22
+ - The Subscription contains an unsupported channel and payload type combination
23
+
24
+ The test will pass if the server either
25
+ 1. rejects the Subscription by responding with a non-201 response, or
26
+ 2. updates the Subscription resource to remove or replace the unsupported value.
27
+ )
28
+
29
+ verifies_requirements 'hl7.fhir.uv.subscriptions_1.1.0@8',
30
+ 'hl7.fhir.uv.subscriptions_1.1.0@9',
31
+ 'hl7.fhir.uv.subscriptions_1.1.0@10',
32
+ 'hl7.fhir.uv.subscriptions_1.1.0@11',
33
+ 'hl7.fhir.uv.subscriptions_1.1.0@12',
34
+ 'hl7.fhir.uv.subscriptions_1.1.0@13'
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 :unsupported_subscription_topic,
48
+ title: 'Unsupported Subscription Topic',
49
+ description: 'A Subscription Topic for the `criteria` element that is not implemented by the server to test for Subscription rejection.',
50
+ optional: true
51
+ input :unsupported_subscription_filter,
52
+ title: 'Unsupported Subscription Filter',
53
+ description: 'A value for `filterCriteria` extension under the `criteria` that is not implemented by the server to test for Subscription rejection.',
54
+ optional: true
55
+ input :unsupported_subscription_channel_type,
56
+ title: 'Unsupported Subscription Channel Type',
57
+ description: 'A value for the `channel.type` element that is not implemented by the server to test for Subscription rejection.',
58
+ optional: true
59
+ input :unsupported_subscription_channel_endpoint,
60
+ title: 'Unsupported Subscription Channel Endpoint',
61
+ description: 'An unsupported value for the `channel.endpoint` element to test for Subscription rejection.',
62
+ optional: true
63
+ input :unsupported_subscription_payload_type,
64
+ title: 'Unsupported Subscription Payload Type',
65
+ description: 'A value for the `content` extension under the `channel.payload` element that is not implemented by the server to test for Subscription rejection.',
66
+ optional: true
67
+ input :unsupported_subscription_channel_payload_combo,
68
+ title: 'Unsupported Subscription Channel and Payload Combination',
69
+ description: %(
70
+ A channel (`channel.type`) and payload type (`content` extension under the `channel.payload` element)
71
+ combination not implemented by the server to test for Subscription
72
+ rejection. Provide in the json format e.g. {channel: <'channel_type'>, payload: <'payload_type'>}.
73
+ ),
74
+ optional: true
75
+
76
+ def unsupported_subscriptions
77
+ [
78
+ {
79
+ 'unsupported_title' => 'cross-version extensions',
80
+ 'field_path' => ['_criteria'],
81
+ 'field_value' => { 'extension' => [{
82
+ url: 'http://hl7.org/fhir/5.0/subscriptions-backport/StructureDefinition/backport-filter-criteria',
83
+ valueString: 'Encounter?patient=Patient/123'
84
+ }] }
85
+ },
86
+ {
87
+ 'unsupported_title' => 'unsupported `SubscriptionTopic`',
88
+ 'field_path' => ['criteria'],
89
+ 'field_value' => unsupported_subscription_topic
90
+ },
91
+ {
92
+ 'unsupported_title' => 'unsupported filter criteria',
93
+ 'field_path' => ['_criteria'],
94
+ 'field_value' => if unsupported_subscription_filter.nil?
95
+ unsupported_subscription_filter
96
+ else
97
+ { 'extension' => [{
98
+ url: 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria',
99
+ valueString: unsupported_subscription_filter
100
+ }] }
101
+ end
102
+ },
103
+ {
104
+ 'unsupported_title' => 'unsupported channel type',
105
+ 'field_path' => ['channel', 'type'],
106
+ 'field_value' => unsupported_subscription_channel_type
107
+ },
108
+ {
109
+ 'unsupported_title' => 'unsupported channel URL',
110
+ 'field_path' => ['channel', 'endpoint'],
111
+ 'field_value' => unsupported_subscription_channel_endpoint
112
+ },
113
+ {
114
+ 'unsupported_title' => 'unsupported channel type',
115
+ 'field_path' => ['channel', 'type'],
116
+ 'field_value' => unsupported_subscription_channel_type
117
+ },
118
+ {
119
+ 'unsupported_title' => 'unsupported payload type',
120
+ 'field_path' => ['channel', 'payload'],
121
+ 'field_value' => unsupported_subscription_payload_type
122
+ }
123
+ ]
124
+ end
125
+
126
+ run do
127
+ assert_valid_json(subscription_resource)
128
+ subscription = JSON.parse(subscription_resource)
129
+
130
+ unsupported_subscriptions.each do |unsupported_info|
131
+ next if unsupported_info['field_value'].blank?
132
+
133
+ field_name = unsupported_info['field_path'].last
134
+
135
+ if unsupported_info['field_path'].length > 1
136
+ outer_field_name = unsupported_info['field_path'].first
137
+ subscription_field = subscription[outer_field_name]
138
+ else
139
+ subscription_field = subscription
140
+ end
141
+
142
+ original_field_value = subscription_field[field_name]
143
+ subscription_field[field_name] = unsupported_info['field_value']
144
+
145
+ send_unsupported_subscription(subscription, unsupported_info['unsupported_title'], [unsupported_info['field_path']],
146
+ [unsupported_info['field_value']])
147
+
148
+ if original_field_value.nil?
149
+ subscription_field.delete(field_name)
150
+ else
151
+ subscription_field[field_name] = original_field_value
152
+ end
153
+ end
154
+
155
+ if unsupported_subscription_channel_payload_combo.present?
156
+ assert_valid_json(unsupported_subscription_channel_payload_combo)
157
+ channel_payload_combo = JSON.parse(unsupported_subscription_channel_payload_combo)
158
+ channel_value = channel_payload_combo['channel']
159
+ payload_value = channel_payload_combo['payload']
160
+
161
+ if channel_value.blank? || payload_value.blank?
162
+ add_message('error', %(
163
+ Channel and payload values are not populated correctly in unsupported channel and payload combination input.))
164
+ else
165
+ subscription_channel = subscription['channel']
166
+ subscription_channel['type'] = channel_value
167
+ subscription_channel['payload'] = payload_value
168
+
169
+ channel_path = ['channel', 'type']
170
+ payload_path = ['channel', 'payload']
171
+
172
+ send_unsupported_subscription(subscription, 'unsupported channel and payload combination', [channel_path, payload_path],
173
+ [channel_value, payload_value])
174
+ end
175
+ end
176
+
177
+ no_error_verification('Unsupported Subscription creation error handling failures.')
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'subscription_rejection/reject_subscriptions_test'
2
+
3
+ module SubscriptionsTestKit
4
+ module SubscriptionsR5BackportR4Server
5
+ class SubscriptionRejectionGroup < Inferno::TestGroup
6
+ id :subscriptions_r5_backport_r4_server_subscription_rejection
7
+ title 'Subscription Creation Rejection Verification'
8
+ description %(
9
+ This test group verifies that the Backport Subscriptions Server supports rejecting unsupported
10
+ Subscription creation requests.
11
+ )
12
+
13
+ input_order :url, :credentials, :subscription_resource, :unsupported_subscription_topic,
14
+ :unsupported_subscription_filter, :unsupported_subscription_channel_type,
15
+ :unsupported_subscription_channel_endpoint, :unsupported_subscription_payload_type,
16
+ :unsupported_subscription_channel_payload_combo
17
+
18
+ test from: :subscriptions_r5_backport_r4_server_reject_subscriptions
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'coverage/capability_statement_group'
2
+ require_relative 'coverage/event_notification_group'
3
+ require_relative 'coverage/handshake_heartbeat_group'
4
+ require_relative 'coverage/status_operation_group'
5
+ require_relative 'coverage/subscription_rejection_group'
6
+
7
+ module SubscriptionsTestKit
8
+ module SubscriptionsR5BackportR4Server
9
+ module Coverage
10
+ class GroupForCoverage < Inferno::TestGroup
11
+ id :subscriptions_r5_backport_r4_server_coverage
12
+ title 'Demonstrate coverage of all Subscription Backport IG requirements'
13
+ description %(
14
+ Demonstrate that the server covers all requirements placed on
15
+ servers by the IG.
16
+ )
17
+
18
+ group from: :subscriptions_r5_backport_r4_server_capability_statement
19
+ group from: :subscriptions_r5_backport_r4_server_event_notification
20
+ group from: :subscriptions_r5_backport_r4_server_handshake_heartbeat
21
+ group from: :subscriptions_r5_backport_r4_server_status_operation
22
+ group from: :subscriptions_r5_backport_r4_server_subscription_rejection
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'common/interaction_group'
2
+ require_relative 'common/interaction_verification_group'
3
+
4
+ module SubscriptionsTestKit
5
+ module SubscriptionsR5BackportR4Server
6
+ class WorkflowGroup < Inferno::TestGroup
7
+ id :subscriptions_r5_backport_r4_server_workflow
8
+ title 'Demonstrate the subscription workflow'
9
+ description %(
10
+ Demonstrate the ability of the server to accept a request for the
11
+ creation of a FHIR Subscription instance and deliver a notification
12
+ for that Subscription. The tester must provide a Subscription instance
13
+ that the server under test supports. Inferno will act as a client,
14
+ creating the Subscription and waiting for a notification based on it.
15
+ Inferno will then verify that the Subscription and the Notification
16
+ match and that the exchange is conformant.
17
+ )
18
+
19
+ run_as_group
20
+
21
+ input_order :url, :credentials, :access_token, :subscription_resource
22
+
23
+ group from: :subscriptions_r5_backport_r4_server_interaction
24
+ group from: :subscriptions_r5_backport_r4_server_interaction_verification
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,79 @@
1
+ require_relative 'subscriptions_r5_backport_r4_server/workflow_group'
2
+ require_relative 'subscriptions_r5_backport_r4_server/coverage_group'
3
+ require_relative '../endpoints/subscription_rest_hook_endpoint'
4
+ require_relative '../urls'
5
+ require_relative '../version'
6
+
7
+ module SubscriptionsTestKit
8
+ module SubscriptionsR5BackportR4Server
9
+ class SubscriptionsR5BackportR4ServerSuite < Inferno::TestSuite
10
+ id :subscriptions_r5_backport_r4_server
11
+ title 'Subscriptions R5 Backport IG v1.1.0 FHIR R4 Server Test Suite'
12
+ short_title 'Subscriptions R4 Server'
13
+ version VERSION
14
+ description File.read(File.join(__dir__, '..', 'docs', 'subscriptions_r5_backport_r4_server_suite_description.md'))
15
+
16
+ links [
17
+ {
18
+ label: 'Report Issue',
19
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit/issues'
20
+ },
21
+ {
22
+ label: 'Open Source',
23
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit'
24
+ },
25
+ {
26
+ label: 'Download',
27
+ url: 'https://github.com/inferno-framework/subscriptions-test-kit/releases'
28
+ },
29
+ {
30
+ label: 'Implementation Guide',
31
+ url: 'https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/'
32
+ }
33
+ ]
34
+
35
+ # These inputs will be available to all tests in this suite
36
+ input :url,
37
+ title: 'FHIR Server Base URL',
38
+ description: %(
39
+ FHIR base URL for the server under test where Inferno will send
40
+ Subscription Creation, $status, and other requests as a part of
41
+ these tests.
42
+ )
43
+
44
+ input :credentials,
45
+ title: 'OAuth Credentials',
46
+ description: 'Credentials for Inferno to include when making requests against the server under test.',
47
+ type: :oauth_credentials,
48
+ optional: true
49
+
50
+ # All FHIR requests in this suite will use this FHIR client
51
+ fhir_client do
52
+ url :url
53
+ oauth_credentials :credentials
54
+ end
55
+
56
+ # All FHIR validation requests will use this FHIR validator
57
+ fhir_resource_validator do
58
+ igs 'hl7.fhir.uv.subscriptions-backport#1.1.0'
59
+
60
+ exclude_message do |message|
61
+ message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
62
+ end
63
+ end
64
+
65
+ def self.extract_token_from_query_params(request)
66
+ request.query_parameters['token']
67
+ end
68
+
69
+ suite_endpoint :post, SUBSCRIPTION_CHANNEL_PATH, SubscriptionRestHookEndpoint
70
+
71
+ resume_test_route :get, RESUME_PASS_PATH do |request|
72
+ SubscriptionsR5BackportR4ServerSuite.extract_token_from_query_params(request)
73
+ end
74
+
75
+ group from: :subscriptions_r5_backport_r4_server_workflow
76
+ group from: :subscriptions_r5_backport_r4_server_coverage
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SubscriptionsTestKit
4
+ NOTIFICATION_TAG = 'subscription_notification'
5
+ SUBSCRIPTION_CREATE_TAG = 'subscription_create'
6
+ SUBSCRIPTION_READ_TAG = 'subscription_read'
7
+ SUBSCRIPTION_STATUS_TAG = 'subscription_status'
8
+ REST_HOOK_HANDSHAKE_NOTIFICATION_TAG = 'rest_hook_handshake_notification'
9
+ REST_HOOK_EVENT_NOTIFICATION_TAG = 'rest_hook_event_notification'
10
+ end