onc_certification_g31_test_kit 1.0.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/config/presets/g31_against_inferno_crd_server_suite.json.erb +24 -0
- data/config/presets/g31_against_ri_br_provider.json.erb +38 -0
- data/execution_scripts/README.md +16 -0
- data/lib/onc_certification_g31_test_kit/documentation_attestation_test.rb +55 -0
- data/lib/onc_certification_g31_test_kit/endpoints/g31_cds_services_discovery_handler.rb +30 -0
- data/lib/onc_certification_g31_test_kit/endpoints/g31_hook_request_endpoint.rb +12 -0
- data/lib/onc_certification_g31_test_kit/g31_certification_suite.rb +358 -0
- data/lib/onc_certification_g31_test_kit/g31_certification_suite_short_id_map.yml +1971 -0
- data/lib/onc_certification_g31_test_kit/g31_crd_import.rb +96 -0
- data/lib/onc_certification_g31_test_kit/g31_options.rb +33 -0
- data/lib/onc_certification_g31_test_kit/g31_requirements.rb +96 -0
- data/lib/onc_certification_g31_test_kit/igs/.keep +0 -0
- data/lib/onc_certification_g31_test_kit/igs/README.md +21 -0
- data/lib/onc_certification_g31_test_kit/metadata.rb +71 -0
- data/lib/onc_certification_g31_test_kit/requirements/(g)(31)_HTI-4_requirements.xlsx +0 -0
- data/lib/onc_certification_g31_test_kit/requirements/(j)(20)_HTI-4_requirements.xlsx +0 -0
- data/lib/onc_certification_g31_test_kit/requirements/generated/g31_certification_requirements_coverage.csv +1296 -0
- data/lib/onc_certification_g31_test_kit/requirements/onc_certification_g31_test_kit_requirements.csv +17 -0
- data/lib/onc_certification_g31_test_kit/version.rb +4 -0
- data/lib/onc_certification_g31_test_kit.rb +1 -0
- metadata +114 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'davinci_crd_test_kit/client/v2.2.1/client_urls'
|
|
2
|
+
require_relative 'g31_options'
|
|
3
|
+
|
|
4
|
+
module ONCCertificationG31TestKit
|
|
5
|
+
module G31ClientURLs
|
|
6
|
+
SUITE_ID = 'g31_certification'.freeze
|
|
7
|
+
|
|
8
|
+
def inferno_base_url
|
|
9
|
+
@inferno_base_url ||= G31CRDImport.base_url
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module G31CRDImport
|
|
14
|
+
STALE_CACHE_IVARS = [:@test_count, :@available_inputs, :@children_available_inputs].freeze
|
|
15
|
+
RUNNABLE_TEXT_FIELDS = [:title, :short_title, :description, :input_instructions].freeze
|
|
16
|
+
INPUT_TEXT_FIELDS = [:title, :description].freeze
|
|
17
|
+
|
|
18
|
+
# Singular references only: statements about "CRD clients" in general are left as is.
|
|
19
|
+
# NOTE: this pattern gets replaced within static text in the suite (descriptions,
|
|
20
|
+
# titles for runnables and inputs). It does not update the same strings within
|
|
21
|
+
# dynamic messages associated with the runnable during testing. This is expected
|
|
22
|
+
# and documented in docs/Technical-Overview.md.
|
|
23
|
+
CRD_CLIENT_PATTERN = /CRD client(?!s)/
|
|
24
|
+
HEALTH_IT_MODULE = 'Health IT Module'.freeze
|
|
25
|
+
|
|
26
|
+
def self.import!(runnable)
|
|
27
|
+
exclude_optional!(runnable)
|
|
28
|
+
rewrite_crd_references!(runnable)
|
|
29
|
+
|
|
30
|
+
runnable
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.exclude_optional!(runnable)
|
|
34
|
+
runnable.all_children.reject(&:required?).each(&:remove_self_from_repository)
|
|
35
|
+
runnable.all_children.select!(&:required?)
|
|
36
|
+
STALE_CACHE_IVARS.each do |ivar|
|
|
37
|
+
runnable.remove_instance_variable(ivar) if runnable.instance_variable_defined?(ivar)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
runnable.all_children.each { |child| exclude_optional!(child) }
|
|
41
|
+
end
|
|
42
|
+
private_class_method :exclude_optional!
|
|
43
|
+
|
|
44
|
+
def self.rewrite_crd_references!(runnable)
|
|
45
|
+
runnable.include(G31ClientURLs) if runnable.include?(DaVinciCRDTestKit::V221::ClientURLs)
|
|
46
|
+
rewrite_runnable_text!(runnable)
|
|
47
|
+
rewrite_input_text!(runnable)
|
|
48
|
+
|
|
49
|
+
runnable.all_children.each { |child| rewrite_crd_references!(child) }
|
|
50
|
+
end
|
|
51
|
+
private_class_method :rewrite_crd_references!
|
|
52
|
+
|
|
53
|
+
def self.rewrite_runnable_text!(runnable)
|
|
54
|
+
RUNNABLE_TEXT_FIELDS.each do |field|
|
|
55
|
+
text = runnable.send(field)
|
|
56
|
+
next if text.nil?
|
|
57
|
+
|
|
58
|
+
rewritten = rewrite_text(text)
|
|
59
|
+
runnable.send(field, rewritten) unless rewritten == text
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
private_class_method :rewrite_runnable_text!
|
|
63
|
+
|
|
64
|
+
def self.rewrite_input_text!(runnable)
|
|
65
|
+
updates = runnable.config.inputs.each_with_object({}) do |(identifier, input), acc|
|
|
66
|
+
input_updates = INPUT_TEXT_FIELDS.each_with_object({}) do |field, field_acc|
|
|
67
|
+
text = input.send(field)
|
|
68
|
+
next if text.nil?
|
|
69
|
+
|
|
70
|
+
rewritten = rewrite_text(text)
|
|
71
|
+
field_acc[field] = rewritten unless rewritten == text
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
acc[identifier] = input_updates if input_updates.any?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
runnable.config(inputs: updates) if updates.any?
|
|
78
|
+
end
|
|
79
|
+
private_class_method :rewrite_input_text!
|
|
80
|
+
|
|
81
|
+
def self.rewrite_text(text)
|
|
82
|
+
text.to_s.gsub(crd_base_url, base_url).gsub(CRD_CLIENT_PATTERN, HEALTH_IT_MODULE)
|
|
83
|
+
end
|
|
84
|
+
private_class_method :rewrite_text
|
|
85
|
+
|
|
86
|
+
# Includes the CRD version prefix, so imported tests point at this suite's v2.2.1 endpoints
|
|
87
|
+
# rather than at the suite root.
|
|
88
|
+
def self.base_url
|
|
89
|
+
"#{Inferno::Application['base_url']}/custom/#{G31ClientURLs::SUITE_ID}#{G31Options::CRD_V221_PREFIX}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.crd_base_url
|
|
93
|
+
"#{Inferno::Application['base_url']}/custom/#{DaVinciCRDTestKit::V221::ClientURLs::SUITE_ID}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ONCCertificationG31TestKit
|
|
2
|
+
module G31Options
|
|
3
|
+
CRD_V221 = '2.2.1'.freeze
|
|
4
|
+
CRD_V221_COMPACT = "v#{CRD_V221.delete('.')}".freeze # v221
|
|
5
|
+
CRD_V221_DOTTED = "v#{CRD_V221}".freeze # v2.2.1
|
|
6
|
+
CRD_V221_PREFIX = "/crd_#{CRD_V221_COMPACT}".freeze # /crd_v221
|
|
7
|
+
CRD_V221_IG_PACKAGE = "hl7.fhir.us.davinci-crd##{CRD_V221}".freeze
|
|
8
|
+
|
|
9
|
+
US_CORE_3 = 'us_core_3'.freeze
|
|
10
|
+
US_CORE_4 = 'us_core_4'.freeze
|
|
11
|
+
US_CORE_5 = 'us_core_5'.freeze
|
|
12
|
+
US_CORE_6 = 'us_core_6'.freeze
|
|
13
|
+
US_CORE_7 = 'us_core_7'.freeze
|
|
14
|
+
|
|
15
|
+
US_CORE_VERSION_NUMBERS = {
|
|
16
|
+
US_CORE_3 => '3.1.1',
|
|
17
|
+
US_CORE_4 => '4.0.0',
|
|
18
|
+
US_CORE_5 => '5.0.1',
|
|
19
|
+
US_CORE_6 => '6.1.0',
|
|
20
|
+
US_CORE_7 => '7.0.0'
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
US_CORE_3_REQUIREMENT = { us_core_version: US_CORE_3 }.freeze
|
|
24
|
+
US_CORE_4_REQUIREMENT = { us_core_version: US_CORE_4 }.freeze
|
|
25
|
+
US_CORE_5_REQUIREMENT = { us_core_version: US_CORE_5 }.freeze
|
|
26
|
+
US_CORE_6_REQUIREMENT = { us_core_version: US_CORE_6 }.freeze
|
|
27
|
+
US_CORE_7_REQUIREMENT = { us_core_version: US_CORE_7 }.freeze
|
|
28
|
+
|
|
29
|
+
def us_core_version
|
|
30
|
+
suite_options[:us_core_version]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module ONCCertificationG31TestKit
|
|
2
|
+
# Maps the § 170.315(g)(31) and § 170.315(j)(20) certification requirements onto the runnables
|
|
3
|
+
# imported from the Da Vinci CRD client suite.
|
|
4
|
+
#
|
|
5
|
+
# The imported runnables already declare the IG-level requirements that they verify, so these
|
|
6
|
+
# regulatory requirements are added to what each one declares rather than replacing it.
|
|
7
|
+
#
|
|
8
|
+
# Regulatory requirements are written at the level of a whole capability, so they are attached to
|
|
9
|
+
# the group that exercises that capability when no single test demonstrates it, and to individual
|
|
10
|
+
# tests when one does.
|
|
11
|
+
module G31Requirements
|
|
12
|
+
G31_SET = '170.315(g)(31)_HTI-4'.freeze
|
|
13
|
+
J20_SET = '170.315(j)(20)_HTI-4'.freeze
|
|
14
|
+
|
|
15
|
+
# Requirement id => the runnables that verify it, identified by the trailing portion of their id
|
|
16
|
+
# within this suite. Keys are the shortest suffix that identifies a single runnable; ids that
|
|
17
|
+
# are reused across groups (e.g., the response attestation) are qualified by their parent.
|
|
18
|
+
REQUIREMENT_MAP = {
|
|
19
|
+
"#{G31_SET}@3" => [
|
|
20
|
+
'crd_v221_client_registration'
|
|
21
|
+
],
|
|
22
|
+
"#{G31_SET}@4" => [
|
|
23
|
+
'g31_hook_invocation'
|
|
24
|
+
],
|
|
25
|
+
"#{G31_SET}@5" => [
|
|
26
|
+
'crd_v221_client_order_sign'
|
|
27
|
+
],
|
|
28
|
+
"#{J20_SET}@1" => [
|
|
29
|
+
'g31_hook_invocation'
|
|
30
|
+
],
|
|
31
|
+
"#{J20_SET}@2" => [
|
|
32
|
+
'crd_v221_client_registration'
|
|
33
|
+
],
|
|
34
|
+
"#{J20_SET}@3" => [
|
|
35
|
+
'crd_v221_order_sign_auth',
|
|
36
|
+
'crd_v221_cross_hook_auth'
|
|
37
|
+
],
|
|
38
|
+
"#{J20_SET}@4" => [
|
|
39
|
+
'crd_v221_order_sign_auth',
|
|
40
|
+
'crd_v221_cross_hook_auth'
|
|
41
|
+
],
|
|
42
|
+
"#{J20_SET}@5" => [
|
|
43
|
+
'crd_v221_order_sign_requests-crd_v221_hook_data_fetch_verification',
|
|
44
|
+
'crd_v221_cross_hook_requests-crd_v221_hook_data_fetch_verification'
|
|
45
|
+
],
|
|
46
|
+
"#{J20_SET}@6" => [
|
|
47
|
+
'crd_v221_client_order_sign',
|
|
48
|
+
'crd_v221_client_cross_hook_interaction'
|
|
49
|
+
],
|
|
50
|
+
"#{J20_SET}@7" => [
|
|
51
|
+
'crd_v221_client_order_sign',
|
|
52
|
+
'crd_v221_client_cross_hook_interaction'
|
|
53
|
+
],
|
|
54
|
+
"#{J20_SET}@8" => [
|
|
55
|
+
'crd_v221_order_sign_requests-crd_v221_hook_data_fetch_verification',
|
|
56
|
+
'crd_v221_cross_hook_requests-crd_v221_hook_data_fetch_verification'
|
|
57
|
+
],
|
|
58
|
+
"#{J20_SET}@9" => [
|
|
59
|
+
'crd_v221_order_sign_responses-crd_v221_card_display_attest_test',
|
|
60
|
+
'crd_v221_cross_hook_responses-crd_v221_card_display_attest_test'
|
|
61
|
+
]
|
|
62
|
+
}.freeze
|
|
63
|
+
|
|
64
|
+
# Adds the requirements above to the runnables that verify them. Raises if a key no longer
|
|
65
|
+
# identifies exactly one runnable, so that a change to the imported suite is caught here rather
|
|
66
|
+
# than silently dropping coverage.
|
|
67
|
+
def self.apply!(suite)
|
|
68
|
+
runnables = [suite, *suite.all_descendants]
|
|
69
|
+
|
|
70
|
+
REQUIREMENT_MAP.each do |requirement_id, runnable_keys|
|
|
71
|
+
runnable_keys.each do |runnable_key|
|
|
72
|
+
add_requirement!(find_runnable!(runnables, runnable_key), requirement_id)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.find_runnable!(runnables, runnable_key)
|
|
78
|
+
matches = runnables.select { |runnable| runnable.id.to_s.end_with?("-#{runnable_key}") }
|
|
79
|
+
|
|
80
|
+
raise "No runnable found for requirement mapping key '#{runnable_key}'" if matches.empty?
|
|
81
|
+
|
|
82
|
+
if matches.length > 1
|
|
83
|
+
raise "Requirement mapping key '#{runnable_key}' matches multiple runnables: " \
|
|
84
|
+
"#{matches.map(&:id).join(', ')}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
matches.first
|
|
88
|
+
end
|
|
89
|
+
private_class_method :find_runnable!
|
|
90
|
+
|
|
91
|
+
def self.add_requirement!(runnable, requirement_id)
|
|
92
|
+
runnable.verifies_requirements(*(runnable.verifies_requirements + [requirement_id]).uniq)
|
|
93
|
+
end
|
|
94
|
+
private_class_method :add_requirement!
|
|
95
|
+
end
|
|
96
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Note on this IGs folder
|
|
2
|
+
|
|
3
|
+
There are three reasons why it would be necessary to put an IG package.tgz in this folder. If none of these apply, you do not need to put any files here, or can consider removing any existing files to make it clear they are unused.
|
|
4
|
+
|
|
5
|
+
## 1. Generated Test Suites
|
|
6
|
+
Some test kits use a "generator" to automatically generate the contents of a test suite for an IG. The IG files are required every time the test suites need to be regenerated. Examples of test kits that use this approach are the US Core Test Kit and CARIN IG for Blue Button® Test Kit.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## 2. Non-published IG
|
|
10
|
+
If your IG, or the specific version of the IG you want to test against, is not published, then the validator service needs to load the IG from file in order to be able to validate resources with it. The IG must be referenced in the `fhir_resource_validator` block in the test suite definition by filename, ie:
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
fhir_resource_validator do
|
|
14
|
+
igs 'igs/filename.tgz'
|
|
15
|
+
|
|
16
|
+
...
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 3. Inferno Validator UI
|
|
21
|
+
The Inferno Validator UI is configured to auto-load any IGs present in the igs folder and include them in all validations. In general, the Inferno team is currently leaving IGs in this folder even if not otherwise necessary to make it easy to re-enable the validator UI.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require_relative 'version'
|
|
2
|
+
|
|
3
|
+
module ONCCertificationG31TestKit
|
|
4
|
+
class Metadata < Inferno::TestKit
|
|
5
|
+
id :onc_certification_g31_test_kit
|
|
6
|
+
title 'ONC Certification (g)(31) Coverage Requirements Discovery API Test Kit'
|
|
7
|
+
description <<~DESCRIPTION
|
|
8
|
+
The ONC Certification (g)(31) Coverage Requirements Discovery API Test Kit is a
|
|
9
|
+
testing tool for Health IT Modules seeking to meet the requirements of the
|
|
10
|
+
Coverage Requirements Discovery criterion § 170.315(g)(31) in the ONC Health
|
|
11
|
+
IT Certification Program.
|
|
12
|
+
<!-- break -->
|
|
13
|
+
|
|
14
|
+
The CRD standard allows clients to support one of several US Core versions. To begin testing,
|
|
15
|
+
select a US Core version for Inferno to verify against, and click 'Create Test Session'.
|
|
16
|
+
|
|
17
|
+
## Status
|
|
18
|
+
|
|
19
|
+
The ONC Certification (g)(31) Coverage Requirements Discovery API Test Kit is actively
|
|
20
|
+
developed and updates are released monthly.
|
|
21
|
+
|
|
22
|
+
The test kit currently tests requirements for the [Coverage Requirements
|
|
23
|
+
Discovery criterion §
|
|
24
|
+
170.315(g)(31)](https://healthit.gov/test-method/provider-prior-authorization-api-coverage-requirements-discovery).
|
|
25
|
+
This includes:
|
|
26
|
+
- Registration
|
|
27
|
+
- CDS Hooks support for the order-sign hook
|
|
28
|
+
- CRD Client capabilities, including support for specific scenarios and must support elements
|
|
29
|
+
- FHIR API
|
|
30
|
+
- Documentation
|
|
31
|
+
|
|
32
|
+
See the test descriptions within the test kit for detail on the specific
|
|
33
|
+
validations performed as part of testing these requirements. These descriptions
|
|
34
|
+
also contain a "View Specification Requirements" link that can be used to see
|
|
35
|
+
the specific requirements verified. Testers seeking help in using these tests
|
|
36
|
+
can find additional details within the [Walkthrough](https://github.com/onc-healthit/onc-certification-g31-test-kit/wiki/Walkthrough)
|
|
37
|
+
on the (g)(31) Test Kit wiki.
|
|
38
|
+
|
|
39
|
+
## Repository and Resources
|
|
40
|
+
|
|
41
|
+
The ONC Certification (g)(31) Coverage Requirements Discovery API Test Kit can be
|
|
42
|
+
[downloaded from its GitHub repository](https://github.com/onc-healthit/onc-certification-g31-test-kit),
|
|
43
|
+
where additional resources and documentation are also available to help users
|
|
44
|
+
get started with the testing process. The
|
|
45
|
+
[Releases](https://github.com/onc-healthit/onc-certification-g31-test-kit/releases)
|
|
46
|
+
page provides information about each new release.
|
|
47
|
+
|
|
48
|
+
## Providing Feedback and Reporting Issues
|
|
49
|
+
|
|
50
|
+
We welcome feedback on the tests, including but not limited to the following areas:
|
|
51
|
+
|
|
52
|
+
- Validation logic, such as potential bugs, lax checks, and unexpected failures.
|
|
53
|
+
- Requirements coverage, such as requirements that have been missed, tests that
|
|
54
|
+
necessitate features that the IG does not require, or other issues with the
|
|
55
|
+
interpretation of the IG's requirements.
|
|
56
|
+
- User experience, such as confusing or missing information in the test UI.
|
|
57
|
+
|
|
58
|
+
Please report any issues with this set of tests in the [issues
|
|
59
|
+
section](https://github.com/onc-healthit/onc-certification-g31-test-kit/issues)
|
|
60
|
+
of the repository.
|
|
61
|
+
DESCRIPTION
|
|
62
|
+
|
|
63
|
+
suite_ids [:g31_certification]
|
|
64
|
+
tags ['Da Vinci', 'CRD', 'US Core']
|
|
65
|
+
last_updated LAST_UPDATED
|
|
66
|
+
version VERSION
|
|
67
|
+
maturity 'Certification'
|
|
68
|
+
authors ['Inferno Team']
|
|
69
|
+
repo 'https://github.com/onc-healthit/onc-certification-g31-test-kit'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
Binary file
|