Skip to content

Commit

Permalink
Add USCore 3.1.1 test group, CRD profile tests
Browse files Browse the repository at this point in the history
  • Loading branch information
elsaperelli committed Nov 5, 2024
1 parent 29c67d4 commit da2ec94
Show file tree
Hide file tree
Showing 33 changed files with 2,515 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ PATH
inferno_core (~> 0.4.42)
jwt (~> 2.6)
smart_app_launch_test_kit (~> 0.4.4)
tls_test_kit (= 0.2.2)
us_core_test_kit (= 0.8.2)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -321,6 +323,10 @@ GEM
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
unicode_utils (1.4.0)
us_core_test_kit (0.8.2)
inferno_core (>= 0.4.37)
smart_app_launch_test_kit (>= 0.4.0)
tls_test_kit (~> 0.2.0)
webmock (3.23.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
Expand Down
2 changes: 2 additions & 0 deletions davinci_dtr_test_kit.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Gem::Specification.new do |spec|
spec.add_dependency 'inferno_core', '~> 0.4.42'
spec.add_dependency 'jwt', '~> 2.6'
spec.add_dependency 'smart_app_launch_test_kit', '~> 0.4.4'
spec.add_dependency 'tls_test_kit', '0.2.2'
spec.add_dependency 'us_core_test_kit', '0.8.2'
spec.required_ruby_version = Gem::Requirement.new('>= 3.1.2')
spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['source_code_uri'] = spec.homepage
Expand Down
112 changes: 112 additions & 0 deletions lib/davinci_dtr_test_kit/date_search_validation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# frozen_string_literal: true

module DaVinciDTRTestKit
module DateSearchValidation
def get_fhir_datetime_range(datetime)
range = { start: DateTime.xmlschema(datetime), end: nil }
range[:end] =
if /^\d{4}$/.match?(datetime) # YYYY
range[:start].next_year - 1.seconds
elsif /^\d{4}-\d{2}$/.match?(datetime) # YYYY-MM
range[:start].next_month - 1.seconds
elsif /^\d{4}-\d{2}-\d{2}$/.match?(datetime) # YYYY-MM-DD
range[:start].next_day - 1.seconds
else # YYYY-MM-DDThh:mm:ss+zz:zz
range[:start]
end
range
end

def get_fhir_period_range(period)
range = { start: nil, end: nil }
range[:start] = DateTime.xmlschema(period.start) unless period.start.nil?
return range if period.end.nil?

period_end_beginning = DateTime.xmlschema(period.end)
range[:end] =
if /^\d{4}$/.match?(period.end) # YYYY
period_end_beginning.next_year - 1.seconds
elsif /^\d{4}-\d{2}$/.match?(period.end) # YYYY-MM
period_end_beginning.next_month - 1.seconds
elsif /^\d{4}-\d{2}-\d{2}$/.match?(period.end) # YYYY-MM-DD
period_end_beginning.next_day - 1.seconds
else # YYYY-MM-DDThh:mm:ss+zz:zz
period_end_beginning
end
range
end

def fhir_date_comparer(search_range, target_range, comparator, extend_start = false, extend_end = false)
# Implicitly, a missing lower boundary is "less than" any actual date. A missing upper boundary is "greater than" any actual date.
case comparator
when 'eq' # the range of the search value fully contains the range of the target value
!target_range[:start].nil? && !target_range[:end].nil? && search_range[:start] <= target_range[:start] && search_range[:end] >= target_range[:end]
when 'ne' # the range of the search value does not fully contain the range of the target value
target_range[:start].nil? || target_range[:end].nil? || search_range[:start] > target_range[:start] || search_range[:end] < target_range[:end]
when 'gt' # the range above the search value intersects (i.e. overlaps) with the range of the target value
target_range[:end].nil? || search_range[:end] < target_range[:end] || (search_range[:end] < (target_range[:end] + 1) && extend_end)
when 'lt' # the range below the search value intersects (i.e. overlaps) with the range of the target value
target_range[:start].nil? || search_range[:start] > target_range[:start] || (search_range[:start] > (target_range[:start] - 1) && extend_start)
when 'ge'
fhir_date_comparer(search_range, target_range, 'gt', extend_start,
extend_end) || fhir_date_comparer(search_range, target_range, 'eq')
when 'le'
fhir_date_comparer(search_range, target_range, 'lt', extend_start,
extend_end) || fhir_date_comparer(search_range, target_range, 'eq')
when 'sa' # the range above the search value contains the range of the target value
!target_range[:start].nil? && search_range[:end] < target_range[:start]
when 'eb' # the range below the search value contains the range of the target value
!target_range[:end].nil? && search_range[:start] > target_range[:end]
when 'ap' # the range of the search value overlaps with the range of the target value
if target_range[:start].nil? || target_range[:end].nil?
(target_range[:start].nil? && search_range[:start] < target_range[:end]) ||
(target_range[:end].nil? && search_range[:end] > target_range[:start])
else
(search_range[:start] >= target_range[:start] && search_range[:start] <= target_range[:end]) ||
(search_range[:end] >= target_range[:start] && search_range[:end] <= target_range[:end])
end
end
end

def validate_date_search(search_value, target_value)
if target_value.instance_of? FHIR::Period
validate_period_search(search_value, target_value)
else
validate_datetime_search(search_value, target_value)
end
end

def validate_datetime_search(search_value, target_value)
comparator = search_value[0..1]
if ['eq', 'ge', 'gt', 'le', 'lt', 'ne', 'sa', 'eb', 'ap'].include? comparator
search_value = search_value[2..-1]
else
comparator = 'eq'
end
search_is_date = is_date?(search_value)
target_is_date = is_date?(target_value)
search_range = get_fhir_datetime_range(search_value)
target_range = get_fhir_datetime_range(target_value)
fhir_date_comparer(search_range, target_range, comparator, !search_is_date && target_is_date,
!search_is_date && target_is_date)
end

def validate_period_search(search_value, target_value)
comparator = search_value[0..1]
if ['eq', 'ge', 'gt', 'le', 'lt', 'ne', 'sa', 'eb', 'ap'].include? comparator
search_value = search_value[2..-1]
else
comparator = 'eq'
end
search_is_date = is_date?(search_value)
search_range = get_fhir_datetime_range(search_value)
target_range = get_fhir_period_range(target_value)
fhir_date_comparer(search_range, target_range, comparator, !search_is_date && is_date?(target_value.start),
!search_is_date && is_date?(target_value.end))
end

def is_date?(value)
/^\d{4}(-\d{2})?(-\d{2})?$/.match?(value) # YYYY or YYYY-MM or YYYY-MM-DD
end
end
end
135 changes: 135 additions & 0 deletions lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
require_relative 'ext/inferno_core/runnable'
require_relative 'ext/inferno_core/record_response_route'
require_relative 'ext/inferno_core/request'
require 'us_core_test_kit'
require 'tls_test_kit'
require_relative 'version'
require_relative 'dtr_options'
require_relative 'profiles/coverage/coverage_read'
require_relative 'profiles/coverage/coverage_validation'
require_relative 'profiles/coverage/coverage_context_search'
require_relative 'profiles/coverage/coverage_patient_search'
require_relative 'profiles/communication_request/communication_request_read'
require_relative 'profiles/communication_request/communication_request_validation'
require_relative 'profiles/device_request/device_request_read'
require_relative 'profiles/device_request/device_request_validation'
require_relative 'profiles/encounter/encounter_read'
require_relative 'profiles/encounter/encounter_validation'
require_relative 'profiles/medication_request/medication_request_read'
require_relative 'profiles/medication_request/medication_request_validation'
require_relative 'profiles/nutrition_order/nutrition_order_read'
require_relative 'profiles/nutrition_order/nutrition_order_validation'
require_relative 'profiles/service_request/service_request_read'
require_relative 'profiles/service_request/service_request_validation'
require_relative 'profiles/task/task_read'
require_relative 'profiles/task/task_validation'
require_relative 'profiles/vision_prescription/vision_prescription_read'
require_relative 'profiles/vision_prescription/vision_prescription_validation'
require 'smart_app_launch/smart_stu1_suite'
require 'smart_app_launch/smart_stu2_suite'

Expand Down Expand Up @@ -35,6 +59,15 @@ class DTRLightEHRSuite < Inferno::TestSuite
title: 'FHIR Endpoint',
description: 'URL of the DTR FHIR server'

# Hl7 Validator Wrapper:
fhir_resource_validator do
igs('hl7.fhir.us.davinci-dtr#2.0.1', 'hl7.fhir.us.davinci-cdex#2.0.0')

exclude_message do |message|
message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
end
end

group do
title 'Authorization'

Expand Down Expand Up @@ -71,5 +104,107 @@ class DTRLightEHRSuite < Inferno::TestSuite
required_suite_options: DTROptions::SMART_2_REQUIREMENT,
run_as_group: true
end

group do
title 'FHIR API'

group from: :'us_core_v311-us_core_v311_fhir_api',
run_as_group: true
end

group do
title 'DTR Light EHR Profiles'

input :credentials,
title: 'OAuth Credentials',
type: :oauth_credentials,
optional: true

# All FHIR requests in this suite will use this FHIR client
fhir_client do
url :url
oauth_credentials :credentials
end

group do
title 'CRD Coverage'

input :coverage_ids

test from: :coverage_read
test from: :coverage_validation
test from: :coverage_context_search
test from: :coverage_patient_search
end

group do
title 'CRD CommunicationRequest'
input :communication_request_ids

test from: :communication_request_read
test from: :communication_request_validation
end

group do
title 'CRD DeviceRequest'
input :device_request_ids

test from: :device_request_read
test from: :device_request_validation
end

group do
title 'CRD Encounter'

input :encounter_ids

test from: :encounter_read
test from: :encounter_validation
end

group do
title 'CRD MedicationRequest'

input :medication_request_ids

test from: :medication_request_read
test from: :medication_request_validation
end

group do
title 'CRD NutritionOrder'

input :nutrition_order_ids

test from: :nutrition_order_read
test from: :nutrition_order_validation
end

group do
title 'CRD ServiceRequest'

input :service_request_ids

test from: :service_request_read
test from: :service_request_validation
end

group do
title 'CDex Task'

input :task_ids

test from: :task_read
test from: :task_validation
end

group do
title 'CRD VisionPrescription'
input :vision_prescription_ids

test from: :vision_prescription_read
test from: :vision_prescription_validation
end
end
end
end
Loading

0 comments on commit da2ec94

Please sign in to comment.