davinci_pas_test_kit 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/pas_server_subscription_creation_against_pas_client.json +32 -0
  3. data/lib/davinci_pas_test_kit/certs/InfernoCA.key +52 -0
  4. data/lib/davinci_pas_test_kit/certs/InfernoCA.pem +35 -0
  5. data/lib/davinci_pas_test_kit/certs/TestKit.pem +32 -0
  6. data/lib/davinci_pas_test_kit/certs/TestKitPrivateKey.key +28 -0
  7. data/lib/davinci_pas_test_kit/client_suite.rb +141 -100
  8. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_other_display_test.rb +46 -0
  9. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_smart_display_test.rb +37 -0
  10. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_udap_display_test.rb +37 -0
  11. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/other_auth_attest_test.rb +36 -0
  12. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_test.rb +24 -10
  13. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_test.rb +23 -10
  14. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_must_support_test.rb +21 -9
  15. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_request_bundle_validation_test.rb +4 -0
  16. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_pended_submit_test.rb +30 -14
  17. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_request_bundle_validation_test.rb +6 -0
  18. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_response_attest.rb +4 -9
  19. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_submit_must_support_test.rb +24 -9
  20. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_subscription_create_test.rb +26 -13
  21. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_subscription_pas_conformance_test.rb +6 -24
  22. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_inquiry_error_test.rb +1 -0
  23. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_submission_error_test.rb +3 -0
  24. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/notification/pas_subscription_notification_test.rb +24 -20
  25. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_approval_group.rb +6 -4
  26. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_auth_smart_group.rb +32 -0
  27. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_auth_udap_group.rb +31 -0
  28. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_denial_group.rb +10 -4
  29. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_must_support_group.rb +29 -0
  30. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_options.rb +25 -0
  31. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_pended_group.rb +11 -4
  32. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_registration_group.rb +63 -0
  33. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_subscription_setup_group.rb +23 -0
  34. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_workflows_group.rb +21 -0
  35. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_server_subscription_input_conformance.rb +35 -0
  36. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_server_subscription_setup.rb +43 -0
  37. data/lib/davinci_pas_test_kit/descriptions.rb +10 -0
  38. data/lib/davinci_pas_test_kit/docs/client_suite_description_v201.md +203 -79
  39. data/lib/davinci_pas_test_kit/docs/demo/PAS Client Suite Demonstration.postman_collection.json +246 -0
  40. data/lib/davinci_pas_test_kit/docs/server_suite_description_v201.md +21 -10
  41. data/lib/davinci_pas_test_kit/endpoints/claim_endpoint.rb +13 -1
  42. data/lib/davinci_pas_test_kit/endpoints/subscription_create_endpoint.rb +13 -1
  43. data/lib/davinci_pas_test_kit/endpoints/subscription_status_endpoint.rb +10 -1
  44. data/lib/davinci_pas_test_kit/endpoints/token_endpoint.rb +29 -15
  45. data/lib/davinci_pas_test_kit/generated/v2.0.1/beneficiary/metadata.yml +2 -1
  46. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/claim_operation_test.rb +1 -1
  47. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim/metadata.yml +28 -17
  48. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/claim_inquiry_operation_test.rb +1 -2
  49. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/client_inquire_request_claim_inquiry_must_support_test.rb +4 -1
  50. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/metadata.yml +7 -1
  51. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_inquiry/server_inquire_request_claim_inquiry_must_support_test.rb +3 -1
  52. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/client_submit_request_claim_update_must_support_test.rb +9 -3
  53. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/metadata.yml +28 -17
  54. data/lib/davinci_pas_test_kit/generated/v2.0.1/claim_update/server_submit_request_claim_update_must_support_test.rb +9 -3
  55. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/metadata.yml +6 -0
  56. data/lib/davinci_pas_test_kit/generated/v2.0.1/claiminquiryresponse/server_inquire_response_claiminquiryresponse_must_support_test.rb +1 -0
  57. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/metadata.yml +8 -0
  58. data/lib/davinci_pas_test_kit/generated/v2.0.1/claimresponse/server_submit_response_claimresponse_must_support_test.rb +1 -0
  59. data/lib/davinci_pas_test_kit/generated/v2.0.1/communication_request/metadata.yml +4 -0
  60. data/lib/davinci_pas_test_kit/generated/v2.0.1/coverage/metadata.yml +11 -5
  61. data/lib/davinci_pas_test_kit/generated/v2.0.1/device_request/metadata.yml +2 -0
  62. data/lib/davinci_pas_test_kit/generated/v2.0.1/encounter/metadata.yml +6 -0
  63. data/lib/davinci_pas_test_kit/generated/v2.0.1/insurer/metadata.yml +4 -2
  64. data/lib/davinci_pas_test_kit/generated/v2.0.1/medication_request/metadata.yml +2 -0
  65. data/lib/davinci_pas_test_kit/generated/v2.0.1/metadata.yml +153 -53
  66. data/lib/davinci_pas_test_kit/generated/v2.0.1/nutrition_order/metadata.yml +2 -0
  67. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/metadata.yml +2 -1
  68. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_request_bundle/server_pas_inquiry_request_bundle_validation_test.rb +0 -2
  69. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/metadata.yml +2 -1
  70. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_inquiry_response_bundle/server_pas_inquiry_response_bundle_validation_test.rb +2 -3
  71. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/metadata.yml +2 -1
  72. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_request_bundle/server_pas_request_bundle_validation_test.rb +0 -2
  73. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/metadata.yml +2 -1
  74. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_response_bundle/server_pas_response_bundle_validation_test.rb +2 -3
  75. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_approval_use_case_group.rb +0 -1
  76. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_denial_use_case_group.rb +0 -1
  77. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_must_support_use_case_group.rb +3 -0
  78. data/lib/davinci_pas_test_kit/generated/v2.0.1/pas_server_pended_use_case_group.rb +10 -3
  79. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner/metadata.yml +2 -1
  80. data/lib/davinci_pas_test_kit/generated/v2.0.1/practitioner_role/metadata.yml +4 -0
  81. data/lib/davinci_pas_test_kit/generated/v2.0.1/requestor/metadata.yml +4 -2
  82. data/lib/davinci_pas_test_kit/generated/v2.0.1/server_suite.rb +8 -5
  83. data/lib/davinci_pas_test_kit/generated/v2.0.1/service_request/metadata.yml +2 -0
  84. data/lib/davinci_pas_test_kit/generated/v2.0.1/task/metadata.yml +4 -0
  85. data/lib/davinci_pas_test_kit/generator/group_generator.rb +20 -4
  86. data/lib/davinci_pas_test_kit/generator/group_metadata_extractor.rb +2 -2
  87. data/lib/davinci_pas_test_kit/generator/ig_resources.rb +4 -0
  88. data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +14 -3
  89. data/lib/davinci_pas_test_kit/generator/operation_test_generator.rb +16 -3
  90. data/lib/davinci_pas_test_kit/generator/templates/group.rb.erb +10 -3
  91. data/lib/davinci_pas_test_kit/generator/templates/must_support.rb.erb +3 -0
  92. data/lib/davinci_pas_test_kit/generator/templates/operation.rb.erb +4 -1
  93. data/lib/davinci_pas_test_kit/generator/templates/suite.rb.erb +8 -5
  94. data/lib/davinci_pas_test_kit/generator/templates/validation.rb.erb +5 -4
  95. data/lib/davinci_pas_test_kit/generator/validation_test_generator.rb +12 -1
  96. data/lib/davinci_pas_test_kit/must_support_test.rb +2 -202
  97. data/lib/davinci_pas_test_kit/pas_bundle_validation.rb +4 -4
  98. data/lib/davinci_pas_test_kit/pas_subscription_verification.rb +30 -0
  99. data/lib/davinci_pas_test_kit/requirements/davinci-pas-test-kit_out_of_scope_requirements.csv +11 -0
  100. data/lib/davinci_pas_test_kit/requirements/davinci-pas-test-kit_requirements.csv +214 -0
  101. data/lib/davinci_pas_test_kit/requirements/generated/davinci-pas-test-kit_requirements_coverage.csv +214 -0
  102. data/lib/davinci_pas_test_kit/session_identification.rb +45 -0
  103. data/lib/davinci_pas_test_kit/tags.rb +1 -0
  104. data/lib/davinci_pas_test_kit/urls.rb +61 -9
  105. data/lib/davinci_pas_test_kit/version.rb +2 -2
  106. data/lib/davinci_pas_test_kit.rb +1 -0
  107. data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +22 -0
  108. data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +284 -0
  109. data/lib/requirements_config.yaml +17 -0
  110. metadata +62 -10
  111. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_request_test.rb +0 -31
  112. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_validation_test.rb +0 -18
  113. data/lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_authentication_group.rb +0 -49
  114. data/lib/davinci_pas_test_kit/generator/must_support_metadata_extractor.rb +0 -327
@@ -0,0 +1,22 @@
1
+ module Inferno
2
+ module DSL
3
+ # This module contains the DSL for defining child entities in the test
4
+ # definition framework.
5
+ module Runnable
6
+ # Set/Get the IDs of requirements verifed by this runnable
7
+ # Set with [] to clear the list
8
+ #
9
+ # @param requirements [Array<String>]
10
+ # @return [Array<String>] the requirement IDs
11
+ def verifies_requirements(*requirement_ids)
12
+ if requirement_ids.empty?
13
+ @requirement_ids || []
14
+ elsif requirement_ids == [[]]
15
+ @requirement_ids = []
16
+ else
17
+ @requirement_ids = requirement_ids
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,284 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ require 'yaml'
5
+ require_relative '../ext/inferno_core/runnable'
6
+
7
+ module InfernoRequirementsTools
8
+ module Tasks
9
+ # This class manages the mapping of test kit tests to requirements that they verify
10
+ # and creates a CSV file with the tests that cover each requirement.
11
+ # It expects a CSV file in the repo at `lib/[test kit id]/requirements/[test kit id]_requirements.csv`
12
+ # that serves as the source of the requirement set for the test kit. The requirements in
13
+ # this files are identified by a requirement set and an id and tests, groups, and suites
14
+ # within in the test kit can claim that they verify a requirement by including a reference
15
+ # to that requirementin the form <requirement set>@<id> in their `verifies_requirements` field.
16
+ # Requirements that are out of scope can be listed in a companion file
17
+ # `lib/[test kit id]/requirements/[test kit id]_out_of_scope_requirements.csv`.
18
+ #
19
+ # The `run` method generates a CSV file at
20
+ # `lib/[test kit id]/requirements/generated/[test kit id]_requirements_coverage.csv``.
21
+ # This file will be identical to the input spreadsheet, plus an additional column which holds a comma separated
22
+ # list of inferno test IDs that test each requirement. These test IDs are Inferno short form IDs that represent the
23
+ # position of the test within its group and suite. For example, the fifth test in the second group will have an ID
24
+ # of 2.05. This ID is also shown in the Inferno web UI.
25
+ #
26
+ # The `run_check` method will check whether the previously generated file is up-to-date.
27
+ class RequirementsCoverage
28
+ VERSION = '0.2.0' # update when making meaningful changes to this method for tracking used versions
29
+ CONFIG = YAML.load_file(File.join('lib', 'requirements_config.yaml'))
30
+
31
+ TEST_KIT_ID = CONFIG['test_kit_id']
32
+ TEST_SUITES = CONFIG['suites'].map do |test_suite|
33
+ Object.const_get(test_suite['class_name'])
34
+ end
35
+
36
+ SUITE_ID_TO_ACTOR_MAP = CONFIG['suites'].each_with_object({}) do |test_suite, hash|
37
+ hash[test_suite['id']] = test_suite['suite_actor']
38
+ end
39
+
40
+ # Derivative constants
41
+ TEST_KIT_CODE_FOLDER = TEST_KIT_ID
42
+ DASHERIZED_TEST_KIT_ID = TEST_KIT_ID.gsub('_', '-')
43
+ INPUT_HEADERS = [
44
+ 'Req Set',
45
+ 'ID',
46
+ 'URL',
47
+ 'Requirement',
48
+ 'Conformance',
49
+ 'Actor',
50
+ 'Sub-Requirement(s)',
51
+ 'Conditionality'
52
+ ].freeze
53
+ SHORT_ID_HEADER = 'Short ID(s)'
54
+ FULL_ID_HEADER = 'Full ID(s)'
55
+ INPUT_FILE_NAME = "#{DASHERIZED_TEST_KIT_ID}_requirements.csv".freeze
56
+ INPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', INPUT_FILE_NAME).freeze
57
+ NOT_TESTED_FILE_NAME = "#{DASHERIZED_TEST_KIT_ID}_out_of_scope_requirements.csv".freeze
58
+ NOT_TESTED_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', NOT_TESTED_FILE_NAME).freeze
59
+ OUTPUT_HEADERS = INPUT_HEADERS + TEST_SUITES.flat_map do |suite|
60
+ ["#{suite.title} #{SHORT_ID_HEADER}", "#{suite.title} #{FULL_ID_HEADER}"]
61
+ end
62
+ OUTPUT_FILE_NAME = "#{DASHERIZED_TEST_KIT_ID}_requirements_coverage.csv".freeze
63
+ OUTPUT_FILE_DIRECTORY = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', 'generated')
64
+ OUTPUT_FILE = File.join(OUTPUT_FILE_DIRECTORY, OUTPUT_FILE_NAME).freeze
65
+
66
+ def input_rows
67
+ @input_rows ||=
68
+ CSV.parse(File.open(INPUT_FILE, 'r:bom|utf-8'), headers: true).map do |row|
69
+ row.to_h.slice(*INPUT_HEADERS)
70
+ end
71
+ end
72
+
73
+ def not_tested_requirements_map
74
+ @not_tested_requirements_map ||= load_not_tested_requirements
75
+ end
76
+
77
+ def load_not_tested_requirements
78
+ return {} unless File.exist?(NOT_TESTED_FILE)
79
+
80
+ not_tested_requirements = {}
81
+ CSV.parse(File.open(NOT_TESTED_FILE, 'r:bom|utf-8'), headers: true).each do |row|
82
+ row_hash = row.to_h
83
+ not_tested_requirements["#{row_hash['Req Set']}@#{row_hash['ID']}"] = row_hash
84
+ end
85
+
86
+ not_tested_requirements
87
+ end
88
+
89
+ # Of the form:
90
+ # {
91
+ # 'req-id-1': [
92
+ # { short_id: 'short-id-1', full_id: 'long-id-1', suite_id: 'suite-id-1' },
93
+ # { short_id: 'short-id-2', full_id: 'long-id-2', suite_id: 'suite-id-2' }
94
+ # ],
95
+ # 'req-id-2': [{ short_id: 'short-id-3', full_id: 'long-id-3', suite_id: 'suite-id-3' }],
96
+ # ...
97
+ # }
98
+ def inferno_requirements_map
99
+ @inferno_requirements_map ||= TEST_SUITES.each_with_object({}) do |suite, requirements_map|
100
+ serialize_requirements(suite, 'suite', suite.id, requirements_map)
101
+ suite.groups.each do |group|
102
+ map_group_requirements(group, suite.id, requirements_map)
103
+ end
104
+ end
105
+ end
106
+
107
+ def new_csv
108
+ @new_csv ||=
109
+ CSV.generate(+"\xEF\xBB\xBF") do |csv|
110
+ csv << OUTPUT_HEADERS
111
+ input_rows.each do |row| # NOTE: use row order from source file
112
+ next if row['Conformance'] == 'DEPRECATED' # filter out deprecated rows
113
+
114
+ TEST_SUITES.each do |suite|
115
+ suite_actor = SUITE_ID_TO_ACTOR_MAP[suite.id]
116
+ if row['Actor']&.include?(suite_actor)
117
+ add_suite_tests_for_row(row, suite)
118
+ else
119
+ row["#{suite.title} #{SHORT_ID_HEADER}"] = 'NA'
120
+ row["#{suite.title} #{FULL_ID_HEADER}"] = 'NA'
121
+ end
122
+ end
123
+ csv << row.values
124
+ end
125
+ end
126
+ end
127
+
128
+ def add_suite_tests_for_row(row, suite)
129
+ set_and_req_id = "#{row['Req Set']}@#{row['ID']}"
130
+ items = get_items_for_requirement(set_and_req_id, suite)
131
+ short_ids = items[0]
132
+ full_ids = items[1]
133
+ if short_ids.blank? && not_tested_requirements_map.key?(set_and_req_id)
134
+ row["#{suite.title} #{SHORT_ID_HEADER}"] = 'Not Tested'
135
+ row["#{suite.title} #{FULL_ID_HEADER}"] = 'Not Tested'
136
+ else
137
+ row["#{suite.title} #{SHORT_ID_HEADER}"] = short_ids&.join(', ')
138
+ row["#{suite.title} #{FULL_ID_HEADER}"] = full_ids&.join(', ')
139
+ end
140
+ end
141
+
142
+ def get_items_for_requirement(set_and_req_id, suite)
143
+ suite_requirement_items = inferno_requirements_map[set_and_req_id]&.filter do |item|
144
+ item[:suite_id] == suite.id
145
+ end
146
+ [
147
+ suite_requirement_items&.map { |item| item[:short_id] },
148
+ suite_requirement_items&.map { |item| item[:full_id] }
149
+ ]
150
+ end
151
+
152
+ def input_requirement_ids
153
+ @input_requirement_ids ||= input_rows.map { |row| "#{row['Req Set']}@#{row['ID']}" }
154
+ end
155
+
156
+ # The requirements present in Inferno that aren't in the input spreadsheet
157
+ def unmatched_requirements_map
158
+ @unmatched_requirements_map ||= inferno_requirements_map.except(*input_requirement_ids)
159
+ end
160
+
161
+ def old_csv
162
+ @old_csv ||= File.read(OUTPUT_FILE)
163
+ end
164
+
165
+ def run
166
+ unless File.exist?(INPUT_FILE)
167
+ puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage generation..."
168
+ exit(1)
169
+ end
170
+
171
+ if unmatched_requirements_map.any?
172
+ puts "WARNING: The following requirements indicated in the test kit are not present in #{INPUT_FILE_NAME}"
173
+ output_requirements_map_table(unmatched_requirements_map)
174
+ end
175
+
176
+ if File.exist?(OUTPUT_FILE)
177
+ if old_csv == new_csv
178
+ puts "'#{OUTPUT_FILE_NAME}' file is up to date."
179
+ return
180
+ else
181
+ puts 'Requirements coverage has changed.'
182
+ end
183
+ else
184
+ puts "No existing #{OUTPUT_FILE_NAME}."
185
+ end
186
+
187
+ puts "Writing to file #{OUTPUT_FILE}..."
188
+ FileUtils.mkdir_p(OUTPUT_FILE_DIRECTORY)
189
+ File.write(OUTPUT_FILE, new_csv)
190
+ puts 'Done.'
191
+ end
192
+
193
+ def run_check
194
+ unless File.exist?(INPUT_FILE)
195
+ puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage check..."
196
+ exit(1)
197
+ end
198
+
199
+ if unmatched_requirements_map.any?
200
+ puts "The following requirements indicated in the test kit are not present in #{INPUT_FILE_NAME}"
201
+ output_requirements_map_table(unmatched_requirements_map)
202
+ end
203
+
204
+ if File.exist?(OUTPUT_FILE)
205
+ if old_csv == new_csv
206
+ puts "'#{OUTPUT_FILE_NAME}' file is up to date."
207
+ return unless unmatched_requirements_map.any?
208
+ else
209
+ puts <<~MESSAGE
210
+ #{OUTPUT_FILE_NAME} file is out of date.
211
+ To regenerate the file, run:
212
+
213
+ bundle exec rake requirements:generate_coverage
214
+
215
+ MESSAGE
216
+ end
217
+ else
218
+ puts <<~MESSAGE
219
+ No existing #{OUTPUT_FILE_NAME} file.
220
+ To generate the file, run:
221
+
222
+ bundle exec rake requirements:generate_coverage
223
+
224
+ MESSAGE
225
+ end
226
+
227
+ puts 'Check failed.'
228
+ exit(1)
229
+ end
230
+
231
+ def map_group_requirements(group, suite_id, requirements_map)
232
+ serialize_requirements(group, group.short_id, suite_id, requirements_map)
233
+ group.tests&.each { |test| serialize_requirements(test, test.short_id, suite_id, requirements_map) }
234
+ group.groups&.each { |subgroup| map_group_requirements(subgroup, suite_id, requirements_map) }
235
+ end
236
+
237
+ def serialize_requirements(runnable, short_id, suite_id, requirements_map)
238
+ runnable.verifies_requirements&.each do |requirement_id|
239
+ requirement_id_string = requirement_id.to_s
240
+
241
+ requirements_map[requirement_id_string] ||= []
242
+ requirements_map[requirement_id_string] << { short_id:, full_id: runnable.id, suite_id: }
243
+ end
244
+ end
245
+
246
+ # Output the requirements in the map like so:
247
+ #
248
+ # requirement_id | short_id | full_id
249
+ # ---------------+------------+----------
250
+ # req-id-1 | short-id-1 | full-id-1
251
+ # req-id-2 | short-id-2 | full-id-2
252
+ #
253
+ def output_requirements_map_table(requirements_map)
254
+ headers = %w[requirement_id short_id full_id]
255
+ col_widths = headers.map(&:length)
256
+ col_widths[0] = [col_widths[0], requirements_map.keys.map(&:length).max].max
257
+ col_widths[1] = ([col_widths[1]] + requirements_map.values.flatten.map { |item| item[:short_id].length }).max
258
+ col_widths[2] = ([col_widths[2]] + requirements_map.values.flatten.map { |item| item[:full_id].length }).max
259
+ col_widths.map { |width| width + 3 }
260
+
261
+ puts [
262
+ headers[0].ljust(col_widths[0]),
263
+ headers[1].ljust(col_widths[1]),
264
+ headers[2].ljust(col_widths[2])
265
+ ].join(' | ')
266
+ puts col_widths.map { |width| '-' * width }.join('-+-')
267
+ output_requirements_map_table_contents(requirements_map, col_widths)
268
+ puts
269
+ end
270
+
271
+ def output_requirements_map_table_contents(requirements_map, col_widths)
272
+ requirements_map.each do |requirement_id, runnables|
273
+ runnables.each do |runnable|
274
+ puts [
275
+ requirement_id.ljust(col_widths[0]),
276
+ runnable[:short_id].ljust(col_widths[1]),
277
+ runnable[:full_id].ljust(col_widths[2])
278
+ ].join(' | ')
279
+ end
280
+ end
281
+ end
282
+ end
283
+ end
284
+ end
@@ -0,0 +1,17 @@
1
+ test_kit_id: davinci_pas_test_kit
2
+
3
+ suites:
4
+ - id: davinci_pas_client_suite_v201
5
+ class_name: DaVinciPASTestKit::DaVinciPASV201::ClientSuite
6
+ suite_actor: Client
7
+ - id: davinci_pas_server_suite_v201
8
+ class_name: DaVinciPASTestKit::DaVinciPASV201::ServerSuite
9
+ suite_actor: Server
10
+
11
+ requirement_sets:
12
+ - id: hl7.fhir.us.davinci-pas_2.0.1
13
+ folder: Prior Auth Support (PAS)
14
+ requirements: All
15
+ actor_map:
16
+ - {spec: Client, test_kit: Client}
17
+ - {spec: Server, test_kit: Server}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: davinci_pas_test_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inferno Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-07 00:00:00.000000000 Z
11
+ date: 2025-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -16,28 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.4
19
+ version: 0.6.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.4
26
+ version: 0.6.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: smart_app_launch_test_kit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.6.2
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: subscriptions_test_kit
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: 0.10.0
47
+ version: 0.11.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.11.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: udap_security_test_kit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.11.4
34
62
  type: :runtime
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
- version: 0.10.0
68
+ version: 0.11.4
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: database_cleaner-sequel
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -104,9 +132,18 @@ files:
104
132
  - LICENSE
105
133
  - config/presets/pas_client_example.json
106
134
  - config/presets/pas_ri.json
135
+ - config/presets/pas_server_subscription_creation_against_pas_client.json
107
136
  - lib/davinci_pas_test_kit.rb
137
+ - lib/davinci_pas_test_kit/certs/InfernoCA.key
138
+ - lib/davinci_pas_test_kit/certs/InfernoCA.pem
139
+ - lib/davinci_pas_test_kit/certs/TestKit.pem
140
+ - lib/davinci_pas_test_kit/certs/TestKitPrivateKey.key
108
141
  - lib/davinci_pas_test_kit/client_suite.rb
109
142
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/claim_response_decision/pas_claim_response_decision_test.rb
143
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_other_display_test.rb
144
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_smart_display_test.rb
145
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/configuration_udap_display_test.rb
146
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_registration/other_auth_attest_test.rb
110
147
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_approval_submit_test.rb
111
148
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_denial_submit_test.rb
112
149
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_inquire_must_support_test.rb
@@ -119,8 +156,6 @@ files:
119
156
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_submit_must_support_test.rb
120
157
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_subscription_create_test.rb
121
158
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_subscription_pas_conformance_test.rb
122
- - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_request_test.rb
123
- - lib/davinci_pas_test_kit/custom_groups/v2.0.1/client_tests/pas_client_token_validation_test.rb
124
159
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/nonconformant_pas_bundle.json
125
160
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_inquiry_error_test.rb
126
161
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/error_tests/pas_submission_error_test.rb
@@ -132,12 +167,22 @@ files:
132
167
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/must_support/service_request_metadata.yml
133
168
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/notification/pas_subscription_notification_test.rb
134
169
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_approval_group.rb
135
- - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_authentication_group.rb
170
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_auth_smart_group.rb
171
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_auth_udap_group.rb
136
172
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_denial_group.rb
173
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_must_support_group.rb
174
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_options.rb
137
175
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_pended_group.rb
176
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_registration_group.rb
177
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_subscription_setup_group.rb
178
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_client_workflows_group.rb
138
179
  - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_error_group.rb
180
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_server_subscription_input_conformance.rb
181
+ - lib/davinci_pas_test_kit/custom_groups/v2.0.1/pas_server_subscription_setup.rb
182
+ - lib/davinci_pas_test_kit/descriptions.rb
139
183
  - lib/davinci_pas_test_kit/docs/PAS Requirements Interpretation.xlsx
140
184
  - lib/davinci_pas_test_kit/docs/client_suite_description_v201.md
185
+ - lib/davinci_pas_test_kit/docs/demo/PAS Client Suite Demonstration.postman_collection.json
141
186
  - lib/davinci_pas_test_kit/docs/server_suite_description_v201.md
142
187
  - lib/davinci_pas_test_kit/endpoints/claim_endpoint.rb
143
188
  - lib/davinci_pas_test_kit/endpoints/subscription_create_endpoint.rb
@@ -254,7 +299,6 @@ files:
254
299
  - lib/davinci_pas_test_kit/generator/ig_metadata_extractor.rb
255
300
  - lib/davinci_pas_test_kit/generator/ig_resources.rb
256
301
  - lib/davinci_pas_test_kit/generator/must_support_check_profiles.rb
257
- - lib/davinci_pas_test_kit/generator/must_support_metadata_extractor.rb
258
302
  - lib/davinci_pas_test_kit/generator/must_support_test_generator.rb
259
303
  - lib/davinci_pas_test_kit/generator/naming.rb
260
304
  - lib/davinci_pas_test_kit/generator/operation_test_generator.rb
@@ -276,13 +320,21 @@ files:
276
320
  - lib/davinci_pas_test_kit/metadata.rb
277
321
  - lib/davinci_pas_test_kit/must_support_test.rb
278
322
  - lib/davinci_pas_test_kit/pas_bundle_validation.rb
323
+ - lib/davinci_pas_test_kit/pas_subscription_verification.rb
324
+ - lib/davinci_pas_test_kit/requirements/davinci-pas-test-kit_out_of_scope_requirements.csv
325
+ - lib/davinci_pas_test_kit/requirements/davinci-pas-test-kit_requirements.csv
326
+ - lib/davinci_pas_test_kit/requirements/generated/davinci-pas-test-kit_requirements_coverage.csv
279
327
  - lib/davinci_pas_test_kit/response_generator.rb
328
+ - lib/davinci_pas_test_kit/session_identification.rb
280
329
  - lib/davinci_pas_test_kit/tags.rb
281
330
  - lib/davinci_pas_test_kit/urls.rb
282
331
  - lib/davinci_pas_test_kit/user_input_response.rb
283
332
  - lib/davinci_pas_test_kit/validation_test.rb
284
333
  - lib/davinci_pas_test_kit/validator_suppressions.rb
285
334
  - lib/davinci_pas_test_kit/version.rb
335
+ - lib/inferno_requirements_tools/ext/inferno_core/runnable.rb
336
+ - lib/inferno_requirements_tools/tasks/requirements_coverage.rb
337
+ - lib/requirements_config.yaml
286
338
  homepage: https://github.com/inferno-framework/davinci-pas-test-kit
287
339
  licenses:
288
340
  - Apache-2.0
@@ -1,31 +0,0 @@
1
- require_relative '../../../urls'
2
-
3
- module DaVinciPASTestKit
4
- module DaVinciPASV201
5
- class PASClientTokenRequestTest < Inferno::Test
6
- include URLs
7
-
8
- id :pas_client_v201_token_request_test
9
- title 'Client makes token request'
10
- description %(
11
- Inferno will wait for the client to make a token request.
12
- )
13
- input :client_id,
14
- title: 'Client ID',
15
- description: %(
16
- Client ID that the client will use to request an access token.
17
- )
18
-
19
- run do
20
- wait(
21
- identifier: client_id,
22
- message: %(
23
- Submit your token request with client id `#{client_id}` to
24
-
25
- `#{token_url}`
26
- )
27
- )
28
- end
29
- end
30
- end
31
- end
@@ -1,18 +0,0 @@
1
- require_relative '../../../tags'
2
-
3
- module DaVinciPASTestKit
4
- module DaVinciPASV201
5
- class PASClientTokentRequestTest < Inferno::Test
6
- id :pas_client_v201_token_validation_test
7
- title 'Client token request is valid'
8
- description 'Inferno will verify that an access token was successfully returned to the client under test.'
9
- output :access_token
10
-
11
- run do
12
- load_tagged_requests(AUTH_TAG)
13
- skip_if requests.empty?, 'No token requests were received'
14
- output access_token: JSON.parse(requests.last.response_body)['access_token']
15
- end
16
- end
17
- end
18
- end
@@ -1,49 +0,0 @@
1
- require_relative 'client_tests/pas_client_token_request_test'
2
- require_relative 'client_tests/pas_client_token_validation_test'
3
-
4
- module DaVinciPASTestKit
5
- module DaVinciPASV201
6
- class PASClientAuthenticationGroup < Inferno::TestGroup
7
- id :pas_client_v201_authentication_group
8
- title 'Demonstrate Authorization'
9
- description %(
10
- This group of tests allows Inferno to act as a OAuth server
11
- and provide access tokens for the client under test to use
12
- when making further requests.
13
-
14
- The tests assume that the authentication workflow starts
15
- after client registration. Upon clicking the "Run Tests" button
16
- in the upper right, Inferno will ask for an input for the `client_id`
17
- that was used for client registration, or manually configured in the
18
- client.
19
-
20
- Before submitting a token request, click the "Submit" button at the
21
- bottom of the dialog to confirm the `client_id` that Inferno will
22
- watch for.
23
-
24
- Finally, make a valid token request that includes the specified `client_id`
25
- to indicated token endpoint. This should be a POST of an `x-www-form-encoded`
26
- body containing keys for `grant_type` with a value of `client_credentials` and
27
- `client_id` with a value of the configured `client_id` value. For example, if
28
- the `client_id` value was `123`, then the body of the request would be:
29
-
30
- ```grant_type=client_credentials&client_id=123```
31
-
32
- The response json object will include an `access_token` key, for example:
33
-
34
- ```{"access_token":"97e792038d922bc3cf388b608e45c318","token_type":"bearer","expires_in":300}```
35
-
36
- The value of the `access_token` key (`97e792038d922bc3cf388b608e45c318` in the example)
37
- must be sent with every subsequent request to Inferno during this session in
38
- the "Authorization" HTTP header with prefix "Bearer: ". In this example, the
39
- Authorization HTTP header would have value:
40
-
41
- ```Bearer 97e792038d922bc3cf388b608e45c318```
42
- )
43
- run_as_group
44
-
45
- test from: :pas_client_v201_token_request_test
46
- test from: :pas_client_v201_token_validation_test
47
- end
48
- end
49
- end