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