subscriptions_test_kit 0.9.2 → 0.9.3
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 +4 -4
- data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +51 -50
- data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +22 -19
- data/lib/subscriptions_test_kit/common/notification_conformance_verification.rb +4 -2
- data/lib/subscriptions_test_kit/endpoints/subscription_create_endpoint.rb +7 -3
- data/lib/subscriptions_test_kit/endpoints/subscription_status_endpoint.rb +16 -11
- data/lib/subscriptions_test_kit/requirements/generated/subscriptions-test-kit_requirements_coverage.csv +50 -50
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/common/subscription_simulation_utils.rb +9 -6
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_payload_verification_test.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/notification_input_verification_test.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/processing_attestation_test.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification/subscription_verification_test.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/conformance_verification_group.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_test.rb +14 -11
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/event_notification_verification_test.rb +6 -5
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification/handshake_notification_verification_test.rb +5 -5
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client/workflow/interaction_verification_group.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_client_suite.rb +5 -3
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/capability_statement/cs_conformance_test.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/capability_statement/topic_discovery_test.rb +3 -3
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/capability_statement_group.rb +3 -3
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/creation_response_conformance_test.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction/subscription_conformance_test.rb +10 -9
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/interaction_group.rb +3 -3
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/common/subscription_status_operation.rb +3 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification/empty_content_group.rb +3 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification/full_resource_content/full_resource_conformance_test.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification/full_resource_content_group.rb +3 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification/id_only_content/id_only_conformance_test.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification/id_only_content_group.rb +3 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/event_notification_group.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/handshake_heartbeat/handshake_conformance_test.rb +7 -6
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/handshake_heartbeat/heartbeat_conformance_test.rb +4 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/status_operation/status_invocation_test.rb +2 -2
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/status_operation_group.rb +1 -1
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server/subscription_rejection/reject_subscriptions_test.rb +29 -25
- data/lib/subscriptions_test_kit/suites/subscriptions_r5_backport_r4_server_suite.rb +3 -2
- data/lib/subscriptions_test_kit/version.rb +1 -3
- metadata +4 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad5fae1148d468463f60e61a0e7c273b90eac5294b1c8d19b588288d3d53ca77
|
4
|
+
data.tar.gz: 62507f2c4a5cc9e39c1906bbb10032d1baa00b8ec33055762016c5ce2d22722c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bad58bc3cdcb1c451bcb28f5dfbe8a5492e5cc8fff49b00f99d35d93588cec7936feeedee3c24984d6c1090ade8f92b35da4c89d83fd8036586f539cd0296ad7
|
7
|
+
data.tar.gz: f26d5875e051b95b24dabc7f45cdba4b9bda8631f76f022aa1e753569e89be8fd264b052ac9662855023c2f685ad9b4ac5473732b8d7538b32d7a2db819e2e6b
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'csv'
|
4
4
|
require 'roo'
|
5
5
|
|
6
6
|
module InfernoRequirementsTools
|
@@ -52,22 +52,26 @@ module InfernoRequirementsTools
|
|
52
52
|
PLANNED_NOT_TESTED_OUTPUT_FILE =
|
53
53
|
File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', PLANNED_NOT_TESTED_OUTPUT_FILE_NAME).freeze
|
54
54
|
|
55
|
-
def
|
56
|
-
@
|
55
|
+
def available_input_worksheets
|
56
|
+
@available_input_worksheets ||= Dir.glob(File.join(@input_directory, '*.xlsx')).reject { |f| f.include?('~$') }
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
# Of the form:
|
60
|
+
# {
|
61
|
+
# req_set_id_1: [row1, row2, row 3, ...],
|
62
|
+
# req_set_id_2: [row1, row2, row 3, ...]
|
63
|
+
# }
|
64
|
+
def input_requirement_sets
|
65
|
+
@input_requirement_sets ||= INPUT_SETS.each_with_object({}) do |req_set_id, hash|
|
66
|
+
req_set_file = available_input_worksheets.find { |worksheet_file| worksheet_file.include?(req_set_id) }
|
67
|
+
|
68
|
+
hash[req_set_id] =
|
69
|
+
unless req_set_file.nil?
|
70
|
+
CSV.parse(Roo::Spreadsheet.open(req_set_file).sheet('Requirements').to_csv,
|
71
|
+
headers: true).map do |row|
|
72
|
+
row.to_h.slice(*INPUT_HEADERS)
|
73
|
+
end
|
74
|
+
end
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
@@ -76,12 +80,11 @@ module InfernoRequirementsTools
|
|
76
80
|
CSV.generate(+"\xEF\xBB\xBF") do |csv| # start with an unnecessary BOM to make viewing in excel easier
|
77
81
|
csv << REQUIREMENTS_OUTPUT_HEADERS
|
78
82
|
|
79
|
-
|
80
|
-
input_rows
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
csv << REQUIREMENTS_OUTPUT_HEADERS.map { |header| row.key?(header) ? row[header] : row["#{header}*"]}
|
83
|
+
input_requirement_sets.each do |req_set_id, input_rows|
|
84
|
+
input_rows.each do |input_row| # NOTE: use row order from source file
|
85
|
+
csv << REQUIREMENTS_OUTPUT_HEADERS.map do |header|
|
86
|
+
header == 'Req Set' ? req_set_id : input_row[header] || input_row["#{header}*"]
|
87
|
+
end
|
85
88
|
end
|
86
89
|
end
|
87
90
|
end
|
@@ -96,19 +99,13 @@ module InfernoRequirementsTools
|
|
96
99
|
CSV.generate(+"\xEF\xBB\xBF") do |csv| # start with an unnecessary BOM to make viewing in excel easier
|
97
100
|
csv << PLANNED_NOT_TESTED_OUTPUT_HEADERS
|
98
101
|
|
99
|
-
|
100
|
-
input_rows
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
csv << [
|
107
|
-
req_set_id,
|
108
|
-
row['ID*'],
|
109
|
-
not_verifiable ? 'Not Verifiable' : 'Not Tested',
|
110
|
-
not_verifiable ? row['Verifiability Details'] : row['Planning To Test Details']
|
111
|
-
]
|
102
|
+
input_requirement_sets.each do |req_set_id, input_rows|
|
103
|
+
input_rows.each do |row|
|
104
|
+
if spreadsheet_value_falsy?(row['Verifiable?'])
|
105
|
+
csv << [req_set_id, row['ID*'], 'Not Verifiable', row['Verifiability Details']]
|
106
|
+
elsif spreadsheet_value_falsy?(row['Planning To Test?'])
|
107
|
+
csv << [req_set_id, row['ID*'], 'Not Tested', row['Planning To Test Details']]
|
108
|
+
end
|
112
109
|
end
|
113
110
|
end
|
114
111
|
end
|
@@ -118,22 +115,9 @@ module InfernoRequirementsTools
|
|
118
115
|
@old_planned_not_tested_csv ||= File.read(PLANNED_NOT_TESTED_OUTPUT_FILE)
|
119
116
|
end
|
120
117
|
|
121
|
-
def check_for_req_set_files(input_directory)
|
122
|
-
available_worksheets = Dir.glob(File.join(input_directory, '*.xlsx')).reject { |f| f.include?('~$') }
|
123
|
-
|
124
|
-
INPUT_SETS.each do |req_set_id|
|
125
|
-
req_set_file = available_worksheets&.find { |worksheet_file| worksheet_file.include?(req_set_id) }
|
126
|
-
|
127
|
-
if req_set_file&.empty?
|
128
|
-
puts "Could not find input file for set #{req_set_id} in directory #{input_directory}. Aborting requirements collection..."
|
129
|
-
exit(1)
|
130
|
-
end
|
131
|
-
input_file_map[req_set_id] = req_set_file
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
118
|
def run(input_directory)
|
136
|
-
|
119
|
+
@input_directory = input_directory
|
120
|
+
check_presence_of_input_files
|
137
121
|
|
138
122
|
update_requirements =
|
139
123
|
if File.exist?(REQUIREMENTS_OUTPUT_FILE)
|
@@ -177,7 +161,8 @@ module InfernoRequirementsTools
|
|
177
161
|
end
|
178
162
|
|
179
163
|
def run_check(input_directory)
|
180
|
-
|
164
|
+
@input_directory = input_directory
|
165
|
+
check_presence_of_input_files
|
181
166
|
|
182
167
|
requirements_ok =
|
183
168
|
if File.exist?(REQUIREMENTS_OUTPUT_FILE)
|
@@ -217,6 +202,22 @@ module InfernoRequirementsTools
|
|
217
202
|
MESSAGE
|
218
203
|
exit(1)
|
219
204
|
end
|
205
|
+
|
206
|
+
def check_presence_of_input_files
|
207
|
+
input_requirement_sets.each do |req_set_id, rows|
|
208
|
+
next unless rows.nil?
|
209
|
+
|
210
|
+
puts %(
|
211
|
+
Could not find input file for set #{req_set_id} in directory #{input_directory}. Aborting requirements
|
212
|
+
collection..."
|
213
|
+
)
|
214
|
+
exit(1)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def spreadsheet_value_falsy?(str)
|
219
|
+
str&.downcase == 'no' || str&.downcase == 'false'
|
220
|
+
end
|
220
221
|
end
|
221
222
|
end
|
222
223
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'csv'
|
4
4
|
require_relative '../ext/inferno_core/runnable'
|
5
5
|
|
6
6
|
module InfernoRequirementsTools
|
@@ -51,12 +51,15 @@ module InfernoRequirementsTools
|
|
51
51
|
INPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', INPUT_FILE_NAME).freeze
|
52
52
|
NOT_TESTED_FILE_NAME = "#{TEST_KIT_ID}_out_of_scope_requirements.csv".freeze
|
53
53
|
NOT_TESTED_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', NOT_TESTED_FILE_NAME).freeze
|
54
|
+
OUTPUT_HEADERS = INPUT_HEADERS + TEST_SUITES.flat_map do |suite|
|
55
|
+
["#{suite.title} #{SHORT_ID_HEADER}", "#{suite.title} #{FULL_ID_HEADER}"]
|
56
|
+
end
|
54
57
|
OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements_coverage.csv".freeze
|
55
58
|
OUTPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', 'generated', OUTPUT_FILE_NAME).freeze
|
56
59
|
|
57
60
|
def input_rows
|
58
61
|
@input_rows ||=
|
59
|
-
CSV.parse(File.open(INPUT_FILE,
|
62
|
+
CSV.parse(File.open(INPUT_FILE, 'r:bom|utf-8'), headers: true).map do |row|
|
60
63
|
row.to_h.slice(*INPUT_HEADERS)
|
61
64
|
end
|
62
65
|
end
|
@@ -66,12 +69,12 @@ module InfernoRequirementsTools
|
|
66
69
|
end
|
67
70
|
|
68
71
|
def load_not_tested_requirements
|
69
|
-
return {} unless File.
|
72
|
+
return {} unless File.exist?(NOT_TESTED_FILE)
|
70
73
|
|
71
74
|
not_tested_requirements = {}
|
72
|
-
CSV.parse(File.open(NOT_TESTED_FILE,
|
75
|
+
CSV.parse(File.open(NOT_TESTED_FILE, 'r:bom|utf-8'), headers: true).each do |row|
|
73
76
|
row_hash = row.to_h
|
74
|
-
not_tested_requirements[
|
77
|
+
not_tested_requirements["#{row_hash['Req Set']}@#{row_hash['ID']}"] = row_hash
|
75
78
|
end
|
76
79
|
|
77
80
|
not_tested_requirements
|
@@ -95,26 +98,24 @@ module InfernoRequirementsTools
|
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
101
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
98
102
|
def new_csv
|
99
103
|
@new_csv ||=
|
100
104
|
CSV.generate(+"\xEF\xBB\xBF") do |csv|
|
101
|
-
|
102
|
-
|
103
|
-
headers << "#{suite.title} #{FULL_ID_HEADER}"
|
104
|
-
end
|
105
|
-
|
106
|
-
csv << output_headers
|
107
|
-
input_rows.each do |row| # note: use row order from source file
|
105
|
+
csv << OUTPUT_HEADERS
|
106
|
+
input_rows.each do |row| # NOTE: use row order from source file
|
108
107
|
next if row['Conformance'] == 'DEPRECATED' # filter out deprecated rows
|
109
|
-
|
108
|
+
|
110
109
|
TEST_SUITES.each do |suite|
|
111
110
|
suite_actor = SUITE_ID_TO_ACTOR_MAP[suite.id]
|
112
|
-
if
|
111
|
+
if row['Actor']&.include?(suite_actor)
|
113
112
|
set_and_req_id = "#{row['Req Set']}@#{row['ID']}"
|
114
|
-
suite_requirement_items = inferno_requirements_map[set_and_req_id]&.filter
|
113
|
+
suite_requirement_items = inferno_requirements_map[set_and_req_id]&.filter do |item|
|
114
|
+
item[:suite_id] == suite.id
|
115
|
+
end
|
115
116
|
short_ids = suite_requirement_items&.map { |item| item[:short_id] }
|
116
117
|
full_ids = suite_requirement_items&.map { |item| item[:full_id] }
|
117
|
-
if short_ids.blank? && not_tested_requirements_map.
|
118
|
+
if short_ids.blank? && not_tested_requirements_map.key?(set_and_req_id)
|
118
119
|
row["#{suite.title} #{SHORT_ID_HEADER}"] = 'Not Tested'
|
119
120
|
row["#{suite.title} #{FULL_ID_HEADER}"] = 'Not Tested'
|
120
121
|
else
|
@@ -131,6 +132,7 @@ module InfernoRequirementsTools
|
|
131
132
|
end
|
132
133
|
end
|
133
134
|
end
|
135
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
134
136
|
|
135
137
|
def input_requirement_ids
|
136
138
|
@input_requirement_ids ||= input_rows.map { |row| "#{row['Req Set']}@#{row['ID']}" }
|
@@ -138,9 +140,7 @@ module InfernoRequirementsTools
|
|
138
140
|
|
139
141
|
# The requirements present in Inferno that aren't in the input spreadsheet
|
140
142
|
def unmatched_requirements_map
|
141
|
-
@unmatched_requirements_map ||= inferno_requirements_map.
|
142
|
-
!input_requirement_ids.include?(requirement_id)
|
143
|
-
end
|
143
|
+
@unmatched_requirements_map ||= inferno_requirements_map.except(*input_requirement_ids)
|
144
144
|
end
|
145
145
|
|
146
146
|
def old_csv
|
@@ -233,6 +233,8 @@ module InfernoRequirementsTools
|
|
233
233
|
# ---------------+------------+----------
|
234
234
|
# req-id-1 | short-id-1 | full-id-1
|
235
235
|
# req-id-2 | short-id-2 | full-id-2
|
236
|
+
#
|
237
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
236
238
|
def output_requirements_map_table(requirements_map)
|
237
239
|
headers = %w[requirement_id short_id full_id]
|
238
240
|
col_widths = headers.map(&:length)
|
@@ -258,6 +260,7 @@ module InfernoRequirementsTools
|
|
258
260
|
end
|
259
261
|
puts
|
260
262
|
end
|
263
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
261
264
|
end
|
262
265
|
end
|
263
266
|
end
|
@@ -32,9 +32,11 @@ module SubscriptionsTestKit
|
|
32
32
|
|
33
33
|
unless subscription_status_entry.request.present? &&
|
34
34
|
(
|
35
|
-
subscription_id
|
36
|
-
subscription_status_entry.request.url.end_with?("Subscription/#{subscription_id}/$status")
|
35
|
+
if subscription_id
|
36
|
+
subscription_status_entry.request.url.end_with?("Subscription/#{subscription_id}/$status")
|
37
|
+
else
|
37
38
|
subscription_status_entry.request.url.match?(%r{Subscription/[^/]+/\$status\z})
|
39
|
+
end
|
38
40
|
)
|
39
41
|
|
40
42
|
add_message('error',
|
@@ -32,7 +32,7 @@ module SubscriptionsTestKit
|
|
32
32
|
existing_subscription_request = requests.find { |r| r.status == 201 }
|
33
33
|
if existing_subscription_request.present?
|
34
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 '\
|
35
|
+
error_text = 'Inferno only supports one subscription per test run. Subscription already created with ' \
|
36
36
|
"ID #{subscription_hash['id']}"
|
37
37
|
response.body = operation_outcome('error', 'business-rule', error_text).to_json
|
38
38
|
return
|
@@ -74,10 +74,14 @@ module SubscriptionsTestKit
|
|
74
74
|
return operation_outcome('error', 'value', 'channel.endpoint is not recognized as a conformant URL')
|
75
75
|
end
|
76
76
|
|
77
|
-
heartbeat_period = subscription
|
77
|
+
heartbeat_period = find_heartbeat_period(subscription)
|
78
|
+
operation_outcome('error', 'not-supported', 'heartbeatPeriod is not supported') unless heartbeat_period.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_heartbeat_period(subscription)
|
82
|
+
subscription&.channel&.extension&.find do |e|
|
78
83
|
e.url == 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-heartbeat-period'
|
79
84
|
end
|
80
|
-
operation_outcome('error', 'not-supported', 'heartbeatPeriod is not supported') unless heartbeat_period.nil?
|
81
85
|
end
|
82
86
|
|
83
87
|
def valid_url?(url)
|
@@ -30,18 +30,9 @@ module SubscriptionsTestKit
|
|
30
30
|
return
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
if id_params&.any? && id_params&.none? { |p| p.valueString == subscription.id }
|
33
|
+
unless subscription_params_match?(params)
|
36
34
|
not_found
|
37
35
|
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
36
|
end
|
46
37
|
end
|
47
38
|
|
@@ -54,6 +45,16 @@ module SubscriptionsTestKit
|
|
54
45
|
request.url).to_json
|
55
46
|
end
|
56
47
|
|
48
|
+
def subscription_params_match?(params)
|
49
|
+
id_params = find_params(params, 'id')
|
50
|
+
|
51
|
+
return false if id_params&.any? && id_params&.none? { |p| p.valueString == subscription.id }
|
52
|
+
|
53
|
+
status_params = find_params(params, 'status')
|
54
|
+
subscription_status = determine_subscription_status_code(subscription.id)
|
55
|
+
status_params.nil? || status_params.none? || status_params.any { p.valueString == subscription_status }
|
56
|
+
end
|
57
|
+
|
57
58
|
def tags
|
58
59
|
[SUBSCRIPTION_STATUS_TAG]
|
59
60
|
end
|
@@ -63,8 +64,12 @@ module SubscriptionsTestKit
|
|
63
64
|
response.body = operation_outcome('error', 'not-found').to_json
|
64
65
|
end
|
65
66
|
|
67
|
+
def find_params(params, name)
|
68
|
+
params&.parameter&.filter { |p| p.name == name }
|
69
|
+
end
|
70
|
+
|
66
71
|
def base_subscription_url
|
67
|
-
request.url.sub(
|
72
|
+
request.url.sub(/(#{Regexp.escape(FHIR_SUBSCRIPTION_PATH)}).*/, '\1')
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|