carin_for_blue_button_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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb +227 -0
  3. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/client_claims_data_attestation_test.rb +32 -0
  4. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb +25 -0
  5. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb +26 -0
  6. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb +25 -0
  7. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb +28 -0
  8. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb +25 -0
  9. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb +27 -0
  10. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb +26 -0
  11. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb +24 -0
  12. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb +25 -0
  13. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb +25 -0
  14. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/client_validation_test.rb +93 -0
  15. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/collection.rb +19 -0
  16. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/next_page_endpoint.rb +24 -0
  17. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_api_endpoint.rb +74 -0
  18. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_id_endpoint.rb +24 -0
  19. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb +24 -0
  20. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb +76 -0
  21. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json +535 -0
  22. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_operation_outcome_resource.json +16 -0
  23. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb +190 -0
  24. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb +45 -0
  25. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb +71 -0
  26. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb +47 -0
  27. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb +71 -0
  28. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb +47 -0
  29. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb +43 -0
  30. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb +7 -0
  31. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb +57 -0
  32. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/user_input_response.rb +32 -0
  33. data/lib/carin_for_blue_button_test_kit/version.rb +1 -1
  34. data/lib/carin_for_blue_button_test_kit.rb +1 -0
  35. data/lib/inferno_requirements_tools/tasks/{map_requirements.rb → requirements_coverage.rb} +91 -60
  36. metadata +34 -4
  37. data/lib/inferno_requirements_tools/tasks/collect_requirements.rb +0 -196
@@ -1,46 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'CSV'
4
- require 'roo'
3
+ require 'csv'
4
+ require 'yaml'
5
5
  require_relative '../ext/inferno_core/runnable'
6
6
 
7
7
  module InfernoRequirementsTools
8
8
  module Tasks
9
- # This class manages the mapping of IG requirements to test kit tests.
10
- # It expects a CSV file in the repo at lib/carin_for_blue_button_test_kit/requirements/Requirements.csv
11
- # This file must have a column with the header 'ID' which holds user-designated IDs for each requirement.
12
- # These requirement IDs must map to the IDs specified in the test kit using `verifies_requirements`
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`.
13
18
  #
14
- # The `run` method generates a CSV file at lib/carin_for_blue_button_test_kit/requirements/Requirements_Coverage.csv.
19
+ # The `run` method generates a CSV file at
20
+ # `lib/[test kit id]/requirements/generated/[test kit id]_requirements_coverage.csv``.
15
21
  # This file will be identical to the input spreadsheet, plus an additional column which holds a comma separated
16
22
  # list of inferno test IDs that test each requirement. These test IDs are Inferno short form IDs that represent the
17
23
  # position of the test within its group and suite. For example, the fifth test in the second group will have an ID
18
24
  # of 2.05. This ID is also shown in the Inferno web UI.
19
- # The output file is also sorted by requirement ID.
20
25
  #
21
26
  # The `run_check` method will check whether the previously generated file is up-to-date.
22
- class MapRequirements
23
- # Update these constants based on the test kit.
24
- TEST_KIT_ID = 'carin-for-blue-button-test-kit'
25
- TEST_SUITES = [CarinForBlueButtonTestKit::CARIN4BBV200::C4BBTestSuite].freeze # list of suite classes
26
- SUITE_ID_TO_ACTOR_MAP = {
27
- 'c4bb_v200' => 'Health Plan'
28
- }.freeze
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
29
39
 
30
40
  # Derivative constants
31
- TEST_KIT_CODE_FOLDER = TEST_KIT_ID.gsub('-', '_')
32
- INPUT_HEADERS = ['Req Set', 'ID', 'URL', 'Requirement', 'Conformance', 'Actor', 'Sub-Requirement(s)',
33
- 'Conditionality'].freeze
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
34
53
  SHORT_ID_HEADER = 'Short ID(s)'
35
54
  FULL_ID_HEADER = 'Full ID(s)'
36
- INPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements.csv"
55
+ INPUT_FILE_NAME = "#{DASHERIZED_TEST_KIT_ID}_requirements.csv".freeze
37
56
  INPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', INPUT_FILE_NAME).freeze
38
- NOT_TESTED_FILE_NAME = "#{TEST_KIT_ID}_out_of_scope_requirements.csv"
57
+ NOT_TESTED_FILE_NAME = "#{DASHERIZED_TEST_KIT_ID}_out_of_scope_requirements.csv".freeze
39
58
  NOT_TESTED_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', NOT_TESTED_FILE_NAME).freeze
40
- OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements_coverage.csv"
41
- OUTPUT_FILE_DIRECTORY = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements', 'generated').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')
42
64
  OUTPUT_FILE = File.join(OUTPUT_FILE_DIRECTORY, OUTPUT_FILE_NAME).freeze
43
- BOM = "\xEF\xBB\xBF"
44
65
 
45
66
  def input_rows
46
67
  @input_rows ||=
@@ -59,7 +80,7 @@ module InfernoRequirementsTools
59
80
  not_tested_requirements = {}
60
81
  CSV.parse(File.open(NOT_TESTED_FILE, 'r:bom|utf-8'), headers: true).each do |row|
61
82
  row_hash = row.to_h
62
- not_tested_requirements["#{row_hash['Req Set']}##{row_hash['ID']}"] = row_hash
83
+ not_tested_requirements["#{row_hash['Req Set']}@#{row_hash['ID']}"] = row_hash
63
84
  end
64
85
 
65
86
  not_tested_requirements
@@ -85,51 +106,56 @@ module InfernoRequirementsTools
85
106
 
86
107
  def new_csv
87
108
  @new_csv ||=
88
- CSV.generate do |csv|
89
- output_headers = TEST_SUITES.each_with_object(INPUT_HEADERS.dup) do |suite, headers|
90
- headers << "#{suite.title} #{SHORT_ID_HEADER}"
91
- headers << "#{suite.title} #{FULL_ID_HEADER}"
92
- end
93
-
94
- csv << output_headers
109
+ CSV.generate(+"\xEF\xBB\xBF") do |csv|
110
+ csv << OUTPUT_HEADERS
95
111
  input_rows.each do |row| # NOTE: use row order from source file
96
- row_actor = row['Actor']
112
+ next if row['Conformance'] == 'DEPRECATED' # filter out deprecated rows
113
+
97
114
  TEST_SUITES.each do |suite|
98
115
  suite_actor = SUITE_ID_TO_ACTOR_MAP[suite.id]
99
- if row_actor&.include?(suite_actor)
100
- set_and_req_id = "#{row['Req Set']}##{row['ID']}"
101
- suite_requirement_items = inferno_requirements_map[set_and_req_id]&.filter do |item|
102
- item[:suite_id] == suite.id
103
- end
104
- short_ids = suite_requirement_items&.map { |item| item[:short_id] }
105
- full_ids = suite_requirement_items&.map { |item| item[:full_id] }
106
- if short_ids.blank? && not_tested_requirements_map.has_key?(set_and_req_id)
107
- row["#{suite.title} #{SHORT_ID_HEADER}"] = 'Not Tested'
108
- row["#{suite.title} #{FULL_ID_HEADER}"] = 'Not Tested'
109
- else
110
- row["#{suite.title} #{SHORT_ID_HEADER}"] = short_ids&.join(', ')
111
- row["#{suite.title} #{FULL_ID_HEADER}"] = full_ids&.join(', ')
112
- end
116
+ if row['Actor']&.include?(suite_actor)
117
+ add_suite_tests_for_row(row, suite)
113
118
  else
114
119
  row["#{suite.title} #{SHORT_ID_HEADER}"] = 'NA'
115
120
  row["#{suite.title} #{FULL_ID_HEADER}"] = 'NA'
116
121
  end
117
122
  end
118
-
119
123
  csv << row.values
120
124
  end
121
125
  end
122
126
  end
123
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
+
124
152
  def input_requirement_ids
125
- @input_requirement_ids ||= input_rows.map { |row| "#{row['Req Set']}##{row['ID']}" }
153
+ @input_requirement_ids ||= input_rows.map { |row| "#{row['Req Set']}@#{row['ID']}" }
126
154
  end
127
155
 
128
156
  # The requirements present in Inferno that aren't in the input spreadsheet
129
157
  def unmatched_requirements_map
130
- @unmatched_requirements_map ||= inferno_requirements_map.filter do |requirement_id, _|
131
- !input_requirement_ids.include?(requirement_id)
132
- end
158
+ @unmatched_requirements_map ||= inferno_requirements_map.except(*input_requirement_ids)
133
159
  end
134
160
 
135
161
  def old_csv
@@ -138,7 +164,7 @@ module InfernoRequirementsTools
138
164
 
139
165
  def run
140
166
  unless File.exist?(INPUT_FILE)
141
- puts "Could not find input file: #{INPUT_FILE}. Aborting requirements mapping..."
167
+ puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage generation..."
142
168
  exit(1)
143
169
  end
144
170
 
@@ -148,11 +174,11 @@ module InfernoRequirementsTools
148
174
  end
149
175
 
150
176
  if File.exist?(OUTPUT_FILE)
151
- if old_csv == (BOM + new_csv)
177
+ if old_csv == new_csv
152
178
  puts "'#{OUTPUT_FILE_NAME}' file is up to date."
153
179
  return
154
180
  else
155
- puts 'Requirements mapping has changed.'
181
+ puts 'Requirements coverage has changed.'
156
182
  end
157
183
  else
158
184
  puts "No existing #{OUTPUT_FILE_NAME}."
@@ -160,13 +186,13 @@ module InfernoRequirementsTools
160
186
 
161
187
  puts "Writing to file #{OUTPUT_FILE}..."
162
188
  FileUtils.mkdir_p(OUTPUT_FILE_DIRECTORY)
163
- File.write(OUTPUT_FILE, BOM + new_csv)
189
+ File.write(OUTPUT_FILE, new_csv)
164
190
  puts 'Done.'
165
191
  end
166
192
 
167
193
  def run_check
168
194
  unless File.exist?(INPUT_FILE)
169
- puts "Could not find input file: #{INPUT_FILE}. Aborting requirements mapping check..."
195
+ puts "Could not find input file: #{INPUT_FILE}. Aborting requirements coverage check..."
170
196
  exit(1)
171
197
  end
172
198
 
@@ -176,7 +202,7 @@ module InfernoRequirementsTools
176
202
  end
177
203
 
178
204
  if File.exist?(OUTPUT_FILE)
179
- if old_csv == (BOM + new_csv)
205
+ if old_csv == new_csv
180
206
  puts "'#{OUTPUT_FILE_NAME}' file is up to date."
181
207
  return unless unmatched_requirements_map.any?
182
208
  else
@@ -184,7 +210,7 @@ module InfernoRequirementsTools
184
210
  #{OUTPUT_FILE_NAME} file is out of date.
185
211
  To regenerate the file, run:
186
212
 
187
- bundle exec rake requirements:map_requirements
213
+ bundle exec rake requirements:generate_coverage
188
214
 
189
215
  MESSAGE
190
216
  end
@@ -193,7 +219,7 @@ module InfernoRequirementsTools
193
219
  No existing #{OUTPUT_FILE_NAME} file.
194
220
  To generate the file, run:
195
221
 
196
- bundle exec rake requirementss:map_requirements
222
+ bundle exec rake requirements:generate_coverage
197
223
 
198
224
  MESSAGE
199
225
  end
@@ -223,6 +249,7 @@ module InfernoRequirementsTools
223
249
  # ---------------+------------+----------
224
250
  # req-id-1 | short-id-1 | full-id-1
225
251
  # req-id-2 | short-id-2 | full-id-2
252
+ #
226
253
  def output_requirements_map_table(requirements_map)
227
254
  headers = %w[requirement_id short_id full_id]
228
255
  col_widths = headers.map(&:length)
@@ -237,6 +264,11 @@ module InfernoRequirementsTools
237
264
  headers[2].ljust(col_widths[2])
238
265
  ].join(' | ')
239
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)
240
272
  requirements_map.each do |requirement_id, runnables|
241
273
  runnables.each do |runnable|
242
274
  puts [
@@ -246,7 +278,6 @@ module InfernoRequirementsTools
246
278
  ].join(' | ')
247
279
  end
248
280
  end
249
- puts
250
281
  end
251
282
  end
252
283
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carin_for_blue_button_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
  - John Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-06 00:00:00.000000000 Z
11
+ date: 2024-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -110,6 +110,37 @@ files:
110
110
  - lib/carin_for_blue_button_test_kit/capability_statement/tests/json_support_test.rb
111
111
  - lib/carin_for_blue_button_test_kit/capability_statement/tests/profile_support_test.rb
112
112
  - lib/carin_for_blue_button_test_kit/carin_search_test.rb
113
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb
114
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/client_claims_data_attestation_test.rb
115
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb
116
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb
117
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb
118
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb
119
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb
120
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb
121
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb
122
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb
123
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb
124
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb
125
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/client_validation_test.rb
126
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/collection.rb
127
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/next_page_endpoint.rb
128
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_api_endpoint.rb
129
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_id_endpoint.rb
130
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb
131
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb
132
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json
133
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_operation_outcome_resource.json
134
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb
135
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb
136
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb
137
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb
138
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb
139
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb
140
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb
141
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb
142
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb
143
+ - lib/carin_for_blue_button_test_kit/client/v2.0.0/user_input_response.rb
113
144
  - lib/carin_for_blue_button_test_kit/custom_groups/v1.1.0/c4bb_smart_launch_group.rb
114
145
  - lib/carin_for_blue_button_test_kit/custom_groups/v2.0.0-dev-nonfinancial/c4bb_smart_launch/smart_scopes_test.rb
115
146
  - lib/carin_for_blue_button_test_kit/custom_groups/v2.0.0-dev-nonfinancial/c4bb_smart_launch/well_known_capabilities_test.rb
@@ -664,8 +695,7 @@ files:
664
695
  - lib/carin_for_blue_button_test_kit/validation_test.rb
665
696
  - lib/carin_for_blue_button_test_kit/version.rb
666
697
  - lib/inferno_requirements_tools/ext/inferno_core/runnable.rb
667
- - lib/inferno_requirements_tools/tasks/collect_requirements.rb
668
- - lib/inferno_requirements_tools/tasks/map_requirements.rb
698
+ - lib/inferno_requirements_tools/tasks/requirements_coverage.rb
669
699
  homepage: https://github.com/inferno-framework/carin-for-blue-button-test-kit
670
700
  licenses:
671
701
  - Apache-2.0
@@ -1,196 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'CSV'
4
- require 'roo'
5
-
6
- module InfernoRequirementsTools
7
- module Tasks
8
- # This class manages the collection of requirements details from
9
- # requirements planning excel workbooks into a CSV representation.
10
- # Currently splits out Requirements and Planned Not Tested Requirements
11
- # into two separate files.
12
- #
13
- # The `run_check` method will check whether the previously generated file is up-to-date.
14
- class CollectRequirements
15
- # Update these constants based on the test kit.
16
- TEST_KIT_ID = 'carin-for-blue-button-test-kit'
17
- INPUT_SETS = ['hl7.fhir.us.carin-bb_2.0.0'].freeze
18
-
19
- # Derivative constants
20
- TEST_KIT_CODE_FOLDER = TEST_KIT_ID.gsub('-', '_')
21
- INPUT_HEADERS = ['ID*', 'URL*', 'Requirement*', 'Conformance*', 'Actor*', 'Sub-Requirement(s)', 'Conditionality',
22
- 'Verifiable?', 'Verifiability Details', 'Planning To Test?', 'Planning To Test Details'].freeze
23
- REQUIREMENTS_OUTPUT_HEADERS = ['Req Set', 'ID', 'URL', 'Requirement', 'Conformance', 'Actor',
24
- 'Sub-Requirement(s)', 'Conditionality'].freeze
25
- REQUIREMENTS_OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_requirements.csv"
26
- REQUIREMENTS_OUTPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements',
27
- REQUIREMENTS_OUTPUT_FILE_NAME).freeze
28
- PLANNED_NOT_TESTED_OUTPUT_HEADERS = ['Req Set', 'ID', 'Reason', 'Details'].freeze
29
- PLANNED_NOT_TESTED_OUTPUT_FILE_NAME = "#{TEST_KIT_ID}_out_of_scope_requirements.csv"
30
- PLANNED_NOT_TESTED_OUTPUT_FILE = File.join('lib', TEST_KIT_CODE_FOLDER, 'requirements',
31
- PLANNED_NOT_TESTED_OUTPUT_FILE_NAME).freeze
32
- BOM = "\xEF\xBB\xBF"
33
-
34
- def input_file_map
35
- @input_file_map ||= {}
36
- end
37
-
38
- def input_rows
39
- @input_rows ||= {}
40
- end
41
-
42
- def input_rows_for_set(req_set_id)
43
- input_rows[req_set_id] = extract_input_rows_for_set(req_set_id) unless input_rows.has_key?(req_set_id)
44
- input_rows[req_set_id]
45
- end
46
-
47
- def extract_input_rows_for_set(req_set_id)
48
- CSV.parse(Roo::Spreadsheet.open(input_file_map[req_set_id]).sheet('Requirements').to_csv,
49
- headers: true).map do |row|
50
- row.to_h.slice(*INPUT_HEADERS)
51
- end
52
- end
53
-
54
- def new_requirements_csv
55
- @new_requirements_csv ||=
56
- CSV.generate do |csv|
57
- csv << REQUIREMENTS_OUTPUT_HEADERS
58
-
59
- INPUT_SETS.each do |req_set_id|
60
- input_rows = input_rows_for_set(req_set_id)
61
- input_rows.each do |row| # NOTE: use row order from source file
62
- row['Req Set'] = req_set_id
63
-
64
- csv << REQUIREMENTS_OUTPUT_HEADERS.map do |header|
65
- row.has_key?(header) ? row[header] : row["#{header}*"]
66
- end
67
- end
68
- end
69
- end
70
- end
71
-
72
- def old_requirements_csv
73
- @old_requirements_csv ||= File.read(REQUIREMENTS_OUTPUT_FILE)
74
- end
75
-
76
- def new_planned_not_tested_csv
77
- @new_planned_not_tested_csv ||=
78
- CSV.generate do |csv|
79
- csv << PLANNED_NOT_TESTED_OUTPUT_HEADERS
80
-
81
- INPUT_SETS.each do |req_set_id|
82
- input_rows = input_rows_for_set(req_set_id)
83
- input_rows.each do |row| # NOTE: use row order from source file
84
- not_verifiable = row['Verifiable?']&.downcase == 'no' || row['Verifiable?']&.downcase == 'false'
85
- not_tested = row['Planning To Test?']&.downcase == 'no' || row['Planning To Test?']&.downcase == 'false'
86
- next unless not_verifiable || not_tested
87
-
88
- csv << [req_set_id,
89
- row['ID*'],
90
- not_verifiable ? 'Not Verifiable' : 'Not Tested',
91
- not_verifiable ? row['Verifiability Details'] : row['Planning To Test Details']]
92
- end
93
- end
94
- end
95
- end
96
-
97
- def old_planned_not_tested_csv
98
- @old_planned_not_tested_csv ||= File.read(PLANNED_NOT_TESTED_OUTPUT_FILE)
99
- end
100
-
101
- def check_for_req_set_files(input_directory)
102
- available_worksheets = Dir.glob(File.join(input_directory, '*.xlsx')).reject { |f| f.include?('~$') }
103
-
104
- INPUT_SETS.each do |req_set_id|
105
- req_set_file = available_worksheets&.find { |worksheet_file| worksheet_file.include?(req_set_id) }
106
-
107
- if req_set_file&.empty?
108
- puts "Could not find input file for set #{req_set_id} in directory #{input_directory}. Aborting requirements collection..."
109
- exit(1)
110
- end
111
- input_file_map[req_set_id] = req_set_file
112
- end
113
- end
114
-
115
- def run(input_directory)
116
- check_for_req_set_files(input_directory)
117
-
118
- update_requirements = if File.exist?(REQUIREMENTS_OUTPUT_FILE)
119
- if old_requirements_csv == (BOM + new_requirements_csv)
120
- puts "'#{REQUIREMENTS_OUTPUT_FILE_NAME}' file is up to date."
121
- false
122
- else
123
- puts 'Requirements set has changed.'
124
- true
125
- end
126
- else
127
- puts "No existing #{REQUIREMENTS_OUTPUT_FILE_NAME}."
128
- true
129
- end
130
- if update_requirements
131
- puts "Writing to file #{REQUIREMENTS_OUTPUT_FILE}..."
132
- File.write(REQUIREMENTS_OUTPUT_FILE, BOM + new_requirements_csv, encoding: Encoding::UTF_8)
133
- end
134
-
135
- udpate_planned_not_tested = if File.exist?(PLANNED_NOT_TESTED_OUTPUT_FILE)
136
- if old_planned_not_tested_csv == (BOM + new_planned_not_tested_csv)
137
- puts "'#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}' file is up to date."
138
- false
139
- else
140
- puts 'Planned Not Tested Requirements set has changed.'
141
- true
142
- end
143
- else
144
- puts "No existing #{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}."
145
- true
146
- end
147
- if udpate_planned_not_tested
148
- puts "Writing to file #{PLANNED_NOT_TESTED_OUTPUT_FILE}..."
149
- File.write(PLANNED_NOT_TESTED_OUTPUT_FILE, BOM + new_planned_not_tested_csv, encoding: Encoding::UTF_8)
150
- end
151
-
152
- puts 'Done.'
153
- end
154
-
155
- def run_check(input_directory)
156
- check_for_req_set_files(input_directory)
157
-
158
- requirements_ok = if File.exist?(REQUIREMENTS_OUTPUT_FILE)
159
- if old_requirements_csv == (BOM + new_requirements_csv)
160
- puts "'#{REQUIREMENTS_OUTPUT_FILE_NAME}' file is up to date."
161
- true
162
- else
163
- puts "#{REQUIREMENTS_OUTPUT_FILE_NAME} file is out of date."
164
- false
165
- end
166
- else
167
- puts "No existing #{REQUIREMENTS_OUTPUT_FILE_NAME} file."
168
- false
169
- end
170
-
171
- planned_not_tested_requirements_ok = if File.exist?(PLANNED_NOT_TESTED_OUTPUT_FILE)
172
- if old_planned_not_tested_csv == (BOM + new_planned_not_tested_csv)
173
- puts "'#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME}' file is up to date."
174
- true
175
- else
176
- puts "#{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME} file is out of date."
177
- false
178
- end
179
- else
180
- puts "No existing #{PLANNED_NOT_TESTED_OUTPUT_FILE_NAME} file."
181
- false
182
- end
183
-
184
- return if planned_not_tested_requirements_ok && requirements_ok
185
-
186
- puts <<~MESSAGE
187
- Check Failed. To resolve, run:
188
-
189
- bundle exec rake "requirements:collect_requirements[<input_directory>]"
190
-
191
- MESSAGE
192
- exit(1)
193
- end
194
- end
195
- end
196
- end