subscriptions_test_kit 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +22 -0
- data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +222 -0
- data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +264 -0
- data/lib/subscriptions_test_kit/common/notification_conformance_verification.rb +310 -0
- data/lib/subscriptions_test_kit/common/subscription_conformance_verification.rb +87 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_empty.json +37 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_full-resource.json +37 -0
- data/lib/subscriptions_test_kit/docs/samples/Subscription_id-only.json +38 -0
- data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_client_suite_description.md +120 -0
- data/lib/subscriptions_test_kit/docs/subscriptions_r5_backport_r4_server_suite_description.md +170 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_create_endpoint.rb +90 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_read_endpoint.rb +32 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_rest_hook_endpoint.rb +66 -0
- data/lib/subscriptions_test_kit/endpoints/subscription_status_endpoint.rb +70 -0
- data/lib/subscriptions_test_kit/igs/README.md +21 -0
- data/lib/subscriptions_test_kit/jobs/send_subscription_notifications.rb +130 -0
- data/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv +136 -0
- data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_out_of_scope_requirements.csv +23 -0
- data/lib/subscriptions_test_kit/requirements/subscriptions-test-kit_requirements.csv +145 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb +140 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/fixtures/capability_statement.json +57 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_payload_verification_test.rb +50 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_verification_test.rb +25 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/processing_attestation_test.rb +38 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/subscription_verification_test.rb +28 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification_group.rb +20 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_test.rb +128 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/event_notification_verification_test.rb +40 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/handshake_notification_verification_test.rb +40 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification_group.rb +16 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow_group.rb +33 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client_suite.rb +66 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/creation_response_conformance_test.rb +51 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/notification_delivery_test.rb +56 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/subscription_conformance_test.rb +72 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_group.rb +24 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification/notification_conformance_test.rb +73 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_verification_group.rb +19 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_creation.rb +63 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_status_operation.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/cs_conformance_test.rb +49 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement/topic_discovery_test.rb +106 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/capability_statement_group.rb +21 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content/empty_conformance_test.rb +63 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/empty_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content/full_resource_conformance_test.rb +68 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/full_resource_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content/id_only_conformance_test.rb +66 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification/id_only_content_group.rb +58 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/event_notification_group.rb +25 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/handshake_conformance_test.rb +67 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat/heartbeat_conformance_test.rb +74 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/handshake_heartbeat_group.rb +19 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation/status_invocation_test.rb +43 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/status_operation_group.rb +15 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection/reject_subscriptions_test.rb +181 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage/subscription_rejection_group.rb +21 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/coverage_group.rb +26 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/workflow_group.rb +27 -0
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server_suite.rb +79 -0
- data/lib/subscriptions_test_kit/tags.rb +10 -0
- data/lib/subscriptions_test_kit/urls.rb +37 -0
- data/lib/subscriptions_test_kit/version.rb +5 -0
- data/lib/subscriptions_test_kit.rb +3 -0
- metadata +194 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
{
|
|
3
|
+
"resourceType" : "Subscription",
|
|
4
|
+
"meta" : {
|
|
5
|
+
"profile" : ["http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription"]
|
|
6
|
+
},
|
|
7
|
+
"status" : "requested",
|
|
8
|
+
"end" : "2020-12-31T12:00:00Z",
|
|
9
|
+
"reason" : "R4 Topic-Based Workflow Subscription for Patient Admission",
|
|
10
|
+
"criteria" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_client/topics/patient-admission",
|
|
11
|
+
"_criteria" : {
|
|
12
|
+
"extension" : [{
|
|
13
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria",
|
|
14
|
+
"valueString" : "Encounter?patient=Patient/123"
|
|
15
|
+
}]
|
|
16
|
+
},
|
|
17
|
+
"channel" : {
|
|
18
|
+
"extension" : [{
|
|
19
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-timeout",
|
|
20
|
+
"valueUnsignedInt" : 60
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-max-count",
|
|
24
|
+
"valuePositiveInt" : 20
|
|
25
|
+
}],
|
|
26
|
+
"type" : "rest-hook",
|
|
27
|
+
"header": ["Authorization: Bearer SAMPLE_TOKEN"],
|
|
28
|
+
"endpoint" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_server/subscription/channel/notification_listener",
|
|
29
|
+
"payload" : "application/json",
|
|
30
|
+
"_payload" : {
|
|
31
|
+
"extension" : [{
|
|
32
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content",
|
|
33
|
+
"valueCode" : "empty"
|
|
34
|
+
}]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
{
|
|
3
|
+
"resourceType" : "Subscription",
|
|
4
|
+
"meta" : {
|
|
5
|
+
"profile" : ["http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription"]
|
|
6
|
+
},
|
|
7
|
+
"status" : "requested",
|
|
8
|
+
"end" : "2020-12-31T12:00:00Z",
|
|
9
|
+
"reason" : "R4 Topic-Based Workflow Subscription for Patient Admission",
|
|
10
|
+
"criteria" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_client/topics/patient-admission",
|
|
11
|
+
"_criteria" : {
|
|
12
|
+
"extension" : [{
|
|
13
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria",
|
|
14
|
+
"valueString" : "Encounter?patient=Patient/123"
|
|
15
|
+
}]
|
|
16
|
+
},
|
|
17
|
+
"channel" : {
|
|
18
|
+
"extension" : [{
|
|
19
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-timeout",
|
|
20
|
+
"valueUnsignedInt" : 60
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-max-count",
|
|
24
|
+
"valuePositiveInt" : 20
|
|
25
|
+
}],
|
|
26
|
+
"type" : "rest-hook",
|
|
27
|
+
"header": ["Authorization: Bearer SAMPLE_TOKEN"],
|
|
28
|
+
"endpoint" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_server/subscription/channel/notification_listener",
|
|
29
|
+
"payload" : "application/json",
|
|
30
|
+
"_payload" : {
|
|
31
|
+
"extension" : [{
|
|
32
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content",
|
|
33
|
+
"valueCode" : "full-resource"
|
|
34
|
+
}]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
"resourceType" : "Subscription",
|
|
5
|
+
"meta" : {
|
|
6
|
+
"profile" : ["http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-subscription"]
|
|
7
|
+
},
|
|
8
|
+
"status" : "requested",
|
|
9
|
+
"end" : "2020-12-31T12:00:00Z",
|
|
10
|
+
"reason" : "R4 Topic-Based Workflow Subscription for Patient Admission",
|
|
11
|
+
"criteria" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_client/topics/patient-admission",
|
|
12
|
+
"_criteria" : {
|
|
13
|
+
"extension" : [{
|
|
14
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria",
|
|
15
|
+
"valueString" : "Encounter?patient=Patient/123"
|
|
16
|
+
}]
|
|
17
|
+
},
|
|
18
|
+
"channel" : {
|
|
19
|
+
"extension" : [{
|
|
20
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-timeout",
|
|
21
|
+
"valueUnsignedInt" : 60
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-max-count",
|
|
25
|
+
"valuePositiveInt" : 20
|
|
26
|
+
}],
|
|
27
|
+
"type" : "rest-hook",
|
|
28
|
+
"header": ["Authorization: Bearer SAMPLE_TOKEN"],
|
|
29
|
+
"endpoint" : "http://inferno.healthit.gov/suites/custom/subscriptions_r5_backport_r4_server/subscription/channel/notification_listener",
|
|
30
|
+
"payload" : "application/json",
|
|
31
|
+
"_payload" : {
|
|
32
|
+
"extension" : [{
|
|
33
|
+
"url" : "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content",
|
|
34
|
+
"valueCode" : "id-only"
|
|
35
|
+
}]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
The Subscriptions R5 Backport IG v1.1.0 FHIR R4 Client Test Suite
|
|
2
|
+
verifies the conformance of
|
|
3
|
+
client systems to the STU 1.1.0 version of the HL7® FHIR®
|
|
4
|
+
[Subscriptions R5 Backport IG](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/).
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
|
|
8
|
+
These tests are a **DRAFT** intended to allow implementers to perform
|
|
9
|
+
preliminary checks of their systems against Subscriptions capabilities backported
|
|
10
|
+
from FHIR R5 to R4 and [provide feedback](https://github.com/inferno-framework/subscriptions-test-kit/issues)
|
|
11
|
+
on the tests. Future versions of these tests may verify other
|
|
12
|
+
requirements and may change the test verification logic.
|
|
13
|
+
|
|
14
|
+
## Test Methodology
|
|
15
|
+
|
|
16
|
+
For these tests Inferno simulates a Subscriptions server application. Inferno will wait for
|
|
17
|
+
the client under test to request a Subscription and then will send notifications
|
|
18
|
+
back to the client based on that Subscription using additional information provided by the tester.
|
|
19
|
+
Using the interactions between Inferno and the client under test, Inferno will verify that
|
|
20
|
+
the client meets the obligations from the implementation guide both on individual interactions
|
|
21
|
+
and in aggregate.
|
|
22
|
+
|
|
23
|
+
Inferno does not implement a real data repository that recognizes resource-level changes
|
|
24
|
+
and so relies on the tester to provide an event notification that Inferno will send back
|
|
25
|
+
to the client under test. Inferno will manipulate this provided notification to generate other
|
|
26
|
+
notifications, such as handshakes and `$status` operation responses, to send
|
|
27
|
+
and respond with as directed by the IG. Inferno will verify that the provided event
|
|
28
|
+
notification is conformant and that it matches the requirements for the Subscription
|
|
29
|
+
sent by the client under test.
|
|
30
|
+
|
|
31
|
+
The content of all Subscription interactions sent by the client,
|
|
32
|
+
as well as tester-provided notifications, will be checked
|
|
33
|
+
for conformance to the Subscriptions IG requirements individually and used in
|
|
34
|
+
aggregate to determine whether required features and functionality are present.
|
|
35
|
+
HL7® FHIR® resources are checked for conformance using the Java validator with
|
|
36
|
+
`tx.fhir.org` as the terminology server.
|
|
37
|
+
|
|
38
|
+
## Running the Tests
|
|
39
|
+
|
|
40
|
+
### Quick Start
|
|
41
|
+
|
|
42
|
+
The following inputs must be provided by the tester at a minimum to execute
|
|
43
|
+
any tests in this suite:
|
|
44
|
+
1. *Access Token*: A `Bearer` token that the client under test will send in the
|
|
45
|
+
`Authorization` header of HTTP requests made against Inferno. Inferno uses the
|
|
46
|
+
value to identify incoming requests that belong to the testing session.
|
|
47
|
+
1. *Notification Bundle*: an `event-notification` conforming to the [R4 Topic-Based
|
|
48
|
+
Subscription Notification Bundle profile](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription-notification-r4.html).
|
|
49
|
+
Inferno uses this as the basis for responses and notifications that it will send
|
|
50
|
+
to the client.
|
|
51
|
+
|
|
52
|
+
All other details needed to interact with the client under test, such as where to send notifications,
|
|
53
|
+
will be determined from the subscription that the client will create. Once the testing start,
|
|
54
|
+
Inferno will wait for a Subscription creation request and then send the relevant handshakes
|
|
55
|
+
and notification requests to the client and verify the interaction.
|
|
56
|
+
|
|
57
|
+
Additional inputs described in the *Additional Configuration Details* section below can enable
|
|
58
|
+
verification of additional content types and some Subscription creation error scenarios.
|
|
59
|
+
|
|
60
|
+
### Sample Execution
|
|
61
|
+
|
|
62
|
+
To try out these tests without a Subscriptions client implementation or performing steps to
|
|
63
|
+
create a Subscription, run them against the Subscriptions server test suite included
|
|
64
|
+
in this test kit. Related presets contain example Subscriptions and event notifications that
|
|
65
|
+
the test kits can use to interact. The server test suite can simulate
|
|
66
|
+
a subscriptions client creating a `rest-hook` Subscription responding to appropriate handshakes
|
|
67
|
+
and notifications.
|
|
68
|
+
|
|
69
|
+
To run the client tests against the server tests:
|
|
70
|
+
1. Start an Inferno session of the Subscriptions Client test suite.
|
|
71
|
+
1. Select one of the *Inferno Subscription R4 Client [content type] Preset* from the Preset dropdown in the
|
|
72
|
+
upper left.
|
|
73
|
+
1. Click the "Run All Tests" button in the upper right and click the "Submit" button in the dialog
|
|
74
|
+
that appears. The simulated server will then be waiting for an interaction.
|
|
75
|
+
1. Start an Inferno session of the Subscriptions Server test suite.
|
|
76
|
+
1. Select the *[content type] Notifications Against The Subscriptions Client Suite* corresponding
|
|
77
|
+
to the content type selected in the client test from the Preset dropdown in the upper left.
|
|
78
|
+
1. Click the "Run All Tests" button in the upper right and click the "Submit" button in the
|
|
79
|
+
dialog that appears. The server tests make a Subscription request will and indicate that
|
|
80
|
+
it is waiting for notifications to be made.
|
|
81
|
+
1. Wait 10-15 seconds while the client session makes requests,
|
|
82
|
+
then click the "Click here" link in the wait dialog to evaluate the notifications.
|
|
83
|
+
1. Back in the client session, click the "click here to complete the test" link
|
|
84
|
+
and respond to the attestation based on the results in the server session and review
|
|
85
|
+
the results.
|
|
86
|
+
|
|
87
|
+
NOTE: Inferno uses the `Bearer` token sent in the `Authorization` HTTP header
|
|
88
|
+
to associate requests with sessions. If multiple concurrent sessions are configured
|
|
89
|
+
to use the same token, they may interfere with each other. To prevent concurrent executors
|
|
90
|
+
of these sample executions from disrupting your session it
|
|
91
|
+
is recommended, but not required, to change all instances of `SAMPLE_TOKEN` in the
|
|
92
|
+
Inferno inputs for both client server suites (including within the Subscription instance body),
|
|
93
|
+
to the same unique value so that the session will not interact with other concurrent users.
|
|
94
|
+
|
|
95
|
+
## Additional Configuration Details
|
|
96
|
+
|
|
97
|
+
The details provided here supplement the documentation of individual fields in the input dialog
|
|
98
|
+
that appears when initiating a test run.
|
|
99
|
+
|
|
100
|
+
### Client Notification Access Token
|
|
101
|
+
|
|
102
|
+
If the client under test needs Inferno to send a specific `Bearer` token in the HTTP `Authorization` header
|
|
103
|
+
when sending notifications and it cannot be specified in the `channel.header` element of the Subscription
|
|
104
|
+
instance that the client sends to Inferno, then a value can be provided here.
|
|
105
|
+
|
|
106
|
+
## Current Limitations
|
|
107
|
+
|
|
108
|
+
This test kit is still in draft form and does not test all of the requirements and features
|
|
109
|
+
described in the Subscriptions IG. You can find information on the requirements
|
|
110
|
+
that the test kit covers and does not cover in the [Requirements
|
|
111
|
+
Coverage](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv)
|
|
112
|
+
CSV document.
|
|
113
|
+
|
|
114
|
+
Specific limitations to highlight include
|
|
115
|
+
- Inferno supports only the `rest-hook` channel type. Support for other channels may be added in the future.
|
|
116
|
+
If there is a channel type that you would like to see verified, please
|
|
117
|
+
[provide feedback](https://github.com/inferno-framework/subscriptions-test-kit/issues) to that effect.
|
|
118
|
+
- Inferno does not test delivery error handling and recovery scenarios, including
|
|
119
|
+
the optional `$events` API and event numbering details.
|
|
120
|
+
- Inferno does not support sending heartbeat notifications.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
The Subscriptions R5 Backport IG v1.1.0 FHIR R4 Server Test Suite
|
|
2
|
+
verifies the conformance of
|
|
3
|
+
server systems to the STU 1.1.0 version of the HL7® FHIR®
|
|
4
|
+
[Subscriptions R5 Backport IG](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/).
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
|
|
8
|
+
These tests are a **DRAFT** intended to allow implementers to perform
|
|
9
|
+
preliminary checks of their systems against Subscriptions capabilities backported
|
|
10
|
+
from FHIR R5 to R4 and [provide feedback](https://github.com/inferno-framework/subscriptions-test-kit/issues)
|
|
11
|
+
on the tests. Future versions of these tests may verify other
|
|
12
|
+
requirements and may change the test verification logic.
|
|
13
|
+
|
|
14
|
+
## Test Methodology
|
|
15
|
+
|
|
16
|
+
For these tests Inferno simulates a Subscriptions client application. Inferno will subscribe
|
|
17
|
+
to certain updates on the server under test and wait for one or more notifications
|
|
18
|
+
indicating changes meeting those criteria. Using the interactions between Inferno and
|
|
19
|
+
the server under test, Inferno will verify that the server under test meets
|
|
20
|
+
the obligations from the implementation guide both on individual interactions
|
|
21
|
+
and in aggregate.
|
|
22
|
+
|
|
23
|
+
Over the course of a test session, Inferno may request multiple Subscriptions to verify
|
|
24
|
+
different features of the IG, e.g., different notification content types. Because the
|
|
25
|
+
choice of what topics and specific features to implement is left to individual servers,
|
|
26
|
+
Inferno does not dictate specific Subscription features or topics. Instead, the
|
|
27
|
+
tester will provide Subsription instances that Inferno will submit, modified lightly if needed,
|
|
28
|
+
e.g., to point to Inferno's notification endpoint, to the server
|
|
29
|
+
as a part of the tests. In order for the tests to pass, the provided Subscription instances
|
|
30
|
+
must themselves be conformant and consistent with the notifications subsequently sent,
|
|
31
|
+
but no other requirements are placed on them,
|
|
32
|
+
except those related to Inferno limitations (see the Current Limitations section below).
|
|
33
|
+
|
|
34
|
+
The content of all interactions sent by the server (responses and notifications),
|
|
35
|
+
as well as tester-provided requests, will be checked
|
|
36
|
+
for conformance to the Subscriptions IG requirements individually and used in
|
|
37
|
+
aggregate to determine whether required features and functionality are present.
|
|
38
|
+
HL7® FHIR® resources are checked for conformance using the Java validator with
|
|
39
|
+
`tx.fhir.org` as the terminology server.
|
|
40
|
+
|
|
41
|
+
## Running the Tests
|
|
42
|
+
|
|
43
|
+
### Quick Start
|
|
44
|
+
|
|
45
|
+
The following inputs must be provided by the tester at a minimum to execute
|
|
46
|
+
any tests in this suite:
|
|
47
|
+
1. *FHIR Server Base URL*: The server's FHIR base URL. Inferno will use this when
|
|
48
|
+
performing Subscription creation requests and other interactions against the server
|
|
49
|
+
under test.
|
|
50
|
+
1. *OAuth Credentials*: Auth credentials for Inferno to use when making requests against the
|
|
51
|
+
server under test. Specifically, Inferno will provide the *Access Token* input as a `Bearer`
|
|
52
|
+
token in the `Authorization` header of HTTP requests. This input is not required if the server
|
|
53
|
+
does not require authorization.
|
|
54
|
+
1. *Notification Access Token*: An access token that the server will send
|
|
55
|
+
as a `Bearer` token in the `Authorization` header of HTTP notifications requests sent to Inferno.
|
|
56
|
+
Inferno uses the value to identify incoming requests that belong to the testing session.
|
|
57
|
+
1. *Workflow Subscription Resource*: A Subscription instance for Inferno to create on the server.
|
|
58
|
+
Inferno will adjust it to be use the `rest-hook` channel and point to its notification endpoint.
|
|
59
|
+
It must be conformant to the [R4/B Topic-Based Subscription profile](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/StructureDefinition-backport-subscription.html).
|
|
60
|
+
|
|
61
|
+
Using these inputs, Inferno will perform a Subscription interaction loop with the server under test:
|
|
62
|
+
creating a Subscription, waiting for notifications, and then verifying the interactions. The tester will
|
|
63
|
+
be responsible for monitoring their system for the new Subscription from Inferno and performing
|
|
64
|
+
an action in their system that triggers an event notification to be sent to Inferno based on
|
|
65
|
+
that Subscription.
|
|
66
|
+
|
|
67
|
+
Additional inputs described in the *Additional Configuration Details* section below can enable
|
|
68
|
+
verification of additional content types and some Subscription creation error scenarios.
|
|
69
|
+
|
|
70
|
+
### Sample Execution
|
|
71
|
+
|
|
72
|
+
To try out these tests without a Subscriptions server implementation or performing steps to
|
|
73
|
+
generate an event notification, run them against the Subscriptions client test suite included
|
|
74
|
+
in this test kit. Related presets contain example Subscriptions and event notifications that
|
|
75
|
+
the test kits can use to interact. The client test suite can run a loop to simulate
|
|
76
|
+
a subscriptions server using the `rest-hook` channel type including responding to a
|
|
77
|
+
Subscription creation request and sending appropriate handshakes and notifications.
|
|
78
|
+
|
|
79
|
+
To run the server tests against the client tests:
|
|
80
|
+
1. Start an Inferno session of the Subscriptions Client test suite.
|
|
81
|
+
1. Select one of the *Inferno Subscription R4 Client [content type] Preset* from the Preset dropdown in the
|
|
82
|
+
upper left.
|
|
83
|
+
1. Click the "Run All Tests" button in the upper right and click the "Submit" button in the dialog
|
|
84
|
+
that appears. The simulated server will then be waiting for an interaction.
|
|
85
|
+
1. Start an Inferno session of the Subscriptions Server test suite.
|
|
86
|
+
1. Select the *[content type] Notifications Against The Subscriptions Client Suite* corresponding
|
|
87
|
+
to the content type selected in the client test from the Preset dropdown in the upper left.
|
|
88
|
+
1. Click the "Run All Tests" button in the upper right and click the "Submit" button in the
|
|
89
|
+
dialog that appears. The server tests make a Subscription request will and indicate that
|
|
90
|
+
it is waiting for notifications to be made.
|
|
91
|
+
1. Wait 10-15 seconds while the client session makes requests,
|
|
92
|
+
then click the "Click here" link in the wait dialog to evaluate the notifications.
|
|
93
|
+
1. Back in the client session, click the "click here to complete the test" link
|
|
94
|
+
and respond to the attestation
|
|
95
|
+
1. Meanwhile, the server tests will have completed and will be ready for review.
|
|
96
|
+
|
|
97
|
+
NOTE: Inferno uses the `Bearer` token sent in the `Authorization` HTTP header
|
|
98
|
+
to associate requests with sessions. If multiple concurrent sessions are configured
|
|
99
|
+
to use the same token, they may interfere with each other. To prevent concurrent executors
|
|
100
|
+
of these sample executions from disrupting your session it
|
|
101
|
+
is recommended, but not required, to change all instances of `SAMPLE_TOKEN` in the
|
|
102
|
+
Inferno inputs for both client server suites (including within the Subscription instance body),
|
|
103
|
+
to the same unique value so that the session will not interact with other concurrent users.
|
|
104
|
+
|
|
105
|
+
## Additional Configuration Details
|
|
106
|
+
|
|
107
|
+
The details provided here supplement the documentation of individual fields in the input dialog
|
|
108
|
+
that appears when initiating a test run.
|
|
109
|
+
|
|
110
|
+
### Subscriptions for other content types
|
|
111
|
+
|
|
112
|
+
To demonstrate the ability of the server under test to serve notifications of multiple different
|
|
113
|
+
content types, additional Subscription instances can be provided in one or more of the
|
|
114
|
+
following inputs:
|
|
115
|
+
- *Empty Notification Subscription Resource*
|
|
116
|
+
- *Id-Only Notification Subscription Resource*
|
|
117
|
+
- *Full-Resource Notification Subscription Resource*
|
|
118
|
+
|
|
119
|
+
When populated, Inferno will perform an interation loop with the server as a part of the
|
|
120
|
+
*Notification Verification* test for the corresponding content type, including requesting that the
|
|
121
|
+
system under test create a Subscription for Inferno, waiting for notifications, and then
|
|
122
|
+
continuing with verification.
|
|
123
|
+
|
|
124
|
+
Additionally, if previously executed during this testing session, Inferno will include
|
|
125
|
+
the Subscription interaction performed as a part of the *Demonstrate the Subscription
|
|
126
|
+
Workflow* group and verify is correctness as a part of the test for the content type
|
|
127
|
+
indicated in that Subscription. Thus, no additional Subscription needs to be provided
|
|
128
|
+
for the content type used in the *Workflow Subscription Resource* input.
|
|
129
|
+
|
|
130
|
+
Examples of Subscriptions that can be used in each of these inputs can be found within the
|
|
131
|
+
test kit source code:
|
|
132
|
+
- [`empty` Notification example](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_empty.json)
|
|
133
|
+
- [`id-only` Notification example](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_id-only.json)
|
|
134
|
+
- [`full-resource` Notification example](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/docs/samples/Subscription_full-resource.json)
|
|
135
|
+
|
|
136
|
+
### Unsupported Subscription creation element values
|
|
137
|
+
|
|
138
|
+
The Subscriptions Backport IG indicates that when accepting new Subscription creation requests
|
|
139
|
+
servers [*SHOULD* check the validity of serveral
|
|
140
|
+
elements](https://hl7.org/fhir/uv/subscriptions-backport/STU1.1/components.html#accepting-subscription-requests).
|
|
141
|
+
Since which values are unsupported are specific to individual implementations, testers that wish
|
|
142
|
+
to verify that the system under test meets these requirements can provide specific values
|
|
143
|
+
in the following input fields:
|
|
144
|
+
|
|
145
|
+
- *Unsupported Subscription Topic*
|
|
146
|
+
- *Unsupported Subscription Filter*
|
|
147
|
+
- *Unsupported Subscription Channel Type*
|
|
148
|
+
- *Unsupported Subscription Channel Endpoint*
|
|
149
|
+
- *Unsupported Subscription Payload Type*
|
|
150
|
+
- *Unsupported Subscription Channel and Payload Combination*
|
|
151
|
+
|
|
152
|
+
In each case, Inferno will take the Subscription provided in the *Workflow Subscription Resource*
|
|
153
|
+
input, modify the corresponding element with the provided value, and expect that either the server
|
|
154
|
+
1. Rejects the Subscription, or
|
|
155
|
+
2. Changes the unsupported element value to something else that is supported
|
|
156
|
+
|
|
157
|
+
## Current Limitations
|
|
158
|
+
|
|
159
|
+
This test kit is still in draft form and does not test all of the requirements and features
|
|
160
|
+
described in the Subscriptions IG. You can find information on the requirements
|
|
161
|
+
that the test kit covers and does not cover in the [Requirements
|
|
162
|
+
Coverage](https://github.com/inferno-framework/subscriptions-test-kit/blob/main/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv)
|
|
163
|
+
CSV document.
|
|
164
|
+
|
|
165
|
+
Specific limitations to highlight include
|
|
166
|
+
- Inferno supports only the `rest-hook` channel type. Support for other channels may be added in the future.
|
|
167
|
+
If there is a channel type that you would like to see verified, please
|
|
168
|
+
[provide feedback](https://github.com/inferno-framework/subscriptions-test-kit/issues) to that effect.
|
|
169
|
+
- Inferno does not test delivery error handling and recovery scenarios, including
|
|
170
|
+
the optional `$events` API and event numbering details.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require_relative '../tags'
|
|
2
|
+
require_relative '../jobs/send_subscription_notifications'
|
|
3
|
+
require_relative '../suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils'
|
|
4
|
+
|
|
5
|
+
module SubscriptionsTestKit
|
|
6
|
+
class SubscriptionCreateEndpoint < Inferno::DSL::SuiteEndpoint
|
|
7
|
+
include SubscriptionsR5BackportR4Client::SubscriptionSimulationUtils
|
|
8
|
+
|
|
9
|
+
def test_run_identifier
|
|
10
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def make_response
|
|
14
|
+
response.format = :json
|
|
15
|
+
response.status = 400
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
subscription = FHIR.from_contents(request.body.string)
|
|
19
|
+
rescue StandardError
|
|
20
|
+
response.body = operation_outcome('error', 'invalid', 'No recognized R4 Subscription in request body').to_json
|
|
21
|
+
return
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
verification_outcome = verify_subscription(subscription)
|
|
25
|
+
if verification_outcome.present?
|
|
26
|
+
response.body = verification_outcome.to_json
|
|
27
|
+
return
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Deny subscription if one already created
|
|
31
|
+
requests = requests_repo.tagged_requests(test_run.test_session_id, tags)
|
|
32
|
+
existing_subscription_request = requests.find { |r| r.status == 201 }
|
|
33
|
+
if existing_subscription_request.present?
|
|
34
|
+
subscription_hash = JSON.parse(existing_subscription_request.response_body)
|
|
35
|
+
error_text = 'Inferno only supports one subscription per test run. Subscription already created with '\
|
|
36
|
+
"ID #{subscription_hash['id']}"
|
|
37
|
+
response.body = operation_outcome('error', 'business-rule', error_text).to_json
|
|
38
|
+
return
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Form response
|
|
42
|
+
notification_json = notification_bundle_input(result)
|
|
43
|
+
subscription_id = SecureRandom.uuid
|
|
44
|
+
# We have to manipulate the raw hash so that we don't lose the _payload primitive extension
|
|
45
|
+
subscription_hash = JSON.parse(request.body.string).merge('id' => subscription_id, 'status' => 'requested')
|
|
46
|
+
subscription_hash['channel']['payload'] = actual_mime_type(subscription)
|
|
47
|
+
response.status = 201
|
|
48
|
+
response.body = subscription_hash.to_json
|
|
49
|
+
|
|
50
|
+
# Kick off notification job
|
|
51
|
+
subscription_url = "#{request.url}/#{subscription_id}"
|
|
52
|
+
client_endpoint = subscription.channel.endpoint
|
|
53
|
+
bearer_token = client_access_token_input(result)
|
|
54
|
+
test_suite_base_url = request.url.chomp('/').chomp(FHIR_SUBSCRIPTION_PATH)
|
|
55
|
+
Inferno::Jobs.perform(Jobs::SendSubscriptionNotifications, test_run.id, test_run.test_session_id, result.id,
|
|
56
|
+
subscription_id, subscription_url, client_endpoint, bearer_token, notification_json,
|
|
57
|
+
test_run_identifier, test_suite_base_url)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def tags
|
|
61
|
+
[SUBSCRIPTION_CREATE_TAG]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def verify_subscription(subscription)
|
|
65
|
+
unless subscription.is_a? FHIR::Subscription
|
|
66
|
+
return operation_outcome('error', 'invalid', 'No recognized R4 Subscription in request body')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
unless subscription.channel&.type == 'rest-hook'
|
|
70
|
+
return operation_outcome('error', 'business-rule', 'channel.type must be rest-hook')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
unless valid_url?(subscription.channel&.endpoint)
|
|
74
|
+
return operation_outcome('error', 'value', 'channel.endpoint is not recognized as a conformant URL')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
heartbeat_period = subscription.channel&.extension&.find do |e|
|
|
78
|
+
e.url == 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-heartbeat-period'
|
|
79
|
+
end
|
|
80
|
+
operation_outcome('error', 'not-supported', 'heartbeatPeriod is not supported') unless heartbeat_period.nil?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def valid_url?(url)
|
|
84
|
+
uri = URI.parse(url)
|
|
85
|
+
%w[http https].include?(uri.scheme)
|
|
86
|
+
rescue URI::InvalidURIError
|
|
87
|
+
false
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative '../tags'
|
|
2
|
+
require_relative '../suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils'
|
|
3
|
+
|
|
4
|
+
module SubscriptionsTestKit
|
|
5
|
+
class SubscriptionReadEndpoint < Inferno::DSL::SuiteEndpoint
|
|
6
|
+
include SubscriptionsR5BackportR4Client::SubscriptionSimulationUtils
|
|
7
|
+
|
|
8
|
+
def test_run_identifier
|
|
9
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def make_response
|
|
13
|
+
response.format = :json
|
|
14
|
+
subscription_id = request.params[:id]
|
|
15
|
+
|
|
16
|
+
subscription = find_subscription(test_run.test_session_id)
|
|
17
|
+
|
|
18
|
+
if subscription.present? && subscription.id == subscription_id
|
|
19
|
+
status_code = determine_subscription_status_code(subscription_id)
|
|
20
|
+
response.body = subscription.source_hash.merge('status' => status_code).to_json
|
|
21
|
+
else
|
|
22
|
+
response.status = 404
|
|
23
|
+
response.body = operation_outcome('error', 'not-found',
|
|
24
|
+
"No subscription exists with ID #{subscription_id}").to_json
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tags
|
|
29
|
+
[SUBSCRIPTION_READ_TAG]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require_relative '../tags'
|
|
2
|
+
module SubscriptionsTestKit
|
|
3
|
+
class SubscriptionRestHookEndpoint < Inferno::DSL::SuiteEndpoint
|
|
4
|
+
def test_run_identifier
|
|
5
|
+
bearer_token = extract_bearer_token(request)
|
|
6
|
+
"notification #{bearer_token}"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Header expected to be a bearer token of the form "Bearer <token>"
|
|
10
|
+
def extract_bearer_token(request)
|
|
11
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def notification_extract_subscription_status(request)
|
|
15
|
+
notification_bundle_entries = request.params[:entry]
|
|
16
|
+
return if notification_bundle_entries.blank?
|
|
17
|
+
|
|
18
|
+
subscription_status_entry = notification_bundle_entries.find do |entry|
|
|
19
|
+
entry[:resource][:resourceType] == 'Parameters'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
subscription_status_entry[:resource]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def extract_notification_type(request)
|
|
26
|
+
subscription_status = notification_extract_subscription_status(request)
|
|
27
|
+
return unless subscription_status.present?
|
|
28
|
+
|
|
29
|
+
notification_type = subscription_status[:parameter].find { |param| param[:name] == 'type' }
|
|
30
|
+
notification_type[:valueCode]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def subscription_status_extract_parameter(parameters, param_name)
|
|
34
|
+
return unless parameters.present?
|
|
35
|
+
|
|
36
|
+
parameters.find do |entry|
|
|
37
|
+
entry[:name] == param_name
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def notification_extract_subscription_id(request)
|
|
42
|
+
subscription_status = notification_extract_subscription_status(request)
|
|
43
|
+
return unless subscription_status.present?
|
|
44
|
+
|
|
45
|
+
subscription_param = subscription_status_extract_parameter(subscription_status[:parameter], 'subscription')
|
|
46
|
+
return unless subscription_param.present?
|
|
47
|
+
|
|
48
|
+
subscription_reference = subscription_param[:valueReference][:reference]
|
|
49
|
+
subscription_reference.split('/').last
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def make_response
|
|
53
|
+
response.status = 200
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def tags
|
|
57
|
+
notification_type = extract_notification_type(request)
|
|
58
|
+
subscription_id = notification_extract_subscription_id(request)
|
|
59
|
+
[notification_type, subscription_id]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def update_result
|
|
63
|
+
results_repo.update(result.id, result: 'pass') unless test.config.options[:accepts_multiple_requests]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require_relative '../tags'
|
|
2
|
+
require_relative '../suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils'
|
|
3
|
+
|
|
4
|
+
module SubscriptionsTestKit
|
|
5
|
+
class SubscriptionStatusEndpoint < Inferno::DSL::SuiteEndpoint
|
|
6
|
+
include SubscriptionsR5BackportR4Client::SubscriptionSimulationUtils
|
|
7
|
+
|
|
8
|
+
def test_run_identifier
|
|
9
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def make_response
|
|
13
|
+
response.format = :json
|
|
14
|
+
subscription = find_subscription(test_run.test_session_id)
|
|
15
|
+
|
|
16
|
+
unless subscription.present?
|
|
17
|
+
not_found
|
|
18
|
+
return
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
subscription_id = request.params[:id]
|
|
22
|
+
|
|
23
|
+
# Handle resource-level status params
|
|
24
|
+
unless subscription_id.present?
|
|
25
|
+
begin
|
|
26
|
+
params = FHIR.from_contents(request.body.string)
|
|
27
|
+
rescue StandardError
|
|
28
|
+
response.status = 400
|
|
29
|
+
response.body = operation_outcome('error', 'invalid', 'Invalid Parameters in request body').to_json
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
id_params = params&.parameter&.filter { |p| p.name == 'id' }
|
|
34
|
+
|
|
35
|
+
if id_params&.any? && id_params&.none? { |p| p.valueString == subscription.id }
|
|
36
|
+
not_found
|
|
37
|
+
return
|
|
38
|
+
else
|
|
39
|
+
status_params = params&.parameter&.filter { |p| p.name == 'status' }
|
|
40
|
+
subscription_status = determine_subscription_status_code(subscription.id)
|
|
41
|
+
if status_params&.any? && status_params.none? { |p| p.valueString == subscription_status }
|
|
42
|
+
not_found
|
|
43
|
+
return
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
notification_json = notification_bundle_input(result)
|
|
49
|
+
subscription_url = "#{base_subscription_url}/#{subscription.id}"
|
|
50
|
+
status_code = determine_subscription_status_code(subscription_id)
|
|
51
|
+
event_count = determine_event_count(test_run.test_session_id)
|
|
52
|
+
response.status = 200
|
|
53
|
+
response.body = derive_status_bundle(notification_json, subscription_url, status_code, event_count,
|
|
54
|
+
request.url).to_json
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def tags
|
|
58
|
+
[SUBSCRIPTION_STATUS_TAG]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def not_found
|
|
62
|
+
response.status = 404
|
|
63
|
+
response.body = operation_outcome('error', 'not-found').to_json
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def base_subscription_url
|
|
67
|
+
request.url.sub(%r{(#{Regexp.escape(FHIR_SUBSCRIPTION_PATH)}).*}, '\1')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|