From abdea164f5cce7cee931fd44e3c41cf5e3ddd0b8 Mon Sep 17 00:00:00 2001 From: Chase Zhou Date: Thu, 20 Jun 2019 17:30:56 -0400 Subject: [PATCH 01/89] Add must support tests --- generators/argonaut-r4/generator.rb | 30 ++++++ generators/argonaut-r4/metadata_extractor.rb | 77 ++++++++++---- lib/app/models/testing_instance.rb | 2 + .../pediatric_bmi_for_age_sequence.rb | 100 +++++++++++++++++- .../pediatric_weight_for_height_sequence.rb | 100 +++++++++++++++++- .../us_core_allergyintolerance_sequence.rb | 28 ++++- .../us_core_r4/us_core_careplan_sequence.rb | 37 ++++++- .../us_core_r4/us_core_careteam_sequence.rb | 31 +++++- .../us_core_r4/us_core_condition_sequence.rb | 31 +++++- .../us_core_r4/us_core_device_sequence.rb | 31 +++++- .../us_core_diagnosticreport_lab_sequence.rb | 49 ++++++++- .../us_core_diagnosticreport_note_sequence.rb | 49 ++++++++- .../us_core_documentreference_sequence.rb | 67 +++++++++++- .../us_core_r4/us_core_encounter_sequence.rb | 67 +++++++++++- .../us_core_r4/us_core_goal_sequence.rb | 34 +++++- .../us_core_immunization_sequence.rb | 37 ++++++- .../us_core_r4/us_core_location_sequence.rb | 43 +++++++- .../us_core_r4/us_core_medication_sequence.rb | 19 +++- .../us_core_medicationrequest_sequence.rb | 40 ++++++- .../us_core_medicationstatement_sequence.rb | 40 ++++++- .../us_core_observation_lab_sequence.rb | 70 +++++++++++- .../us_core_organization_sequence.rb | 52 ++++++++- .../us_core_r4/us_core_patient_sequence.rb | 79 +++++++++++++- .../us_core_practitioner_sequence.rb | 37 ++++++- .../us_core_practitionerrole_sequence.rb | 43 +++++++- .../us_core_r4/us_core_procedure_sequence.rb | 31 +++++- .../us_core_smokingstatus_sequence.rb | 31 +++++- lib/app/sequence_base.rb | 11 ++ 28 files changed, 1196 insertions(+), 70 deletions(-) diff --git a/generators/argonaut-r4/generator.rb b/generators/argonaut-r4/generator.rb index 4d7290baa..f45983ab5 100644 --- a/generators/argonaut-r4/generator.rb +++ b/generators/argonaut-r4/generator.rb @@ -56,6 +56,7 @@ def generate_tests(metadata) create_interaction_test(sequence, interaction) end + create_must_support_test(sequence) create_resource_profile_test(sequence) create_references_resolved_test(sequence) end @@ -139,6 +140,35 @@ def create_interaction_test(sequence, interaction) sequence[:tests] << interaction_test end +def create_must_support_test(sequence) + test = { + tests_that: 'Demonstrates that the server can supply must supported elements', + index: format('%02d', sequence[:tests].length + 1), + link: 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support', + test_code: '' + } + + sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| + test[:test_code] += %( + element_found = @instance.must_support_confirmed.include?('#{extension[:id]}') || @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == '#{extension[:url]}' } + skip 'Could not find #{extension[:id]} in the provided resource' unless element_found + @instance.must_support_confirmed += '#{extension[:id]},') + end + + sequence[:must_supports].select { |must_support| must_support[:type] == 'element' }.each do |element| + truncated_path = element[:path].gsub("#{sequence[:resource]}.", '') + test[:test_code] += %( + element_found = @instance.must_support_confirmed.include?('#{element[:path]}') || can_resolve_path(@#{sequence[:resource].downcase}, '#{truncated_path}') + skip 'Could not find #{element[:path]} in the provided resource' unless element_found + @instance.must_support_confirmed += '#{element[:path]},') + end + + test[:test_code] += %( + @instance.save!) + + sequence[:tests] << test +end + def create_resource_profile_test(sequence) test = { tests_that: "#{sequence[:resource]} resources associated with Patient conform to Argonaut profiles", diff --git a/generators/argonaut-r4/metadata_extractor.rb b/generators/argonaut-r4/metadata_extractor.rb index e39af328c..8e1228a95 100644 --- a/generators/argonaut-r4/metadata_extractor.rb +++ b/generators/argonaut-r4/metadata_extractor.rb @@ -31,6 +31,26 @@ def extract_metadata @metadata end + def build_new_sequence(resource, profile) + base_name = profile.split('StructureDefinition/')[1] + { + name: base_name.tr('-', '_'), + classname: base_name + .split('-') + .map(&:capitalize) + .join + .gsub('UsCore', 'UsCoreR4') + 'Sequence', + resource: resource['type'], + profile: profile_uri(base_name), # link in capability statement is incorrect + interactions: [], + searches: [], + search_param_descriptions: {}, + element_descriptions: {}, + must_supports: [], + tests: [] + } + end + def extract_metadata_from_resources(resources) data = { sequences: [] @@ -38,35 +58,15 @@ def extract_metadata_from_resources(resources) resources.each do |resource| resource['supportedProfile'].each do |supported_profile| - new_sequence = { - name: supported_profile.split('StructureDefinition/')[1].tr('-', '_'), - classname: supported_profile - .split('StructureDefinition/')[1] - .split('-') - .map(&:capitalize) - .join - .gsub('UsCore', 'UsCoreR4') + 'Sequence', - resource: resource['type'], - profile: profile_uri(supported_profile.split('StructureDefinition/')[1]), # link in capability statement is incorrect - interactions: [], - searches: [], - search_param_descriptions: {}, - element_descriptions: {}, - tests: [] - } + new_sequence = build_new_sequence(resource, supported_profile) - # add each basic search type add_basic_searches(resource, new_sequence) - - # add each search combination add_combo_searches(resource, new_sequence) - - # add each interaction add_interactions(resource, new_sequence) profile_definition = get_json_from_uri(new_sequence[:profile]) + add_must_support_elements(profile_definition, new_sequence) add_search_param_descriptions(profile_definition, new_sequence) - add_element_definitions(profile_definition, new_sequence) data[:sequences] << new_sequence @@ -119,6 +119,39 @@ def add_interactions(resource, sequence) end end + def add_must_support_elements(profile_definition, sequence) + profile_definition['snapshot']['element'].select { |el| el['mustSupport'] }.each do |element| + if element['path'].end_with? 'extension' + sequence[:must_supports] << + { + type: 'extension', + id: element['id'], + path: element['path'], + url: element['type'].first['profile'].first + } + next + end + + path = element['path'] + if path.include? '[x]' + variable_el = profile_definition['snapshot']['element'].select { |el| el['id'] == (path.split('[x]').first + '[x]') }.first + variable_el['type'].each do |type| + sequence[:must_supports] << + { + type: 'element', + path: path.gsub('[x]', type['code']) + } + end + else + sequence[:must_supports] << + { + type: 'element', + path: path + } + end + end + end + def add_search_param_descriptions(profile_definition, sequence) sequence[:search_param_descriptions].each_key do |param| search_param_definition = get_json_from_uri(search_param_uri(sequence[:resource], param.to_s)) diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index 3b4eae6b4..2986b5572 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -51,6 +51,8 @@ class TestingInstance property :dynamic_registration_token, String + property :must_support_confirmed, String, default:'' + has n, :sequence_results has n, :supported_resources, order: [:index.asc] has n, :resource_references diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index 4ad188bf4..2bb2efe13 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -217,9 +217,105 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') + skip 'Could not find Observation.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.status,' + element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') + skip 'Could not find Observation.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category,' + element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') + skip 'Could not find Observation.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding') || can_resolve_path(@observation, 'category.coding') + skip 'Could not find Observation.category.coding in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding.system') || can_resolve_path(@observation, 'category.coding.system') + skip 'Could not find Observation.category.coding.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding.system,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding.code') || can_resolve_path(@observation, 'category.coding.code') + skip 'Could not find Observation.category.coding.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding.code,' + element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') + skip 'Could not find Observation.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.subject,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') + skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') + skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.value') || can_resolve_path(@observation, 'valueQuantity.value') + skip 'Could not find Observation.valueQuantity.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.value,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.unit') || can_resolve_path(@observation, 'valueQuantity.unit') + skip 'Could not find Observation.valueQuantity.unit in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.unit,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.system') || can_resolve_path(@observation, 'valueQuantity.system') + skip 'Could not find Observation.valueQuantity.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.system,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.code') || can_resolve_path(@observation, 'valueQuantity.code') + skip 'Could not find Observation.valueQuantity.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.code,' + element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') + skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.dataAbsentReason,' + element_found = @instance.must_support_confirmed.include?('Observation.component') || can_resolve_path(@observation, 'component') + skip 'Could not find Observation.component in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component,' + element_found = @instance.must_support_confirmed.include?('Observation.component.code') || can_resolve_path(@observation, 'component.code') + skip 'Could not find Observation.component.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.code,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueQuantity') || can_resolve_path(@observation, 'component.valueQuantity') + skip 'Could not find Observation.component.valueQuantity in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueQuantity,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueCodeableConcept') || can_resolve_path(@observation, 'component.valueCodeableConcept') + skip 'Could not find Observation.component.valueCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueCodeableConcept,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuestring') || can_resolve_path(@observation, 'component.valuestring') + skip 'Could not find Observation.component.valuestring in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuestring,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueboolean') || can_resolve_path(@observation, 'component.valueboolean') + skip 'Could not find Observation.component.valueboolean in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueboolean,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueinteger') || can_resolve_path(@observation, 'component.valueinteger') + skip 'Could not find Observation.component.valueinteger in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueinteger,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueRange') || can_resolve_path(@observation, 'component.valueRange') + skip 'Could not find Observation.component.valueRange in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueRange,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueRatio') || can_resolve_path(@observation, 'component.valueRatio') + skip 'Could not find Observation.component.valueRatio in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueRatio,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueSampledData') || can_resolve_path(@observation, 'component.valueSampledData') + skip 'Could not find Observation.component.valueSampledData in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueSampledData,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuetime') || can_resolve_path(@observation, 'component.valuetime') + skip 'Could not find Observation.component.valuetime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuetime,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuedateTime') || can_resolve_path(@observation, 'component.valuedateTime') + skip 'Could not find Observation.component.valuedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuePeriod') || can_resolve_path(@observation, 'component.valuePeriod') + skip 'Could not find Observation.component.valuePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.component.dataAbsentReason') || can_resolve_path(@observation, 'component.dataAbsentReason') + skip 'Could not find Observation.component.dataAbsentReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.dataAbsentReason,' + @instance.save! + end + + test 'Observation resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-bmi-for-age.json' desc %( ) @@ -232,7 +328,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index acedfcb84..ffa121ba2 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -217,9 +217,105 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') + skip 'Could not find Observation.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.status,' + element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') + skip 'Could not find Observation.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category,' + element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') + skip 'Could not find Observation.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding') || can_resolve_path(@observation, 'category.coding') + skip 'Could not find Observation.category.coding in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding.system') || can_resolve_path(@observation, 'category.coding.system') + skip 'Could not find Observation.category.coding.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding.system,' + element_found = @instance.must_support_confirmed.include?('Observation.category.coding.code') || can_resolve_path(@observation, 'category.coding.code') + skip 'Could not find Observation.category.coding.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category.coding.code,' + element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') + skip 'Could not find Observation.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.subject,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') + skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') + skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.value') || can_resolve_path(@observation, 'valueQuantity.value') + skip 'Could not find Observation.valueQuantity.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.value,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.unit') || can_resolve_path(@observation, 'valueQuantity.unit') + skip 'Could not find Observation.valueQuantity.unit in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.unit,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.system') || can_resolve_path(@observation, 'valueQuantity.system') + skip 'Could not find Observation.valueQuantity.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.system,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.code') || can_resolve_path(@observation, 'valueQuantity.code') + skip 'Could not find Observation.valueQuantity.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity.code,' + element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') + skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.dataAbsentReason,' + element_found = @instance.must_support_confirmed.include?('Observation.component') || can_resolve_path(@observation, 'component') + skip 'Could not find Observation.component in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component,' + element_found = @instance.must_support_confirmed.include?('Observation.component.code') || can_resolve_path(@observation, 'component.code') + skip 'Could not find Observation.component.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.code,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueQuantity') || can_resolve_path(@observation, 'component.valueQuantity') + skip 'Could not find Observation.component.valueQuantity in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueQuantity,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueCodeableConcept') || can_resolve_path(@observation, 'component.valueCodeableConcept') + skip 'Could not find Observation.component.valueCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueCodeableConcept,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuestring') || can_resolve_path(@observation, 'component.valuestring') + skip 'Could not find Observation.component.valuestring in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuestring,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueboolean') || can_resolve_path(@observation, 'component.valueboolean') + skip 'Could not find Observation.component.valueboolean in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueboolean,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueinteger') || can_resolve_path(@observation, 'component.valueinteger') + skip 'Could not find Observation.component.valueinteger in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueinteger,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueRange') || can_resolve_path(@observation, 'component.valueRange') + skip 'Could not find Observation.component.valueRange in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueRange,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueRatio') || can_resolve_path(@observation, 'component.valueRatio') + skip 'Could not find Observation.component.valueRatio in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueRatio,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valueSampledData') || can_resolve_path(@observation, 'component.valueSampledData') + skip 'Could not find Observation.component.valueSampledData in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valueSampledData,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuetime') || can_resolve_path(@observation, 'component.valuetime') + skip 'Could not find Observation.component.valuetime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuetime,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuedateTime') || can_resolve_path(@observation, 'component.valuedateTime') + skip 'Could not find Observation.component.valuedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.component.valuePeriod') || can_resolve_path(@observation, 'component.valuePeriod') + skip 'Could not find Observation.component.valuePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.valuePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.component.dataAbsentReason') || can_resolve_path(@observation, 'component.dataAbsentReason') + skip 'Could not find Observation.component.dataAbsentReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.component.dataAbsentReason,' + @instance.save! + end + + test 'Observation resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-weight-for-height.json' desc %( ) @@ -232,7 +328,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 8fec0fd7f..6be05656a 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -145,9 +145,33 @@ def validate_resource_item(resource, property, value) validate_history_reply(@allergyintolerance, versioned_resource_class('AllergyIntolerance')) end - test 'AllergyIntolerance resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.clinicalStatus') || can_resolve_path(@allergyintolerance, 'clinicalStatus') + skip 'Could not find AllergyIntolerance.clinicalStatus in the provided resource' unless element_found + @instance.must_support_confirmed += 'AllergyIntolerance.clinicalStatus,' + element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.verificationStatus') || can_resolve_path(@allergyintolerance, 'verificationStatus') + skip 'Could not find AllergyIntolerance.verificationStatus in the provided resource' unless element_found + @instance.must_support_confirmed += 'AllergyIntolerance.verificationStatus,' + element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.code') || can_resolve_path(@allergyintolerance, 'code') + skip 'Could not find AllergyIntolerance.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'AllergyIntolerance.code,' + element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.patient') || can_resolve_path(@allergyintolerance, 'patient') + skip 'Could not find AllergyIntolerance.patient in the provided resource' unless element_found + @instance.must_support_confirmed += 'AllergyIntolerance.patient,' + @instance.save! + end + + test 'AllergyIntolerance resources associated with Patient conform to Argonaut profiles' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-allergyintolerance.json' desc %( ) @@ -160,7 +184,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '08' + id '09' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index 28913b11d..8f31684ca 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -193,9 +193,42 @@ def validate_resource_item(resource, property, value) validate_history_reply(@careplan, versioned_resource_class('CarePlan')) end - test 'CarePlan resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '09' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('CarePlan.text') || can_resolve_path(@careplan, 'text') + skip 'Could not find CarePlan.text in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.text,' + element_found = @instance.must_support_confirmed.include?('CarePlan.text.status') || can_resolve_path(@careplan, 'text.status') + skip 'Could not find CarePlan.text.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.text.status,' + element_found = @instance.must_support_confirmed.include?('CarePlan.status') || can_resolve_path(@careplan, 'status') + skip 'Could not find CarePlan.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.status,' + element_found = @instance.must_support_confirmed.include?('CarePlan.intent') || can_resolve_path(@careplan, 'intent') + skip 'Could not find CarePlan.intent in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.intent,' + element_found = @instance.must_support_confirmed.include?('CarePlan.category') || can_resolve_path(@careplan, 'category') + skip 'Could not find CarePlan.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.category,' + element_found = @instance.must_support_confirmed.include?('CarePlan.category') || can_resolve_path(@careplan, 'category') + skip 'Could not find CarePlan.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.category,' + element_found = @instance.must_support_confirmed.include?('CarePlan.subject') || can_resolve_path(@careplan, 'subject') + skip 'Could not find CarePlan.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'CarePlan.subject,' + @instance.save! + end + + test 'CarePlan resources associated with Patient conform to Argonaut profiles' do + metadata do + id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careplan.json' desc %( ) @@ -208,7 +241,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '10' + id '11' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 61169f318..421bd93c8 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -122,9 +122,36 @@ def validate_resource_item(resource, property, value) validate_history_reply(@careteam, versioned_resource_class('CareTeam')) end - test 'CareTeam resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '06' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('CareTeam.status') || can_resolve_path(@careteam, 'status') + skip 'Could not find CareTeam.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'CareTeam.status,' + element_found = @instance.must_support_confirmed.include?('CareTeam.subject') || can_resolve_path(@careteam, 'subject') + skip 'Could not find CareTeam.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'CareTeam.subject,' + element_found = @instance.must_support_confirmed.include?('CareTeam.participant') || can_resolve_path(@careteam, 'participant') + skip 'Could not find CareTeam.participant in the provided resource' unless element_found + @instance.must_support_confirmed += 'CareTeam.participant,' + element_found = @instance.must_support_confirmed.include?('CareTeam.participant.role') || can_resolve_path(@careteam, 'participant.role') + skip 'Could not find CareTeam.participant.role in the provided resource' unless element_found + @instance.must_support_confirmed += 'CareTeam.participant.role,' + element_found = @instance.must_support_confirmed.include?('CareTeam.participant.member') || can_resolve_path(@careteam, 'participant.member') + skip 'Could not find CareTeam.participant.member in the provided resource' unless element_found + @instance.must_support_confirmed += 'CareTeam.participant.member,' + @instance.save! + end + + test 'CareTeam resources associated with Patient conform to Argonaut profiles' do + metadata do + id '07' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careteam.json' desc %( ) @@ -137,7 +164,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '07' + id '08' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index a14ebddac..e7129b3fc 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -217,9 +217,36 @@ def validate_resource_item(resource, property, value) validate_history_reply(@condition, versioned_resource_class('Condition')) end - test 'Condition resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Condition.clinicalStatus') || can_resolve_path(@condition, 'clinicalStatus') + skip 'Could not find Condition.clinicalStatus in the provided resource' unless element_found + @instance.must_support_confirmed += 'Condition.clinicalStatus,' + element_found = @instance.must_support_confirmed.include?('Condition.verificationStatus') || can_resolve_path(@condition, 'verificationStatus') + skip 'Could not find Condition.verificationStatus in the provided resource' unless element_found + @instance.must_support_confirmed += 'Condition.verificationStatus,' + element_found = @instance.must_support_confirmed.include?('Condition.category') || can_resolve_path(@condition, 'category') + skip 'Could not find Condition.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Condition.category,' + element_found = @instance.must_support_confirmed.include?('Condition.code') || can_resolve_path(@condition, 'code') + skip 'Could not find Condition.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Condition.code,' + element_found = @instance.must_support_confirmed.include?('Condition.subject') || can_resolve_path(@condition, 'subject') + skip 'Could not find Condition.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Condition.subject,' + @instance.save! + end + + test 'Condition resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-condition.json' desc %( ) @@ -232,7 +259,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index 0861e2736..2cfaae900 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -145,9 +145,36 @@ def validate_resource_item(resource, property, value) validate_history_reply(@device, versioned_resource_class('Device')) end - test 'Device resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Device.udiCarrier') || can_resolve_path(@device, 'udiCarrier') + skip 'Could not find Device.udiCarrier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Device.udiCarrier,' + element_found = @instance.must_support_confirmed.include?('Device.udiCarrier.carrierAIDC') || can_resolve_path(@device, 'udiCarrier.carrierAIDC') + skip 'Could not find Device.udiCarrier.carrierAIDC in the provided resource' unless element_found + @instance.must_support_confirmed += 'Device.udiCarrier.carrierAIDC,' + element_found = @instance.must_support_confirmed.include?('Device.udiCarrier.carrierHRF') || can_resolve_path(@device, 'udiCarrier.carrierHRF') + skip 'Could not find Device.udiCarrier.carrierHRF in the provided resource' unless element_found + @instance.must_support_confirmed += 'Device.udiCarrier.carrierHRF,' + element_found = @instance.must_support_confirmed.include?('Device.type') || can_resolve_path(@device, 'type') + skip 'Could not find Device.type in the provided resource' unless element_found + @instance.must_support_confirmed += 'Device.type,' + element_found = @instance.must_support_confirmed.include?('Device.patient') || can_resolve_path(@device, 'patient') + skip 'Could not find Device.patient in the provided resource' unless element_found + @instance.must_support_confirmed += 'Device.patient,' + @instance.save! + end + + test 'Device resources associated with Patient conform to Argonaut profiles' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-device.json' desc %( ) @@ -160,7 +187,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '08' + id '09' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index e4d2a127e..747baead0 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -270,9 +270,54 @@ def validate_resource_item(resource, property, value) validate_history_reply(@diagnosticreport, versioned_resource_class('DiagnosticReport')) end - test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.status') || can_resolve_path(@diagnosticreport, 'status') + skip 'Could not find DiagnosticReport.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.status,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.category') || can_resolve_path(@diagnosticreport, 'category') + skip 'Could not find DiagnosticReport.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.category,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.code') || can_resolve_path(@diagnosticreport, 'code') + skip 'Could not find DiagnosticReport.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.code,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.subject') || can_resolve_path(@diagnosticreport, 'subject') + skip 'Could not find DiagnosticReport.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.subject,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivedateTime') || can_resolve_path(@diagnosticreport, 'effectivedateTime') + skip 'Could not find DiagnosticReport.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivePeriod') || can_resolve_path(@diagnosticreport, 'effectivePeriod') + skip 'Could not find DiagnosticReport.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.issued') || can_resolve_path(@diagnosticreport, 'issued') + skip 'Could not find DiagnosticReport.issued in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.issued,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.performer') || can_resolve_path(@diagnosticreport, 'performer') + skip 'Could not find DiagnosticReport.performer in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.performer,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.result') || can_resolve_path(@diagnosticreport, 'result') + skip 'Could not find DiagnosticReport.result in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.result,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.media') || can_resolve_path(@diagnosticreport, 'media') + skip 'Could not find DiagnosticReport.media in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.media,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.presentedForm') || can_resolve_path(@diagnosticreport, 'presentedForm') + skip 'Could not find DiagnosticReport.presentedForm in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.presentedForm,' + @instance.save! + end + + test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-lab.json' desc %( ) @@ -285,7 +330,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '14' + id '15' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index 9783a9a06..4fcda3d3c 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -270,9 +270,54 @@ def validate_resource_item(resource, property, value) validate_history_reply(@diagnosticreport, versioned_resource_class('DiagnosticReport')) end - test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.status') || can_resolve_path(@diagnosticreport, 'status') + skip 'Could not find DiagnosticReport.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.status,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.category') || can_resolve_path(@diagnosticreport, 'category') + skip 'Could not find DiagnosticReport.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.category,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.code') || can_resolve_path(@diagnosticreport, 'code') + skip 'Could not find DiagnosticReport.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.code,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.subject') || can_resolve_path(@diagnosticreport, 'subject') + skip 'Could not find DiagnosticReport.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.subject,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.encounter') || can_resolve_path(@diagnosticreport, 'encounter') + skip 'Could not find DiagnosticReport.encounter in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.encounter,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivedateTime') || can_resolve_path(@diagnosticreport, 'effectivedateTime') + skip 'Could not find DiagnosticReport.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivePeriod') || can_resolve_path(@diagnosticreport, 'effectivePeriod') + skip 'Could not find DiagnosticReport.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.issued') || can_resolve_path(@diagnosticreport, 'issued') + skip 'Could not find DiagnosticReport.issued in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.issued,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.performer') || can_resolve_path(@diagnosticreport, 'performer') + skip 'Could not find DiagnosticReport.performer in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.performer,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.media') || can_resolve_path(@diagnosticreport, 'media') + skip 'Could not find DiagnosticReport.media in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.media,' + element_found = @instance.must_support_confirmed.include?('DiagnosticReport.presentedForm') || can_resolve_path(@diagnosticreport, 'presentedForm') + skip 'Could not find DiagnosticReport.presentedForm in the provided resource' unless element_found + @instance.must_support_confirmed += 'DiagnosticReport.presentedForm,' + @instance.save! + end + + test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-note.json' desc %( ) @@ -285,7 +330,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '14' + id '15' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index cb372728d..985d4ac24 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -276,9 +276,72 @@ def validate_resource_item(resource, property, value) validate_history_reply(@documentreference, versioned_resource_class('DocumentReference')) end - test 'DocumentReference resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('DocumentReference.identifier') || can_resolve_path(@documentreference, 'identifier') + skip 'Could not find DocumentReference.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.identifier,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.status') || can_resolve_path(@documentreference, 'status') + skip 'Could not find DocumentReference.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.status,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.type') || can_resolve_path(@documentreference, 'type') + skip 'Could not find DocumentReference.type in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.type,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.category') || can_resolve_path(@documentreference, 'category') + skip 'Could not find DocumentReference.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.category,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.subject') || can_resolve_path(@documentreference, 'subject') + skip 'Could not find DocumentReference.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.subject,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.date') || can_resolve_path(@documentreference, 'date') + skip 'Could not find DocumentReference.date in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.date,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.author') || can_resolve_path(@documentreference, 'author') + skip 'Could not find DocumentReference.author in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.author,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.custodian') || can_resolve_path(@documentreference, 'custodian') + skip 'Could not find DocumentReference.custodian in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.custodian,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content') || can_resolve_path(@documentreference, 'content') + skip 'Could not find DocumentReference.content in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment') || can_resolve_path(@documentreference, 'content.attachment') + skip 'Could not find DocumentReference.content.attachment in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content.attachment,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.contentType') || can_resolve_path(@documentreference, 'content.attachment.contentType') + skip 'Could not find DocumentReference.content.attachment.contentType in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content.attachment.contentType,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.data') || can_resolve_path(@documentreference, 'content.attachment.data') + skip 'Could not find DocumentReference.content.attachment.data in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content.attachment.data,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.url') || can_resolve_path(@documentreference, 'content.attachment.url') + skip 'Could not find DocumentReference.content.attachment.url in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content.attachment.url,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.content.format') || can_resolve_path(@documentreference, 'content.format') + skip 'Could not find DocumentReference.content.format in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.content.format,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.context') || can_resolve_path(@documentreference, 'context') + skip 'Could not find DocumentReference.context in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.context,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.context.encounter') || can_resolve_path(@documentreference, 'context.encounter') + skip 'Could not find DocumentReference.context.encounter in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.context.encounter,' + element_found = @instance.must_support_confirmed.include?('DocumentReference.context.period') || can_resolve_path(@documentreference, 'context.period') + skip 'Could not find DocumentReference.context.period in the provided resource' unless element_found + @instance.must_support_confirmed += 'DocumentReference.context.period,' + @instance.save! + end + + test 'DocumentReference resources associated with Patient conform to Argonaut profiles' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-documentreference.json' desc %( ) @@ -291,7 +354,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '14' + id '15' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index b96594e62..d09435836 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -257,9 +257,72 @@ def validate_resource_item(resource, property, value) validate_history_reply(@encounter, versioned_resource_class('Encounter')) end - test 'Encounter resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '12' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Encounter.identifier') || can_resolve_path(@encounter, 'identifier') + skip 'Could not find Encounter.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.identifier,' + element_found = @instance.must_support_confirmed.include?('Encounter.identifier.system') || can_resolve_path(@encounter, 'identifier.system') + skip 'Could not find Encounter.identifier.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.identifier.system,' + element_found = @instance.must_support_confirmed.include?('Encounter.identifier.value') || can_resolve_path(@encounter, 'identifier.value') + skip 'Could not find Encounter.identifier.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.identifier.value,' + element_found = @instance.must_support_confirmed.include?('Encounter.status') || can_resolve_path(@encounter, 'status') + skip 'Could not find Encounter.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.status,' + element_found = @instance.must_support_confirmed.include?('Encounter.class') || can_resolve_path(@encounter, 'class') + skip 'Could not find Encounter.class in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.class,' + element_found = @instance.must_support_confirmed.include?('Encounter.type') || can_resolve_path(@encounter, 'type') + skip 'Could not find Encounter.type in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.type,' + element_found = @instance.must_support_confirmed.include?('Encounter.subject') || can_resolve_path(@encounter, 'subject') + skip 'Could not find Encounter.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.subject,' + element_found = @instance.must_support_confirmed.include?('Encounter.participant') || can_resolve_path(@encounter, 'participant') + skip 'Could not find Encounter.participant in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.participant,' + element_found = @instance.must_support_confirmed.include?('Encounter.participant.type') || can_resolve_path(@encounter, 'participant.type') + skip 'Could not find Encounter.participant.type in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.participant.type,' + element_found = @instance.must_support_confirmed.include?('Encounter.participant.period') || can_resolve_path(@encounter, 'participant.period') + skip 'Could not find Encounter.participant.period in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.participant.period,' + element_found = @instance.must_support_confirmed.include?('Encounter.participant.individual') || can_resolve_path(@encounter, 'participant.individual') + skip 'Could not find Encounter.participant.individual in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.participant.individual,' + element_found = @instance.must_support_confirmed.include?('Encounter.period') || can_resolve_path(@encounter, 'period') + skip 'Could not find Encounter.period in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.period,' + element_found = @instance.must_support_confirmed.include?('Encounter.reasonCode') || can_resolve_path(@encounter, 'reasonCode') + skip 'Could not find Encounter.reasonCode in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.reasonCode,' + element_found = @instance.must_support_confirmed.include?('Encounter.hospitalization') || can_resolve_path(@encounter, 'hospitalization') + skip 'Could not find Encounter.hospitalization in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.hospitalization,' + element_found = @instance.must_support_confirmed.include?('Encounter.hospitalization.dischargeDisposition') || can_resolve_path(@encounter, 'hospitalization.dischargeDisposition') + skip 'Could not find Encounter.hospitalization.dischargeDisposition in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.hospitalization.dischargeDisposition,' + element_found = @instance.must_support_confirmed.include?('Encounter.location') || can_resolve_path(@encounter, 'location') + skip 'Could not find Encounter.location in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.location,' + element_found = @instance.must_support_confirmed.include?('Encounter.location.location') || can_resolve_path(@encounter, 'location.location') + skip 'Could not find Encounter.location.location in the provided resource' unless element_found + @instance.must_support_confirmed += 'Encounter.location.location,' + @instance.save! + end + + test 'Encounter resources associated with Patient conform to Argonaut profiles' do + metadata do + id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-encounter.json' desc %( ) @@ -272,7 +335,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '13' + id '14' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index 31455eca9..bc4d04673 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -165,9 +165,39 @@ def validate_resource_item(resource, property, value) validate_history_reply(@goal, versioned_resource_class('Goal')) end - test 'Goal resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Goal.lifecycleStatus') || can_resolve_path(@goal, 'lifecycleStatus') + skip 'Could not find Goal.lifecycleStatus in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.lifecycleStatus,' + element_found = @instance.must_support_confirmed.include?('Goal.description') || can_resolve_path(@goal, 'description') + skip 'Could not find Goal.description in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.description,' + element_found = @instance.must_support_confirmed.include?('Goal.subject') || can_resolve_path(@goal, 'subject') + skip 'Could not find Goal.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.subject,' + element_found = @instance.must_support_confirmed.include?('Goal.target') || can_resolve_path(@goal, 'target') + skip 'Could not find Goal.target in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.target,' + element_found = @instance.must_support_confirmed.include?('Goal.target.duedate') || can_resolve_path(@goal, 'target.duedate') + skip 'Could not find Goal.target.duedate in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.target.duedate,' + element_found = @instance.must_support_confirmed.include?('Goal.target.dueDuration') || can_resolve_path(@goal, 'target.dueDuration') + skip 'Could not find Goal.target.dueDuration in the provided resource' unless element_found + @instance.must_support_confirmed += 'Goal.target.dueDuration,' + @instance.save! + end + + test 'Goal resources associated with Patient conform to Argonaut profiles' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-goal.json' desc %( ) @@ -180,7 +210,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '09' + id '10' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index ea7d3ee0e..a769188ba 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -165,9 +165,42 @@ def validate_resource_item(resource, property, value) validate_history_reply(@immunization, versioned_resource_class('Immunization')) end - test 'Immunization resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Immunization.status') || can_resolve_path(@immunization, 'status') + skip 'Could not find Immunization.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.status,' + element_found = @instance.must_support_confirmed.include?('Immunization.statusReason') || can_resolve_path(@immunization, 'statusReason') + skip 'Could not find Immunization.statusReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.statusReason,' + element_found = @instance.must_support_confirmed.include?('Immunization.vaccineCode') || can_resolve_path(@immunization, 'vaccineCode') + skip 'Could not find Immunization.vaccineCode in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.vaccineCode,' + element_found = @instance.must_support_confirmed.include?('Immunization.patient') || can_resolve_path(@immunization, 'patient') + skip 'Could not find Immunization.patient in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.patient,' + element_found = @instance.must_support_confirmed.include?('Immunization.occurrencedateTime') || can_resolve_path(@immunization, 'occurrencedateTime') + skip 'Could not find Immunization.occurrencedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.occurrencedateTime,' + element_found = @instance.must_support_confirmed.include?('Immunization.occurrencestring') || can_resolve_path(@immunization, 'occurrencestring') + skip 'Could not find Immunization.occurrencestring in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.occurrencestring,' + element_found = @instance.must_support_confirmed.include?('Immunization.primarySource') || can_resolve_path(@immunization, 'primarySource') + skip 'Could not find Immunization.primarySource in the provided resource' unless element_found + @instance.must_support_confirmed += 'Immunization.primarySource,' + @instance.save! + end + + test 'Immunization resources associated with Patient conform to Argonaut profiles' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-immunization.json' desc %( ) @@ -180,7 +213,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '09' + id '10' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index 6fc6e6703..cfdd15958 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -206,9 +206,48 @@ def validate_resource_item(resource, property, value) validate_history_reply(@location, versioned_resource_class('Location')) end - test 'Location resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Location.status') || can_resolve_path(@location, 'status') + skip 'Could not find Location.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.status,' + element_found = @instance.must_support_confirmed.include?('Location.name') || can_resolve_path(@location, 'name') + skip 'Could not find Location.name in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.name,' + element_found = @instance.must_support_confirmed.include?('Location.telecom') || can_resolve_path(@location, 'telecom') + skip 'Could not find Location.telecom in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.telecom,' + element_found = @instance.must_support_confirmed.include?('Location.address') || can_resolve_path(@location, 'address') + skip 'Could not find Location.address in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.address,' + element_found = @instance.must_support_confirmed.include?('Location.address.line') || can_resolve_path(@location, 'address.line') + skip 'Could not find Location.address.line in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.address.line,' + element_found = @instance.must_support_confirmed.include?('Location.address.city') || can_resolve_path(@location, 'address.city') + skip 'Could not find Location.address.city in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.address.city,' + element_found = @instance.must_support_confirmed.include?('Location.address.state') || can_resolve_path(@location, 'address.state') + skip 'Could not find Location.address.state in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.address.state,' + element_found = @instance.must_support_confirmed.include?('Location.address.postalCode') || can_resolve_path(@location, 'address.postalCode') + skip 'Could not find Location.address.postalCode in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.address.postalCode,' + element_found = @instance.must_support_confirmed.include?('Location.managingOrganization') || can_resolve_path(@location, 'managingOrganization') + skip 'Could not find Location.managingOrganization in the provided resource' unless element_found + @instance.must_support_confirmed += 'Location.managingOrganization,' + @instance.save! + end + + test 'Location resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-location.json' desc %( ) @@ -221,7 +260,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index 58842d85f..2ed1612e9 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -85,9 +85,24 @@ class UsCoreR4MedicationSequence < SequenceBase validate_history_reply(@medication, versioned_resource_class('Medication')) end - test 'Medication resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '05' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Medication.code') || can_resolve_path(@medication, 'code') + skip 'Could not find Medication.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Medication.code,' + @instance.save! + end + + test 'Medication resources associated with Patient conform to Argonaut profiles' do + metadata do + id '06' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medication.json' desc %( ) @@ -100,7 +115,7 @@ class UsCoreR4MedicationSequence < SequenceBase test 'All references can be resolved' do metadata do - id '06' + id '07' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index c4b2e8a52..c1373744f 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -165,9 +165,45 @@ def validate_resource_item(resource, property, value) validate_history_reply(@medicationrequest, versioned_resource_class('MedicationRequest')) end - test 'MedicationRequest resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('MedicationRequest.status') || can_resolve_path(@medicationrequest, 'status') + skip 'Could not find MedicationRequest.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.status,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.medicationCodeableConcept') || can_resolve_path(@medicationrequest, 'medicationCodeableConcept') + skip 'Could not find MedicationRequest.medicationCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.medicationCodeableConcept,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.medicationReference') || can_resolve_path(@medicationrequest, 'medicationReference') + skip 'Could not find MedicationRequest.medicationReference in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.medicationReference,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.subject') || can_resolve_path(@medicationrequest, 'subject') + skip 'Could not find MedicationRequest.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.subject,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.authoredOn') || can_resolve_path(@medicationrequest, 'authoredOn') + skip 'Could not find MedicationRequest.authoredOn in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.authoredOn,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.requester') || can_resolve_path(@medicationrequest, 'requester') + skip 'Could not find MedicationRequest.requester in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.requester,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.dosageInstruction') || can_resolve_path(@medicationrequest, 'dosageInstruction') + skip 'Could not find MedicationRequest.dosageInstruction in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.dosageInstruction,' + element_found = @instance.must_support_confirmed.include?('MedicationRequest.dosageInstruction.text') || can_resolve_path(@medicationrequest, 'dosageInstruction.text') + skip 'Could not find MedicationRequest.dosageInstruction.text in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationRequest.dosageInstruction.text,' + @instance.save! + end + + test 'MedicationRequest resources associated with Patient conform to Argonaut profiles' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationrequest.json' desc %( ) @@ -180,7 +216,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '09' + id '10' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index 8664da0fe..e9b74fbb1 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -165,9 +165,45 @@ def validate_resource_item(resource, property, value) validate_history_reply(@medicationstatement, versioned_resource_class('MedicationStatement')) end - test 'MedicationStatement resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('MedicationStatement.status') || can_resolve_path(@medicationstatement, 'status') + skip 'Could not find MedicationStatement.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.status,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.medicationCodeableConcept') || can_resolve_path(@medicationstatement, 'medicationCodeableConcept') + skip 'Could not find MedicationStatement.medicationCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.medicationCodeableConcept,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.medicationReference') || can_resolve_path(@medicationstatement, 'medicationReference') + skip 'Could not find MedicationStatement.medicationReference in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.medicationReference,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.subject') || can_resolve_path(@medicationstatement, 'subject') + skip 'Could not find MedicationStatement.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.subject,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.effectivedateTime') || can_resolve_path(@medicationstatement, 'effectivedateTime') + skip 'Could not find MedicationStatement.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.effectivePeriod') || can_resolve_path(@medicationstatement, 'effectivePeriod') + skip 'Could not find MedicationStatement.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.dateAsserted') || can_resolve_path(@medicationstatement, 'dateAsserted') + skip 'Could not find MedicationStatement.dateAsserted in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.dateAsserted,' + element_found = @instance.must_support_confirmed.include?('MedicationStatement.derivedFrom') || can_resolve_path(@medicationstatement, 'derivedFrom') + skip 'Could not find MedicationStatement.derivedFrom in the provided resource' unless element_found + @instance.must_support_confirmed += 'MedicationStatement.derivedFrom,' + @instance.save! + end + + test 'MedicationStatement resources associated with Patient conform to Argonaut profiles' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationstatement.json' desc %( ) @@ -180,7 +216,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '09' + id '10' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index 458afcbf4..0cc11db77 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -217,9 +217,75 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') + skip 'Could not find Observation.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.status,' + element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') + skip 'Could not find Observation.category in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.category,' + element_found = @instance.must_support_confirmed.include?('Observation.code') || can_resolve_path(@observation, 'code') + skip 'Could not find Observation.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.code,' + element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') + skip 'Could not find Observation.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.subject,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') + skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') + skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.effectivePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity') || can_resolve_path(@observation, 'valueQuantity') + skip 'Could not find Observation.valueQuantity in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueQuantity,' + element_found = @instance.must_support_confirmed.include?('Observation.valueCodeableConcept') || can_resolve_path(@observation, 'valueCodeableConcept') + skip 'Could not find Observation.valueCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueCodeableConcept,' + element_found = @instance.must_support_confirmed.include?('Observation.valuestring') || can_resolve_path(@observation, 'valuestring') + skip 'Could not find Observation.valuestring in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valuestring,' + element_found = @instance.must_support_confirmed.include?('Observation.valueboolean') || can_resolve_path(@observation, 'valueboolean') + skip 'Could not find Observation.valueboolean in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueboolean,' + element_found = @instance.must_support_confirmed.include?('Observation.valueinteger') || can_resolve_path(@observation, 'valueinteger') + skip 'Could not find Observation.valueinteger in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueinteger,' + element_found = @instance.must_support_confirmed.include?('Observation.valueRange') || can_resolve_path(@observation, 'valueRange') + skip 'Could not find Observation.valueRange in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueRange,' + element_found = @instance.must_support_confirmed.include?('Observation.valueRatio') || can_resolve_path(@observation, 'valueRatio') + skip 'Could not find Observation.valueRatio in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueRatio,' + element_found = @instance.must_support_confirmed.include?('Observation.valueSampledData') || can_resolve_path(@observation, 'valueSampledData') + skip 'Could not find Observation.valueSampledData in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueSampledData,' + element_found = @instance.must_support_confirmed.include?('Observation.valuetime') || can_resolve_path(@observation, 'valuetime') + skip 'Could not find Observation.valuetime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valuetime,' + element_found = @instance.must_support_confirmed.include?('Observation.valuedateTime') || can_resolve_path(@observation, 'valuedateTime') + skip 'Could not find Observation.valuedateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valuedateTime,' + element_found = @instance.must_support_confirmed.include?('Observation.valuePeriod') || can_resolve_path(@observation, 'valuePeriod') + skip 'Could not find Observation.valuePeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valuePeriod,' + element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') + skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.dataAbsentReason,' + @instance.save! + end + + test 'Observation resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-observation-lab.json' desc %( ) @@ -232,7 +298,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index 69c4189cd..a58a3183b 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -140,9 +140,57 @@ def validate_resource_item(resource, property, value) validate_history_reply(@organization, versioned_resource_class('Organization')) end - test 'Organization resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Organization.identifier') || can_resolve_path(@organization, 'identifier') + skip 'Could not find Organization.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.identifier,' + element_found = @instance.must_support_confirmed.include?('Organization.identifier.system') || can_resolve_path(@organization, 'identifier.system') + skip 'Could not find Organization.identifier.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.identifier.system,' + element_found = @instance.must_support_confirmed.include?('Organization.active') || can_resolve_path(@organization, 'active') + skip 'Could not find Organization.active in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.active,' + element_found = @instance.must_support_confirmed.include?('Organization.name') || can_resolve_path(@organization, 'name') + skip 'Could not find Organization.name in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.name,' + element_found = @instance.must_support_confirmed.include?('Organization.telecom') || can_resolve_path(@organization, 'telecom') + skip 'Could not find Organization.telecom in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.telecom,' + element_found = @instance.must_support_confirmed.include?('Organization.address') || can_resolve_path(@organization, 'address') + skip 'Could not find Organization.address in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address,' + element_found = @instance.must_support_confirmed.include?('Organization.address.line') || can_resolve_path(@organization, 'address.line') + skip 'Could not find Organization.address.line in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address.line,' + element_found = @instance.must_support_confirmed.include?('Organization.address.city') || can_resolve_path(@organization, 'address.city') + skip 'Could not find Organization.address.city in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address.city,' + element_found = @instance.must_support_confirmed.include?('Organization.address.state') || can_resolve_path(@organization, 'address.state') + skip 'Could not find Organization.address.state in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address.state,' + element_found = @instance.must_support_confirmed.include?('Organization.address.postalCode') || can_resolve_path(@organization, 'address.postalCode') + skip 'Could not find Organization.address.postalCode in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address.postalCode,' + element_found = @instance.must_support_confirmed.include?('Organization.address.country') || can_resolve_path(@organization, 'address.country') + skip 'Could not find Organization.address.country in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.address.country,' + element_found = @instance.must_support_confirmed.include?('Organization.endpoint') || can_resolve_path(@organization, 'endpoint') + skip 'Could not find Organization.endpoint in the provided resource' unless element_found + @instance.must_support_confirmed += 'Organization.endpoint,' + @instance.save! + end + + test 'Organization resources associated with Patient conform to Argonaut profiles' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-organization.json' desc %( ) @@ -155,7 +203,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '08' + id '09' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index 511db4a49..55ae8d82a 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -260,9 +260,84 @@ def validate_resource_item(resource, property, value) validate_history_reply(@patient, versioned_resource_class('Patient')) end - test 'Patient resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '12' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Patient.extension:race') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race' } + skip 'Could not find Patient.extension:race in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.extension:race,' + element_found = @instance.must_support_confirmed.include?('Patient.extension:ethnicity') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity' } + skip 'Could not find Patient.extension:ethnicity in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.extension:ethnicity,' + element_found = @instance.must_support_confirmed.include?('Patient.extension:birthsex') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } + skip 'Could not find Patient.extension:birthsex in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.extension:birthsex,' + element_found = @instance.must_support_confirmed.include?('Patient.identifier') || can_resolve_path(@patient, 'identifier') + skip 'Could not find Patient.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.identifier,' + element_found = @instance.must_support_confirmed.include?('Patient.identifier.system') || can_resolve_path(@patient, 'identifier.system') + skip 'Could not find Patient.identifier.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.identifier.system,' + element_found = @instance.must_support_confirmed.include?('Patient.identifier.value') || can_resolve_path(@patient, 'identifier.value') + skip 'Could not find Patient.identifier.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.identifier.value,' + element_found = @instance.must_support_confirmed.include?('Patient.name') || can_resolve_path(@patient, 'name') + skip 'Could not find Patient.name in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.name,' + element_found = @instance.must_support_confirmed.include?('Patient.name.family') || can_resolve_path(@patient, 'name.family') + skip 'Could not find Patient.name.family in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.name.family,' + element_found = @instance.must_support_confirmed.include?('Patient.name.given') || can_resolve_path(@patient, 'name.given') + skip 'Could not find Patient.name.given in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.name.given,' + element_found = @instance.must_support_confirmed.include?('Patient.telecom') || can_resolve_path(@patient, 'telecom') + skip 'Could not find Patient.telecom in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.telecom,' + element_found = @instance.must_support_confirmed.include?('Patient.telecom.system') || can_resolve_path(@patient, 'telecom.system') + skip 'Could not find Patient.telecom.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.telecom.system,' + element_found = @instance.must_support_confirmed.include?('Patient.telecom.value') || can_resolve_path(@patient, 'telecom.value') + skip 'Could not find Patient.telecom.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.telecom.value,' + element_found = @instance.must_support_confirmed.include?('Patient.gender') || can_resolve_path(@patient, 'gender') + skip 'Could not find Patient.gender in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.gender,' + element_found = @instance.must_support_confirmed.include?('Patient.birthDate') || can_resolve_path(@patient, 'birthDate') + skip 'Could not find Patient.birthDate in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.birthDate,' + element_found = @instance.must_support_confirmed.include?('Patient.address') || can_resolve_path(@patient, 'address') + skip 'Could not find Patient.address in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.address,' + element_found = @instance.must_support_confirmed.include?('Patient.address.line') || can_resolve_path(@patient, 'address.line') + skip 'Could not find Patient.address.line in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.address.line,' + element_found = @instance.must_support_confirmed.include?('Patient.address.city') || can_resolve_path(@patient, 'address.city') + skip 'Could not find Patient.address.city in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.address.city,' + element_found = @instance.must_support_confirmed.include?('Patient.address.state') || can_resolve_path(@patient, 'address.state') + skip 'Could not find Patient.address.state in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.address.state,' + element_found = @instance.must_support_confirmed.include?('Patient.address.postalCode') || can_resolve_path(@patient, 'address.postalCode') + skip 'Could not find Patient.address.postalCode in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.address.postalCode,' + element_found = @instance.must_support_confirmed.include?('Patient.communication') || can_resolve_path(@patient, 'communication') + skip 'Could not find Patient.communication in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.communication,' + element_found = @instance.must_support_confirmed.include?('Patient.communication.language') || can_resolve_path(@patient, 'communication.language') + skip 'Could not find Patient.communication.language in the provided resource' unless element_found + @instance.must_support_confirmed += 'Patient.communication.language,' + @instance.save! + end + + test 'Patient resources associated with Patient conform to Argonaut profiles' do + metadata do + id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-patient.json' desc %( ) @@ -275,7 +350,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '13' + id '14' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index 5fb4e3a3a..a57da3b22 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -148,9 +148,42 @@ def validate_resource_item(resource, property, value) validate_history_reply(@practitioner, versioned_resource_class('Practitioner')) end - test 'Practitioner resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Practitioner.identifier') || can_resolve_path(@practitioner, 'identifier') + skip 'Could not find Practitioner.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.identifier,' + element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.system') || can_resolve_path(@practitioner, 'identifier.system') + skip 'Could not find Practitioner.identifier.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.identifier.system,' + element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.value') || can_resolve_path(@practitioner, 'identifier.value') + skip 'Could not find Practitioner.identifier.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.identifier.value,' + element_found = @instance.must_support_confirmed.include?('Practitioner.identifier') || can_resolve_path(@practitioner, 'identifier') + skip 'Could not find Practitioner.identifier in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.identifier,' + element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.system') || can_resolve_path(@practitioner, 'identifier.system') + skip 'Could not find Practitioner.identifier.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.identifier.system,' + element_found = @instance.must_support_confirmed.include?('Practitioner.name') || can_resolve_path(@practitioner, 'name') + skip 'Could not find Practitioner.name in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.name,' + element_found = @instance.must_support_confirmed.include?('Practitioner.name.family') || can_resolve_path(@practitioner, 'name.family') + skip 'Could not find Practitioner.name.family in the provided resource' unless element_found + @instance.must_support_confirmed += 'Practitioner.name.family,' + @instance.save! + end + + test 'Practitioner resources associated with Patient conform to Argonaut profiles' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitioner.json' desc %( ) @@ -163,7 +196,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '08' + id '09' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index c9f925b8b..d6b3b98cb 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -144,9 +144,48 @@ def validate_resource_item(resource, property, value) validate_history_reply(@practitionerrole, versioned_resource_class('PractitionerRole')) end - test 'PractitionerRole resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('PractitionerRole.practitioner') || can_resolve_path(@practitionerrole, 'practitioner') + skip 'Could not find PractitionerRole.practitioner in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.practitioner,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.organization') || can_resolve_path(@practitionerrole, 'organization') + skip 'Could not find PractitionerRole.organization in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.organization,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.code') || can_resolve_path(@practitionerrole, 'code') + skip 'Could not find PractitionerRole.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.code,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.specialty') || can_resolve_path(@practitionerrole, 'specialty') + skip 'Could not find PractitionerRole.specialty in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.specialty,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.location') || can_resolve_path(@practitionerrole, 'location') + skip 'Could not find PractitionerRole.location in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.location,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom') || can_resolve_path(@practitionerrole, 'telecom') + skip 'Could not find PractitionerRole.telecom in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.telecom,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom.system') || can_resolve_path(@practitionerrole, 'telecom.system') + skip 'Could not find PractitionerRole.telecom.system in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.telecom.system,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom.value') || can_resolve_path(@practitionerrole, 'telecom.value') + skip 'Could not find PractitionerRole.telecom.value in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.telecom.value,' + element_found = @instance.must_support_confirmed.include?('PractitionerRole.endpoint') || can_resolve_path(@practitionerrole, 'endpoint') + skip 'Could not find PractitionerRole.endpoint in the provided resource' unless element_found + @instance.must_support_confirmed += 'PractitionerRole.endpoint,' + @instance.save! + end + + test 'PractitionerRole resources associated with Patient conform to Argonaut profiles' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitionerrole.json' desc %( ) @@ -159,7 +198,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '08' + id '09' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index 2cc6d1472..606e2ff1d 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -191,9 +191,36 @@ def validate_resource_item(resource, property, value) validate_history_reply(@procedure, versioned_resource_class('Procedure')) end - test 'Procedure resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '09' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Procedure.status') || can_resolve_path(@procedure, 'status') + skip 'Could not find Procedure.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Procedure.status,' + element_found = @instance.must_support_confirmed.include?('Procedure.code') || can_resolve_path(@procedure, 'code') + skip 'Could not find Procedure.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Procedure.code,' + element_found = @instance.must_support_confirmed.include?('Procedure.subject') || can_resolve_path(@procedure, 'subject') + skip 'Could not find Procedure.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Procedure.subject,' + element_found = @instance.must_support_confirmed.include?('Procedure.performeddateTime') || can_resolve_path(@procedure, 'performeddateTime') + skip 'Could not find Procedure.performeddateTime in the provided resource' unless element_found + @instance.must_support_confirmed += 'Procedure.performeddateTime,' + element_found = @instance.must_support_confirmed.include?('Procedure.performedPeriod') || can_resolve_path(@procedure, 'performedPeriod') + skip 'Could not find Procedure.performedPeriod in the provided resource' unless element_found + @instance.must_support_confirmed += 'Procedure.performedPeriod,' + @instance.save! + end + + test 'Procedure resources associated with Patient conform to Argonaut profiles' do + metadata do + id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-procedure.json' desc %( ) @@ -206,7 +233,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '10' + id '11' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 2016235cb..4b7198ac9 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -217,9 +217,36 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Demonstrates that the server can supply must supported elements' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' + desc %( + ) + versions :r4 + end + + element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') + skip 'Could not find Observation.status in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.status,' + element_found = @instance.must_support_confirmed.include?('Observation.code') || can_resolve_path(@observation, 'code') + skip 'Could not find Observation.code in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.code,' + element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') + skip 'Could not find Observation.subject in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.subject,' + element_found = @instance.must_support_confirmed.include?('Observation.issued') || can_resolve_path(@observation, 'issued') + skip 'Could not find Observation.issued in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.issued,' + element_found = @instance.must_support_confirmed.include?('Observation.valueCodeableConcept') || can_resolve_path(@observation, 'valueCodeableConcept') + skip 'Could not find Observation.valueCodeableConcept in the provided resource' unless element_found + @instance.must_support_confirmed += 'Observation.valueCodeableConcept,' + @instance.save! + end + + test 'Observation resources associated with Patient conform to Argonaut profiles' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-smokingstatus.json' desc %( ) @@ -232,7 +259,7 @@ def validate_resource_item(resource, property, value) test 'All references can be resolved' do metadata do - id '11' + id '12' link 'https://www.hl7.org/fhir/DSTU2/references.html' desc %( ) diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index d5f467ba8..4a2abf860 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -746,6 +746,17 @@ def check_resource_against_profile(resource, resource_type, specified_profile = end assert(errors.empty?, errors.join("
\n")) end + + def can_resolve_path(element, path) + return true if path.empty? + + path_ary = path.split('.') + el_as_array = Array.wrap(element) + cur_path_part = path_ary.delete_at(0) + return false unless el_as_array.any? { |el| !el.try(cur_path_part.to_sym).nil? } + + el_as_array.any? { |el| can_resolve_path(el.send(cur_path_part), path_ary.join('.')) } + end end Dir.glob(File.join(__dir__, 'modules', '**', '*_sequence.rb')).each { |file| require file } From db6faa1ee466be20a568c6f780ade0f950d70433 Mon Sep 17 00:00:00 2001 From: Chase Zhou Date: Thu, 20 Jun 2019 18:09:54 -0400 Subject: [PATCH 02/89] fix lints --- generators/argonaut-r4/generator.rb | 4 +++- lib/app/models/testing_instance.rb | 2 +- lib/app/modules/us_core_r4/us_core_encounter_sequence.rb | 2 +- lib/app/modules/us_core_r4/us_core_patient_sequence.rb | 9 ++++++--- lib/app/sequence_base.rb | 9 +-------- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/generators/argonaut-r4/generator.rb b/generators/argonaut-r4/generator.rb index f45983ab5..35b6860ba 100644 --- a/generators/argonaut-r4/generator.rb +++ b/generators/argonaut-r4/generator.rb @@ -150,13 +150,15 @@ def create_must_support_test(sequence) sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| test[:test_code] += %( - element_found = @instance.must_support_confirmed.include?('#{extension[:id]}') || @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == '#{extension[:url]}' } + extension_found = @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == '#{extension[:url]}' } + element_found = @instance.must_support_confirmed.include?('#{extension[:id]}') || extension_found skip 'Could not find #{extension[:id]} in the provided resource' unless element_found @instance.must_support_confirmed += '#{extension[:id]},') end sequence[:must_supports].select { |must_support| must_support[:type] == 'element' }.each do |element| truncated_path = element[:path].gsub("#{sequence[:resource]}.", '') + truncated_path = 'local_class' if truncated_path == 'class' # class is mapped to local_class in fhir_models test[:test_code] += %( element_found = @instance.must_support_confirmed.include?('#{element[:path]}') || can_resolve_path(@#{sequence[:resource].downcase}, '#{truncated_path}') skip 'Could not find #{element[:path]} in the provided resource' unless element_found diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index 2986b5572..0a6aaece8 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -51,7 +51,7 @@ class TestingInstance property :dynamic_registration_token, String - property :must_support_confirmed, String, default:'' + property :must_support_confirmed, String, default: '' has n, :sequence_results has n, :supported_resources, order: [:index.asc] diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index d09435836..765ac327a 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -278,7 +278,7 @@ def validate_resource_item(resource, property, value) element_found = @instance.must_support_confirmed.include?('Encounter.status') || can_resolve_path(@encounter, 'status') skip 'Could not find Encounter.status in the provided resource' unless element_found @instance.must_support_confirmed += 'Encounter.status,' - element_found = @instance.must_support_confirmed.include?('Encounter.class') || can_resolve_path(@encounter, 'class') + element_found = @instance.must_support_confirmed.include?('Encounter.class') || can_resolve_path(@encounter, 'local_class') skip 'Could not find Encounter.class in the provided resource' unless element_found @instance.must_support_confirmed += 'Encounter.class,' element_found = @instance.must_support_confirmed.include?('Encounter.type') || can_resolve_path(@encounter, 'type') diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index 55ae8d82a..400b1058c 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -269,13 +269,16 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Patient.extension:race') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race' } + extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race' } + element_found = @instance.must_support_confirmed.include?('Patient.extension:race') || extension_found skip 'Could not find Patient.extension:race in the provided resource' unless element_found @instance.must_support_confirmed += 'Patient.extension:race,' - element_found = @instance.must_support_confirmed.include?('Patient.extension:ethnicity') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity' } + extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity' } + element_found = @instance.must_support_confirmed.include?('Patient.extension:ethnicity') || extension_found skip 'Could not find Patient.extension:ethnicity in the provided resource' unless element_found @instance.must_support_confirmed += 'Patient.extension:ethnicity,' - element_found = @instance.must_support_confirmed.include?('Patient.extension:birthsex') || @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } + extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } + element_found = @instance.must_support_confirmed.include?('Patient.extension:birthsex') || extension_found skip 'Could not find Patient.extension:birthsex in the provided resource' unless element_found @instance.must_support_confirmed += 'Patient.extension:birthsex,' element_found = @instance.must_support_confirmed.include?('Patient.identifier') || can_resolve_path(@patient, 'identifier') diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 4a2abf860..453e4456f 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -23,14 +23,7 @@ class SequenceBase include SkipHelpers include Inferno::WebDriver - STATUS = { - pass: 'pass', - fail: 'fail', - error: 'error', - todo: 'todo', - wait: 'wait', - skip: 'skip' - }.freeze + STATUS = { pass: 'pass', fail: 'fail', error: 'error', todo: 'todo', wait: 'wait', skip: 'skip' }.freeze @@test_index = 0 From f2fb771264d6f7c622332a6182aed3ea58de044a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Jun 2019 19:30:13 -0400 Subject: [PATCH 03/89] check must supports iteratively --- generators/argonaut-r4/generator.rb | 57 +++++--- generators/argonaut-r4/metadata_extractor.rb | 4 +- .../argonaut-r4/templates/sequence.rb.erb | 2 +- .../pediatric_bmi_for_age_sequence.rb | 130 +++++++----------- .../pediatric_weight_for_height_sequence.rb | 130 +++++++----------- .../us_core_allergyintolerance_sequence.rb | 34 +++-- .../us_core_r4/us_core_careplan_sequence.rb | 46 ++++--- .../us_core_r4/us_core_careteam_sequence.rb | 38 +++-- .../us_core_r4/us_core_condition_sequence.rb | 38 +++-- .../us_core_r4/us_core_device_sequence.rb | 38 +++-- .../us_core_diagnosticreport_lab_sequence.rb | 62 ++++----- .../us_core_diagnosticreport_note_sequence.rb | 62 ++++----- .../us_core_documentreference_sequence.rb | 86 +++++------- .../us_core_r4/us_core_encounter_sequence.rb | 86 +++++------- .../us_core_r4/us_core_goal_sequence.rb | 42 +++--- .../us_core_immunization_sequence.rb | 46 ++++--- .../us_core_r4/us_core_location_sequence.rb | 54 ++++---- .../us_core_r4/us_core_medication_sequence.rb | 22 ++- .../us_core_medicationrequest_sequence.rb | 50 +++---- .../us_core_medicationstatement_sequence.rb | 50 +++---- .../us_core_observation_lab_sequence.rb | 90 +++++------- .../us_core_organization_sequence.rb | 66 ++++----- .../us_core_r4/us_core_patient_sequence.rb | 105 ++++++-------- .../us_core_practitioner_sequence.rb | 46 ++++--- .../us_core_practitionerrole_sequence.rb | 54 ++++---- .../us_core_r4/us_core_procedure_sequence.rb | 38 +++-- .../us_core_smokingstatus_sequence.rb | 38 +++-- lib/app/sequence_base.rb | 4 +- 28 files changed, 728 insertions(+), 790 deletions(-) diff --git a/generators/argonaut-r4/generator.rb b/generators/argonaut-r4/generator.rb index 35b6860ba..12784ca63 100644 --- a/generators/argonaut-r4/generator.rb +++ b/generators/argonaut-r4/generator.rb @@ -75,7 +75,7 @@ def generate_sequence(sequence) def create_authorization_test(sequence) authorization_test = { tests_that: "Server rejects #{sequence[:resource]} search without authorization", - index: format('%02d', (sequence[:tests].length + 1)), + index: sequence[:tests].length + 1, link: 'http://www.fhir.org/guides/argonaut/r2/Conformance-server.html' } @@ -93,11 +93,11 @@ def create_authorization_test(sequence) def create_search_test(sequence, search_param) search_test = { tests_that: "Server returns expected results from #{sequence[:resource]} search by #{search_param[:names].join('+')}", - index: format('%02d', (sequence[:tests].length + 1)), + index: sequence[:tests].length + 1, link: 'https://build.fhir.org/ig/HL7/US-Core-R4/CapabilityStatement-us-core-server.html' } - is_first_search = search_test[:index] == '02' # if first search - fix this check later + is_first_search = search_test[:index] == 2 # if first search - fix this check later search_test[:test_code] = if is_first_search %(#{get_search_params(search_param[:names], sequence)} @@ -127,7 +127,7 @@ def create_search_test(sequence, search_param) def create_interaction_test(sequence, interaction) interaction_test = { tests_that: "#{sequence[:resource]} #{interaction[:code]} resource supported", - index: format('%02d', (sequence[:tests].length + 1)), + index: sequence[:tests].length + 1, link: 'https://build.fhir.org/ig/HL7/US-Core-R4/CapabilityStatement-us-core-server.html' } @@ -143,27 +143,44 @@ def create_interaction_test(sequence, interaction) def create_must_support_test(sequence) test = { tests_that: 'Demonstrates that the server can supply must supported elements', - index: format('%02d', sequence[:tests].length + 1), + index: sequence[:tests].length + 1, link: 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support', test_code: '' } - + + extensions_list = '' sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| - test[:test_code] += %( - extension_found = @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == '#{extension[:url]}' } - element_found = @instance.must_support_confirmed.include?('#{extension[:id]}') || extension_found - skip 'Could not find #{extension[:id]} in the provided resource' unless element_found - @instance.must_support_confirmed += '#{extension[:id]},') + extensions_list += %( + '#{extension[:id]}': '#{extension[:url]}',) end - + test[:test_code] += %( + extensions_list = {#{extensions_list} + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == url } + skip "Could not find \#{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "\#{id.to_s}," unless already_found + end) + + elements_list = '' sequence[:must_supports].select { |must_support| must_support[:type] == 'element' }.each do |element| - truncated_path = element[:path].gsub("#{sequence[:resource]}.", '') - truncated_path = 'local_class' if truncated_path == 'class' # class is mapped to local_class in fhir_models - test[:test_code] += %( - element_found = @instance.must_support_confirmed.include?('#{element[:path]}') || can_resolve_path(@#{sequence[:resource].downcase}, '#{truncated_path}') - skip 'Could not find #{element[:path]} in the provided resource' unless element_found - @instance.must_support_confirmed += '#{element[:path]},') + element[:path] = element[:path].gsub('.class', '.local_class') # class is mapped to local_class in fhir_models + elements_list += %( + '#{element[:path]}',) end + + test[:test_code] += %( + + must_support_elements = [#{elements_list} + ] + must_support_elements.each do |path| + truncated_path = path.gsub('#{sequence[:resource]}.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@#{sequence[:resource].downcase}, truncated_path) + skip "Could not find \#{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "\#{path}," unless already_found + end) test[:test_code] += %( @instance.save!) @@ -174,7 +191,7 @@ def create_must_support_test(sequence) def create_resource_profile_test(sequence) test = { tests_that: "#{sequence[:resource]} resources associated with Patient conform to Argonaut profiles", - index: format('%02d', (sequence[:tests].length + 1)), + index: sequence[:tests].length + 1, link: sequence[:profile] } test[:test_code] = %( @@ -187,7 +204,7 @@ def create_resource_profile_test(sequence) def create_references_resolved_test(sequence) test = { tests_that: 'All references can be resolved', - index: format('%02d', (sequence[:tests].length + 1)), + index: sequence[:tests].length + 1, link: 'https://www.hl7.org/fhir/DSTU2/references.html' } diff --git a/generators/argonaut-r4/metadata_extractor.rb b/generators/argonaut-r4/metadata_extractor.rb index 8e1228a95..e0f21a425 100644 --- a/generators/argonaut-r4/metadata_extractor.rb +++ b/generators/argonaut-r4/metadata_extractor.rb @@ -134,8 +134,8 @@ def add_must_support_elements(profile_definition, sequence) path = element['path'] if path.include? '[x]' - variable_el = profile_definition['snapshot']['element'].select { |el| el['id'] == (path.split('[x]').first + '[x]') }.first - variable_el['type'].each do |type| + choice_el = profile_definition['snapshot']['element'].find { |el| el['id'] == (path.split('[x]').first + '[x]') } + choice_el['type'].each do |type| sequence[:must_supports] << { type: 'element', diff --git a/generators/argonaut-r4/templates/sequence.rb.erb b/generators/argonaut-r4/templates/sequence.rb.erb index 3e1ea3db6..869dc6d60 100644 --- a/generators/argonaut-r4/templates/sequence.rb.erb +++ b/generators/argonaut-r4/templates/sequence.rb.erb @@ -25,7 +25,7 @@ module Inferno test '<%=test[:tests_that]%>' do metadata do - id '<%=test[:index]%>' + id '<%=format('%02d', test[:index])%>' link '<%=test[:link]%>' desc %( ) diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index 2bb2efe13..52be1d47c 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -226,90 +226,52 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') - skip 'Could not find Observation.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.status,' - element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') - skip 'Could not find Observation.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category,' - element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') - skip 'Could not find Observation.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding') || can_resolve_path(@observation, 'category.coding') - skip 'Could not find Observation.category.coding in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding.system') || can_resolve_path(@observation, 'category.coding.system') - skip 'Could not find Observation.category.coding.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding.system,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding.code') || can_resolve_path(@observation, 'category.coding.code') - skip 'Could not find Observation.category.coding.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding.code,' - element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') - skip 'Could not find Observation.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.subject,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') - skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') - skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.value') || can_resolve_path(@observation, 'valueQuantity.value') - skip 'Could not find Observation.valueQuantity.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.value,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.unit') || can_resolve_path(@observation, 'valueQuantity.unit') - skip 'Could not find Observation.valueQuantity.unit in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.unit,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.system') || can_resolve_path(@observation, 'valueQuantity.system') - skip 'Could not find Observation.valueQuantity.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.system,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.code') || can_resolve_path(@observation, 'valueQuantity.code') - skip 'Could not find Observation.valueQuantity.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.code,' - element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') - skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.dataAbsentReason,' - element_found = @instance.must_support_confirmed.include?('Observation.component') || can_resolve_path(@observation, 'component') - skip 'Could not find Observation.component in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component,' - element_found = @instance.must_support_confirmed.include?('Observation.component.code') || can_resolve_path(@observation, 'component.code') - skip 'Could not find Observation.component.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.code,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueQuantity') || can_resolve_path(@observation, 'component.valueQuantity') - skip 'Could not find Observation.component.valueQuantity in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueQuantity,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueCodeableConcept') || can_resolve_path(@observation, 'component.valueCodeableConcept') - skip 'Could not find Observation.component.valueCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueCodeableConcept,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuestring') || can_resolve_path(@observation, 'component.valuestring') - skip 'Could not find Observation.component.valuestring in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuestring,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueboolean') || can_resolve_path(@observation, 'component.valueboolean') - skip 'Could not find Observation.component.valueboolean in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueboolean,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueinteger') || can_resolve_path(@observation, 'component.valueinteger') - skip 'Could not find Observation.component.valueinteger in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueinteger,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueRange') || can_resolve_path(@observation, 'component.valueRange') - skip 'Could not find Observation.component.valueRange in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueRange,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueRatio') || can_resolve_path(@observation, 'component.valueRatio') - skip 'Could not find Observation.component.valueRatio in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueRatio,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueSampledData') || can_resolve_path(@observation, 'component.valueSampledData') - skip 'Could not find Observation.component.valueSampledData in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueSampledData,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuetime') || can_resolve_path(@observation, 'component.valuetime') - skip 'Could not find Observation.component.valuetime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuetime,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuedateTime') || can_resolve_path(@observation, 'component.valuedateTime') - skip 'Could not find Observation.component.valuedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuePeriod') || can_resolve_path(@observation, 'component.valuePeriod') - skip 'Could not find Observation.component.valuePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.component.dataAbsentReason') || can_resolve_path(@observation, 'component.dataAbsentReason') - skip 'Could not find Observation.component.dataAbsentReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.dataAbsentReason,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @observation.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Observation.status', + 'Observation.category', + 'Observation.category', + 'Observation.category.coding', + 'Observation.category.coding.system', + 'Observation.category.coding.code', + 'Observation.subject', + 'Observation.effectivedateTime', + 'Observation.effectivePeriod', + 'Observation.valueQuantity.value', + 'Observation.valueQuantity.unit', + 'Observation.valueQuantity.system', + 'Observation.valueQuantity.code', + 'Observation.dataAbsentReason', + 'Observation.component', + 'Observation.component.code', + 'Observation.component.valueQuantity', + 'Observation.component.valueCodeableConcept', + 'Observation.component.valuestring', + 'Observation.component.valueboolean', + 'Observation.component.valueinteger', + 'Observation.component.valueRange', + 'Observation.component.valueRatio', + 'Observation.component.valueSampledData', + 'Observation.component.valuetime', + 'Observation.component.valuedateTime', + 'Observation.component.valuePeriod', + 'Observation.component.dataAbsentReason', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@observation, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index ffa121ba2..b8757b838 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -226,90 +226,52 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') - skip 'Could not find Observation.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.status,' - element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') - skip 'Could not find Observation.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category,' - element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') - skip 'Could not find Observation.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding') || can_resolve_path(@observation, 'category.coding') - skip 'Could not find Observation.category.coding in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding.system') || can_resolve_path(@observation, 'category.coding.system') - skip 'Could not find Observation.category.coding.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding.system,' - element_found = @instance.must_support_confirmed.include?('Observation.category.coding.code') || can_resolve_path(@observation, 'category.coding.code') - skip 'Could not find Observation.category.coding.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category.coding.code,' - element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') - skip 'Could not find Observation.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.subject,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') - skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') - skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.value') || can_resolve_path(@observation, 'valueQuantity.value') - skip 'Could not find Observation.valueQuantity.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.value,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.unit') || can_resolve_path(@observation, 'valueQuantity.unit') - skip 'Could not find Observation.valueQuantity.unit in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.unit,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.system') || can_resolve_path(@observation, 'valueQuantity.system') - skip 'Could not find Observation.valueQuantity.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.system,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity.code') || can_resolve_path(@observation, 'valueQuantity.code') - skip 'Could not find Observation.valueQuantity.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity.code,' - element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') - skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.dataAbsentReason,' - element_found = @instance.must_support_confirmed.include?('Observation.component') || can_resolve_path(@observation, 'component') - skip 'Could not find Observation.component in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component,' - element_found = @instance.must_support_confirmed.include?('Observation.component.code') || can_resolve_path(@observation, 'component.code') - skip 'Could not find Observation.component.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.code,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueQuantity') || can_resolve_path(@observation, 'component.valueQuantity') - skip 'Could not find Observation.component.valueQuantity in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueQuantity,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueCodeableConcept') || can_resolve_path(@observation, 'component.valueCodeableConcept') - skip 'Could not find Observation.component.valueCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueCodeableConcept,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuestring') || can_resolve_path(@observation, 'component.valuestring') - skip 'Could not find Observation.component.valuestring in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuestring,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueboolean') || can_resolve_path(@observation, 'component.valueboolean') - skip 'Could not find Observation.component.valueboolean in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueboolean,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueinteger') || can_resolve_path(@observation, 'component.valueinteger') - skip 'Could not find Observation.component.valueinteger in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueinteger,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueRange') || can_resolve_path(@observation, 'component.valueRange') - skip 'Could not find Observation.component.valueRange in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueRange,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueRatio') || can_resolve_path(@observation, 'component.valueRatio') - skip 'Could not find Observation.component.valueRatio in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueRatio,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valueSampledData') || can_resolve_path(@observation, 'component.valueSampledData') - skip 'Could not find Observation.component.valueSampledData in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valueSampledData,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuetime') || can_resolve_path(@observation, 'component.valuetime') - skip 'Could not find Observation.component.valuetime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuetime,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuedateTime') || can_resolve_path(@observation, 'component.valuedateTime') - skip 'Could not find Observation.component.valuedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.component.valuePeriod') || can_resolve_path(@observation, 'component.valuePeriod') - skip 'Could not find Observation.component.valuePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.valuePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.component.dataAbsentReason') || can_resolve_path(@observation, 'component.dataAbsentReason') - skip 'Could not find Observation.component.dataAbsentReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.component.dataAbsentReason,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @observation.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Observation.status', + 'Observation.category', + 'Observation.category', + 'Observation.category.coding', + 'Observation.category.coding.system', + 'Observation.category.coding.code', + 'Observation.subject', + 'Observation.effectivedateTime', + 'Observation.effectivePeriod', + 'Observation.valueQuantity.value', + 'Observation.valueQuantity.unit', + 'Observation.valueQuantity.system', + 'Observation.valueQuantity.code', + 'Observation.dataAbsentReason', + 'Observation.component', + 'Observation.component.code', + 'Observation.component.valueQuantity', + 'Observation.component.valueCodeableConcept', + 'Observation.component.valuestring', + 'Observation.component.valueboolean', + 'Observation.component.valueinteger', + 'Observation.component.valueRange', + 'Observation.component.valueRatio', + 'Observation.component.valueSampledData', + 'Observation.component.valuetime', + 'Observation.component.valuedateTime', + 'Observation.component.valuePeriod', + 'Observation.component.dataAbsentReason', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@observation, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 6be05656a..04b46336e 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -154,18 +154,28 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.clinicalStatus') || can_resolve_path(@allergyintolerance, 'clinicalStatus') - skip 'Could not find AllergyIntolerance.clinicalStatus in the provided resource' unless element_found - @instance.must_support_confirmed += 'AllergyIntolerance.clinicalStatus,' - element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.verificationStatus') || can_resolve_path(@allergyintolerance, 'verificationStatus') - skip 'Could not find AllergyIntolerance.verificationStatus in the provided resource' unless element_found - @instance.must_support_confirmed += 'AllergyIntolerance.verificationStatus,' - element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.code') || can_resolve_path(@allergyintolerance, 'code') - skip 'Could not find AllergyIntolerance.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'AllergyIntolerance.code,' - element_found = @instance.must_support_confirmed.include?('AllergyIntolerance.patient') || can_resolve_path(@allergyintolerance, 'patient') - skip 'Could not find AllergyIntolerance.patient in the provided resource' unless element_found - @instance.must_support_confirmed += 'AllergyIntolerance.patient,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @allergyintolerance.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'AllergyIntolerance.clinicalStatus', + 'AllergyIntolerance.verificationStatus', + 'AllergyIntolerance.code', + 'AllergyIntolerance.patient', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('AllergyIntolerance.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@allergyintolerance, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index 8f31684ca..b1c916a89 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -202,27 +202,31 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('CarePlan.text') || can_resolve_path(@careplan, 'text') - skip 'Could not find CarePlan.text in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.text,' - element_found = @instance.must_support_confirmed.include?('CarePlan.text.status') || can_resolve_path(@careplan, 'text.status') - skip 'Could not find CarePlan.text.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.text.status,' - element_found = @instance.must_support_confirmed.include?('CarePlan.status') || can_resolve_path(@careplan, 'status') - skip 'Could not find CarePlan.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.status,' - element_found = @instance.must_support_confirmed.include?('CarePlan.intent') || can_resolve_path(@careplan, 'intent') - skip 'Could not find CarePlan.intent in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.intent,' - element_found = @instance.must_support_confirmed.include?('CarePlan.category') || can_resolve_path(@careplan, 'category') - skip 'Could not find CarePlan.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.category,' - element_found = @instance.must_support_confirmed.include?('CarePlan.category') || can_resolve_path(@careplan, 'category') - skip 'Could not find CarePlan.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.category,' - element_found = @instance.must_support_confirmed.include?('CarePlan.subject') || can_resolve_path(@careplan, 'subject') - skip 'Could not find CarePlan.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'CarePlan.subject,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @careplan.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'CarePlan.text', + 'CarePlan.text.status', + 'CarePlan.status', + 'CarePlan.intent', + 'CarePlan.category', + 'CarePlan.category', + 'CarePlan.subject', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('CarePlan.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@careplan, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 421bd93c8..3cfa67d45 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -131,21 +131,29 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('CareTeam.status') || can_resolve_path(@careteam, 'status') - skip 'Could not find CareTeam.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'CareTeam.status,' - element_found = @instance.must_support_confirmed.include?('CareTeam.subject') || can_resolve_path(@careteam, 'subject') - skip 'Could not find CareTeam.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'CareTeam.subject,' - element_found = @instance.must_support_confirmed.include?('CareTeam.participant') || can_resolve_path(@careteam, 'participant') - skip 'Could not find CareTeam.participant in the provided resource' unless element_found - @instance.must_support_confirmed += 'CareTeam.participant,' - element_found = @instance.must_support_confirmed.include?('CareTeam.participant.role') || can_resolve_path(@careteam, 'participant.role') - skip 'Could not find CareTeam.participant.role in the provided resource' unless element_found - @instance.must_support_confirmed += 'CareTeam.participant.role,' - element_found = @instance.must_support_confirmed.include?('CareTeam.participant.member') || can_resolve_path(@careteam, 'participant.member') - skip 'Could not find CareTeam.participant.member in the provided resource' unless element_found - @instance.must_support_confirmed += 'CareTeam.participant.member,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @careteam.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'CareTeam.status', + 'CareTeam.subject', + 'CareTeam.participant', + 'CareTeam.participant.role', + 'CareTeam.participant.member', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('CareTeam.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@careteam, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index e7129b3fc..ebc2edb17 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -226,21 +226,29 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Condition.clinicalStatus') || can_resolve_path(@condition, 'clinicalStatus') - skip 'Could not find Condition.clinicalStatus in the provided resource' unless element_found - @instance.must_support_confirmed += 'Condition.clinicalStatus,' - element_found = @instance.must_support_confirmed.include?('Condition.verificationStatus') || can_resolve_path(@condition, 'verificationStatus') - skip 'Could not find Condition.verificationStatus in the provided resource' unless element_found - @instance.must_support_confirmed += 'Condition.verificationStatus,' - element_found = @instance.must_support_confirmed.include?('Condition.category') || can_resolve_path(@condition, 'category') - skip 'Could not find Condition.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Condition.category,' - element_found = @instance.must_support_confirmed.include?('Condition.code') || can_resolve_path(@condition, 'code') - skip 'Could not find Condition.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Condition.code,' - element_found = @instance.must_support_confirmed.include?('Condition.subject') || can_resolve_path(@condition, 'subject') - skip 'Could not find Condition.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Condition.subject,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @condition.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Condition.clinicalStatus', + 'Condition.verificationStatus', + 'Condition.category', + 'Condition.code', + 'Condition.subject', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Condition.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@condition, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index 2cfaae900..8ace32ac7 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -154,21 +154,29 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Device.udiCarrier') || can_resolve_path(@device, 'udiCarrier') - skip 'Could not find Device.udiCarrier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Device.udiCarrier,' - element_found = @instance.must_support_confirmed.include?('Device.udiCarrier.carrierAIDC') || can_resolve_path(@device, 'udiCarrier.carrierAIDC') - skip 'Could not find Device.udiCarrier.carrierAIDC in the provided resource' unless element_found - @instance.must_support_confirmed += 'Device.udiCarrier.carrierAIDC,' - element_found = @instance.must_support_confirmed.include?('Device.udiCarrier.carrierHRF') || can_resolve_path(@device, 'udiCarrier.carrierHRF') - skip 'Could not find Device.udiCarrier.carrierHRF in the provided resource' unless element_found - @instance.must_support_confirmed += 'Device.udiCarrier.carrierHRF,' - element_found = @instance.must_support_confirmed.include?('Device.type') || can_resolve_path(@device, 'type') - skip 'Could not find Device.type in the provided resource' unless element_found - @instance.must_support_confirmed += 'Device.type,' - element_found = @instance.must_support_confirmed.include?('Device.patient') || can_resolve_path(@device, 'patient') - skip 'Could not find Device.patient in the provided resource' unless element_found - @instance.must_support_confirmed += 'Device.patient,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @device.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Device.udiCarrier', + 'Device.udiCarrier.carrierAIDC', + 'Device.udiCarrier.carrierHRF', + 'Device.type', + 'Device.patient', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Device.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@device, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index 747baead0..3c729eb8c 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -279,39 +279,35 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.status') || can_resolve_path(@diagnosticreport, 'status') - skip 'Could not find DiagnosticReport.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.status,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.category') || can_resolve_path(@diagnosticreport, 'category') - skip 'Could not find DiagnosticReport.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.category,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.code') || can_resolve_path(@diagnosticreport, 'code') - skip 'Could not find DiagnosticReport.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.code,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.subject') || can_resolve_path(@diagnosticreport, 'subject') - skip 'Could not find DiagnosticReport.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.subject,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivedateTime') || can_resolve_path(@diagnosticreport, 'effectivedateTime') - skip 'Could not find DiagnosticReport.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivePeriod') || can_resolve_path(@diagnosticreport, 'effectivePeriod') - skip 'Could not find DiagnosticReport.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.issued') || can_resolve_path(@diagnosticreport, 'issued') - skip 'Could not find DiagnosticReport.issued in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.issued,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.performer') || can_resolve_path(@diagnosticreport, 'performer') - skip 'Could not find DiagnosticReport.performer in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.performer,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.result') || can_resolve_path(@diagnosticreport, 'result') - skip 'Could not find DiagnosticReport.result in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.result,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.media') || can_resolve_path(@diagnosticreport, 'media') - skip 'Could not find DiagnosticReport.media in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.media,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.presentedForm') || can_resolve_path(@diagnosticreport, 'presentedForm') - skip 'Could not find DiagnosticReport.presentedForm in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.presentedForm,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @diagnosticreport.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'DiagnosticReport.status', + 'DiagnosticReport.category', + 'DiagnosticReport.code', + 'DiagnosticReport.subject', + 'DiagnosticReport.effectivedateTime', + 'DiagnosticReport.effectivePeriod', + 'DiagnosticReport.issued', + 'DiagnosticReport.performer', + 'DiagnosticReport.result', + 'DiagnosticReport.media', + 'DiagnosticReport.presentedForm', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('DiagnosticReport.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@diagnosticreport, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index 4fcda3d3c..00673bf3c 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -279,39 +279,35 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.status') || can_resolve_path(@diagnosticreport, 'status') - skip 'Could not find DiagnosticReport.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.status,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.category') || can_resolve_path(@diagnosticreport, 'category') - skip 'Could not find DiagnosticReport.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.category,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.code') || can_resolve_path(@diagnosticreport, 'code') - skip 'Could not find DiagnosticReport.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.code,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.subject') || can_resolve_path(@diagnosticreport, 'subject') - skip 'Could not find DiagnosticReport.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.subject,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.encounter') || can_resolve_path(@diagnosticreport, 'encounter') - skip 'Could not find DiagnosticReport.encounter in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.encounter,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivedateTime') || can_resolve_path(@diagnosticreport, 'effectivedateTime') - skip 'Could not find DiagnosticReport.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.effectivePeriod') || can_resolve_path(@diagnosticreport, 'effectivePeriod') - skip 'Could not find DiagnosticReport.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.issued') || can_resolve_path(@diagnosticreport, 'issued') - skip 'Could not find DiagnosticReport.issued in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.issued,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.performer') || can_resolve_path(@diagnosticreport, 'performer') - skip 'Could not find DiagnosticReport.performer in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.performer,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.media') || can_resolve_path(@diagnosticreport, 'media') - skip 'Could not find DiagnosticReport.media in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.media,' - element_found = @instance.must_support_confirmed.include?('DiagnosticReport.presentedForm') || can_resolve_path(@diagnosticreport, 'presentedForm') - skip 'Could not find DiagnosticReport.presentedForm in the provided resource' unless element_found - @instance.must_support_confirmed += 'DiagnosticReport.presentedForm,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @diagnosticreport.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'DiagnosticReport.status', + 'DiagnosticReport.category', + 'DiagnosticReport.code', + 'DiagnosticReport.subject', + 'DiagnosticReport.encounter', + 'DiagnosticReport.effectivedateTime', + 'DiagnosticReport.effectivePeriod', + 'DiagnosticReport.issued', + 'DiagnosticReport.performer', + 'DiagnosticReport.media', + 'DiagnosticReport.presentedForm', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('DiagnosticReport.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@diagnosticreport, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index 985d4ac24..d80f5a998 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -285,57 +285,41 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('DocumentReference.identifier') || can_resolve_path(@documentreference, 'identifier') - skip 'Could not find DocumentReference.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.identifier,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.status') || can_resolve_path(@documentreference, 'status') - skip 'Could not find DocumentReference.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.status,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.type') || can_resolve_path(@documentreference, 'type') - skip 'Could not find DocumentReference.type in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.type,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.category') || can_resolve_path(@documentreference, 'category') - skip 'Could not find DocumentReference.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.category,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.subject') || can_resolve_path(@documentreference, 'subject') - skip 'Could not find DocumentReference.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.subject,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.date') || can_resolve_path(@documentreference, 'date') - skip 'Could not find DocumentReference.date in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.date,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.author') || can_resolve_path(@documentreference, 'author') - skip 'Could not find DocumentReference.author in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.author,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.custodian') || can_resolve_path(@documentreference, 'custodian') - skip 'Could not find DocumentReference.custodian in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.custodian,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content') || can_resolve_path(@documentreference, 'content') - skip 'Could not find DocumentReference.content in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment') || can_resolve_path(@documentreference, 'content.attachment') - skip 'Could not find DocumentReference.content.attachment in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content.attachment,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.contentType') || can_resolve_path(@documentreference, 'content.attachment.contentType') - skip 'Could not find DocumentReference.content.attachment.contentType in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content.attachment.contentType,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.data') || can_resolve_path(@documentreference, 'content.attachment.data') - skip 'Could not find DocumentReference.content.attachment.data in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content.attachment.data,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content.attachment.url') || can_resolve_path(@documentreference, 'content.attachment.url') - skip 'Could not find DocumentReference.content.attachment.url in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content.attachment.url,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.content.format') || can_resolve_path(@documentreference, 'content.format') - skip 'Could not find DocumentReference.content.format in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.content.format,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.context') || can_resolve_path(@documentreference, 'context') - skip 'Could not find DocumentReference.context in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.context,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.context.encounter') || can_resolve_path(@documentreference, 'context.encounter') - skip 'Could not find DocumentReference.context.encounter in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.context.encounter,' - element_found = @instance.must_support_confirmed.include?('DocumentReference.context.period') || can_resolve_path(@documentreference, 'context.period') - skip 'Could not find DocumentReference.context.period in the provided resource' unless element_found - @instance.must_support_confirmed += 'DocumentReference.context.period,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @documentreference.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'DocumentReference.identifier', + 'DocumentReference.status', + 'DocumentReference.type', + 'DocumentReference.category', + 'DocumentReference.subject', + 'DocumentReference.date', + 'DocumentReference.author', + 'DocumentReference.custodian', + 'DocumentReference.content', + 'DocumentReference.content.attachment', + 'DocumentReference.content.attachment.contentType', + 'DocumentReference.content.attachment.data', + 'DocumentReference.content.attachment.url', + 'DocumentReference.content.format', + 'DocumentReference.context', + 'DocumentReference.context.encounter', + 'DocumentReference.context.period', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('DocumentReference.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@documentreference, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index 765ac327a..fb686e30b 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -266,57 +266,41 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Encounter.identifier') || can_resolve_path(@encounter, 'identifier') - skip 'Could not find Encounter.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.identifier,' - element_found = @instance.must_support_confirmed.include?('Encounter.identifier.system') || can_resolve_path(@encounter, 'identifier.system') - skip 'Could not find Encounter.identifier.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.identifier.system,' - element_found = @instance.must_support_confirmed.include?('Encounter.identifier.value') || can_resolve_path(@encounter, 'identifier.value') - skip 'Could not find Encounter.identifier.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.identifier.value,' - element_found = @instance.must_support_confirmed.include?('Encounter.status') || can_resolve_path(@encounter, 'status') - skip 'Could not find Encounter.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.status,' - element_found = @instance.must_support_confirmed.include?('Encounter.class') || can_resolve_path(@encounter, 'local_class') - skip 'Could not find Encounter.class in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.class,' - element_found = @instance.must_support_confirmed.include?('Encounter.type') || can_resolve_path(@encounter, 'type') - skip 'Could not find Encounter.type in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.type,' - element_found = @instance.must_support_confirmed.include?('Encounter.subject') || can_resolve_path(@encounter, 'subject') - skip 'Could not find Encounter.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.subject,' - element_found = @instance.must_support_confirmed.include?('Encounter.participant') || can_resolve_path(@encounter, 'participant') - skip 'Could not find Encounter.participant in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.participant,' - element_found = @instance.must_support_confirmed.include?('Encounter.participant.type') || can_resolve_path(@encounter, 'participant.type') - skip 'Could not find Encounter.participant.type in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.participant.type,' - element_found = @instance.must_support_confirmed.include?('Encounter.participant.period') || can_resolve_path(@encounter, 'participant.period') - skip 'Could not find Encounter.participant.period in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.participant.period,' - element_found = @instance.must_support_confirmed.include?('Encounter.participant.individual') || can_resolve_path(@encounter, 'participant.individual') - skip 'Could not find Encounter.participant.individual in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.participant.individual,' - element_found = @instance.must_support_confirmed.include?('Encounter.period') || can_resolve_path(@encounter, 'period') - skip 'Could not find Encounter.period in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.period,' - element_found = @instance.must_support_confirmed.include?('Encounter.reasonCode') || can_resolve_path(@encounter, 'reasonCode') - skip 'Could not find Encounter.reasonCode in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.reasonCode,' - element_found = @instance.must_support_confirmed.include?('Encounter.hospitalization') || can_resolve_path(@encounter, 'hospitalization') - skip 'Could not find Encounter.hospitalization in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.hospitalization,' - element_found = @instance.must_support_confirmed.include?('Encounter.hospitalization.dischargeDisposition') || can_resolve_path(@encounter, 'hospitalization.dischargeDisposition') - skip 'Could not find Encounter.hospitalization.dischargeDisposition in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.hospitalization.dischargeDisposition,' - element_found = @instance.must_support_confirmed.include?('Encounter.location') || can_resolve_path(@encounter, 'location') - skip 'Could not find Encounter.location in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.location,' - element_found = @instance.must_support_confirmed.include?('Encounter.location.location') || can_resolve_path(@encounter, 'location.location') - skip 'Could not find Encounter.location.location in the provided resource' unless element_found - @instance.must_support_confirmed += 'Encounter.location.location,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @encounter.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Encounter.identifier', + 'Encounter.identifier.system', + 'Encounter.identifier.value', + 'Encounter.status', + 'Encounter.local_class', + 'Encounter.type', + 'Encounter.subject', + 'Encounter.participant', + 'Encounter.participant.type', + 'Encounter.participant.period', + 'Encounter.participant.individual', + 'Encounter.period', + 'Encounter.reasonCode', + 'Encounter.hospitalization', + 'Encounter.hospitalization.dischargeDisposition', + 'Encounter.location', + 'Encounter.location.location', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Encounter.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@encounter, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index bc4d04673..20b0239e9 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -174,24 +174,30 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Goal.lifecycleStatus') || can_resolve_path(@goal, 'lifecycleStatus') - skip 'Could not find Goal.lifecycleStatus in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.lifecycleStatus,' - element_found = @instance.must_support_confirmed.include?('Goal.description') || can_resolve_path(@goal, 'description') - skip 'Could not find Goal.description in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.description,' - element_found = @instance.must_support_confirmed.include?('Goal.subject') || can_resolve_path(@goal, 'subject') - skip 'Could not find Goal.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.subject,' - element_found = @instance.must_support_confirmed.include?('Goal.target') || can_resolve_path(@goal, 'target') - skip 'Could not find Goal.target in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.target,' - element_found = @instance.must_support_confirmed.include?('Goal.target.duedate') || can_resolve_path(@goal, 'target.duedate') - skip 'Could not find Goal.target.duedate in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.target.duedate,' - element_found = @instance.must_support_confirmed.include?('Goal.target.dueDuration') || can_resolve_path(@goal, 'target.dueDuration') - skip 'Could not find Goal.target.dueDuration in the provided resource' unless element_found - @instance.must_support_confirmed += 'Goal.target.dueDuration,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @goal.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Goal.lifecycleStatus', + 'Goal.description', + 'Goal.subject', + 'Goal.target', + 'Goal.target.duedate', + 'Goal.target.dueDuration', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Goal.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@goal, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index a769188ba..3965f39c4 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -174,27 +174,31 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Immunization.status') || can_resolve_path(@immunization, 'status') - skip 'Could not find Immunization.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.status,' - element_found = @instance.must_support_confirmed.include?('Immunization.statusReason') || can_resolve_path(@immunization, 'statusReason') - skip 'Could not find Immunization.statusReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.statusReason,' - element_found = @instance.must_support_confirmed.include?('Immunization.vaccineCode') || can_resolve_path(@immunization, 'vaccineCode') - skip 'Could not find Immunization.vaccineCode in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.vaccineCode,' - element_found = @instance.must_support_confirmed.include?('Immunization.patient') || can_resolve_path(@immunization, 'patient') - skip 'Could not find Immunization.patient in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.patient,' - element_found = @instance.must_support_confirmed.include?('Immunization.occurrencedateTime') || can_resolve_path(@immunization, 'occurrencedateTime') - skip 'Could not find Immunization.occurrencedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.occurrencedateTime,' - element_found = @instance.must_support_confirmed.include?('Immunization.occurrencestring') || can_resolve_path(@immunization, 'occurrencestring') - skip 'Could not find Immunization.occurrencestring in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.occurrencestring,' - element_found = @instance.must_support_confirmed.include?('Immunization.primarySource') || can_resolve_path(@immunization, 'primarySource') - skip 'Could not find Immunization.primarySource in the provided resource' unless element_found - @instance.must_support_confirmed += 'Immunization.primarySource,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @immunization.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Immunization.status', + 'Immunization.statusReason', + 'Immunization.vaccineCode', + 'Immunization.patient', + 'Immunization.occurrencedateTime', + 'Immunization.occurrencestring', + 'Immunization.primarySource', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Immunization.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@immunization, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index cfdd15958..b4886359f 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -215,33 +215,33 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Location.status') || can_resolve_path(@location, 'status') - skip 'Could not find Location.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.status,' - element_found = @instance.must_support_confirmed.include?('Location.name') || can_resolve_path(@location, 'name') - skip 'Could not find Location.name in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.name,' - element_found = @instance.must_support_confirmed.include?('Location.telecom') || can_resolve_path(@location, 'telecom') - skip 'Could not find Location.telecom in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.telecom,' - element_found = @instance.must_support_confirmed.include?('Location.address') || can_resolve_path(@location, 'address') - skip 'Could not find Location.address in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.address,' - element_found = @instance.must_support_confirmed.include?('Location.address.line') || can_resolve_path(@location, 'address.line') - skip 'Could not find Location.address.line in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.address.line,' - element_found = @instance.must_support_confirmed.include?('Location.address.city') || can_resolve_path(@location, 'address.city') - skip 'Could not find Location.address.city in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.address.city,' - element_found = @instance.must_support_confirmed.include?('Location.address.state') || can_resolve_path(@location, 'address.state') - skip 'Could not find Location.address.state in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.address.state,' - element_found = @instance.must_support_confirmed.include?('Location.address.postalCode') || can_resolve_path(@location, 'address.postalCode') - skip 'Could not find Location.address.postalCode in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.address.postalCode,' - element_found = @instance.must_support_confirmed.include?('Location.managingOrganization') || can_resolve_path(@location, 'managingOrganization') - skip 'Could not find Location.managingOrganization in the provided resource' unless element_found - @instance.must_support_confirmed += 'Location.managingOrganization,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @location.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Location.status', + 'Location.name', + 'Location.telecom', + 'Location.address', + 'Location.address.line', + 'Location.address.city', + 'Location.address.state', + 'Location.address.postalCode', + 'Location.managingOrganization', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Location.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@location, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index 2ed1612e9..cfca486ac 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -94,9 +94,25 @@ class UsCoreR4MedicationSequence < SequenceBase versions :r4 end - element_found = @instance.must_support_confirmed.include?('Medication.code') || can_resolve_path(@medication, 'code') - skip 'Could not find Medication.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Medication.code,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @medication.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Medication.code', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Medication.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@medication, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index c1373744f..a7cb05d50 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -174,30 +174,32 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('MedicationRequest.status') || can_resolve_path(@medicationrequest, 'status') - skip 'Could not find MedicationRequest.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.status,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.medicationCodeableConcept') || can_resolve_path(@medicationrequest, 'medicationCodeableConcept') - skip 'Could not find MedicationRequest.medicationCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.medicationCodeableConcept,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.medicationReference') || can_resolve_path(@medicationrequest, 'medicationReference') - skip 'Could not find MedicationRequest.medicationReference in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.medicationReference,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.subject') || can_resolve_path(@medicationrequest, 'subject') - skip 'Could not find MedicationRequest.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.subject,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.authoredOn') || can_resolve_path(@medicationrequest, 'authoredOn') - skip 'Could not find MedicationRequest.authoredOn in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.authoredOn,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.requester') || can_resolve_path(@medicationrequest, 'requester') - skip 'Could not find MedicationRequest.requester in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.requester,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.dosageInstruction') || can_resolve_path(@medicationrequest, 'dosageInstruction') - skip 'Could not find MedicationRequest.dosageInstruction in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.dosageInstruction,' - element_found = @instance.must_support_confirmed.include?('MedicationRequest.dosageInstruction.text') || can_resolve_path(@medicationrequest, 'dosageInstruction.text') - skip 'Could not find MedicationRequest.dosageInstruction.text in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationRequest.dosageInstruction.text,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @medicationrequest.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'MedicationRequest.status', + 'MedicationRequest.medicationCodeableConcept', + 'MedicationRequest.medicationReference', + 'MedicationRequest.subject', + 'MedicationRequest.authoredOn', + 'MedicationRequest.requester', + 'MedicationRequest.dosageInstruction', + 'MedicationRequest.dosageInstruction.text', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('MedicationRequest.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@medicationrequest, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index e9b74fbb1..6dc108ebb 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -174,30 +174,32 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('MedicationStatement.status') || can_resolve_path(@medicationstatement, 'status') - skip 'Could not find MedicationStatement.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.status,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.medicationCodeableConcept') || can_resolve_path(@medicationstatement, 'medicationCodeableConcept') - skip 'Could not find MedicationStatement.medicationCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.medicationCodeableConcept,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.medicationReference') || can_resolve_path(@medicationstatement, 'medicationReference') - skip 'Could not find MedicationStatement.medicationReference in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.medicationReference,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.subject') || can_resolve_path(@medicationstatement, 'subject') - skip 'Could not find MedicationStatement.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.subject,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.effectivedateTime') || can_resolve_path(@medicationstatement, 'effectivedateTime') - skip 'Could not find MedicationStatement.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.effectivePeriod') || can_resolve_path(@medicationstatement, 'effectivePeriod') - skip 'Could not find MedicationStatement.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.dateAsserted') || can_resolve_path(@medicationstatement, 'dateAsserted') - skip 'Could not find MedicationStatement.dateAsserted in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.dateAsserted,' - element_found = @instance.must_support_confirmed.include?('MedicationStatement.derivedFrom') || can_resolve_path(@medicationstatement, 'derivedFrom') - skip 'Could not find MedicationStatement.derivedFrom in the provided resource' unless element_found - @instance.must_support_confirmed += 'MedicationStatement.derivedFrom,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @medicationstatement.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'MedicationStatement.status', + 'MedicationStatement.medicationCodeableConcept', + 'MedicationStatement.medicationReference', + 'MedicationStatement.subject', + 'MedicationStatement.effectivedateTime', + 'MedicationStatement.effectivePeriod', + 'MedicationStatement.dateAsserted', + 'MedicationStatement.derivedFrom', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('MedicationStatement.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@medicationstatement, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index 0cc11db77..11c50b343 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -226,60 +226,42 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') - skip 'Could not find Observation.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.status,' - element_found = @instance.must_support_confirmed.include?('Observation.category') || can_resolve_path(@observation, 'category') - skip 'Could not find Observation.category in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.category,' - element_found = @instance.must_support_confirmed.include?('Observation.code') || can_resolve_path(@observation, 'code') - skip 'Could not find Observation.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.code,' - element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') - skip 'Could not find Observation.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.subject,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivedateTime') || can_resolve_path(@observation, 'effectivedateTime') - skip 'Could not find Observation.effectivedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.effectivePeriod') || can_resolve_path(@observation, 'effectivePeriod') - skip 'Could not find Observation.effectivePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.effectivePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.valueQuantity') || can_resolve_path(@observation, 'valueQuantity') - skip 'Could not find Observation.valueQuantity in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueQuantity,' - element_found = @instance.must_support_confirmed.include?('Observation.valueCodeableConcept') || can_resolve_path(@observation, 'valueCodeableConcept') - skip 'Could not find Observation.valueCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueCodeableConcept,' - element_found = @instance.must_support_confirmed.include?('Observation.valuestring') || can_resolve_path(@observation, 'valuestring') - skip 'Could not find Observation.valuestring in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valuestring,' - element_found = @instance.must_support_confirmed.include?('Observation.valueboolean') || can_resolve_path(@observation, 'valueboolean') - skip 'Could not find Observation.valueboolean in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueboolean,' - element_found = @instance.must_support_confirmed.include?('Observation.valueinteger') || can_resolve_path(@observation, 'valueinteger') - skip 'Could not find Observation.valueinteger in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueinteger,' - element_found = @instance.must_support_confirmed.include?('Observation.valueRange') || can_resolve_path(@observation, 'valueRange') - skip 'Could not find Observation.valueRange in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueRange,' - element_found = @instance.must_support_confirmed.include?('Observation.valueRatio') || can_resolve_path(@observation, 'valueRatio') - skip 'Could not find Observation.valueRatio in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueRatio,' - element_found = @instance.must_support_confirmed.include?('Observation.valueSampledData') || can_resolve_path(@observation, 'valueSampledData') - skip 'Could not find Observation.valueSampledData in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueSampledData,' - element_found = @instance.must_support_confirmed.include?('Observation.valuetime') || can_resolve_path(@observation, 'valuetime') - skip 'Could not find Observation.valuetime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valuetime,' - element_found = @instance.must_support_confirmed.include?('Observation.valuedateTime') || can_resolve_path(@observation, 'valuedateTime') - skip 'Could not find Observation.valuedateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valuedateTime,' - element_found = @instance.must_support_confirmed.include?('Observation.valuePeriod') || can_resolve_path(@observation, 'valuePeriod') - skip 'Could not find Observation.valuePeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valuePeriod,' - element_found = @instance.must_support_confirmed.include?('Observation.dataAbsentReason') || can_resolve_path(@observation, 'dataAbsentReason') - skip 'Could not find Observation.dataAbsentReason in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.dataAbsentReason,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @observation.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Observation.status', + 'Observation.category', + 'Observation.code', + 'Observation.subject', + 'Observation.effectivedateTime', + 'Observation.effectivePeriod', + 'Observation.valueQuantity', + 'Observation.valueCodeableConcept', + 'Observation.valuestring', + 'Observation.valueboolean', + 'Observation.valueinteger', + 'Observation.valueRange', + 'Observation.valueRatio', + 'Observation.valueSampledData', + 'Observation.valuetime', + 'Observation.valuedateTime', + 'Observation.valuePeriod', + 'Observation.dataAbsentReason', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@observation, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index a58a3183b..222564ffb 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -149,42 +149,36 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Organization.identifier') || can_resolve_path(@organization, 'identifier') - skip 'Could not find Organization.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.identifier,' - element_found = @instance.must_support_confirmed.include?('Organization.identifier.system') || can_resolve_path(@organization, 'identifier.system') - skip 'Could not find Organization.identifier.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.identifier.system,' - element_found = @instance.must_support_confirmed.include?('Organization.active') || can_resolve_path(@organization, 'active') - skip 'Could not find Organization.active in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.active,' - element_found = @instance.must_support_confirmed.include?('Organization.name') || can_resolve_path(@organization, 'name') - skip 'Could not find Organization.name in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.name,' - element_found = @instance.must_support_confirmed.include?('Organization.telecom') || can_resolve_path(@organization, 'telecom') - skip 'Could not find Organization.telecom in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.telecom,' - element_found = @instance.must_support_confirmed.include?('Organization.address') || can_resolve_path(@organization, 'address') - skip 'Could not find Organization.address in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address,' - element_found = @instance.must_support_confirmed.include?('Organization.address.line') || can_resolve_path(@organization, 'address.line') - skip 'Could not find Organization.address.line in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address.line,' - element_found = @instance.must_support_confirmed.include?('Organization.address.city') || can_resolve_path(@organization, 'address.city') - skip 'Could not find Organization.address.city in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address.city,' - element_found = @instance.must_support_confirmed.include?('Organization.address.state') || can_resolve_path(@organization, 'address.state') - skip 'Could not find Organization.address.state in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address.state,' - element_found = @instance.must_support_confirmed.include?('Organization.address.postalCode') || can_resolve_path(@organization, 'address.postalCode') - skip 'Could not find Organization.address.postalCode in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address.postalCode,' - element_found = @instance.must_support_confirmed.include?('Organization.address.country') || can_resolve_path(@organization, 'address.country') - skip 'Could not find Organization.address.country in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.address.country,' - element_found = @instance.must_support_confirmed.include?('Organization.endpoint') || can_resolve_path(@organization, 'endpoint') - skip 'Could not find Organization.endpoint in the provided resource' unless element_found - @instance.must_support_confirmed += 'Organization.endpoint,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @organization.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Organization.identifier', + 'Organization.identifier.system', + 'Organization.active', + 'Organization.name', + 'Organization.telecom', + 'Organization.address', + 'Organization.address.line', + 'Organization.address.city', + 'Organization.address.state', + 'Organization.address.postalCode', + 'Organization.address.country', + 'Organization.endpoint', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Organization.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@organization, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index 400b1058c..657ada79a 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -269,72 +269,45 @@ def validate_resource_item(resource, property, value) versions :r4 end - extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race' } - element_found = @instance.must_support_confirmed.include?('Patient.extension:race') || extension_found - skip 'Could not find Patient.extension:race in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.extension:race,' - extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity' } - element_found = @instance.must_support_confirmed.include?('Patient.extension:ethnicity') || extension_found - skip 'Could not find Patient.extension:ethnicity in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.extension:ethnicity,' - extension_found = @patient.extension.any? { |extension| extension.url == 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } - element_found = @instance.must_support_confirmed.include?('Patient.extension:birthsex') || extension_found - skip 'Could not find Patient.extension:birthsex in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.extension:birthsex,' - element_found = @instance.must_support_confirmed.include?('Patient.identifier') || can_resolve_path(@patient, 'identifier') - skip 'Could not find Patient.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.identifier,' - element_found = @instance.must_support_confirmed.include?('Patient.identifier.system') || can_resolve_path(@patient, 'identifier.system') - skip 'Could not find Patient.identifier.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.identifier.system,' - element_found = @instance.must_support_confirmed.include?('Patient.identifier.value') || can_resolve_path(@patient, 'identifier.value') - skip 'Could not find Patient.identifier.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.identifier.value,' - element_found = @instance.must_support_confirmed.include?('Patient.name') || can_resolve_path(@patient, 'name') - skip 'Could not find Patient.name in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.name,' - element_found = @instance.must_support_confirmed.include?('Patient.name.family') || can_resolve_path(@patient, 'name.family') - skip 'Could not find Patient.name.family in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.name.family,' - element_found = @instance.must_support_confirmed.include?('Patient.name.given') || can_resolve_path(@patient, 'name.given') - skip 'Could not find Patient.name.given in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.name.given,' - element_found = @instance.must_support_confirmed.include?('Patient.telecom') || can_resolve_path(@patient, 'telecom') - skip 'Could not find Patient.telecom in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.telecom,' - element_found = @instance.must_support_confirmed.include?('Patient.telecom.system') || can_resolve_path(@patient, 'telecom.system') - skip 'Could not find Patient.telecom.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.telecom.system,' - element_found = @instance.must_support_confirmed.include?('Patient.telecom.value') || can_resolve_path(@patient, 'telecom.value') - skip 'Could not find Patient.telecom.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.telecom.value,' - element_found = @instance.must_support_confirmed.include?('Patient.gender') || can_resolve_path(@patient, 'gender') - skip 'Could not find Patient.gender in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.gender,' - element_found = @instance.must_support_confirmed.include?('Patient.birthDate') || can_resolve_path(@patient, 'birthDate') - skip 'Could not find Patient.birthDate in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.birthDate,' - element_found = @instance.must_support_confirmed.include?('Patient.address') || can_resolve_path(@patient, 'address') - skip 'Could not find Patient.address in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.address,' - element_found = @instance.must_support_confirmed.include?('Patient.address.line') || can_resolve_path(@patient, 'address.line') - skip 'Could not find Patient.address.line in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.address.line,' - element_found = @instance.must_support_confirmed.include?('Patient.address.city') || can_resolve_path(@patient, 'address.city') - skip 'Could not find Patient.address.city in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.address.city,' - element_found = @instance.must_support_confirmed.include?('Patient.address.state') || can_resolve_path(@patient, 'address.state') - skip 'Could not find Patient.address.state in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.address.state,' - element_found = @instance.must_support_confirmed.include?('Patient.address.postalCode') || can_resolve_path(@patient, 'address.postalCode') - skip 'Could not find Patient.address.postalCode in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.address.postalCode,' - element_found = @instance.must_support_confirmed.include?('Patient.communication') || can_resolve_path(@patient, 'communication') - skip 'Could not find Patient.communication in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.communication,' - element_found = @instance.must_support_confirmed.include?('Patient.communication.language') || can_resolve_path(@patient, 'communication.language') - skip 'Could not find Patient.communication.language in the provided resource' unless element_found - @instance.must_support_confirmed += 'Patient.communication.language,' + extensions_list = { + 'Patient.extension:race': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race', + 'Patient.extension:ethnicity': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity', + 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex', + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @patient.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Patient.identifier', + 'Patient.identifier.system', + 'Patient.identifier.value', + 'Patient.name', + 'Patient.name.family', + 'Patient.name.given', + 'Patient.telecom', + 'Patient.telecom.system', + 'Patient.telecom.value', + 'Patient.gender', + 'Patient.birthDate', + 'Patient.address', + 'Patient.address.line', + 'Patient.address.city', + 'Patient.address.state', + 'Patient.address.postalCode', + 'Patient.communication', + 'Patient.communication.language', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Patient.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@patient, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index a57da3b22..c2a26ee93 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -157,27 +157,31 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Practitioner.identifier') || can_resolve_path(@practitioner, 'identifier') - skip 'Could not find Practitioner.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.identifier,' - element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.system') || can_resolve_path(@practitioner, 'identifier.system') - skip 'Could not find Practitioner.identifier.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.identifier.system,' - element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.value') || can_resolve_path(@practitioner, 'identifier.value') - skip 'Could not find Practitioner.identifier.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.identifier.value,' - element_found = @instance.must_support_confirmed.include?('Practitioner.identifier') || can_resolve_path(@practitioner, 'identifier') - skip 'Could not find Practitioner.identifier in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.identifier,' - element_found = @instance.must_support_confirmed.include?('Practitioner.identifier.system') || can_resolve_path(@practitioner, 'identifier.system') - skip 'Could not find Practitioner.identifier.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.identifier.system,' - element_found = @instance.must_support_confirmed.include?('Practitioner.name') || can_resolve_path(@practitioner, 'name') - skip 'Could not find Practitioner.name in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.name,' - element_found = @instance.must_support_confirmed.include?('Practitioner.name.family') || can_resolve_path(@practitioner, 'name.family') - skip 'Could not find Practitioner.name.family in the provided resource' unless element_found - @instance.must_support_confirmed += 'Practitioner.name.family,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @practitioner.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Practitioner.identifier', + 'Practitioner.identifier.system', + 'Practitioner.identifier.value', + 'Practitioner.identifier', + 'Practitioner.identifier.system', + 'Practitioner.name', + 'Practitioner.name.family', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Practitioner.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@practitioner, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index d6b3b98cb..2773976db 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -153,33 +153,33 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('PractitionerRole.practitioner') || can_resolve_path(@practitionerrole, 'practitioner') - skip 'Could not find PractitionerRole.practitioner in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.practitioner,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.organization') || can_resolve_path(@practitionerrole, 'organization') - skip 'Could not find PractitionerRole.organization in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.organization,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.code') || can_resolve_path(@practitionerrole, 'code') - skip 'Could not find PractitionerRole.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.code,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.specialty') || can_resolve_path(@practitionerrole, 'specialty') - skip 'Could not find PractitionerRole.specialty in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.specialty,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.location') || can_resolve_path(@practitionerrole, 'location') - skip 'Could not find PractitionerRole.location in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.location,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom') || can_resolve_path(@practitionerrole, 'telecom') - skip 'Could not find PractitionerRole.telecom in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.telecom,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom.system') || can_resolve_path(@practitionerrole, 'telecom.system') - skip 'Could not find PractitionerRole.telecom.system in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.telecom.system,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.telecom.value') || can_resolve_path(@practitionerrole, 'telecom.value') - skip 'Could not find PractitionerRole.telecom.value in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.telecom.value,' - element_found = @instance.must_support_confirmed.include?('PractitionerRole.endpoint') || can_resolve_path(@practitionerrole, 'endpoint') - skip 'Could not find PractitionerRole.endpoint in the provided resource' unless element_found - @instance.must_support_confirmed += 'PractitionerRole.endpoint,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @practitionerrole.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'PractitionerRole.practitioner', + 'PractitionerRole.organization', + 'PractitionerRole.code', + 'PractitionerRole.specialty', + 'PractitionerRole.location', + 'PractitionerRole.telecom', + 'PractitionerRole.telecom.system', + 'PractitionerRole.telecom.value', + 'PractitionerRole.endpoint', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('PractitionerRole.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@practitionerrole, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index 606e2ff1d..7cc3e9880 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -200,21 +200,29 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Procedure.status') || can_resolve_path(@procedure, 'status') - skip 'Could not find Procedure.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Procedure.status,' - element_found = @instance.must_support_confirmed.include?('Procedure.code') || can_resolve_path(@procedure, 'code') - skip 'Could not find Procedure.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Procedure.code,' - element_found = @instance.must_support_confirmed.include?('Procedure.subject') || can_resolve_path(@procedure, 'subject') - skip 'Could not find Procedure.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Procedure.subject,' - element_found = @instance.must_support_confirmed.include?('Procedure.performeddateTime') || can_resolve_path(@procedure, 'performeddateTime') - skip 'Could not find Procedure.performeddateTime in the provided resource' unless element_found - @instance.must_support_confirmed += 'Procedure.performeddateTime,' - element_found = @instance.must_support_confirmed.include?('Procedure.performedPeriod') || can_resolve_path(@procedure, 'performedPeriod') - skip 'Could not find Procedure.performedPeriod in the provided resource' unless element_found - @instance.must_support_confirmed += 'Procedure.performedPeriod,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @procedure.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Procedure.status', + 'Procedure.code', + 'Procedure.subject', + 'Procedure.performeddateTime', + 'Procedure.performedPeriod', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Procedure.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@procedure, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 4b7198ac9..61d0d5cf5 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -226,21 +226,29 @@ def validate_resource_item(resource, property, value) versions :r4 end - element_found = @instance.must_support_confirmed.include?('Observation.status') || can_resolve_path(@observation, 'status') - skip 'Could not find Observation.status in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.status,' - element_found = @instance.must_support_confirmed.include?('Observation.code') || can_resolve_path(@observation, 'code') - skip 'Could not find Observation.code in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.code,' - element_found = @instance.must_support_confirmed.include?('Observation.subject') || can_resolve_path(@observation, 'subject') - skip 'Could not find Observation.subject in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.subject,' - element_found = @instance.must_support_confirmed.include?('Observation.issued') || can_resolve_path(@observation, 'issued') - skip 'Could not find Observation.issued in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.issued,' - element_found = @instance.must_support_confirmed.include?('Observation.valueCodeableConcept') || can_resolve_path(@observation, 'valueCodeableConcept') - skip 'Could not find Observation.valueCodeableConcept in the provided resource' unless element_found - @instance.must_support_confirmed += 'Observation.valueCodeableConcept,' + extensions_list = { + } + extensions_list.each do |id, url| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || @observation.extension.any? { |extension| extension.url == url } + skip "Could not find #{id.to_s} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id.to_s}," unless already_found + end + + must_support_elements = [ + 'Observation.status', + 'Observation.code', + 'Observation.subject', + 'Observation.issued', + 'Observation.valueCodeableConcept', + ] + must_support_elements.each do |path| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(@observation, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end @instance.save! end diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 453e4456f..f488548f4 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -745,8 +745,8 @@ def can_resolve_path(element, path) path_ary = path.split('.') el_as_array = Array.wrap(element) - cur_path_part = path_ary.delete_at(0) - return false unless el_as_array.any? { |el| !el.try(cur_path_part.to_sym).nil? } + cur_path_part = path_ary.shift.to_sym + return false if el_as_array.none? { |el| el.try(cur_path_part).present? } el_as_array.any? { |el| can_resolve_path(el.send(cur_path_part), path_ary.join('.')) } end From cc30d67a0e6fe650d553c229c816206851f24459 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Jun 2019 19:45:09 -0400 Subject: [PATCH 04/89] lint errors --- generators/argonaut-r4/generator.rb | 35 ++++++++++--------- .../pediatric_bmi_for_age_sequence.rb | 11 +----- .../pediatric_weight_for_height_sequence.rb | 11 +----- .../us_core_allergyintolerance_sequence.rb | 11 +----- .../us_core_r4/us_core_careplan_sequence.rb | 11 +----- .../us_core_r4/us_core_careteam_sequence.rb | 11 +----- .../us_core_r4/us_core_condition_sequence.rb | 11 +----- .../us_core_r4/us_core_device_sequence.rb | 11 +----- .../us_core_diagnosticreport_lab_sequence.rb | 11 +----- .../us_core_diagnosticreport_note_sequence.rb | 11 +----- .../us_core_documentreference_sequence.rb | 11 +----- .../us_core_r4/us_core_encounter_sequence.rb | 11 +----- .../us_core_r4/us_core_goal_sequence.rb | 11 +----- .../us_core_immunization_sequence.rb | 11 +----- .../us_core_r4/us_core_location_sequence.rb | 11 +----- .../us_core_r4/us_core_medication_sequence.rb | 11 +----- .../us_core_medicationrequest_sequence.rb | 11 +----- .../us_core_medicationstatement_sequence.rb | 11 +----- .../us_core_observation_lab_sequence.rb | 11 +----- .../us_core_organization_sequence.rb | 11 +----- .../us_core_r4/us_core_patient_sequence.rb | 8 ++--- .../us_core_practitioner_sequence.rb | 11 +----- .../us_core_practitionerrole_sequence.rb | 11 +----- .../us_core_r4/us_core_procedure_sequence.rb | 11 +----- .../us_core_smokingstatus_sequence.rb | 11 +----- 25 files changed, 46 insertions(+), 250 deletions(-) diff --git a/generators/argonaut-r4/generator.rb b/generators/argonaut-r4/generator.rb index 12784ca63..c7d37facb 100644 --- a/generators/argonaut-r4/generator.rb +++ b/generators/argonaut-r4/generator.rb @@ -147,32 +147,34 @@ def create_must_support_test(sequence) link: 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support', test_code: '' } - - extensions_list = '' + + extensions_list = [] sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| - extensions_list += %( - '#{extension[:id]}': '#{extension[:url]}',) + extensions_list << "'#{extension[:id]}': '#{extension[:url]}'" end - test[:test_code] += %( - extensions_list = {#{extensions_list} + if extensions_list.any? + test[:test_code] += %( + extensions_list = { + #{extensions_list.join(",\n ")} } extensions_list.each do |id, url| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == url } - skip "Could not find \#{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "\#{id.to_s}," unless already_found - end) - - elements_list = '' + skip "Could not find \#{id} in the provided resource" unless element_found + @instance.must_support_confirmed += "\#{id}," unless already_found + end +) + end + elements_list = [] sequence[:must_supports].select { |must_support| must_support[:type] == 'element' }.each do |element| element[:path] = element[:path].gsub('.class', '.local_class') # class is mapped to local_class in fhir_models - elements_list += %( - '#{element[:path]}',) + elements_list << "'#{element[:path]}'" end - - test[:test_code] += %( - must_support_elements = [#{elements_list} + if elements_list.any? + test[:test_code] += %( + must_support_elements = [ + #{elements_list.join(",\n ")} ] must_support_elements.each do |path| truncated_path = path.gsub('#{sequence[:resource]}.', '') @@ -181,6 +183,7 @@ def create_must_support_test(sequence) skip "Could not find \#{path} in the provided resource" unless element_found @instance.must_support_confirmed += "\#{path}," unless already_found end) + end test[:test_code] += %( @instance.save!) diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index 52be1d47c..59407b88f 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -226,15 +226,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @observation.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Observation.status', 'Observation.category', @@ -263,7 +254,7 @@ def validate_resource_item(resource, property, value) 'Observation.component.valuetime', 'Observation.component.valuedateTime', 'Observation.component.valuePeriod', - 'Observation.component.dataAbsentReason', + 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| truncated_path = path.gsub('Observation.', '') diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index b8757b838..90ba0ce8f 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -226,15 +226,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @observation.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Observation.status', 'Observation.category', @@ -263,7 +254,7 @@ def validate_resource_item(resource, property, value) 'Observation.component.valuetime', 'Observation.component.valuedateTime', 'Observation.component.valuePeriod', - 'Observation.component.dataAbsentReason', + 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| truncated_path = path.gsub('Observation.', '') diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 04b46336e..6a6448d7e 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -154,20 +154,11 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @allergyintolerance.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'AllergyIntolerance.clinicalStatus', 'AllergyIntolerance.verificationStatus', 'AllergyIntolerance.code', - 'AllergyIntolerance.patient', + 'AllergyIntolerance.patient' ] must_support_elements.each do |path| truncated_path = path.gsub('AllergyIntolerance.', '') diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index b1c916a89..b4f0a3e69 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -202,15 +202,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @careplan.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'CarePlan.text', 'CarePlan.text.status', @@ -218,7 +209,7 @@ def validate_resource_item(resource, property, value) 'CarePlan.intent', 'CarePlan.category', 'CarePlan.category', - 'CarePlan.subject', + 'CarePlan.subject' ] must_support_elements.each do |path| truncated_path = path.gsub('CarePlan.', '') diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 3cfa67d45..67ccc8c0c 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -131,21 +131,12 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @careteam.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'CareTeam.status', 'CareTeam.subject', 'CareTeam.participant', 'CareTeam.participant.role', - 'CareTeam.participant.member', + 'CareTeam.participant.member' ] must_support_elements.each do |path| truncated_path = path.gsub('CareTeam.', '') diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index ebc2edb17..ede787ed7 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -226,21 +226,12 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @condition.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Condition.clinicalStatus', 'Condition.verificationStatus', 'Condition.category', 'Condition.code', - 'Condition.subject', + 'Condition.subject' ] must_support_elements.each do |path| truncated_path = path.gsub('Condition.', '') diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index 8ace32ac7..8cf84e4da 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -154,21 +154,12 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @device.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Device.udiCarrier', 'Device.udiCarrier.carrierAIDC', 'Device.udiCarrier.carrierHRF', 'Device.type', - 'Device.patient', + 'Device.patient' ] must_support_elements.each do |path| truncated_path = path.gsub('Device.', '') diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index 3c729eb8c..421a611d2 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -279,15 +279,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @diagnosticreport.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -299,7 +290,7 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.performer', 'DiagnosticReport.result', 'DiagnosticReport.media', - 'DiagnosticReport.presentedForm', + 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| truncated_path = path.gsub('DiagnosticReport.', '') diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index 00673bf3c..ae5b17b00 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -279,15 +279,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @diagnosticreport.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -299,7 +290,7 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.issued', 'DiagnosticReport.performer', 'DiagnosticReport.media', - 'DiagnosticReport.presentedForm', + 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| truncated_path = path.gsub('DiagnosticReport.', '') diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index d80f5a998..6d3d38534 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -285,15 +285,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @documentreference.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'DocumentReference.identifier', 'DocumentReference.status', @@ -311,7 +302,7 @@ def validate_resource_item(resource, property, value) 'DocumentReference.content.format', 'DocumentReference.context', 'DocumentReference.context.encounter', - 'DocumentReference.context.period', + 'DocumentReference.context.period' ] must_support_elements.each do |path| truncated_path = path.gsub('DocumentReference.', '') diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index fb686e30b..7479c996b 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -266,15 +266,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @encounter.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Encounter.identifier', 'Encounter.identifier.system', @@ -292,7 +283,7 @@ def validate_resource_item(resource, property, value) 'Encounter.hospitalization', 'Encounter.hospitalization.dischargeDisposition', 'Encounter.location', - 'Encounter.location.location', + 'Encounter.location.location' ] must_support_elements.each do |path| truncated_path = path.gsub('Encounter.', '') diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index 20b0239e9..a3971d19f 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -174,22 +174,13 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @goal.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Goal.lifecycleStatus', 'Goal.description', 'Goal.subject', 'Goal.target', 'Goal.target.duedate', - 'Goal.target.dueDuration', + 'Goal.target.dueDuration' ] must_support_elements.each do |path| truncated_path = path.gsub('Goal.', '') diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index 3965f39c4..de0519bf7 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -174,15 +174,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @immunization.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Immunization.status', 'Immunization.statusReason', @@ -190,7 +181,7 @@ def validate_resource_item(resource, property, value) 'Immunization.patient', 'Immunization.occurrencedateTime', 'Immunization.occurrencestring', - 'Immunization.primarySource', + 'Immunization.primarySource' ] must_support_elements.each do |path| truncated_path = path.gsub('Immunization.', '') diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index b4886359f..d58f6016e 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -215,15 +215,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @location.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Location.status', 'Location.name', @@ -233,7 +224,7 @@ def validate_resource_item(resource, property, value) 'Location.address.city', 'Location.address.state', 'Location.address.postalCode', - 'Location.managingOrganization', + 'Location.managingOrganization' ] must_support_elements.each do |path| truncated_path = path.gsub('Location.', '') diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index cfca486ac..e3ed821e7 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -94,17 +94,8 @@ class UsCoreR4MedicationSequence < SequenceBase versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @medication.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ - 'Medication.code', + 'Medication.code' ] must_support_elements.each do |path| truncated_path = path.gsub('Medication.', '') diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index a7cb05d50..6045040c9 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -174,15 +174,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @medicationrequest.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'MedicationRequest.status', 'MedicationRequest.medicationCodeableConcept', @@ -191,7 +182,7 @@ def validate_resource_item(resource, property, value) 'MedicationRequest.authoredOn', 'MedicationRequest.requester', 'MedicationRequest.dosageInstruction', - 'MedicationRequest.dosageInstruction.text', + 'MedicationRequest.dosageInstruction.text' ] must_support_elements.each do |path| truncated_path = path.gsub('MedicationRequest.', '') diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index 6dc108ebb..06c934955 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -174,15 +174,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @medicationstatement.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'MedicationStatement.status', 'MedicationStatement.medicationCodeableConcept', @@ -191,7 +182,7 @@ def validate_resource_item(resource, property, value) 'MedicationStatement.effectivedateTime', 'MedicationStatement.effectivePeriod', 'MedicationStatement.dateAsserted', - 'MedicationStatement.derivedFrom', + 'MedicationStatement.derivedFrom' ] must_support_elements.each do |path| truncated_path = path.gsub('MedicationStatement.', '') diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index 11c50b343..f37f1ed1b 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -226,15 +226,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @observation.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Observation.status', 'Observation.category', @@ -253,7 +244,7 @@ def validate_resource_item(resource, property, value) 'Observation.valuetime', 'Observation.valuedateTime', 'Observation.valuePeriod', - 'Observation.dataAbsentReason', + 'Observation.dataAbsentReason' ] must_support_elements.each do |path| truncated_path = path.gsub('Observation.', '') diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index 222564ffb..4e69c4980 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -149,15 +149,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @organization.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Organization.identifier', 'Organization.identifier.system', @@ -170,7 +161,7 @@ def validate_resource_item(resource, property, value) 'Organization.address.state', 'Organization.address.postalCode', 'Organization.address.country', - 'Organization.endpoint', + 'Organization.endpoint' ] must_support_elements.each do |path| truncated_path = path.gsub('Organization.', '') diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index 657ada79a..ed0c4dfa1 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -272,13 +272,13 @@ def validate_resource_item(resource, property, value) extensions_list = { 'Patient.extension:race': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race', 'Patient.extension:ethnicity': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity', - 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex', + 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } extensions_list.each do |id, url| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || @patient.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found + skip "Could not find #{id} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id}," unless already_found end must_support_elements = [ @@ -299,7 +299,7 @@ def validate_resource_item(resource, property, value) 'Patient.address.state', 'Patient.address.postalCode', 'Patient.communication', - 'Patient.communication.language', + 'Patient.communication.language' ] must_support_elements.each do |path| truncated_path = path.gsub('Patient.', '') diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index c2a26ee93..dc560d971 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -157,15 +157,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @practitioner.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Practitioner.identifier', 'Practitioner.identifier.system', @@ -173,7 +164,7 @@ def validate_resource_item(resource, property, value) 'Practitioner.identifier', 'Practitioner.identifier.system', 'Practitioner.name', - 'Practitioner.name.family', + 'Practitioner.name.family' ] must_support_elements.each do |path| truncated_path = path.gsub('Practitioner.', '') diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index 2773976db..499732270 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -153,15 +153,6 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @practitionerrole.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'PractitionerRole.practitioner', 'PractitionerRole.organization', @@ -171,7 +162,7 @@ def validate_resource_item(resource, property, value) 'PractitionerRole.telecom', 'PractitionerRole.telecom.system', 'PractitionerRole.telecom.value', - 'PractitionerRole.endpoint', + 'PractitionerRole.endpoint' ] must_support_elements.each do |path| truncated_path = path.gsub('PractitionerRole.', '') diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index 7cc3e9880..a7b9dbe70 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -200,21 +200,12 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @procedure.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Procedure.status', 'Procedure.code', 'Procedure.subject', 'Procedure.performeddateTime', - 'Procedure.performedPeriod', + 'Procedure.performedPeriod' ] must_support_elements.each do |path| truncated_path = path.gsub('Procedure.', '') diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 61d0d5cf5..1fba0138d 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -226,21 +226,12 @@ def validate_resource_item(resource, property, value) versions :r4 end - extensions_list = { - } - extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @observation.extension.any? { |extension| extension.url == url } - skip "Could not find #{id.to_s} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id.to_s}," unless already_found - end - must_support_elements = [ 'Observation.status', 'Observation.code', 'Observation.subject', 'Observation.issued', - 'Observation.valueCodeableConcept', + 'Observation.valueCodeableConcept' ] must_support_elements.each do |path| truncated_path = path.gsub('Observation.', '') From 5da035e6c532cb3e1a177a6b5ffed3a6aa498c0a Mon Sep 17 00:00:00 2001 From: Chase Zhou Date: Mon, 24 Jun 2019 10:39:54 -0400 Subject: [PATCH 05/89] increase maximum class size --- .rubocop_todo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f1b9e8620..eba6a4470 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -50,7 +50,7 @@ Metrics/BlockNesting: # Offense count: 60 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 594 + Max: 600 # Offense count: 38 Metrics/CyclomaticComplexity: From 14f711c88fbecd7e96f8b23ed4fe2658ca25166c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jun 2019 20:16:44 -0400 Subject: [PATCH 06/89] changed argonaut to us core r4 and now checking all resources replied for must supports --- .../{argonaut-r4 => uscore-r4}/generator.rb | 27 +++++++++++-------- .../metadata_extractor.rb | 0 .../templates/module.yml.erb | 0 .../templates/sequence.rb.erb | 0 .../pediatric_bmi_for_age_sequence.rb | 17 +++++++----- .../pediatric_weight_for_height_sequence.rb | 17 +++++++----- .../us_core_allergyintolerance_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_careplan_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_careteam_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_condition_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_device_sequence.rb | 17 +++++++----- .../us_core_diagnosticreport_lab_sequence.rb | 17 +++++++----- .../us_core_diagnosticreport_note_sequence.rb | 17 +++++++----- .../us_core_documentreference_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_encounter_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_goal_sequence.rb | 17 +++++++----- .../us_core_immunization_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_location_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_medication_sequence.rb | 14 +++++----- .../us_core_medicationrequest_sequence.rb | 17 +++++++----- .../us_core_medicationstatement_sequence.rb | 17 +++++++----- .../us_core_observation_lab_sequence.rb | 17 +++++++----- .../us_core_organization_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_patient_sequence.rb | 27 +++++++++++-------- .../us_core_practitioner_sequence.rb | 17 +++++++----- .../us_core_practitionerrole_sequence.rb | 17 +++++++----- .../us_core_r4/us_core_procedure_sequence.rb | 17 +++++++----- .../us_core_smokingstatus_sequence.rb | 17 +++++++----- 28 files changed, 260 insertions(+), 182 deletions(-) rename generators/{argonaut-r4 => uscore-r4}/generator.rb (93%) rename generators/{argonaut-r4 => uscore-r4}/metadata_extractor.rb (100%) rename generators/{argonaut-r4 => uscore-r4}/templates/module.yml.erb (100%) rename generators/{argonaut-r4 => uscore-r4}/templates/sequence.rb.erb (100%) diff --git a/generators/argonaut-r4/generator.rb b/generators/uscore-r4/generator.rb similarity index 93% rename from generators/argonaut-r4/generator.rb rename to generators/uscore-r4/generator.rb index c7d37facb..2ef112dc3 100644 --- a/generators/argonaut-r4/generator.rb +++ b/generators/uscore-r4/generator.rb @@ -105,12 +105,13 @@ def create_search_test(sequence, search_param) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @#{sequence[:resource].downcase} = reply.try(:resource).try(:entry).try(:first).try(:resource) + @#{sequence[:resource].downcase}_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('#{sequence[:resource]}'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('#{sequence[:resource]}'), reply)) else @@ -158,10 +159,12 @@ def create_must_support_test(sequence) #{extensions_list.join(",\n ")} } extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @#{sequence[:resource].downcase}.extension.any? { |extension| extension.url == url } - skip "Could not find \#{id} in the provided resource" unless element_found - @instance.must_support_confirmed += "\#{id}," unless already_found + @#{sequence[:resource].downcase}_ary.each do |resource| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || resource.extension.any? { |extension| extension.url == url } + skip "Could not find \#{id} in the provided resource" unless element_found + @instance.must_support_confirmed += "\#{id}," unless already_found + end end ) end @@ -177,11 +180,13 @@ def create_must_support_test(sequence) #{elements_list.join(",\n ")} ] must_support_elements.each do |path| - truncated_path = path.gsub('#{sequence[:resource]}.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@#{sequence[:resource].downcase}, truncated_path) - skip "Could not find \#{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "\#{path}," unless already_found + @#{sequence[:resource].downcase}_ary.each do |resource| + truncated_path = path.gsub('#{sequence[:resource]}.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find \#{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "\#{path}," unless already_found + end end) end @@ -193,7 +198,7 @@ def create_must_support_test(sequence) def create_resource_profile_test(sequence) test = { - tests_that: "#{sequence[:resource]} resources associated with Patient conform to Argonaut profiles", + tests_that: "#{sequence[:resource]} resources associated with Patient conform to US Core R4 profiles", index: sequence[:tests].length + 1, link: sequence[:profile] } diff --git a/generators/argonaut-r4/metadata_extractor.rb b/generators/uscore-r4/metadata_extractor.rb similarity index 100% rename from generators/argonaut-r4/metadata_extractor.rb rename to generators/uscore-r4/metadata_extractor.rb diff --git a/generators/argonaut-r4/templates/module.yml.erb b/generators/uscore-r4/templates/module.yml.erb similarity index 100% rename from generators/argonaut-r4/templates/module.yml.erb rename to generators/uscore-r4/templates/module.yml.erb diff --git a/generators/argonaut-r4/templates/sequence.rb.erb b/generators/uscore-r4/templates/sequence.rb.erb similarity index 100% rename from generators/argonaut-r4/templates/sequence.rb.erb rename to generators/uscore-r4/templates/sequence.rb.erb diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index 59407b88f..29b73feaf 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @observation = reply.try(:resource).try(:entry).try(:first).try(:resource) + @observation_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Observation'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) end @@ -257,16 +258,18 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@observation, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @observation_ary.each do |resource| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-bmi-for-age.json' diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index 90ba0ce8f..4b900fc00 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @observation = reply.try(:resource).try(:entry).try(:first).try(:resource) + @observation_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Observation'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) end @@ -257,16 +258,18 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@observation, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @observation_ary.each do |resource| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-weight-for-height.json' diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 6a6448d7e..fe362f55f 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @allergyintolerance = reply.try(:resource).try(:entry).try(:first).try(:resource) + @allergyintolerance_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('AllergyIntolerance'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('AllergyIntolerance'), reply) end @@ -161,16 +162,18 @@ def validate_resource_item(resource, property, value) 'AllergyIntolerance.patient' ] must_support_elements.each do |path| - truncated_path = path.gsub('AllergyIntolerance.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@allergyintolerance, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @allergyintolerance_ary.each do |resource| + truncated_path = path.gsub('AllergyIntolerance.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'AllergyIntolerance resources associated with Patient conform to Argonaut profiles' do + test 'AllergyIntolerance resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-allergyintolerance.json' diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index b4f0a3e69..f80b1bb30 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -74,12 +74,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @careplan = reply.try(:resource).try(:entry).try(:first).try(:resource) + @careplan_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('CarePlan'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('CarePlan'), reply) end @@ -212,16 +213,18 @@ def validate_resource_item(resource, property, value) 'CarePlan.subject' ] must_support_elements.each do |path| - truncated_path = path.gsub('CarePlan.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@careplan, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @careplan_ary.each do |resource| + truncated_path = path.gsub('CarePlan.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'CarePlan resources associated with Patient conform to Argonaut profiles' do + test 'CarePlan resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careplan.json' diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 67ccc8c0c..219164324 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -67,12 +67,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @careteam = reply.try(:resource).try(:entry).try(:first).try(:resource) + @careteam_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('CareTeam'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('CareTeam'), reply) end @@ -139,16 +140,18 @@ def validate_resource_item(resource, property, value) 'CareTeam.participant.member' ] must_support_elements.each do |path| - truncated_path = path.gsub('CareTeam.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@careteam, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @careteam_ary.each do |resource| + truncated_path = path.gsub('CareTeam.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'CareTeam resources associated with Patient conform to Argonaut profiles' do + test 'CareTeam resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careteam.json' diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index ede787ed7..9a969a48f 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -82,12 +82,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @condition = reply.try(:resource).try(:entry).try(:first).try(:resource) + @condition_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Condition'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Condition'), reply) end @@ -234,16 +235,18 @@ def validate_resource_item(resource, property, value) 'Condition.subject' ] must_support_elements.each do |path| - truncated_path = path.gsub('Condition.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@condition, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @condition_ary.each do |resource| + truncated_path = path.gsub('Condition.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Condition resources associated with Patient conform to Argonaut profiles' do + test 'Condition resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-condition.json' diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index 8cf84e4da..bef30f122 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @device = reply.try(:resource).try(:entry).try(:first).try(:resource) + @device_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Device'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Device'), reply) end @@ -162,16 +163,18 @@ def validate_resource_item(resource, property, value) 'Device.patient' ] must_support_elements.each do |path| - truncated_path = path.gsub('Device.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@device, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @device_ary.each do |resource| + truncated_path = path.gsub('Device.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Device resources associated with Patient conform to Argonaut profiles' do + test 'Device resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-device.json' diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index 421a611d2..368010802 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @diagnosticreport = reply.try(:resource).try(:entry).try(:first).try(:resource) + @diagnosticreport_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('DiagnosticReport'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('DiagnosticReport'), reply) end @@ -293,16 +294,18 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - truncated_path = path.gsub('DiagnosticReport.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@diagnosticreport, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @diagnosticreport_ary.each do |resource| + truncated_path = path.gsub('DiagnosticReport.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do metadata do id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-lab.json' diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index ae5b17b00..c317e2002 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @diagnosticreport = reply.try(:resource).try(:entry).try(:first).try(:resource) + @diagnosticreport_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('DiagnosticReport'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('DiagnosticReport'), reply) end @@ -293,16 +294,18 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - truncated_path = path.gsub('DiagnosticReport.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@diagnosticreport, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @diagnosticreport_ary.each do |resource| + truncated_path = path.gsub('DiagnosticReport.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'DiagnosticReport resources associated with Patient conform to Argonaut profiles' do + test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do metadata do id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-note.json' diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index 6d3d38534..3fbce05d3 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -85,12 +85,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @documentreference = reply.try(:resource).try(:entry).try(:first).try(:resource) + @documentreference_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('DocumentReference'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('DocumentReference'), reply) end @@ -305,16 +306,18 @@ def validate_resource_item(resource, property, value) 'DocumentReference.context.period' ] must_support_elements.each do |path| - truncated_path = path.gsub('DocumentReference.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@documentreference, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @documentreference_ary.each do |resource| + truncated_path = path.gsub('DocumentReference.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'DocumentReference resources associated with Patient conform to Argonaut profiles' do + test 'DocumentReference resources associated with Patient conform to US Core R4 profiles' do metadata do id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-documentreference.json' diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index 7479c996b..72959d773 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -84,12 +84,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @encounter = reply.try(:resource).try(:entry).try(:first).try(:resource) + @encounter_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Encounter'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Encounter'), reply) end @@ -286,16 +287,18 @@ def validate_resource_item(resource, property, value) 'Encounter.location.location' ] must_support_elements.each do |path| - truncated_path = path.gsub('Encounter.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@encounter, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @encounter_ary.each do |resource| + truncated_path = path.gsub('Encounter.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Encounter resources associated with Patient conform to Argonaut profiles' do + test 'Encounter resources associated with Patient conform to US Core R4 profiles' do metadata do id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-encounter.json' diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index a3971d19f..e1a87ea33 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @goal = reply.try(:resource).try(:entry).try(:first).try(:resource) + @goal_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Goal'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Goal'), reply) end @@ -183,16 +184,18 @@ def validate_resource_item(resource, property, value) 'Goal.target.dueDuration' ] must_support_elements.each do |path| - truncated_path = path.gsub('Goal.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@goal, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @goal_ary.each do |resource| + truncated_path = path.gsub('Goal.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Goal resources associated with Patient conform to Argonaut profiles' do + test 'Goal resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-goal.json' diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index de0519bf7..95e2599e8 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @immunization = reply.try(:resource).try(:entry).try(:first).try(:resource) + @immunization_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Immunization'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Immunization'), reply) end @@ -184,16 +185,18 @@ def validate_resource_item(resource, property, value) 'Immunization.primarySource' ] must_support_elements.each do |path| - truncated_path = path.gsub('Immunization.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@immunization, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @immunization_ary.each do |resource| + truncated_path = path.gsub('Immunization.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Immunization resources associated with Patient conform to Argonaut profiles' do + test 'Immunization resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-immunization.json' diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index d58f6016e..c1f6cf8c8 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -75,12 +75,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @location = reply.try(:resource).try(:entry).try(:first).try(:resource) + @location_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Location'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Location'), reply) end @@ -227,16 +228,18 @@ def validate_resource_item(resource, property, value) 'Location.managingOrganization' ] must_support_elements.each do |path| - truncated_path = path.gsub('Location.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@location, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @location_ary.each do |resource| + truncated_path = path.gsub('Location.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Location resources associated with Patient conform to Argonaut profiles' do + test 'Location resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-location.json' diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index e3ed821e7..a4467ebe9 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -98,16 +98,18 @@ class UsCoreR4MedicationSequence < SequenceBase 'Medication.code' ] must_support_elements.each do |path| - truncated_path = path.gsub('Medication.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@medication, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @medication_ary.each do |resource| + truncated_path = path.gsub('Medication.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Medication resources associated with Patient conform to Argonaut profiles' do + test 'Medication resources associated with Patient conform to US Core R4 profiles' do metadata do id '06' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medication.json' diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index 6045040c9..aa0565f38 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @medicationrequest = reply.try(:resource).try(:entry).try(:first).try(:resource) + @medicationrequest_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('MedicationRequest'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('MedicationRequest'), reply) end @@ -185,16 +186,18 @@ def validate_resource_item(resource, property, value) 'MedicationRequest.dosageInstruction.text' ] must_support_elements.each do |path| - truncated_path = path.gsub('MedicationRequest.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@medicationrequest, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @medicationrequest_ary.each do |resource| + truncated_path = path.gsub('MedicationRequest.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'MedicationRequest resources associated with Patient conform to Argonaut profiles' do + test 'MedicationRequest resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationrequest.json' diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index 06c934955..839e88a55 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @medicationstatement = reply.try(:resource).try(:entry).try(:first).try(:resource) + @medicationstatement_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('MedicationStatement'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('MedicationStatement'), reply) end @@ -185,16 +186,18 @@ def validate_resource_item(resource, property, value) 'MedicationStatement.derivedFrom' ] must_support_elements.each do |path| - truncated_path = path.gsub('MedicationStatement.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@medicationstatement, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @medicationstatement_ary.each do |resource| + truncated_path = path.gsub('MedicationStatement.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'MedicationStatement resources associated with Patient conform to Argonaut profiles' do + test 'MedicationStatement resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationstatement.json' diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index f37f1ed1b..def9a1a21 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @observation = reply.try(:resource).try(:entry).try(:first).try(:resource) + @observation_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Observation'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) end @@ -247,16 +248,18 @@ def validate_resource_item(resource, property, value) 'Observation.dataAbsentReason' ] must_support_elements.each do |path| - truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@observation, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @observation_ary.each do |resource| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-observation-lab.json' diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index 4e69c4980..de1ceedeb 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -66,12 +66,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @organization = reply.try(:resource).try(:entry).try(:first).try(:resource) + @organization_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Organization'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Organization'), reply) end @@ -164,16 +165,18 @@ def validate_resource_item(resource, property, value) 'Organization.endpoint' ] must_support_elements.each do |path| - truncated_path = path.gsub('Organization.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@organization, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @organization_ary.each do |resource| + truncated_path = path.gsub('Organization.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Organization resources associated with Patient conform to Argonaut profiles' do + test 'Organization resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-organization.json' diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index ed0c4dfa1..f6d96f197 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -87,12 +87,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @patient = reply.try(:resource).try(:entry).try(:first).try(:resource) + @patient_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Patient'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Patient'), reply) end @@ -275,10 +276,12 @@ def validate_resource_item(resource, property, value) 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } extensions_list.each do |id, url| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || @patient.extension.any? { |extension| extension.url == url } - skip "Could not find #{id} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{id}," unless already_found + @patient_ary.each do |resource| + already_found = @instance.must_support_confirmed.include?(id.to_s) + element_found = already_found || resource.extension.any? { |extension| extension.url == url } + skip "Could not find #{id} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{id}," unless already_found + end end must_support_elements = [ @@ -302,16 +305,18 @@ def validate_resource_item(resource, property, value) 'Patient.communication.language' ] must_support_elements.each do |path| - truncated_path = path.gsub('Patient.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@patient, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @patient_ary.each do |resource| + truncated_path = path.gsub('Patient.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Patient resources associated with Patient conform to Argonaut profiles' do + test 'Patient resources associated with Patient conform to US Core R4 profiles' do metadata do id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-patient.json' diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index dc560d971..11e9f31cf 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -74,12 +74,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @practitioner = reply.try(:resource).try(:entry).try(:first).try(:resource) + @practitioner_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Practitioner'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Practitioner'), reply) end @@ -167,16 +168,18 @@ def validate_resource_item(resource, property, value) 'Practitioner.name.family' ] must_support_elements.each do |path| - truncated_path = path.gsub('Practitioner.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@practitioner, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @practitioner_ary.each do |resource| + truncated_path = path.gsub('Practitioner.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Practitioner resources associated with Patient conform to Argonaut profiles' do + test 'Practitioner resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitioner.json' diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index 499732270..9b0ac6cfd 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -70,12 +70,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @practitionerrole = reply.try(:resource).try(:entry).try(:first).try(:resource) + @practitionerrole_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('PractitionerRole'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('PractitionerRole'), reply) end @@ -165,16 +166,18 @@ def validate_resource_item(resource, property, value) 'PractitionerRole.endpoint' ] must_support_elements.each do |path| - truncated_path = path.gsub('PractitionerRole.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@practitionerrole, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @practitionerrole_ary.each do |resource| + truncated_path = path.gsub('PractitionerRole.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'PractitionerRole resources associated with Patient conform to Argonaut profiles' do + test 'PractitionerRole resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitionerrole.json' diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index a7b9dbe70..4358a0e8d 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -75,12 +75,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @procedure = reply.try(:resource).try(:entry).try(:first).try(:resource) + @procedure_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Procedure'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Procedure'), reply) end @@ -208,16 +209,18 @@ def validate_resource_item(resource, property, value) 'Procedure.performedPeriod' ] must_support_elements.each do |path| - truncated_path = path.gsub('Procedure.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@procedure, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @procedure_ary.each do |resource| + truncated_path = path.gsub('Procedure.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Procedure resources associated with Patient conform to Argonaut profiles' do + test 'Procedure resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-procedure.json' diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 1fba0138d..6714118e5 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -79,12 +79,13 @@ def validate_resource_item(resource, property, value) assert_response_ok(reply) assert_bundle_response(reply) - resource_count = reply.try(:resource).try(:entry).try(:length) || 0 + resource_count = reply&.resource&.entry&.length || 0 @resources_found = true if resource_count.positive? skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found @observation = reply.try(:resource).try(:entry).try(:first).try(:resource) + @observation_ary = reply&.resource&.entry&.map { |entry| entry&.resource } validate_search_reply(versioned_resource_class('Observation'), reply, search_params) save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) end @@ -234,16 +235,18 @@ def validate_resource_item(resource, property, value) 'Observation.valueCodeableConcept' ] must_support_elements.each do |path| - truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(@observation, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @observation_ary.each do |resource| + truncated_path = path.gsub('Observation.', '') + already_found = @instance.must_support_confirmed.include?(path) + element_found = already_found || can_resolve_path(resource, truncated_path) + skip "Could not find #{path} in the provided resource" unless element_found + @instance.must_support_confirmed += "#{path}," unless already_found + end end @instance.save! end - test 'Observation resources associated with Patient conform to Argonaut profiles' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-smokingstatus.json' From 9f1ec7c382b4912cbbc608cea21ae462056fb08b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jun 2019 20:53:40 -0400 Subject: [PATCH 07/89] some bug fixes --- generators/uscore-r4/generator.rb | 7 +++++-- .../modules/us_core_r4/pediatric_bmi_for_age_sequence.rb | 3 ++- .../us_core_r4/pediatric_weight_for_height_sequence.rb | 3 ++- .../us_core_r4/us_core_allergyintolerance_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_careplan_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_careteam_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_condition_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_device_sequence.rb | 3 ++- .../us_core_r4/us_core_diagnosticreport_lab_sequence.rb | 3 ++- .../us_core_r4/us_core_diagnosticreport_note_sequence.rb | 3 ++- .../us_core_r4/us_core_documentreference_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_encounter_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_goal_sequence.rb | 3 ++- .../modules/us_core_r4/us_core_immunization_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_location_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_medication_sequence.rb | 3 ++- .../us_core_r4/us_core_medicationrequest_sequence.rb | 3 ++- .../us_core_r4/us_core_medicationstatement_sequence.rb | 3 ++- .../modules/us_core_r4/us_core_observation_lab_sequence.rb | 3 ++- .../modules/us_core_r4/us_core_organization_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_patient_sequence.rb | 5 +++-- .../modules/us_core_r4/us_core_practitioner_sequence.rb | 3 ++- .../us_core_r4/us_core_practitionerrole_sequence.rb | 3 ++- lib/app/modules/us_core_r4/us_core_procedure_sequence.rb | 3 ++- .../modules/us_core_r4/us_core_smokingstatus_sequence.rb | 3 ++- 25 files changed, 54 insertions(+), 27 deletions(-) diff --git a/generators/uscore-r4/generator.rb b/generators/uscore-r4/generator.rb index 2ef112dc3..b448c799d 100644 --- a/generators/uscore-r4/generator.rb +++ b/generators/uscore-r4/generator.rb @@ -149,6 +149,9 @@ def create_must_support_test(sequence) test_code: '' } + test[:test_code] += %( + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @#{sequence[:resource].downcase}_ary&.any?) + extensions_list = [] sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| extensions_list << "'#{extension[:id]}': '#{extension[:url]}'" @@ -159,7 +162,7 @@ def create_must_support_test(sequence) #{extensions_list.join(",\n ")} } extensions_list.each do |id, url| - @#{sequence[:resource].downcase}_ary.each do |resource| + @#{sequence[:resource].downcase}_ary&.each do |resource| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || resource.extension.any? { |extension| extension.url == url } skip "Could not find \#{id} in the provided resource" unless element_found @@ -180,7 +183,7 @@ def create_must_support_test(sequence) #{elements_list.join(",\n ")} ] must_support_elements.each do |path| - @#{sequence[:resource].downcase}_ary.each do |resource| + @#{sequence[:resource].downcase}_ary&.each do |resource| truncated_path = path.gsub('#{sequence[:resource]}.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index 29b73feaf..e64a90aa3 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -227,6 +227,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? must_support_elements = [ 'Observation.status', 'Observation.category', @@ -258,7 +259,7 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - @observation_ary.each do |resource| + @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index 4b900fc00..02900512e 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -227,6 +227,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? must_support_elements = [ 'Observation.status', 'Observation.category', @@ -258,7 +259,7 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - @observation_ary.each do |resource| + @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index fe362f55f..7eed4d82b 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -155,6 +155,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @allergyintolerance_ary&.any? must_support_elements = [ 'AllergyIntolerance.clinicalStatus', 'AllergyIntolerance.verificationStatus', @@ -162,7 +163,7 @@ def validate_resource_item(resource, property, value) 'AllergyIntolerance.patient' ] must_support_elements.each do |path| - @allergyintolerance_ary.each do |resource| + @allergyintolerance_ary&.each do |resource| truncated_path = path.gsub('AllergyIntolerance.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index f80b1bb30..432c15bbb 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -203,6 +203,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @careplan_ary&.any? must_support_elements = [ 'CarePlan.text', 'CarePlan.text.status', @@ -213,7 +214,7 @@ def validate_resource_item(resource, property, value) 'CarePlan.subject' ] must_support_elements.each do |path| - @careplan_ary.each do |resource| + @careplan_ary&.each do |resource| truncated_path = path.gsub('CarePlan.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 219164324..47bd28566 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -132,6 +132,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @careteam_ary&.any? must_support_elements = [ 'CareTeam.status', 'CareTeam.subject', @@ -140,7 +141,7 @@ def validate_resource_item(resource, property, value) 'CareTeam.participant.member' ] must_support_elements.each do |path| - @careteam_ary.each do |resource| + @careteam_ary&.each do |resource| truncated_path = path.gsub('CareTeam.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index 9a969a48f..2736d4a0a 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -227,6 +227,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @condition_ary&.any? must_support_elements = [ 'Condition.clinicalStatus', 'Condition.verificationStatus', @@ -235,7 +236,7 @@ def validate_resource_item(resource, property, value) 'Condition.subject' ] must_support_elements.each do |path| - @condition_ary.each do |resource| + @condition_ary&.each do |resource| truncated_path = path.gsub('Condition.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index bef30f122..f106545d3 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -155,6 +155,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @device_ary&.any? must_support_elements = [ 'Device.udiCarrier', 'Device.udiCarrier.carrierAIDC', @@ -163,7 +164,7 @@ def validate_resource_item(resource, property, value) 'Device.patient' ] must_support_elements.each do |path| - @device_ary.each do |resource| + @device_ary&.each do |resource| truncated_path = path.gsub('Device.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index 368010802..8dcb12dce 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -280,6 +280,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @diagnosticreport_ary&.any? must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -294,7 +295,7 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - @diagnosticreport_ary.each do |resource| + @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index c317e2002..7c4c9a9a1 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -280,6 +280,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @diagnosticreport_ary&.any? must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -294,7 +295,7 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - @diagnosticreport_ary.each do |resource| + @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index 3fbce05d3..4efa03d08 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -286,6 +286,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @documentreference_ary&.any? must_support_elements = [ 'DocumentReference.identifier', 'DocumentReference.status', @@ -306,7 +307,7 @@ def validate_resource_item(resource, property, value) 'DocumentReference.context.period' ] must_support_elements.each do |path| - @documentreference_ary.each do |resource| + @documentreference_ary&.each do |resource| truncated_path = path.gsub('DocumentReference.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index 72959d773..953331239 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -267,6 +267,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @encounter_ary&.any? must_support_elements = [ 'Encounter.identifier', 'Encounter.identifier.system', @@ -287,7 +288,7 @@ def validate_resource_item(resource, property, value) 'Encounter.location.location' ] must_support_elements.each do |path| - @encounter_ary.each do |resource| + @encounter_ary&.each do |resource| truncated_path = path.gsub('Encounter.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index e1a87ea33..9c91367d9 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -175,6 +175,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @goal_ary&.any? must_support_elements = [ 'Goal.lifecycleStatus', 'Goal.description', @@ -184,7 +185,7 @@ def validate_resource_item(resource, property, value) 'Goal.target.dueDuration' ] must_support_elements.each do |path| - @goal_ary.each do |resource| + @goal_ary&.each do |resource| truncated_path = path.gsub('Goal.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index 95e2599e8..349f73d3b 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -175,6 +175,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @immunization_ary&.any? must_support_elements = [ 'Immunization.status', 'Immunization.statusReason', @@ -185,7 +186,7 @@ def validate_resource_item(resource, property, value) 'Immunization.primarySource' ] must_support_elements.each do |path| - @immunization_ary.each do |resource| + @immunization_ary&.each do |resource| truncated_path = path.gsub('Immunization.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index c1f6cf8c8..1b8dd7649 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -216,6 +216,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @location_ary&.any? must_support_elements = [ 'Location.status', 'Location.name', @@ -228,7 +229,7 @@ def validate_resource_item(resource, property, value) 'Location.managingOrganization' ] must_support_elements.each do |path| - @location_ary.each do |resource| + @location_ary&.each do |resource| truncated_path = path.gsub('Location.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index a4467ebe9..de5d1456c 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -94,11 +94,12 @@ class UsCoreR4MedicationSequence < SequenceBase versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medication_ary&.any? must_support_elements = [ 'Medication.code' ] must_support_elements.each do |path| - @medication_ary.each do |resource| + @medication_ary&.each do |resource| truncated_path = path.gsub('Medication.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index aa0565f38..5ed70a215 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -175,6 +175,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medicationrequest_ary&.any? must_support_elements = [ 'MedicationRequest.status', 'MedicationRequest.medicationCodeableConcept', @@ -186,7 +187,7 @@ def validate_resource_item(resource, property, value) 'MedicationRequest.dosageInstruction.text' ] must_support_elements.each do |path| - @medicationrequest_ary.each do |resource| + @medicationrequest_ary&.each do |resource| truncated_path = path.gsub('MedicationRequest.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index 839e88a55..ac4f10db7 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -175,6 +175,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medicationstatement_ary&.any? must_support_elements = [ 'MedicationStatement.status', 'MedicationStatement.medicationCodeableConcept', @@ -186,7 +187,7 @@ def validate_resource_item(resource, property, value) 'MedicationStatement.derivedFrom' ] must_support_elements.each do |path| - @medicationstatement_ary.each do |resource| + @medicationstatement_ary&.each do |resource| truncated_path = path.gsub('MedicationStatement.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index def9a1a21..6cbab16a7 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -227,6 +227,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? must_support_elements = [ 'Observation.status', 'Observation.category', @@ -248,7 +249,7 @@ def validate_resource_item(resource, property, value) 'Observation.dataAbsentReason' ] must_support_elements.each do |path| - @observation_ary.each do |resource| + @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index de1ceedeb..b10245141 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -150,6 +150,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @organization_ary&.any? must_support_elements = [ 'Organization.identifier', 'Organization.identifier.system', @@ -165,7 +166,7 @@ def validate_resource_item(resource, property, value) 'Organization.endpoint' ] must_support_elements.each do |path| - @organization_ary.each do |resource| + @organization_ary&.each do |resource| truncated_path = path.gsub('Organization.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index f6d96f197..9bf32ddbb 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -270,13 +270,14 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @patient_ary&.any? extensions_list = { 'Patient.extension:race': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race', 'Patient.extension:ethnicity': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity', 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } extensions_list.each do |id, url| - @patient_ary.each do |resource| + @patient_ary&.each do |resource| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || resource.extension.any? { |extension| extension.url == url } skip "Could not find #{id} in the provided resource" unless element_found @@ -305,7 +306,7 @@ def validate_resource_item(resource, property, value) 'Patient.communication.language' ] must_support_elements.each do |path| - @patient_ary.each do |resource| + @patient_ary&.each do |resource| truncated_path = path.gsub('Patient.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index 11e9f31cf..f54536506 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -158,6 +158,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @practitioner_ary&.any? must_support_elements = [ 'Practitioner.identifier', 'Practitioner.identifier.system', @@ -168,7 +169,7 @@ def validate_resource_item(resource, property, value) 'Practitioner.name.family' ] must_support_elements.each do |path| - @practitioner_ary.each do |resource| + @practitioner_ary&.each do |resource| truncated_path = path.gsub('Practitioner.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index 9b0ac6cfd..45a636293 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -154,6 +154,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @practitionerrole_ary&.any? must_support_elements = [ 'PractitionerRole.practitioner', 'PractitionerRole.organization', @@ -166,7 +167,7 @@ def validate_resource_item(resource, property, value) 'PractitionerRole.endpoint' ] must_support_elements.each do |path| - @practitionerrole_ary.each do |resource| + @practitionerrole_ary&.each do |resource| truncated_path = path.gsub('PractitionerRole.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index 4358a0e8d..f339417f9 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -201,6 +201,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @procedure_ary&.any? must_support_elements = [ 'Procedure.status', 'Procedure.code', @@ -209,7 +210,7 @@ def validate_resource_item(resource, property, value) 'Procedure.performedPeriod' ] must_support_elements.each do |path| - @procedure_ary.each do |resource| + @procedure_ary&.each do |resource| truncated_path = path.gsub('Procedure.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 6714118e5..29ef53cdf 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -227,6 +227,7 @@ def validate_resource_item(resource, property, value) versions :r4 end + skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? must_support_elements = [ 'Observation.status', 'Observation.code', @@ -235,7 +236,7 @@ def validate_resource_item(resource, property, value) 'Observation.valueCodeableConcept' ] must_support_elements.each do |path| - @observation_ary.each do |resource| + @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) From 846ece1662eff573117944716831e39cb397e7a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jun 2019 22:55:27 -0400 Subject: [PATCH 08/89] don't skip until checked all resources --- generators/uscore-r4/generator.rb | 10 +++++++--- .../us_core_r4/pediatric_bmi_for_age_sequence.rb | 6 ++++-- .../us_core_r4/pediatric_weight_for_height_sequence.rb | 6 ++++-- .../us_core_r4/us_core_allergyintolerance_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_careplan_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_careteam_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_condition_sequence.rb | 6 ++++-- lib/app/modules/us_core_r4/us_core_device_sequence.rb | 6 ++++-- .../us_core_diagnosticreport_lab_sequence.rb | 6 ++++-- .../us_core_diagnosticreport_note_sequence.rb | 6 ++++-- .../us_core_r4/us_core_documentreference_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_encounter_sequence.rb | 6 ++++-- lib/app/modules/us_core_r4/us_core_goal_sequence.rb | 6 ++++-- .../us_core_r4/us_core_immunization_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_location_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_medication_sequence.rb | 6 ++++-- .../us_core_r4/us_core_medicationrequest_sequence.rb | 6 ++++-- .../us_core_r4/us_core_medicationstatement_sequence.rb | 6 ++++-- .../us_core_r4/us_core_observation_lab_sequence.rb | 6 ++++-- .../us_core_r4/us_core_organization_sequence.rb | 6 ++++-- lib/app/modules/us_core_r4/us_core_patient_sequence.rb | 10 +++++++--- .../us_core_r4/us_core_practitioner_sequence.rb | 6 ++++-- .../us_core_r4/us_core_practitionerrole_sequence.rb | 6 ++++-- .../modules/us_core_r4/us_core_procedure_sequence.rb | 6 ++++-- .../us_core_r4/us_core_smokingstatus_sequence.rb | 6 ++++-- 25 files changed, 106 insertions(+), 52 deletions(-) diff --git a/generators/uscore-r4/generator.rb b/generators/uscore-r4/generator.rb index b448c799d..babe66be6 100644 --- a/generators/uscore-r4/generator.rb +++ b/generators/uscore-r4/generator.rb @@ -162,12 +162,14 @@ def create_must_support_test(sequence) #{extensions_list.join(",\n ")} } extensions_list.each do |id, url| + element_found = false @#{sequence[:resource].downcase}_ary&.each do |resource| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || resource.extension.any? { |extension| extension.url == url } - skip "Could not find \#{id} in the provided resource" unless element_found @instance.must_support_confirmed += "\#{id}," unless already_found + break if element_found end + skip "Could not find \#{id} in the provided resource" unless element_found end ) end @@ -183,13 +185,15 @@ def create_must_support_test(sequence) #{elements_list.join(",\n ")} ] must_support_elements.each do |path| + element_found = false @#{sequence[:resource].downcase}_ary&.each do |resource| truncated_path = path.gsub('#{sequence[:resource]}.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find \#{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "\#{path}," unless already_found + @instance.must_support_confirmed += "\#{path}," if element_found && !already_found + break if element_found end + skip "Could not find \#{path} in the provided resource" unless element_found end) end diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index e64a90aa3..a2f84cd56 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -259,13 +259,15 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| + element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index 02900512e..9f4665d38 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -259,13 +259,15 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| + element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 7eed4d82b..63697d46c 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -163,13 +163,15 @@ def validate_resource_item(resource, property, value) 'AllergyIntolerance.patient' ] must_support_elements.each do |path| + element_found = false @allergyintolerance_ary&.each do |resource| truncated_path = path.gsub('AllergyIntolerance.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index 432c15bbb..086e0880f 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -214,13 +214,15 @@ def validate_resource_item(resource, property, value) 'CarePlan.subject' ] must_support_elements.each do |path| + element_found = false @careplan_ary&.each do |resource| truncated_path = path.gsub('CarePlan.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 47bd28566..3ef69de49 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -141,13 +141,15 @@ def validate_resource_item(resource, property, value) 'CareTeam.participant.member' ] must_support_elements.each do |path| + element_found = false @careteam_ary&.each do |resource| truncated_path = path.gsub('CareTeam.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index 2736d4a0a..44fcb672c 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -236,13 +236,15 @@ def validate_resource_item(resource, property, value) 'Condition.subject' ] must_support_elements.each do |path| + element_found = false @condition_ary&.each do |resource| truncated_path = path.gsub('Condition.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index f106545d3..f0ddec497 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -164,13 +164,15 @@ def validate_resource_item(resource, property, value) 'Device.patient' ] must_support_elements.each do |path| + element_found = false @device_ary&.each do |resource| truncated_path = path.gsub('Device.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index 8dcb12dce..df6d17045 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -295,13 +295,15 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| + element_found = false @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index 7c4c9a9a1..687ce4057 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -295,13 +295,15 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| + element_found = false @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index 4efa03d08..c8a977627 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -307,13 +307,15 @@ def validate_resource_item(resource, property, value) 'DocumentReference.context.period' ] must_support_elements.each do |path| + element_found = false @documentreference_ary&.each do |resource| truncated_path = path.gsub('DocumentReference.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index 953331239..586a3997b 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -288,13 +288,15 @@ def validate_resource_item(resource, property, value) 'Encounter.location.location' ] must_support_elements.each do |path| + element_found = false @encounter_ary&.each do |resource| truncated_path = path.gsub('Encounter.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index 9c91367d9..5422f4cf6 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -185,13 +185,15 @@ def validate_resource_item(resource, property, value) 'Goal.target.dueDuration' ] must_support_elements.each do |path| + element_found = false @goal_ary&.each do |resource| truncated_path = path.gsub('Goal.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index 349f73d3b..7e5309ab3 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -186,13 +186,15 @@ def validate_resource_item(resource, property, value) 'Immunization.primarySource' ] must_support_elements.each do |path| + element_found = false @immunization_ary&.each do |resource| truncated_path = path.gsub('Immunization.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index 1b8dd7649..9682599d4 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -229,13 +229,15 @@ def validate_resource_item(resource, property, value) 'Location.managingOrganization' ] must_support_elements.each do |path| + element_found = false @location_ary&.each do |resource| truncated_path = path.gsub('Location.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index de5d1456c..d4f118e07 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -99,13 +99,15 @@ class UsCoreR4MedicationSequence < SequenceBase 'Medication.code' ] must_support_elements.each do |path| + element_found = false @medication_ary&.each do |resource| truncated_path = path.gsub('Medication.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index 5ed70a215..a5ea65b62 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -187,13 +187,15 @@ def validate_resource_item(resource, property, value) 'MedicationRequest.dosageInstruction.text' ] must_support_elements.each do |path| + element_found = false @medicationrequest_ary&.each do |resource| truncated_path = path.gsub('MedicationRequest.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index ac4f10db7..0c802695b 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -187,13 +187,15 @@ def validate_resource_item(resource, property, value) 'MedicationStatement.derivedFrom' ] must_support_elements.each do |path| + element_found = false @medicationstatement_ary&.each do |resource| truncated_path = path.gsub('MedicationStatement.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index 6cbab16a7..1f117a464 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -249,13 +249,15 @@ def validate_resource_item(resource, property, value) 'Observation.dataAbsentReason' ] must_support_elements.each do |path| + element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index b10245141..8533a35b2 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -166,13 +166,15 @@ def validate_resource_item(resource, property, value) 'Organization.endpoint' ] must_support_elements.each do |path| + element_found = false @organization_ary&.each do |resource| truncated_path = path.gsub('Organization.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index 9bf32ddbb..b87b03336 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -277,12 +277,14 @@ def validate_resource_item(resource, property, value) 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } extensions_list.each do |id, url| + element_found = false @patient_ary&.each do |resource| already_found = @instance.must_support_confirmed.include?(id.to_s) element_found = already_found || resource.extension.any? { |extension| extension.url == url } - skip "Could not find #{id} in the provided resource" unless element_found @instance.must_support_confirmed += "#{id}," unless already_found + break if element_found end + skip "Could not find #{id} in the provided resource" unless element_found end must_support_elements = [ @@ -306,13 +308,15 @@ def validate_resource_item(resource, property, value) 'Patient.communication.language' ] must_support_elements.each do |path| + element_found = false @patient_ary&.each do |resource| truncated_path = path.gsub('Patient.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index f54536506..edf76fcbe 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -169,13 +169,15 @@ def validate_resource_item(resource, property, value) 'Practitioner.name.family' ] must_support_elements.each do |path| + element_found = false @practitioner_ary&.each do |resource| truncated_path = path.gsub('Practitioner.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index 45a636293..483b035fa 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -167,13 +167,15 @@ def validate_resource_item(resource, property, value) 'PractitionerRole.endpoint' ] must_support_elements.each do |path| + element_found = false @practitionerrole_ary&.each do |resource| truncated_path = path.gsub('PractitionerRole.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index f339417f9..601ce802b 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -210,13 +210,15 @@ def validate_resource_item(resource, property, value) 'Procedure.performedPeriod' ] must_support_elements.each do |path| + element_found = false @procedure_ary&.each do |resource| truncated_path = path.gsub('Procedure.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 29ef53cdf..991371ca3 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -236,13 +236,15 @@ def validate_resource_item(resource, property, value) 'Observation.valueCodeableConcept' ] must_support_elements.each do |path| + element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') already_found = @instance.must_support_confirmed.include?(path) element_found = already_found || can_resolve_path(resource, truncated_path) - skip "Could not find #{path} in the provided resource" unless element_found - @instance.must_support_confirmed += "#{path}," unless already_found + @instance.must_support_confirmed += "#{path}," if element_found && !already_found + break if element_found end + skip "Could not find #{path} in the provided resource" unless element_found end @instance.save! end From 8b7616519515da36e53d3e411b315c7f8c8c63cf Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 26 Jun 2019 12:23:21 -0400 Subject: [PATCH 09/89] Potential updates to must_support implementation. --- generators/uscore-r4/generator.rb | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/generators/uscore-r4/generator.rb b/generators/uscore-r4/generator.rb index babe66be6..d7c3d97bb 100644 --- a/generators/uscore-r4/generator.rb +++ b/generators/uscore-r4/generator.rb @@ -56,8 +56,8 @@ def generate_tests(metadata) create_interaction_test(sequence, interaction) end - create_must_support_test(sequence) create_resource_profile_test(sequence) + create_must_support_test(sequence) create_references_resolved_test(sequence) end end @@ -143,7 +143,7 @@ def create_interaction_test(sequence, interaction) def create_must_support_test(sequence) test = { - tests_that: 'Demonstrates that the server can supply must supported elements', + tests_that: "At least one of every must support element is provided in any #{sequences[:resource]} for this patient.", index: sequence[:tests].length + 1, link: 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support', test_code: '' @@ -152,6 +152,10 @@ def create_must_support_test(sequence) test[:test_code] += %( skip 'No resources appear to be available for this patient. Please use patients with more information' unless @#{sequence[:resource].downcase}_ary&.any?) + test[:test_code] += %( + must_support_confirmed = {} + ) + extensions_list = [] sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| extensions_list << "'#{extension[:id]}': '#{extension[:url]}'" @@ -164,12 +168,10 @@ def create_must_support_test(sequence) extensions_list.each do |id, url| element_found = false @#{sequence[:resource].downcase}_ary&.each do |resource| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || resource.extension.any? { |extension| extension.url == url } - @instance.must_support_confirmed += "\#{id}," unless already_found - break if element_found + must_support_confirmed[id] = true if resource.extension.any? { |extension| extension.url == url } + break if must_support_confirmed[id] end - skip "Could not find \#{id} in the provided resource" unless element_found + skip "Could not find \#{id} in any of the \#{@#{sequence[:resource].downcase}_ary.length} provided #{sequence[:resource]} resource(s)" unless must_support_confirmed[id] end ) end @@ -185,15 +187,12 @@ def create_must_support_test(sequence) #{elements_list.join(",\n ")} ] must_support_elements.each do |path| - element_found = false @#{sequence[:resource].downcase}_ary&.each do |resource| truncated_path = path.gsub('#{sequence[:resource]}.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "\#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find \#{path} in the provided resource" unless element_found + skip "Could not find \#{path} in any of the \#{@#{sequence[:resource].downcase}_ary.length} provided #{sequence[:resource]} resource(s)" unless must_support_confirmed[path] end) end From c5daa60dbd51ad2f05d1575b40860d7b75cb5f79 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 10:55:18 -0400 Subject: [PATCH 10/89] fix FHIR.logger --- lib/app/endpoint.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/endpoint.rb b/lib/app/endpoint.rb index d4c76457a..2fe8c855d 100644 --- a/lib/app/endpoint.rb +++ b/lib/app/endpoint.rb @@ -33,7 +33,7 @@ class Endpoint < Sinatra::Base # FIXME: Really don't want a direct dependency to DataMapper here DataMapper.logger = Inferno.logger if Inferno::ENVIRONMENT == :development - FHIR.logger = Inferno.logger + FHIR.logger = FHIR::STU3.logger = FHIR::DSTU2.logger = Inferno.logger Inferno.logger.info "Environment: #{Inferno::ENVIRONMENT}" From 5d3ec13481db1e13e40e3506806d56ea9f6e0c17 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 10:57:15 -0400 Subject: [PATCH 11/89] use Inferno.logger instead of FHIR.logger --- lib/app/endpoint/home.rb | 2 +- .../smart/token_introspection_sequence.rb | 6 +++--- lib/app/utils/exceptions.rb | 8 ++++---- lib/app/utils/terminology.rb | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/app/endpoint/home.rb b/lib/app/endpoint/home.rb index b25c50cd3..9a4f29ade 100644 --- a/lib/app/endpoint/home.rb +++ b/lib/app/endpoint/home.rb @@ -282,7 +282,7 @@ class Home < Endpoint inferno_module = Inferno::Module.get(params[:module]) if inferno_module.nil? - FHIR.logger.error "Unknown module: #{params[:module]}" + Inferno.logger.error "Unknown module: #{params[:module]}" halt 404, "Unknown module: #{params[:module]}" end diff --git a/lib/app/modules/smart/token_introspection_sequence.rb b/lib/app/modules/smart/token_introspection_sequence.rb index 96cea0da1..a79b4e4aa 100644 --- a/lib/app/modules/smart/token_introspection_sequence.rb +++ b/lib/app/modules/smart/token_introspection_sequence.rb @@ -70,7 +70,7 @@ class TokenIntrospectionSequence < SequenceBase @introspection_response_body = JSON.parse(@introspection_response.body) assert !@introspection_response_body.nil?, 'No introspection response body' - FHIR.logger.debug "Introspection response: #{@introspection_response}" + Inferno.logger.debug "Introspection response: #{@introspection_response}" assert !(@introspection_response['error'] || @introspection_response['error_description']), 'Got an error from the introspection endpoint' end @@ -106,7 +106,7 @@ class TokenIntrospectionSequence < SequenceBase expected_scopes = @instance.scopes.split(' ') actual_scopes = @introspection_response_body['scope'].split(' ') - FHIR.logger.debug "Introspection: Expected scopes #{expected_scopes}, Actual scopes #{actual_scopes}" + Inferno.logger.debug "Introspection: Expected scopes #{expected_scopes}, Actual scopes #{actual_scopes}" missing_scopes = (expected_scopes - actual_scopes) assert missing_scopes.empty?, "Introspection response did not include expected scopes: #{missing_scopes}" @@ -167,7 +167,7 @@ class TokenIntrospectionSequence < SequenceBase @introspection_response_body = JSON.parse(@introspection_response.body) assert !@introspection_response_body.nil?, 'No refresh token introspection response body' - FHIR.logger.debug "Refresh Token Introspection response: #{@introspection_response}" + Inferno.logger.debug "Refresh Token Introspection response: #{@introspection_response}" assert !(@introspection_response['error'] || @introspection_response['error_description']), 'Got an error from the introspection endpoint' end diff --git a/lib/app/utils/exceptions.rb b/lib/app/utils/exceptions.rb index 2f6f63983..79c02a92c 100644 --- a/lib/app/utils/exceptions.rb +++ b/lib/app/utils/exceptions.rb @@ -5,7 +5,7 @@ class AssertionException < RuntimeError attr_accessor :details def initialize(message, details = nil) super(message) - FHIR.logger.error "AssertionException: #{message}" + Inferno.logger.error "AssertionException: #{message}" @details = details end end @@ -14,7 +14,7 @@ class SkipException < RuntimeError attr_accessor :details def initialize(message = '', details = nil) super(message) - FHIR.logger.info "SkipException: #{message}" + Inferno.logger.info "SkipException: #{message}" @details = details end end @@ -22,14 +22,14 @@ def initialize(message = '', details = nil) class TodoException < RuntimeError def initialize(message = '') super(message) - FHIR.logger.info "TodoException: #{message}" + Inferno.logger.info "TodoException: #{message}" end end class PassException < RuntimeError def initialize(message = '') super(message) - FHIR.logger.info "PassException: #{message}" + Inferno.logger.info "PassException: #{message}" end end diff --git a/lib/app/utils/terminology.rb b/lib/app/utils/terminology.rb index 00816ee3e..8b6b1076f 100644 --- a/lib/app/utils/terminology.rb +++ b/lib/app/utils/terminology.rb @@ -49,7 +49,7 @@ def self.load_terminology @@top_lab_code_descriptions[row[0]] = row[1] unless row[1].nil? end rescue StandardError => e - FHIR.logger.error e + Inferno.logger.error e end begin @@ -70,7 +70,7 @@ def self.load_terminology code_system_hash[code] = description end rescue StandardError => error - FHIR.logger.error error + Inferno.logger.error error end begin @@ -87,7 +87,7 @@ def self.load_terminology @@core_snomed[code] = description end rescue StandardError => error - FHIR.logger.error error + Inferno.logger.error error end begin @@ -99,7 +99,7 @@ def self.load_terminology end @@common_ucum.uniq! rescue StandardError => error - FHIR.logger.error error + Inferno.logger.error error end @@loaded = true @@ -132,14 +132,14 @@ def self.create_validators(type) @known_valuesets.each do |k, vs| next if (k == 'http://fhir.org/guides/argonaut/ValueSet/argo-codesystem') || (k == 'http://fhir.org/guides/argonaut/ValueSet/languages') - puts "Processing #{k}" + Inferno.logger.debug "Processing #{k}" filename = "#{root_dir}/#{(URI(vs.url).host + URI(vs.url).path).gsub(%r{[./]}, '_')}.msgpack" save_bloom_to_file(vs.valueset, filename) validators << { url: k, file: File.basename(filename), count: vs.count, type: 'bloom' } end vs = Inferno::Terminology::Valueset.new(@db) Inferno::Terminology::Valueset::SAB.each do |k, _v| - puts "Processing #{k}" + Inferno.logger.debug "Processing #{k}" cs = vs.code_system_set(k) filename = "#{root_dir}/#{(URI(k).host + URI(k).path).gsub(%r{[./]}, '_')}.msgpack" save_bloom_to_file(cs, filename) @@ -153,14 +153,14 @@ def self.create_validators(type) @known_valuesets.each do |k, vs| next if (k == 'http://fhir.org/guides/argonaut/ValueSet/argo-codesystem') || (k == 'http://fhir.org/guides/argonaut/ValueSet/languages') - puts "Processing #{k}" + Inferno.logger.debug "Processing #{k}" filename = "#{root_dir}/#{(URI(vs.url).host + URI(vs.url).path).gsub(%r{[./]}, '_')}.csv" save_csv_to_file(vs.valueset, filename) validators << { url: k, file: File.basename(filename), count: vs.count, type: 'csv' } end vs = Inferno::Terminology::Valueset.new(@db) Inferno::Terminology::Valueset::SAB.each do |k, _v| - puts "Processing #{k}" + Inferno.logger.debug "Processing #{k}" cs = vs.code_system_set(k) filename = "#{root_dir}/#{(URI(k).host + URI(k).path).gsub(%r{[./]}, '_')}.csv" save_csv_to_file(cs, filename) From ceaf0fb8096ed5d5df5a832b266262d182ed837d Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 12:29:36 -0400 Subject: [PATCH 12/89] add pry-byebug --- Gemfile | 1 + Gemfile.lock | 8 ++++++++ lib/app.rb | 1 + lib/tasks/tasks.rake | 1 + 4 files changed, 11 insertions(+) diff --git a/Gemfile b/Gemfile index 6fa973087..102c78d38 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ gem 'fhir_client' gem 'json-jwt' gem 'kramdown' gem 'pry' +gem 'pry-byebug' gem 'rack-test' gem 'rake' gem 'rb-readline' diff --git a/Gemfile.lock b/Gemfile.lock index e4dbbdbe7..8be222197 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -22,6 +22,7 @@ GEM bloomer (1.0.0) bitarray msgpack + byebug (11.0.1) childprocess (1.0.1) rake (< 13.0) coderay (1.1.2) @@ -152,6 +153,9 @@ GEM pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) + pry-byebug (3.7.0) + byebug (~> 11.0) + pry (~> 0.10) psych (3.1.0) public_suffix (3.0.3) rack (2.0.7) @@ -233,6 +237,7 @@ DEPENDENCIES json-jwt kramdown pry + pry-byebug rack-test rake rb-readline @@ -246,3 +251,6 @@ DEPENDENCIES thin time_difference webmock + +BUNDLED WITH + 2.0.1 diff --git a/lib/app.rb b/lib/app.rb index 1cc4f1c23..7672a6860 100644 --- a/lib/app.rb +++ b/lib/app.rb @@ -9,6 +9,7 @@ require 'rest-client' require 'time_difference' require 'pry' +require 'pry-byebug' require 'dm-core' require 'dm-migrations' require 'jwt' diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake index ff0c56faa..70d4fda18 100644 --- a/lib/tasks/tasks.rake +++ b/lib/tasks/tasks.rake @@ -2,6 +2,7 @@ require 'fhir_client' require 'pry' +require 'pry-byebug' require 'dm-core' require 'csv' require 'colorize' From 3b9a10ba10c1bd5d10cedc3633b216ba80974917 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 12:38:31 -0400 Subject: [PATCH 13/89] log to temp file in tests --- lib/app/endpoint.rb | 22 +++++++++++++--------- test/test_helper.rb | 3 +++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/app/endpoint.rb b/lib/app/endpoint.rb index 2fe8c855d..03e71dabc 100644 --- a/lib/app/endpoint.rb +++ b/lib/app/endpoint.rb @@ -20,15 +20,19 @@ class Endpoint < Sinatra::Base Inferno::EXTRAS = settings.include_extras if settings.logging_enabled - Inferno.logger = if settings.log_to_file - ::Logger.new('logs.log', level: settings.log_level.to_sym, progname: 'Inferno') - else - l = ::Logger.new(STDOUT, level: settings.log_level.to_sym, progname: 'Inferno') - l.formatter = proc do |severity, _datetime, progname, msg| - "#{severity} | #{progname} | #{msg}\n" - end - l - end + Inferno.logger = + if ENV['RACK_ENV'] == 'test' + FileUtils.mkdir_p 'tmp' + ::Logger.new(File.join('tmp', 'test.log'), level: settings.log_level.to_sym, progname: 'Inferno') + elsif settings.log_to_file + ::Logger.new('logs.log', level: settings.log_level.to_sym, progname: 'Inferno') + else + l = ::Logger.new(STDOUT, level: settings.log_level.to_sym, progname: 'Inferno') + l.formatter = proc do |severity, _datetime, progname, msg| + "#{severity} | #{progname} | #{msg}\n" + end + l + end # FIXME: Really don't want a direct dependency to DataMapper here DataMapper.logger = Inferno.logger if Inferno::ENVIRONMENT == :development diff --git a/test/test_helper.rb b/test/test_helper.rb index d01f7ff08..34fdaee8c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -11,6 +11,9 @@ require 'rack/test' require 'json/jwt' +test_log_filename = File.join('tmp', 'test.log') +FileUtils.rm test_log_filename if File.exist? test_log_filename + # require File.expand_path '../../app.rb', __FILE__ require_relative '../lib/app' From 4c8663753e92f4efb54a185c2e13413105d3c8b7 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 13:21:02 -0400 Subject: [PATCH 14/89] use Inferno.logger for csv file writing messages --- lib/tasks/tasks.rake | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake index 70d4fda18..ebb5bf384 100644 --- a/lib/tasks/tasks.rake +++ b/lib/tasks/tasks.rake @@ -151,6 +151,12 @@ def execute(instance, sequences) return_value end +def file_path(filename) + return filename unless ENV['RACK_ENV'] == 'test' + FileUtils.mkdir_p 'tmp' + File.join('tmp', filename) +end + namespace :inferno do |_argv| # Exports a CSV containing the test metadata desc 'Generate List of All Tests' @@ -180,8 +186,10 @@ namespace :inferno do |_argv| end end - File.write(args.filename, csv_out) - puts "Writing to #{args.filename}" + filename = file_path(args.filename) + + File.write(filename, csv_out) + Inferno.logger.info "Writing to #{filename}" end desc 'Generate automated run script' From 27f0ad763bdb6516a042b5a909e6854d28ac5a98 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 13:34:57 -0400 Subject: [PATCH 15/89] remove output in test --- test/unit/valueset_test.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/valueset_test.rb b/test/unit/valueset_test.rb index 337b82f8e..2ad913e7c 100644 --- a/test/unit/valueset_test.rb +++ b/test/unit/valueset_test.rb @@ -79,7 +79,6 @@ def test_medication_codes_bloom_filter total += 1 end assert hits.zero?, 'Expected to invalid codes to match' - puts "Hits: #{hits}, Total: #{total}" assert !bf.include?('9999'), 'Expected 9999 to fail' end end From 4a6824dd1fe4308474e3cb72d36e9567adce26a9 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 13:36:06 -0400 Subject: [PATCH 16/89] fix deprecation warning --- test/model/supported_resource_test.rb | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/test/model/supported_resource_test.rb b/test/model/supported_resource_test.rb index 4b8205511..9bc337109 100644 --- a/test/model/supported_resource_test.rb +++ b/test/model/supported_resource_test.rb @@ -22,6 +22,7 @@ def setup %i[read vread search history authorized] } } + resource2 = resource1.deep_dup resource2[:attributes][:supported] = false resource2[:description] = 'not supported, but supports all operations' @@ -32,9 +33,13 @@ def setup resource3[:description] = 'supported and supports all operations except vread' resource3[:expected_respones][:validate_supported_interactions] = %i[read search history authorized] - @test_cases = [resource1, resource2, resource3] + @supported_test_cases = [resource1, resource3] + @supported_test_cases.each do |test_case| + test_case[:instance] = Inferno::Models::SupportedResource.create(test_case[:attributes]) + end - @test_cases.each do |test_case| + @unsupported_test_cases = [resource2] + @unsupported_test_cases.each do |test_case| test_case[:instance] = Inferno::Models::SupportedResource.create(test_case[:attributes]) end end @@ -43,10 +48,22 @@ def validate_supported_interactions(resource_to_test, expected_response) assert_equal expected_response, resource_to_test.supported_interactions end - def test_all_pass - @test_cases.each do |test_case| + def validate_unsupported_interactions(resource_to_test, expected_response) + assert_nil expected_response + assert_nil resource_to_test.supported_interactions + end + + def test_supported_interactions_all_pass + @supported_test_cases.each do |test_case| validate_supported_interactions(test_case[:instance], test_case[:expected_respones][:validate_supported_interactions]) end end + + def test_unsupported_interactions_all_pass + @unsupported_test_cases.each do |test_case| + validate_unsupported_interactions(test_case[:instance], + test_case[:expected_respones][:validate_supported_interactions]) + end + end end From 467500dcd3e4988a45be0d6188e5c3c19b0e70f1 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Thu, 27 Jun 2019 13:46:36 -0400 Subject: [PATCH 17/89] fix linting errors --- lib/tasks/tasks.rake | 1 + test/model/supported_resource_test.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tasks/tasks.rake b/lib/tasks/tasks.rake index ebb5bf384..a9de86b80 100644 --- a/lib/tasks/tasks.rake +++ b/lib/tasks/tasks.rake @@ -153,6 +153,7 @@ end def file_path(filename) return filename unless ENV['RACK_ENV'] == 'test' + FileUtils.mkdir_p 'tmp' File.join('tmp', filename) end diff --git a/test/model/supported_resource_test.rb b/test/model/supported_resource_test.rb index 9bc337109..f6c6f24b3 100644 --- a/test/model/supported_resource_test.rb +++ b/test/model/supported_resource_test.rb @@ -63,7 +63,7 @@ def test_supported_interactions_all_pass def test_unsupported_interactions_all_pass @unsupported_test_cases.each do |test_case| validate_unsupported_interactions(test_case[:instance], - test_case[:expected_respones][:validate_supported_interactions]) + test_case[:expected_respones][:validate_supported_interactions]) end end end From ec85c33d7defd14a82ee7f585a43b5f41331fdf8 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Fri, 28 Jun 2019 09:45:53 -0400 Subject: [PATCH 18/89] update Dockerfile to use new version of bundler --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f56e0d426..be8a0e645 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM ruby:2.5 # Install gems into a temporary directory COPY Gemfile* ./ -RUN bundle install +RUN gem install bundler && bundle install # Expose the port EXPOSE 4567 From 3892cb4372c331ff363744f581cb142b7df01527 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Fri, 28 Jun 2019 12:13:38 -0400 Subject: [PATCH 19/89] comming new test to check version --- .../core/capability_statement_sequence.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index 4651f835b..e9bd5f62b 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -71,9 +71,24 @@ class CapabilityStatementSequence < SequenceBase end end - test 'FHIR server supports the conformance interaction that defines how it supports resources' do + test 'Test FHIR version' do metadata do id '02' + link '' + desc %( + Testing that the FHIR client is the same version that was version as the testing instance that was selected. + ) + end + + #@client.detect_version is a symbol + assert_equal(@instance.fhir_version, @client.detect_version.to_s, "FHIR client version does not match with instance version"); + + end + + + test 'FHIR server supports the conformance interaction that defines how it supports resources' do + metadata do + id '03' link 'http://hl7.org/fhir/DSTU2/http.html#conformance' desc %( The conformance 'whole system' interaction provides a method to get the conformance statement for From d60542d2bc941486b17818d37c4ad31d157cbfb9 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Sun, 30 Jun 2019 10:53:45 -0400 Subject: [PATCH 20/89] Minor fixes to us core generator. --- generators/uscore-r4/generator.rb | 10 +- generators/uscore-r4/metadata_extractor.rb | 1 + lib/app/modules/us_core_module.yml | 49 +- .../pediatric_bmi_for_age_sequence.rb | 40 +- .../pediatric_weight_for_height_sequence.rb | 40 +- .../us_core_allergyintolerance_sequence.rb | 40 +- .../us_core_r4/us_core_careplan_sequence.rb | 40 +- .../us_core_r4/us_core_careteam_sequence.rb | 40 +- .../us_core_r4/us_core_condition_sequence.rb | 40 +- .../us_core_r4/us_core_device_sequence.rb | 40 +- .../us_core_diagnosticreport_lab_sequence.rb | 40 +- .../us_core_diagnosticreport_note_sequence.rb | 40 +- .../us_core_documentreference_sequence.rb | 40 +- .../us_core_r4/us_core_encounter_sequence.rb | 40 +- .../us_core_r4/us_core_goal_sequence.rb | 40 +- .../us_core_immunization_sequence.rb | 40 +- .../us_core_r4/us_core_location_sequence.rb | 40 +- .../us_core_r4/us_core_medication_sequence.rb | 40 +- .../us_core_medicationrequest_sequence.rb | 40 +- .../us_core_medicationstatement_sequence.rb | 40 +- .../us_core_observation_lab_sequence.rb | 40 +- .../us_core_organization_sequence.rb | 40 +- .../us_core_r4/us_core_patient_sequence.rb | 49 +- .../us_core_practitioner_sequence.rb | 40 +- .../us_core_practitionerrole_sequence.rb | 40 +- .../us_core_r4/us_core_procedure_sequence.rb | 40 +- .../us_core_smokingstatus_sequence.rb | 40 +- ...tructureDefinition-us-core-medication.json | 1097 +++++++++++++++++ 28 files changed, 1611 insertions(+), 515 deletions(-) create mode 100644 resources/us_core_r4/StructureDefinition-us-core-medication.json diff --git a/generators/uscore-r4/generator.rb b/generators/uscore-r4/generator.rb index d7c3d97bb..5f2055e0b 100644 --- a/generators/uscore-r4/generator.rb +++ b/generators/uscore-r4/generator.rb @@ -143,7 +143,7 @@ def create_interaction_test(sequence, interaction) def create_must_support_test(sequence) test = { - tests_that: "At least one of every must support element is provided in any #{sequences[:resource]} for this patient.", + tests_that: "At least one of every must support element is provided in any #{sequence[:resource]} for this patient.", index: sequence[:tests].length + 1, link: 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support', test_code: '' @@ -153,8 +153,7 @@ def create_must_support_test(sequence) skip 'No resources appear to be available for this patient. Please use patients with more information' unless @#{sequence[:resource].downcase}_ary&.any?) test[:test_code] += %( - must_support_confirmed = {} - ) + must_support_confirmed = {}) extensions_list = [] sequence[:must_supports].select { |must_support| must_support[:type] == 'extension' }.each do |extension| @@ -166,7 +165,6 @@ def create_must_support_test(sequence) #{extensions_list.join(",\n ")} } extensions_list.each do |id, url| - element_found = false @#{sequence[:resource].downcase}_ary&.each do |resource| must_support_confirmed[id] = true if resource.extension.any? { |extension| extension.url == url } break if must_support_confirmed[id] @@ -192,7 +190,9 @@ def create_must_support_test(sequence) must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) break if must_support_confirmed[path] end - skip "Could not find \#{path} in any of the \#{@#{sequence[:resource].downcase}_ary.length} provided #{sequence[:resource]} resource(s)" unless must_support_confirmed[path] + resource_count = @#{sequence[:resource].downcase}_ary.length + + skip "Could not find \#{path} in any of the \#{resource_count} provided #{sequence[:resource]} resource(s)" unless must_support_confirmed[path] end) end diff --git a/generators/uscore-r4/metadata_extractor.rb b/generators/uscore-r4/metadata_extractor.rb index e0f21a425..8d5592909 100644 --- a/generators/uscore-r4/metadata_extractor.rb +++ b/generators/uscore-r4/metadata_extractor.rb @@ -2,6 +2,7 @@ class MetadataExtractor CAPABILITY_STATEMENT_URI = 'https://build.fhir.org/ig/HL7/US-Core-R4/CapabilityStatement-us-core-server.json' + OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE def profile_uri(profile) "https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-#{profile}.json" diff --git a/lib/app/modules/us_core_module.yml b/lib/app/modules/us_core_module.yml index 352799717..e057e7584 100644 --- a/lib/app/modules/us_core_module.yml +++ b/lib/app/modules/us_core_module.yml @@ -21,27 +21,28 @@ test_sets: - name: US Core R4 run_all: true sequences: - - UsCoreR4AllergyintoleranceSequence - - UsCoreR4CareplanSequence - - UsCoreR4CareteamSequence - - UsCoreR4ConditionSequence - - UsCoreR4DeviceSequence - - UsCoreR4DiagnosticreportNoteSequence - - UsCoreR4DiagnosticreportLabSequence - - UsCoreR4DocumentreferenceSequence - - UsCoreR4EncounterSequence - - UsCoreR4GoalSequence - - UsCoreR4ImmunizationSequence - - UsCoreR4LocationSequence - - UsCoreR4MedicationSequence - - UsCoreR4MedicationrequestSequence - - UsCoreR4MedicationstatementSequence - - UsCoreR4SmokingstatusSequence - - PediatricWeightForHeightSequence - - UsCoreR4ObservationLabSequence - - PediatricBmiForAgeSequence - - UsCoreR4OrganizationSequence - - UsCoreR4PatientSequence - - UsCoreR4PractitionerSequence - - UsCoreR4PractitionerroleSequence - - UsCoreR4ProcedureSequence \ No newline at end of file + - UsCoreR4AllergyintoleranceSequence + - UsCoreR4CareplanSequence + - UsCoreR4CareteamSequence + - UsCoreR4ConditionSequence + - UsCoreR4DeviceSequence + - UsCoreR4DiagnosticreportNoteSequence + - UsCoreR4DiagnosticreportLabSequence + - UsCoreR4DocumentreferenceSequence + - UsCoreR4EncounterSequence + - UsCoreR4GoalSequence + - UsCoreR4ImmunizationSequence + - UsCoreR4LocationSequence + - UsCoreR4MedicationSequence + - UsCoreR4MedicationrequestSequence + - UsCoreR4MedicationstatementSequence + - UsCoreR4SmokingstatusSequence + - PediatricWeightForHeightSequence + - UsCoreR4ObservationLabSequence + - PediatricBmiForAgeSequence + - UsCoreR4OrganizationSequence + - UsCoreR4PatientSequence + - UsCoreR4PractitionerSequence + - UsCoreR4PractitionerroleSequence + - UsCoreR4ProcedureSequence + - R4ProvenanceSequence diff --git a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb index a2f84cd56..ffb907d0f 100644 --- a/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_bmi_for_age_sequence.rb @@ -218,9 +218,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-bmi-for-age.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Observation') + end + + test 'At least one of every must support element is provided in any Observation for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -228,6 +241,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Observation.status', 'Observation.category', @@ -259,30 +273,16 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @observation_ary.length - test 'Observation resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-bmi-for-age.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Observation resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Observation') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb index 9f4665d38..28e3b673e 100644 --- a/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb +++ b/lib/app/modules/us_core_r4/pediatric_weight_for_height_sequence.rb @@ -218,9 +218,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-weight-for-height.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Observation') + end + + test 'At least one of every must support element is provided in any Observation for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -228,6 +241,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Observation.status', 'Observation.category', @@ -259,30 +273,16 @@ def validate_resource_item(resource, property, value) 'Observation.component.dataAbsentReason' ] must_support_elements.each do |path| - element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @observation_ary.length - test 'Observation resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-pediatric-weight-for-height.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Observation resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Observation') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb index 63697d46c..54f14fdb4 100644 --- a/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_allergyintolerance_sequence.rb @@ -146,9 +146,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@allergyintolerance, versioned_resource_class('AllergyIntolerance')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'AllergyIntolerance resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-allergyintolerance.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('AllergyIntolerance') + end + + test 'At least one of every must support element is provided in any AllergyIntolerance for this patient.' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -156,6 +169,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @allergyintolerance_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'AllergyIntolerance.clinicalStatus', 'AllergyIntolerance.verificationStatus', @@ -163,30 +177,16 @@ def validate_resource_item(resource, property, value) 'AllergyIntolerance.patient' ] must_support_elements.each do |path| - element_found = false @allergyintolerance_ary&.each do |resource| truncated_path = path.gsub('AllergyIntolerance.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @allergyintolerance_ary.length - test 'AllergyIntolerance resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '08' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-allergyintolerance.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided AllergyIntolerance resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('AllergyIntolerance') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb index 086e0880f..fb43d34a9 100644 --- a/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careplan_sequence.rb @@ -194,9 +194,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@careplan, versioned_resource_class('CarePlan')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'CarePlan resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careplan.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('CarePlan') + end + + test 'At least one of every must support element is provided in any CarePlan for this patient.' do + metadata do + id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -204,6 +217,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @careplan_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'CarePlan.text', 'CarePlan.text.status', @@ -214,30 +228,16 @@ def validate_resource_item(resource, property, value) 'CarePlan.subject' ] must_support_elements.each do |path| - element_found = false @careplan_ary&.each do |resource| truncated_path = path.gsub('CarePlan.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @careplan_ary.length - test 'CarePlan resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '10' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careplan.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided CarePlan resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('CarePlan') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb index 3ef69de49..6861ab5c2 100644 --- a/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_careteam_sequence.rb @@ -123,9 +123,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@careteam, versioned_resource_class('CareTeam')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'CareTeam resources associated with Patient conform to US Core R4 profiles' do metadata do id '06' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careteam.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('CareTeam') + end + + test 'At least one of every must support element is provided in any CareTeam for this patient.' do + metadata do + id '07' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -133,6 +146,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @careteam_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'CareTeam.status', 'CareTeam.subject', @@ -141,30 +155,16 @@ def validate_resource_item(resource, property, value) 'CareTeam.participant.member' ] must_support_elements.each do |path| - element_found = false @careteam_ary&.each do |resource| truncated_path = path.gsub('CareTeam.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @careteam_ary.length - test 'CareTeam resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '07' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-careteam.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided CareTeam resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('CareTeam') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb index 44fcb672c..30a8bdbee 100644 --- a/lib/app/modules/us_core_r4/us_core_condition_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_condition_sequence.rb @@ -218,9 +218,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@condition, versioned_resource_class('Condition')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Condition resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-condition.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Condition') + end + + test 'At least one of every must support element is provided in any Condition for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -228,6 +241,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @condition_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Condition.clinicalStatus', 'Condition.verificationStatus', @@ -236,30 +250,16 @@ def validate_resource_item(resource, property, value) 'Condition.subject' ] must_support_elements.each do |path| - element_found = false @condition_ary&.each do |resource| truncated_path = path.gsub('Condition.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @condition_ary.length - test 'Condition resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-condition.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Condition resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Condition') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_device_sequence.rb b/lib/app/modules/us_core_r4/us_core_device_sequence.rb index f0ddec497..49642acb2 100644 --- a/lib/app/modules/us_core_r4/us_core_device_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_device_sequence.rb @@ -146,9 +146,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@device, versioned_resource_class('Device')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Device resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-device.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Device') + end + + test 'At least one of every must support element is provided in any Device for this patient.' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -156,6 +169,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @device_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Device.udiCarrier', 'Device.udiCarrier.carrierAIDC', @@ -164,30 +178,16 @@ def validate_resource_item(resource, property, value) 'Device.patient' ] must_support_elements.each do |path| - element_found = false @device_ary&.each do |resource| truncated_path = path.gsub('Device.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @device_ary.length - test 'Device resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '08' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-device.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Device resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Device') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb index df6d17045..a36786eb7 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_lab_sequence.rb @@ -271,9 +271,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@diagnosticreport, versioned_resource_class('DiagnosticReport')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-lab.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('DiagnosticReport') + end + + test 'At least one of every must support element is provided in any DiagnosticReport for this patient.' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -281,6 +294,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @diagnosticreport_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -295,30 +309,16 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - element_found = false @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @diagnosticreport_ary.length - test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '14' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-lab.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided DiagnosticReport resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('DiagnosticReport') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb index 687ce4057..c08177b98 100644 --- a/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_diagnosticreport_note_sequence.rb @@ -271,9 +271,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@diagnosticreport, versioned_resource_class('DiagnosticReport')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-note.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('DiagnosticReport') + end + + test 'At least one of every must support element is provided in any DiagnosticReport for this patient.' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -281,6 +294,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @diagnosticreport_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'DiagnosticReport.status', 'DiagnosticReport.category', @@ -295,30 +309,16 @@ def validate_resource_item(resource, property, value) 'DiagnosticReport.presentedForm' ] must_support_elements.each do |path| - element_found = false @diagnosticreport_ary&.each do |resource| truncated_path = path.gsub('DiagnosticReport.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @diagnosticreport_ary.length - test 'DiagnosticReport resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '14' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-diagnosticreport-note.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided DiagnosticReport resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('DiagnosticReport') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb index c8a977627..aca01712e 100644 --- a/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_documentreference_sequence.rb @@ -277,9 +277,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@documentreference, versioned_resource_class('DocumentReference')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'DocumentReference resources associated with Patient conform to US Core R4 profiles' do metadata do id '13' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-documentreference.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('DocumentReference') + end + + test 'At least one of every must support element is provided in any DocumentReference for this patient.' do + metadata do + id '14' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -287,6 +300,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @documentreference_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'DocumentReference.identifier', 'DocumentReference.status', @@ -307,30 +321,16 @@ def validate_resource_item(resource, property, value) 'DocumentReference.context.period' ] must_support_elements.each do |path| - element_found = false @documentreference_ary&.each do |resource| truncated_path = path.gsub('DocumentReference.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @documentreference_ary.length - test 'DocumentReference resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '14' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-documentreference.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided DocumentReference resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('DocumentReference') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb index 586a3997b..2c845845c 100644 --- a/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_encounter_sequence.rb @@ -258,9 +258,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@encounter, versioned_resource_class('Encounter')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Encounter resources associated with Patient conform to US Core R4 profiles' do metadata do id '12' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-encounter.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Encounter') + end + + test 'At least one of every must support element is provided in any Encounter for this patient.' do + metadata do + id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -268,6 +281,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @encounter_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Encounter.identifier', 'Encounter.identifier.system', @@ -288,30 +302,16 @@ def validate_resource_item(resource, property, value) 'Encounter.location.location' ] must_support_elements.each do |path| - element_found = false @encounter_ary&.each do |resource| truncated_path = path.gsub('Encounter.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @encounter_ary.length - test 'Encounter resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '13' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-encounter.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Encounter resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Encounter') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb index 5422f4cf6..4297f7502 100644 --- a/lib/app/modules/us_core_r4/us_core_goal_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_goal_sequence.rb @@ -166,9 +166,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@goal, versioned_resource_class('Goal')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Goal resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-goal.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Goal') + end + + test 'At least one of every must support element is provided in any Goal for this patient.' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -176,6 +189,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @goal_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Goal.lifecycleStatus', 'Goal.description', @@ -185,30 +199,16 @@ def validate_resource_item(resource, property, value) 'Goal.target.dueDuration' ] must_support_elements.each do |path| - element_found = false @goal_ary&.each do |resource| truncated_path = path.gsub('Goal.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @goal_ary.length - test 'Goal resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '09' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-goal.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Goal resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Goal') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb index 7e5309ab3..a3dccf096 100644 --- a/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_immunization_sequence.rb @@ -166,9 +166,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@immunization, versioned_resource_class('Immunization')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Immunization resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-immunization.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Immunization') + end + + test 'At least one of every must support element is provided in any Immunization for this patient.' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -176,6 +189,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @immunization_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Immunization.status', 'Immunization.statusReason', @@ -186,30 +200,16 @@ def validate_resource_item(resource, property, value) 'Immunization.primarySource' ] must_support_elements.each do |path| - element_found = false @immunization_ary&.each do |resource| truncated_path = path.gsub('Immunization.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @immunization_ary.length - test 'Immunization resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '09' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-immunization.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Immunization resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Immunization') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_location_sequence.rb b/lib/app/modules/us_core_r4/us_core_location_sequence.rb index 9682599d4..d4811dfaa 100644 --- a/lib/app/modules/us_core_r4/us_core_location_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_location_sequence.rb @@ -207,9 +207,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@location, versioned_resource_class('Location')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Location resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-location.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Location') + end + + test 'At least one of every must support element is provided in any Location for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -217,6 +230,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @location_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Location.status', 'Location.name', @@ -229,30 +243,16 @@ def validate_resource_item(resource, property, value) 'Location.managingOrganization' ] must_support_elements.each do |path| - element_found = false @location_ary&.each do |resource| truncated_path = path.gsub('Location.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @location_ary.length - test 'Location resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-location.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Location resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Location') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb index d4f118e07..03adcb0d3 100644 --- a/lib/app/modules/us_core_r4/us_core_medication_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medication_sequence.rb @@ -85,9 +85,22 @@ class UsCoreR4MedicationSequence < SequenceBase validate_history_reply(@medication, versioned_resource_class('Medication')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Medication resources associated with Patient conform to US Core R4 profiles' do metadata do id '05' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medication.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Medication') + end + + test 'At least one of every must support element is provided in any Medication for this patient.' do + metadata do + id '06' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -95,34 +108,21 @@ class UsCoreR4MedicationSequence < SequenceBase end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medication_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Medication.code' ] must_support_elements.each do |path| - element_found = false @medication_ary&.each do |resource| truncated_path = path.gsub('Medication.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @medication_ary.length - test 'Medication resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '06' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medication.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Medication resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Medication') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb index a5ea65b62..0e9553104 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationrequest_sequence.rb @@ -166,9 +166,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@medicationrequest, versioned_resource_class('MedicationRequest')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'MedicationRequest resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationrequest.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('MedicationRequest') + end + + test 'At least one of every must support element is provided in any MedicationRequest for this patient.' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -176,6 +189,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medicationrequest_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'MedicationRequest.status', 'MedicationRequest.medicationCodeableConcept', @@ -187,30 +201,16 @@ def validate_resource_item(resource, property, value) 'MedicationRequest.dosageInstruction.text' ] must_support_elements.each do |path| - element_found = false @medicationrequest_ary&.each do |resource| truncated_path = path.gsub('MedicationRequest.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @medicationrequest_ary.length - test 'MedicationRequest resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '09' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationrequest.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided MedicationRequest resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('MedicationRequest') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb index 0c802695b..3ef9f8be1 100644 --- a/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_medicationstatement_sequence.rb @@ -166,9 +166,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@medicationstatement, versioned_resource_class('MedicationStatement')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'MedicationStatement resources associated with Patient conform to US Core R4 profiles' do metadata do id '08' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationstatement.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('MedicationStatement') + end + + test 'At least one of every must support element is provided in any MedicationStatement for this patient.' do + metadata do + id '09' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -176,6 +189,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @medicationstatement_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'MedicationStatement.status', 'MedicationStatement.medicationCodeableConcept', @@ -187,30 +201,16 @@ def validate_resource_item(resource, property, value) 'MedicationStatement.derivedFrom' ] must_support_elements.each do |path| - element_found = false @medicationstatement_ary&.each do |resource| truncated_path = path.gsub('MedicationStatement.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @medicationstatement_ary.length - test 'MedicationStatement resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '09' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-medicationstatement.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided MedicationStatement resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('MedicationStatement') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb index 1f117a464..0b7a0f11d 100644 --- a/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_observation_lab_sequence.rb @@ -218,9 +218,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-observation-lab.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Observation') + end + + test 'At least one of every must support element is provided in any Observation for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -228,6 +241,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Observation.status', 'Observation.category', @@ -249,30 +263,16 @@ def validate_resource_item(resource, property, value) 'Observation.dataAbsentReason' ] must_support_elements.each do |path| - element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @observation_ary.length - test 'Observation resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-observation-lab.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Observation resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Observation') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb index 8533a35b2..620dce5f9 100644 --- a/lib/app/modules/us_core_r4/us_core_organization_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_organization_sequence.rb @@ -141,9 +141,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@organization, versioned_resource_class('Organization')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Organization resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-organization.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Organization') + end + + test 'At least one of every must support element is provided in any Organization for this patient.' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -151,6 +164,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @organization_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Organization.identifier', 'Organization.identifier.system', @@ -166,30 +180,16 @@ def validate_resource_item(resource, property, value) 'Organization.endpoint' ] must_support_elements.each do |path| - element_found = false @organization_ary&.each do |resource| truncated_path = path.gsub('Organization.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @organization_ary.length - test 'Organization resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '08' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-organization.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Organization resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Organization') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb index b87b03336..e86b49a10 100644 --- a/lib/app/modules/us_core_r4/us_core_patient_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_patient_sequence.rb @@ -261,9 +261,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@patient, versioned_resource_class('Patient')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Patient resources associated with Patient conform to US Core R4 profiles' do metadata do id '12' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-patient.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Patient') + end + + test 'At least one of every must support element is provided in any Patient for this patient.' do + metadata do + id '13' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -271,20 +284,18 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @patient_ary&.any? + must_support_confirmed = {} extensions_list = { 'Patient.extension:race': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race', 'Patient.extension:ethnicity': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity', 'Patient.extension:birthsex': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex' } extensions_list.each do |id, url| - element_found = false @patient_ary&.each do |resource| - already_found = @instance.must_support_confirmed.include?(id.to_s) - element_found = already_found || resource.extension.any? { |extension| extension.url == url } - @instance.must_support_confirmed += "#{id}," unless already_found - break if element_found + must_support_confirmed[id] = true if resource.extension.any? { |extension| extension.url == url } + break if must_support_confirmed[id] end - skip "Could not find #{id} in the provided resource" unless element_found + skip "Could not find #{id} in any of the #{@patient_ary.length} provided Patient resource(s)" unless must_support_confirmed[id] end must_support_elements = [ @@ -308,30 +319,16 @@ def validate_resource_item(resource, property, value) 'Patient.communication.language' ] must_support_elements.each do |path| - element_found = false @patient_ary&.each do |resource| truncated_path = path.gsub('Patient.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @patient_ary.length - test 'Patient resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '13' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-patient.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Patient resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Patient') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb index edf76fcbe..54e6cecc0 100644 --- a/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitioner_sequence.rb @@ -149,9 +149,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@practitioner, versioned_resource_class('Practitioner')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Practitioner resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitioner.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Practitioner') + end + + test 'At least one of every must support element is provided in any Practitioner for this patient.' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -159,6 +172,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @practitioner_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Practitioner.identifier', 'Practitioner.identifier.system', @@ -169,30 +183,16 @@ def validate_resource_item(resource, property, value) 'Practitioner.name.family' ] must_support_elements.each do |path| - element_found = false @practitioner_ary&.each do |resource| truncated_path = path.gsub('Practitioner.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @practitioner_ary.length - test 'Practitioner resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '08' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitioner.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Practitioner resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Practitioner') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb index 483b035fa..9756fca2d 100644 --- a/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_practitionerrole_sequence.rb @@ -145,9 +145,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@practitionerrole, versioned_resource_class('PractitionerRole')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'PractitionerRole resources associated with Patient conform to US Core R4 profiles' do metadata do id '07' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitionerrole.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('PractitionerRole') + end + + test 'At least one of every must support element is provided in any PractitionerRole for this patient.' do + metadata do + id '08' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -155,6 +168,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @practitionerrole_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'PractitionerRole.practitioner', 'PractitionerRole.organization', @@ -167,30 +181,16 @@ def validate_resource_item(resource, property, value) 'PractitionerRole.endpoint' ] must_support_elements.each do |path| - element_found = false @practitionerrole_ary&.each do |resource| truncated_path = path.gsub('PractitionerRole.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @practitionerrole_ary.length - test 'PractitionerRole resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '08' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-practitionerrole.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided PractitionerRole resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('PractitionerRole') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb index 601ce802b..9aeea54e1 100644 --- a/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_procedure_sequence.rb @@ -192,9 +192,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@procedure, versioned_resource_class('Procedure')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Procedure resources associated with Patient conform to US Core R4 profiles' do metadata do id '09' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-procedure.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Procedure') + end + + test 'At least one of every must support element is provided in any Procedure for this patient.' do + metadata do + id '10' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -202,6 +215,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @procedure_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Procedure.status', 'Procedure.code', @@ -210,30 +224,16 @@ def validate_resource_item(resource, property, value) 'Procedure.performedPeriod' ] must_support_elements.each do |path| - element_found = false @procedure_ary&.each do |resource| truncated_path = path.gsub('Procedure.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @procedure_ary.length - test 'Procedure resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '10' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-procedure.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Procedure resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Procedure') + @instance.save! end test 'All references can be resolved' do diff --git a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb index 991371ca3..3b82b2a9e 100644 --- a/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_smokingstatus_sequence.rb @@ -218,9 +218,22 @@ def validate_resource_item(resource, property, value) validate_history_reply(@observation, versioned_resource_class('Observation')) end - test 'Demonstrates that the server can supply must supported elements' do + test 'Observation resources associated with Patient conform to US Core R4 profiles' do metadata do id '10' + link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-smokingstatus.json' + desc %( + ) + versions :r4 + end + + skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + test_resources_against_profile('Observation') + end + + test 'At least one of every must support element is provided in any Observation for this patient.' do + metadata do + id '11' link 'https://build.fhir.org/ig/HL7/US-Core-R4/general-guidance.html/#must-support' desc %( ) @@ -228,6 +241,7 @@ def validate_resource_item(resource, property, value) end skip 'No resources appear to be available for this patient. Please use patients with more information' unless @observation_ary&.any? + must_support_confirmed = {} must_support_elements = [ 'Observation.status', 'Observation.code', @@ -236,30 +250,16 @@ def validate_resource_item(resource, property, value) 'Observation.valueCodeableConcept' ] must_support_elements.each do |path| - element_found = false @observation_ary&.each do |resource| truncated_path = path.gsub('Observation.', '') - already_found = @instance.must_support_confirmed.include?(path) - element_found = already_found || can_resolve_path(resource, truncated_path) - @instance.must_support_confirmed += "#{path}," if element_found && !already_found - break if element_found + must_support_confirmed[path] = true if can_resolve_path(resource, truncated_path) + break if must_support_confirmed[path] end - skip "Could not find #{path} in the provided resource" unless element_found - end - @instance.save! - end + resource_count = @observation_ary.length - test 'Observation resources associated with Patient conform to US Core R4 profiles' do - metadata do - id '11' - link 'https://build.fhir.org/ig/HL7/US-Core-R4/StructureDefinition-us-core-smokingstatus.json' - desc %( - ) - versions :r4 + skip "Could not find #{path} in any of the #{resource_count} provided Observation resource(s)" unless must_support_confirmed[path] end - - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found - test_resources_against_profile('Observation') + @instance.save! end test 'All references can be resolved' do diff --git a/resources/us_core_r4/StructureDefinition-us-core-medication.json b/resources/us_core_r4/StructureDefinition-us-core-medication.json new file mode 100644 index 000000000..5021b5903 --- /dev/null +++ b/resources/us_core_r4/StructureDefinition-us-core-medication.json @@ -0,0 +1,1097 @@ +{ + "resourceType": "StructureDefinition", + "id": "us-core-medication", + "text": { + "status": "generated", + "div": "" + }, + "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-medication", + "version": "3.0.0", + "name": "USCoreMedicationProfile", + "title": "US Core Medication Profile", + "status": "active", + "experimental": false, + "date": "2019-05-21T00:00:00+00:00", + "publisher": "HL7 US Realm Steering Committee", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://www.healthit.gov" + } + ] + } + ], + "description": "Defines constraints and extensions on the Medication resource for the minimal set of data to query and retrieve patient retrieving patient's medication information.", + "jurisdiction": [ + { + "coding": [ + { + "system": "urn:iso:std:iso:3166", + "code": "US", + "display": "United States of America" + } + ] + } + ], + "fhirVersion": "4.0.0", + "mapping": [ + { + "identity": "argonaut-dq-dstu2", + "uri": "http://unknown.org/Argonaut-DQ-DSTU2", + "name": "Argonaut-DQ-DSTU2" + }, + { + "identity": "script10.6", + "uri": "http://ncpdp.org/SCRIPT10_6", + "name": "Mapping to NCPDP SCRIPT 10.6" + }, + { + "identity": "rim", + "uri": "http://hl7.org/v3", + "name": "RIM Mapping" + }, + { + "identity": "w5", + "uri": "http://hl7.org/fhir/fivews", + "name": "FiveWs Pattern Mapping" + }, + { + "identity": "v2", + "uri": "http://hl7.org/v2", + "name": "HL7 v2 Mapping" + } + ], + "kind": "resource", + "abstract": false, + "type": "Medication", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Medication", + "derivation": "constraint", + "snapshot": { + "element": [ + { + "id": "Medication", + "path": "Medication", + "short": "Definition of a Medication", + "definition": "The US Core Medication Profile is based upon the core FHIR Medication Resource and created to meet the 2015 Edition Common Clinical Data Set 'Medications' requirements.", + "min": 0, + "max": "*", + "base": { + "path": "Medication", + "min": 0, + "max": "*" + }, + "constraint": [ + { + "key": "dom-2", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL NOT contain nested Resources", + "expression": "contained.contained.empty()", + "xpath": "not(parent::f:contained and f:contained)", + "source": "DomainResource" + }, + { + "key": "dom-4", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated", + "expression": "contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:versionId)) and not(exists(f:contained/*/f:meta/f:lastUpdated))", + "source": "DomainResource" + }, + { + "key": "dom-3", + "severity": "error", + "human": "If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource", + "expression": "contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()", + "xpath": "not(exists(for $contained in f:contained return $contained[not(parent::*/descendant::f:reference/@value=concat('#', $contained/*/id/@value) or descendant::f:reference[@value='#'])]))", + "source": "DomainResource" + }, + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice", + "valueBoolean": true + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation", + "valueMarkdown": "When a resource has no narrative, only systems that fully understand the data can display the resource to a human safely. Including a human readable representation in the resource makes for a much more robust eco-system and cheaper handling of resources by intermediary systems. Some ecosystems restrict distribution of resources to only those systems that do fully understand the resources, and as a consequence implementers may believe that the narrative is superfluous. However experience shows that such eco-systems often open up to new participants over time." + } + ], + "key": "dom-6", + "severity": "warning", + "human": "A resource should have narrative for robust management", + "expression": "text.div.exists()", + "xpath": "exists(f:text/h:div)", + "source": "DomainResource" + }, + { + "key": "dom-5", + "severity": "error", + "human": "If a resource is contained in another resource, it SHALL NOT have a security label", + "expression": "contained.meta.security.empty()", + "xpath": "not(exists(f:contained/*/f:meta/f:security))", + "source": "DomainResource" + } + ], + "mustSupport": false, + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Entity. Role, or Act" + }, + { + "identity": "script10.6", + "map": "NewRx/MedicationPrescribed\r-or-\rRxFill/MedicationDispensed\r-or-\rRxHistoryResponse/MedicationDispensed\r-or-\rRxHistoryResponse/MedicationPrescribed" + }, + { + "identity": "rim", + "map": "ManufacturedProduct[classCode=ADMM]" + }, + { + "identity": "argonaut-dq-dstu2", + "map": "Medication" + } + ] + }, + { + "id": "Medication.id", + "path": "Medication.id", + "short": "Logical id of this artifact", + "definition": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.", + "comment": "The only time that a resource does not have an id is when it is being submitted to the server using a create operation.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "id" + } + ], + "isModifier": false, + "isSummary": true + }, + { + "id": "Medication.meta", + "path": "Medication.meta", + "short": "Metadata about the resource", + "definition": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.meta", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Meta" + } + ], + "isModifier": false, + "isSummary": true + }, + { + "id": "Medication.implicitRules", + "path": "Medication.implicitRules", + "short": "A set of rules under which this content was created", + "definition": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.", + "comment": "Asserting this rule set restricts the content to be only understood by a limited set of trading partners. This inherently limits the usefulness of the data in the long term. However, the existing health eco-system is highly fractured, and not yet ready to define, collect, and exchange data in a generally computable sense. Wherever possible, implementers and/or specification writers should avoid using this element. Often, when used, the URL is a reference to an implementation guide that defines these special rules as part of it's narrative along with other profiles, value sets, etc.", + "min": 0, + "max": "1", + "base": { + "path": "Resource.implicitRules", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "uri" + } + ], + "isModifier": true, + "isModifierReason": "This element is labeled as a modifier because the implicit rules may provide additional knowledge about the resource that modifies it's meaning or interpretation", + "isSummary": true + }, + { + "id": "Medication.language", + "path": "Medication.language", + "short": "Language of the resource content", + "definition": "The base language in which the resource is written.", + "comment": "Language is provided to support indexing and accessibility (typically, services such as text to speech use the language tag). The html language tag in the narrative applies to the narrative. The language tag on the resource may be used to specify the language of other presentations generated from the data in the resource. Not all the content has to be in the base language. The Resource.language should not be assumed to apply to the narrative automatically. If a language is specified, it should it also be specified on the div element in the html (see rules in HTML5 for information about the relationship between xml:lang and the html lang attribute).", + "min": 0, + "max": "1", + "base": { + "path": "Resource.language", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet", + "valueCanonical": "http://hl7.org/fhir/ValueSet/all-languages" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "Language" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-isCommonBinding", + "valueBoolean": true + } + ], + "strength": "preferred", + "description": "A human language.", + "valueSet": "http://hl7.org/fhir/ValueSet/languages" + } + }, + { + "id": "Medication.text", + "path": "Medication.text", + "short": "Text summary of the resource, for human interpretation", + "definition": "A human-readable narrative that contains a summary of the resource and can be used to represent the content of the resource to a human. The narrative need not encode all the structured data, but is required to contain sufficient detail to make it \"clinically safe\" for a human to just read the narrative. Resource definitions may define what content should be represented in the narrative to ensure clinical safety.", + "comment": "Contained resources do not have narrative. Resources that are not contained SHOULD have a narrative. In some cases, a resource may only have text with little or no additional discrete data (as long as all minOccurs=1 elements are satisfied). This may be necessary for data from legacy systems where information is captured as a \"text blob\" or where text is additionally entered raw or narrated and encoded information is added later.", + "alias": [ + "narrative", + "html", + "xhtml", + "display" + ], + "min": 0, + "max": "1", + "base": { + "path": "DomainResource.text", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Narrative" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "Act.text?" + } + ] + }, + { + "id": "Medication.contained", + "path": "Medication.contained", + "short": "Contained, inline Resources", + "definition": "These resources do not have an independent existence apart from the resource that contains them - they cannot be identified independently, and nor can they have their own independent transaction scope.", + "comment": "This should never be done when the content can be identified properly, as once identification is lost, it is extremely difficult (and context dependent) to restore it again. Contained resources may have profiles and tags In their meta elements, but SHALL NOT have security labels.", + "alias": [ + "inline resources", + "anonymous resources", + "contained resources" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.contained", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Resource" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Medication.extension", + "path": "Medication.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Medication.modifierExtension", + "path": "Medication.modifierExtension", + "short": "Extensions that cannot be ignored", + "definition": "May be used to represent additional information that is not part of the basic definition of the resource and that modifies the understanding of the element that contains it and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](http://hl7.org/fhir/R4/extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "DomainResource.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the resource that contains them", + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Medication.identifier", + "path": "Medication.identifier", + "short": "Business identifier for this medication", + "definition": "Business identifier for this medication.", + "comment": "The serial number could be included as an identifier.", + "min": 0, + "max": "*", + "base": { + "path": "Medication.identifier", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Identifier" + } + ], + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "w5", + "map": "FiveWs.identifier" + }, + { + "identity": "rim", + "map": ".id" + } + ] + }, + { + "id": "Medication.code", + "path": "Medication.code", + "short": "Codes that identify this medication", + "definition": "A code (or set of codes) that specify this medication, or a textual description if no code is available. Usage note: This could be a standard medication code such as a code from RxNorm, SNOMED CT, IDMP etc. It could also be a national or local formulary code, optionally with translations to other code systems.", + "comment": "Depending on the context of use, the code that was actually selected by the user (prescriber, dispenser, etc.) will have the coding.userSelected set to true. As described in the coding datatype: \"A coding may be marked as a \"userSelected\" if a user selected the particular coded value in a user interface (e.g. the user selects an item in a pick-list). If a user selected coding exists, it is the preferred choice for performing translations etc. Other codes can only be literal translations to alternative code systems, or codes at a lower level of granularity (e.g. a generic code for a vendor-specific primary one).", + "min": 1, + "max": "1", + "base": { + "path": "Medication.code", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "mustSupport": true, + "isModifier": false, + "isSummary": true, + "binding": { + "strength": "extensible", + "description": "Prescribable medications", + "valueSet": "http://hl7.org/fhir/us/core/ValueSet/us-core-medication-codes" + }, + "mapping": [ + { + "identity": "script10.6", + "map": "coding.code = //element(*,MedicationType)/DrugCoded/ProductCode\r\rcoding.system = //element(*,MedicationType)/DrugCoded/ProductCodeQualifier\r\rcoding.display = //element(*,MedicationType)/DrugDescription" + }, + { + "identity": "w5", + "map": "FiveWs.class" + }, + { + "identity": "v2", + "map": "RXO-1.1-Requested Give Code.code / RXE-2.1-Give Code.code / RXD-2.1-Dispense/Give Code.code / RXG-4.1-Give Code.code /RXA-5.1-Administered Code.code / RXC-2.1 Component Code" + }, + { + "identity": "rim", + "map": ".code" + }, + { + "identity": "argonaut-dq-dstu2", + "map": "Medication.code" + } + ] + }, + { + "id": "Medication.status", + "path": "Medication.status", + "short": "active | inactive | entered-in-error", + "definition": "A code to indicate if the medication is in active use.", + "comment": "This status is intended to identify if the medication in a local system is in active use within a drug database or inventory. For example, a pharmacy system may create a new drug file record for a compounded product \"ABC Hospital Special Cream\" with an active status. At some point in the future, it may be determined that the drug record was created with an error and the status is changed to \"entered in error\". This status is not intended to specify if a medication is part of a particular formulary. It is possible that the drug record may be referenced by multiple formularies or catalogues and each of those entries would have a separate status.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.status", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "code" + } + ], + "isModifier": true, + "isModifierReason": "This element changes the interpretation of all descriptive attributes.", + "isSummary": true, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MedicationStatus" + } + ], + "strength": "required", + "description": "A coded concept defining if the medication is in active use.", + "valueSet": "http://hl7.org/fhir/ValueSet/medication-status|4.0.0" + }, + "mapping": [ + { + "identity": "rim", + "map": ".statusCode" + } + ] + }, + { + "id": "Medication.manufacturer", + "path": "Medication.manufacturer", + "short": "Manufacturer of the item", + "definition": "Describes the details of the manufacturer of the medication product. This is not intended to represent the distributor of a medication product.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.manufacturer", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Organization" + ] + } + ], + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "script10.6", + "map": "no mapping" + }, + { + "identity": "w5", + "map": "FiveWs.actor" + }, + { + "identity": "v2", + "map": "RXD-20-Substance Manufacturer Name / RXG-21-Substance Manufacturer Name / RXA-17-Substance Manufacturer Name" + }, + { + "identity": "rim", + "map": ".player.scopingRole[typeCode=MANU].scoper" + } + ] + }, + { + "id": "Medication.form", + "path": "Medication.form", + "short": "powder | tablets | capsule +", + "definition": "Describes the form of the item. Powder; tablets; capsule.", + "comment": "When Medication is referenced from MedicationRequest, this is the ordered form. When Medication is referenced within MedicationDispense, this is the dispensed form. When Medication is referenced within MedicationAdministration, this is administered form.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.form", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + } + ], + "isModifier": false, + "isSummary": false, + "binding": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName", + "valueString": "MedicationForm" + } + ], + "strength": "example", + "description": "A coded concept defining the form of a medication.", + "valueSet": "http://hl7.org/fhir/ValueSet/medication-form-codes" + }, + "mapping": [ + { + "identity": "script10.6", + "map": "coding.code = //element(*,DrugCodedType)/FormCode\r\rcoding.system = //element(*,DrugCodedType)/FormSourceCode" + }, + { + "identity": "v2", + "map": "RXO-5-Requested Dosage Form / RXE-6-Give Dosage Form / RXD-6-Actual Dosage Form / RXG-8-Give Dosage Form / RXA-8-Administered Dosage Form" + }, + { + "identity": "rim", + "map": ".formCode" + } + ] + }, + { + "id": "Medication.amount", + "path": "Medication.amount", + "short": "Amount of drug in package", + "definition": "Specific amount of the drug in the packaged product. For example, when specifying a product that has the same strength (For example, Insulin glargine 100 unit per mL solution for injection), this attribute provides additional clarification of the package amount (For example, 3 mL, 10mL, etc.).", + "min": 0, + "max": "1", + "base": { + "path": "Medication.amount", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Ratio" + } + ], + "isModifier": false, + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": ".quantity" + } + ] + }, + { + "id": "Medication.ingredient", + "path": "Medication.ingredient", + "short": "Active or inactive ingredient", + "definition": "Identifies a particular constituent of interest in the product.", + "comment": "The ingredients need not be a complete list. If an ingredient is not specified, this does not indicate whether an ingredient is present or absent. If an ingredient is specified it does not mean that all ingredients are specified. It is possible to specify both inactive and active ingredients.", + "min": 0, + "max": "*", + "base": { + "path": "Medication.ingredient", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "Element" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": ".scopesRole[typeCode=INGR]" + } + ] + }, + { + "id": "Medication.ingredient.id", + "path": "Medication.ingredient.id", + "representation": [ + "xmlAttr" + ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "string" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Medication.ingredient.extension", + "path": "Medication.ingredient.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Medication.ingredient.modifierExtension", + "path": "Medication.ingredient.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](http://hl7.org/fhir/R4/extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Medication.ingredient.item[x]", + "path": "Medication.ingredient.item[x]", + "short": "The actual ingredient or content", + "definition": "The actual ingredient - either a substance (simple ingredient) or another medication of a medication.", + "requirements": "The ingredient may reference a substance (for example, amoxicillin) or another medication (for example in the case of a compounded product, Glaxal Base).", + "min": 1, + "max": "1", + "base": { + "path": "Medication.ingredient.item[x]", + "min": 1, + "max": "1" + }, + "type": [ + { + "code": "CodeableConcept" + }, + { + "code": "Reference", + "targetProfile": [ + "http://hl7.org/fhir/StructureDefinition/Substance", + "http://hl7.org/fhir/StructureDefinition/Medication" + ] + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "script10.6", + "map": "coding.code = //element(*,MedicationType)/DrugCoded/ProductCode\r\rcoding.system = //element(*,MedicationType)/DrugCoded/ProductCodeQualifier\r\rcoding.display = //element(*,MedicationType)/DrugDescription" + }, + { + "identity": "v2", + "map": "RXC-2-Component Code if medication: RXO-1-Requested Give Code / RXE-2-Give Code / RXD-2-Dispense/Give Code / RXG-4-Give Code / RXA-5-Administered Code" + }, + { + "identity": "rim", + "map": ".player" + } + ] + }, + { + "id": "Medication.ingredient.isActive", + "path": "Medication.ingredient.isActive", + "short": "Active ingredient indicator", + "definition": "Indication of whether this ingredient affects the therapeutic action of the drug.", + "requirements": "True indicates that the ingredient affects the therapeutic action of the drug (i.e. active). \rFalse indicates that the ingredient does not affect the therapeutic action of the drug (i.e. inactive).", + "min": 0, + "max": "1", + "base": { + "path": "Medication.ingredient.isActive", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "boolean" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "NA" + } + ] + }, + { + "id": "Medication.ingredient.strength", + "path": "Medication.ingredient.strength", + "short": "Quantity of ingredient present", + "definition": "Specifies how many (or how much) of the items there are in this Medication. For example, 250 mg per tablet. This is expressed as a ratio where the numerator is 250mg and the denominator is 1 tablet.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.ingredient.strength", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "Ratio" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "script10.6", + "map": "//element(*,DrugCodedType)/Strength" + }, + { + "identity": "v2", + "map": "RXC-3-Component Amount & RXC-4-Component Units if medication: RXO-2-Requested Give Amount - Minimum & RXO-4-Requested Give Units / RXO-3-Requested Give Amount - Maximum & RXO-4-Requested Give Units / RXO-11-Requested Dispense Amount & RXO-12-Requested Dispense Units / RXE-3-Give Amount - Minimum & RXE-5-Give Units / RXE-4-Give Amount - Maximum & RXE-5-Give Units / RXE-10-Dispense Amount & RXE-10-Dispense Units" + }, + { + "identity": "rim", + "map": ".quantity" + } + ] + }, + { + "id": "Medication.batch", + "path": "Medication.batch", + "short": "Details about packaged medications", + "definition": "Information that only applies to packages (not products).", + "min": 0, + "max": "1", + "base": { + "path": "Medication.batch", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "BackboneElement" + } + ], + "constraint": [ + { + "key": "ele-1", + "severity": "error", + "human": "All FHIR elements must have a @value or children", + "expression": "hasValue() or (children().count() > id.count())", + "xpath": "@value|f:*|h:div", + "source": "Element" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "script10.6", + "map": "no mapping" + }, + { + "identity": "rim", + "map": ".player[classCode=CONT]" + } + ] + }, + { + "id": "Medication.batch.id", + "path": "Medication.batch.id", + "representation": [ + "xmlAttr" + ], + "short": "Unique id for inter-element referencing", + "definition": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.", + "min": 0, + "max": "1", + "base": { + "path": "Element.id", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "string" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Medication.batch.extension", + "path": "Medication.batch.extension", + "short": "Additional content defined by implementations", + "definition": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "alias": [ + "extensions", + "user content" + ], + "min": 0, + "max": "*", + "base": { + "path": "Element.extension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "rim", + "map": "n/a" + } + ] + }, + { + "id": "Medication.batch.modifierExtension", + "path": "Medication.batch.modifierExtension", + "short": "Extensions that cannot be ignored even if unrecognized", + "definition": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).", + "comment": "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.", + "requirements": "Modifier extensions allow for extensions that *cannot* be safely ignored to be clearly distinguished from the vast majority of extensions which can be safely ignored. This promotes interoperability by eliminating the need for implementers to prohibit the presence of extensions. For further information, see the [definition of modifier extensions](http://hl7.org/fhir/R4/extensibility.html#modifierExtension).", + "alias": [ + "extensions", + "user content", + "modifiers" + ], + "min": 0, + "max": "*", + "base": { + "path": "BackboneElement.modifierExtension", + "min": 0, + "max": "*" + }, + "type": [ + { + "code": "Extension" + } + ], + "isModifier": true, + "isModifierReason": "Modifier extensions are expected to modify the meaning or interpretation of the element that contains them", + "isSummary": true, + "mapping": [ + { + "identity": "rim", + "map": "N/A" + } + ] + }, + { + "id": "Medication.batch.lotNumber", + "path": "Medication.batch.lotNumber", + "short": "Identifier assigned to batch", + "definition": "The assigned lot number of a batch of the specified product.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.batch.lotNumber", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "string" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "script10.6", + "map": "no mapping" + }, + { + "identity": "v2", + "map": "RXA-15 Substance Lot Number / RXG-19 Substance Lot Number" + }, + { + "identity": "rim", + "map": ".id" + } + ] + }, + { + "id": "Medication.batch.expirationDate", + "path": "Medication.batch.expirationDate", + "short": "When batch will expire", + "definition": "When this specific batch of product will expire.", + "min": 0, + "max": "1", + "base": { + "path": "Medication.batch.expirationDate", + "min": 0, + "max": "1" + }, + "type": [ + { + "code": "dateTime" + } + ], + "isModifier": false, + "isSummary": false, + "mapping": [ + { + "identity": "script10.6", + "map": "no mapping" + }, + { + "identity": "v2", + "map": "RXA-16 Substance Expiration Date / RXG-20 Substance Expiration Date" + }, + { + "identity": "rim", + "map": "participation[typeCode=CSM].role[classCode=INST].scopedRole.scoper[classCode=MMAT].expirationTime" + } + ] + } + ] + }, + "differential": { + "element": [ + { + "id": "Medication", + "path": "Medication", + "definition": "The US Core Medication Profile is based upon the core FHIR Medication Resource and created to meet the 2015 Edition Common Clinical Data Set 'Medications' requirements.", + "mustSupport": false, + "isModifier": false, + "mapping": [ + { + "identity": "argonaut-dq-dstu2", + "map": "Medication" + } + ] + }, + { + "id": "Medication.code", + "path": "Medication.code", + "min": 1, + "max": "1", + "mustSupport": true, + "isModifier": false, + "binding": { + "strength": "extensible", + "description": "Prescribable medications", + "valueSet": "http://hl7.org/fhir/us/core/ValueSet/us-core-medication-codes" + }, + "mapping": [ + { + "identity": "argonaut-dq-dstu2", + "map": "Medication.code" + } + ] + } + ] + } +} \ No newline at end of file From b3e999830a0c5cc4548425b2977e1cc85b857258 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Mon, 1 Jul 2019 11:56:10 -0400 Subject: [PATCH 21/89] commiting before merge --- Gemfile.lock | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gemfile.lock b/Gemfile.lock index e4dbbdbe7..c911cae29 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -246,3 +246,6 @@ DEPENDENCIES thin time_difference webmock + +BUNDLED WITH + 1.16.1 From 138eea4682ca2106c6d025637a7ca9ab7e8f3860 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Mon, 1 Jul 2019 12:48:58 -0400 Subject: [PATCH 22/89] updated link to documentation for the FHIR version test --- Gemfile.lock | 2 +- lib/app/modules/core/capability_statement_sequence.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8be222197..d1fb44c02 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -253,4 +253,4 @@ DEPENDENCIES webmock BUNDLED WITH - 2.0.1 + 1.16.1 diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index e9bd5f62b..8b843dde8 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -74,7 +74,7 @@ class CapabilityStatementSequence < SequenceBase test 'Test FHIR version' do metadata do id '02' - link '' + link 'http://www.hl7.org/fhir/directory.cfml' desc %( Testing that the FHIR client is the same version that was version as the testing instance that was selected. ) From 1d1e00b288f071386b32b1af632c684a2b994449 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Mon, 1 Jul 2019 13:04:02 -0400 Subject: [PATCH 23/89] fixed formatting issues --- lib/app/modules/core/capability_statement_sequence.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index 8b843dde8..638af1ea2 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -80,12 +80,10 @@ class CapabilityStatementSequence < SequenceBase ) end - #@client.detect_version is a symbol - assert_equal(@instance.fhir_version, @client.detect_version.to_s, "FHIR client version does not match with instance version"); - + # @client.detect_version is a symbol + assert_equal(@instance.fhir_version, @client.detect_version.to_s, 'FHIR client version does not match with instance version') end - test 'FHIR server supports the conformance interaction that defines how it supports resources' do metadata do id '03' From 4fa5821cb51023a4831da03e5764814dc7bbfbc5 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Wed, 19 Jun 2019 08:19:38 -0400 Subject: [PATCH 24/89] initial refactors --- lib/app/sequence_base.rb | 52 +++++++------- lib/app/utils/validation.rb | 110 ++++++++++++++--------------- test/unit/argonaut_fixture_test.rb | 4 +- 3 files changed, 82 insertions(+), 84 deletions(-) diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 7dd9de640..9cf111948 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -36,7 +36,7 @@ class SequenceBase @@conformance_supports = {} @@defines = {} @@versions = {} - @@test_metadata = {} + @@test_metadata = Hash.new { |hash, key| hash[key] = [] } @@optional = [] @@show_uris = [] @@ -329,7 +329,7 @@ def self.test_id_prefix(test_id_prefix = nil) end def self.tests - @@test_metadata[sequence_name] || [] + @@test_metadata[sequence_name] end def optional? @@ -373,7 +373,6 @@ def self.preconditions_met_for?(instance) # this must be called to ensure that the child class is referenced in self.sequence_name def self.extends_sequence(klass) @@test_metadata[klass.sequence_name].each do |metadata| - @@test_metadata[sequence_name] ||= [] @@test_metadata[sequence_name] << metadata @@test_metadata[sequence_name].last[:test_index] = @@test_metadata[sequence_name].length - 1 define_method metadata[:method_name], metadata[:method] @@ -390,13 +389,12 @@ def self.test(name, &block) test_index = @@test_index test_method = "#{@@test_index.to_s.rjust(4, '0')} #{name} test".downcase.tr(' ', '_').to_sym - @@test_metadata[sequence_name] ||= [] @@test_metadata[sequence_name] << { name: name, test_index: test_index, required: true, versions: FHIR::VERSIONS } - test_index_in_sequence = @@test_metadata[sequence_name].length - 1 + current_test = @@test_metadata[sequence_name].last wrapped = lambda do instance_eval(&block) if @metadata_only # just run the test to hit the metadata block @@ -405,19 +403,23 @@ def self.test(name, &block) @links = [] @requires = [] @validates = [] - result = Models::TestResult.new(test_id: @@test_metadata[sequence_name][test_index_in_sequence][:test_id], - name: name, - ref: @@test_metadata[sequence_name][test_index_in_sequence][:ref], - required: @@test_metadata[sequence_name][test_index_in_sequence][:required], - description: @@test_metadata[sequence_name][test_index_in_sequence][:description], - url: @@test_metadata[sequence_name][test_index_in_sequence][:url], - versions: @@test_metadata[sequence_name][test_index_in_sequence][:versions].join(','), - result: STATUS[:pass], - test_index: test_index) + test_id = current_test[:test_id] + versions = current_test[:versions] + result = Models::TestResult.new( + test_id: test_id, + name: name, + ref: current_test[:ref], + required: current_test[:required], + description: current_test[:description], + url: current_test[:url], + versions: versions.join(','), + result: STATUS[:pass], + test_index: test_index + ) begin - fhir_version_included = @@test_metadata[sequence_name][test_index_in_sequence][:versions].include? @instance.fhir_version&.to_sym - skip_unless(fhir_version_included, 'This test does not run with this FHIR version') unless @instance.fhir_version.nil? - Inferno.logger.info "Starting Test: #{@@test_metadata[sequence_name][test_index_in_sequence][:test_id]} [#{name}]" + fhir_version_included = @instance.fhir_version.present? && versions.include?(@instance.fhir_version&.to_sym) + skip_unless(fhir_version_included, 'This test does not run with this FHIR version') + Inferno.logger.info "Starting Test: #{test_id} [#{name}]" instance_eval(&block) rescue AssertionException, ClientException => e result.fail! @@ -446,15 +448,15 @@ def self.test(name, &block) result.error! result.message = "Fatal Error: #{e.message}" end - result.test_warnings = @test_warnings.map { |w| Models::TestWarning.new(message: w) } unless @test_warnings.empty? - Inferno.logger.info "Finished Test: #{@@test_metadata[sequence_name][test_index_in_sequence][:test_id]} [#{result.result}]" + result.test_warnings = @test_warnings.map { |w| Models::TestWarning.new(message: w) } + Inferno.logger.info "Finished Test: #{test_id} [#{result.result}]" result end define_method test_method, wrapped - @@test_metadata[sequence_name][test_index_in_sequence][:method] = wrapped - @@test_metadata[sequence_name][test_index_in_sequence][:method_name] = test_method + current_test[:method] = wrapped + current_test[:method_name] = test_method instance = new(nil, nil, nil, nil, true) begin @@ -644,8 +646,8 @@ def validate_vread_reply(resource, klass) attr_accessor :profiles_failed def test_resources_against_profile(resource_type, specified_profile = nil) - @profiles_encountered ||= [] - @profiles_failed ||= {} + @profiles_encountered ||= Set.new + @profiles_failed ||= Hash.new { |hash, key| hash[key] = [] } all_errors = [] @@ -665,12 +667,10 @@ def test_resources_against_profile(resource_type, specified_profile = nil) end if p @profiles_encountered << p.url - @profiles_encountered.uniq! errors = p.validate_resource(resource) @test_warnings.concat(p.warnings.reject(&:empty?)) unless errors.empty? errors.map! { |e| "#{resource_type}/#{resource_id}: #{e}" } - @profiles_failed[p.url] = [] unless @profiles_failed[p.url] @profiles_failed[p.url].concat(errors) end all_errors.concat(errors) @@ -732,11 +732,9 @@ def check_resource_against_profile(resource, resource_type, specified_profile = end if p @profiles_encountered << p.url - @profiles_encountered.uniq! errors = p.validate_resource(resource) unless errors.empty? errors.map! { |e| "#{resource_type}/#{resource.id}: #{e}" } - @profiles_failed[p.url] = [] unless @profiles_failed[p.url] @profiles_failed[p.url].concat(errors) end else diff --git a/lib/app/utils/validation.rb b/lib/app/utils/validation.rb index 7be1205f5..ee58a3fae 100644 --- a/lib/app/utils/validation.rb +++ b/lib/app/utils/validation.rb @@ -28,7 +28,7 @@ def self.get_resource(json, version) DEFINITIONS[resource.url] = resource if resource.resourceType == 'StructureDefinition' profiled_type = resource.snapshot.element.first.path # will this always be the first? - RESOURCES[version][profiled_type] = [] unless RESOURCES[version][profiled_type] + RESOURCES[version][profiled_type] ||= [] RESOURCES[version][profiled_type] << resource elsif resource.resourceType == 'ValueSet' VALUESETS[resource.url] = resource @@ -56,11 +56,12 @@ def self.get_resource(json, version) def self.guess_profile(resource, version) # if the profile is given, we don't need to guess - if resource&.meta&.profile && !resource&.meta&.profile&.empty? + if resource&.meta&.profile&.present? resource.meta.profile.each do |uri| return DEFINITIONS[uri] if DEFINITIONS[uri] end end + if version == :dstu2 guess_dstu2_profile(resource) elsif version == :stu3 @@ -71,69 +72,68 @@ def self.guess_profile(resource, version) end def self.guess_dstu2_profile(resource) - if resource - candidates = RESOURCES[:dstu2][resource.resourceType] - if candidates && !candidates.empty? - # Special cases where there are multiple profiles per Resource type - if resource.resourceType == 'Observation' - if resource.code&.coding && resource.code.coding.any? { |coding| coding.code == '72166-2' } - return DEFINITIONS[ARGONAUT_URIS[:smoking_status]] - elsif resource.category&.coding && resource.category.coding.any? { |coding| coding.code == 'laboratory' } - return DEFINITIONS[ARGONAUT_URIS[:observation_results]] - elsif resource.category&.coding && resource.category.coding.any? { |coding| coding.code == 'vital-signs' } - return DEFINITIONS[ARGONAUT_URIS[:vital_signs]] - end - elsif resource.resourceType == 'CarePlan' - if resource.category.any? { |category| category.coding.any? { |coding| coding.code == 'careteam' } } - return DEFINITIONS[ARGONAUT_URIS[:care_team]] - else - return DEFINITIONS[ARGONAUT_URIS[:care_plan]] - end - end - # Otherwise, guess the first profile that matches on resource type - return candidates.first + return if resource.blank? + + candidates = RESOURCES[:dstu2][resource.resourceType] + return if candidates.blank? + + # Special cases where there are multiple profiles per Resource type + if resource.resourceType == 'Observation' + if resource&.code&.coding&.any? { |coding| coding&.code == '72166-2' } + return DEFINITIONS[ARGONAUT_URIS[:smoking_status]] + elsif resource&.category&.coding&.any? { |coding| coding&.code == 'laboratory' } + return DEFINITIONS[ARGONAUT_URIS[:observation_results]] + elsif resource&.category&.coding&.any? { |coding| coding&.code == 'vital-signs' } + return DEFINITIONS[ARGONAUT_URIS[:vital_signs]] + end + elsif resource.resourceType == 'CarePlan' + if resource&.category&.any? { |category| category&.coding&.any? { |coding| coding&.code == 'careteam' } } + return DEFINITIONS[ARGONAUT_URIS[:care_team]] + else + return DEFINITIONS[ARGONAUT_URIS[:care_plan]] end end - nil + + # Otherwise, guess the first profile that matches on resource type + candidates.first end def self.guess_stu3_profile(resource) - if resource - candidates = RESOURCES[:stu3][resource.resourceType] - if candidates && !candidates.empty? - # Special cases where there are multiple profiles per Resource type - if resource.resourceType == 'ExplanationOfBenefit' - if resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'CARRIER' } - return DEFINITIONS[BLUEBUTTON_URIS[:carrier]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'DME' } - return DEFINITIONS[BLUEBUTTON_URIS[:dme]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'HHA' } - return DEFINITIONS[BLUEBUTTON_URIS[:hha]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'HOSPICE' } - return DEFINITIONS[BLUEBUTTON_URIS[:hospice]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'INPATIENT' } - return DEFINITIONS[BLUEBUTTON_URIS[:inpatient]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'OUTPATIENT' } - return DEFINITIONS[BLUEBUTTON_URIS[:outpatient]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'PDE' } - return DEFINITIONS[BLUEBUTTON_URIS[:pde]] - elsif resource.type&.coding && resource.type.coding.any? { |coding| coding.code == 'SNF' } - return DEFINITIONS[BLUEBUTTON_URIS[:snf]] - end - end - # Otherwise, guess the first profile that matches on resource type - return candidates.first + return if resource.blank? + + candidates = RESOURCES[:stu3][resource.resourceType] + return if candidates.blank? + + # Special cases where there are multiple profiles per Resource type + if resource.resourceType == 'ExplanationOfBenefit' + if resource&.type&.coding&.any? { |coding| coding.code == 'CARRIER' } + return DEFINITIONS[BLUEBUTTON_URIS[:carrier]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'DME' } + return DEFINITIONS[BLUEBUTTON_URIS[:dme]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'HHA' } + return DEFINITIONS[BLUEBUTTON_URIS[:hha]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'HOSPICE' } + return DEFINITIONS[BLUEBUTTON_URIS[:hospice]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'INPATIENT' } + return DEFINITIONS[BLUEBUTTON_URIS[:inpatient]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'OUTPATIENT' } + return DEFINITIONS[BLUEBUTTON_URIS[:outpatient]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'PDE' } + return DEFINITIONS[BLUEBUTTON_URIS[:pde]] + elsif resource&.type&.coding&.any? { |coding| coding.code == 'SNF' } + return DEFINITIONS[BLUEBUTTON_URIS[:snf]] end end - nil + + # Otherwise, guess the first profile that matches on resource type + candidates.first end def self.guess_r4_profile(resource) - if resource - candidates = RESOURCES[:r4][resource.resourceType] - return candidates.first if candidates && !candidates.empty? - end - nil + return if resource.blank? + + candidates = RESOURCES[:r4][resource.resourceType] + return candidates.first if candidates.present? end end end diff --git a/test/unit/argonaut_fixture_test.rb b/test/unit/argonaut_fixture_test.rb index 62f592d94..806b4aca4 100644 --- a/test/unit/argonaut_fixture_test.rb +++ b/test/unit/argonaut_fixture_test.rb @@ -22,8 +22,8 @@ def test_invalid_fixture_fails_against_profiles errors = [] @invalid.entry.each do |entry| profile = Inferno::ValidationUtil.guess_profile(entry.resource, :dstu2) - errors += profile.validate_resource(entry.resource) unless profile.nil? + errors += profile.validate_resource(entry.resource) if profile.present? end - assert !errors.empty?, 'Expected numerous validation errors.' + assert errors.present?, 'Expected numerous validation errors.' end end From 7d64b083fbb12c35d28d76140290fe911192403f Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Wed, 19 Jun 2019 12:30:01 -0400 Subject: [PATCH 25/89] refactor sequence_base --- lib/app/endpoint/home.rb | 4 +- lib/app/models/sequence_result.rb | 40 ++++++++++ lib/app/models/testing_instance.rb | 10 +++ lib/app/sequence_base.rb | 114 +++++++++-------------------- 4 files changed, 86 insertions(+), 82 deletions(-) diff --git a/lib/app/endpoint/home.rb b/lib/app/endpoint/home.rb index 9a4f29ade..d8b954b63 100644 --- a/lib/app/endpoint/home.rb +++ b/lib/app/endpoint/home.rb @@ -129,7 +129,7 @@ class Home < Endpoint out << js_hide_wait_modal out << js_show_test_modal - count = sequence_result.test_results.length + count = sequence_result.result_count submitted_test_cases_count = sequence_result.next_test_cases.split(',') total_tests = submitted_test_cases_count.reduce(first_test_count) do |total, set| @@ -361,7 +361,7 @@ class Home < Endpoint x.sequence_name == sequence_result.name end - current_test_count = sequence_result.test_results.length + current_test_count = sequence_result.result_count sequence.tests.each_with_index do |test, index| next if index < current_test_count diff --git a/lib/app/models/sequence_result.rb b/lib/app/models/sequence_result.rb index 5a63b8bb6..453528384 100644 --- a/lib/app/models/sequence_result.rb +++ b/lib/app/models/sequence_result.rb @@ -52,6 +52,46 @@ def reset! 'optional_total' ].each { |field| send("#{field}=", 0) } end + + def result_count + test_results.length + end + + def update_result_counts + test_results.each do |result| + if result.required + self.required_total += 1 + else + self.optional_total += 1 + end + case result.result + when ResultStatuses::PASS + if result.required + self.required_passed += 1 + else + self.optional_passed += 1 + end + when ResultStatuses::TODO + self.todo_count += 1 + when ResultStatuses::FAIL + if result.required + self.result = result.result unless error? + end + when ResultStatuses::ERROR + if result.required + self.error_count += 1 + self.result = result.result + end + when ResultStatuses::SKIP + if result.required + self.skip_count += 1 + self.result = result.result if pass? + end + when ResultStatuses::WAIT + self.result = result.result + end + end + end end end end diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index e0346ecdd..fa2722c70 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -236,6 +236,16 @@ def post_resource_references(resource_type: nil, resource_id: nil) reload end + def versioned_conformance_class + if fhir_version == 'dstu2' + FHIR::DSTU2::Conformance + elsif fhir_version == 'stu3' + FHIR::STU3::CapabilityStatement + else + FHIR::CapabilityStatement + end + end + private def interaction_supported?(capabilities, interaction_code) diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 9cf111948..1e04c532d 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -9,6 +9,7 @@ require_relative 'utils/walk' require_relative 'utils/web_driver' require_relative 'utils/terminology' +require_relative 'utils/result_statuses' require 'bloomer' require 'bloomer/msgpackable' @@ -23,8 +24,6 @@ class SequenceBase include SkipHelpers include Inferno::WebDriver - STATUS = { pass: 'pass', fail: 'fail', error: 'error', todo: 'todo', wait: 'wait', skip: 'skip' }.freeze - @@test_index = 0 @@group = {} @@ -43,6 +42,9 @@ class SequenceBase @@test_id_prefixes = {} + delegate :versioned_resource_class, to: :@client + delegate :versioned_conformance_class, to: :@instance + def initialize(instance, client, disable_tls_tests = false, sequence_result = nil, metadata_only = false) @client = client @instance = instance @@ -60,7 +62,7 @@ def resume(request = nil, headers = nil, params = nil, fail_message = nil, &bloc @sequence_result.test_results.last.pass! if fail_message.present? - @sequence_result.test_results.last.result = STATUS[:fail] + @sequence_result.test_results.last.fail! @sequence_result.test_results.last.message = fail_message end @@ -88,7 +90,7 @@ def start(test_set_id = nil, test_case_id = nil, &block) if @sequence_result.nil? @sequence_result = Models::SequenceResult.new( name: sequence_name, - result: STATUS[:pass], + result: ResultStatuses::PASS, testing_instance: @instance, required: !optional?, test_set_id: test_set_id, @@ -98,7 +100,7 @@ def start(test_set_id = nil, test_case_id = nil, &block) @sequence_result.save! end - start_at = @sequence_result.test_results.length + start_at = @sequence_result.result_count load_input_params(sequence_name) @@ -109,14 +111,15 @@ def start(test_set_id = nil, test_case_id = nil, &block) run_tests(methods, &block) update_output(sequence_name, output_results) - @sequence_result.output_results = output_results.to_json if output_results.present? - @sequence_result.reset! - @sequence_result.pass! + @sequence_result.tap do |result| + result.output_results = output_results.to_json if output_results.present? - update_result_counts + result.reset! + result.pass! - @sequence_result + result.update_result_counts + end end def load_input_params(sequence_name) @@ -199,42 +202,6 @@ def run_tests(methods) end end - def update_result_counts - @sequence_result.test_results.each do |result| - if result.required - @sequence_result.required_total += 1 - else - @sequence_result.optional_total += 1 - end - case result.result - when STATUS[:pass] - if result.required - @sequence_result.required_passed += 1 - else - @sequence_result.optional_passed += 1 - end - when STATUS[:todo] - @sequence_result.todo_count += 1 - when STATUS[:fail] - if result.required - @sequence_result.result = result.result unless @sequence_result.error? - end - when STATUS[:error] - if result.required - @sequence_result.error_count += 1 - @sequence_result.result = result.result - end - when STATUS[:skip] - if result.required - @sequence_result.skip_count += 1 - @sequence_result.result = result.result if @sequence_result.pass? - end - when STATUS[:wait] - @sequence_result.result = result.result - end - end - end - def self.test_count new(nil, nil).test_count end @@ -256,8 +223,6 @@ def self.sequence_name name.demodulize end - attr_reader :sequence_result - def self.title(title = nil) @@titles[sequence_name] = title unless title.nil? @@titles[sequence_name] || sequence_name @@ -413,7 +378,7 @@ def self.test(name, &block) description: current_test[:description], url: current_test[:url], versions: versions.join(','), - result: STATUS[:pass], + result: ResultStatuses::PASS, test_index: test_index ) begin @@ -539,12 +504,8 @@ def get_resource_by_params(klass, params = {}) @client.search(klass, options) end - def versioned_resource_class(klass) - @client.versioned_resource_class klass - end - - def check_sort_order(entries) - relevant_entries = entries.reject { |x| x.request.try(:local_method) == 'DELETE' } + def validate_sort_order(entries) + relevant_entries = entries.reject { |entry| entry.request&.local_method == 'DELETE' } begin relevant_entries.map!(&:resource).map!(&:meta).compact rescue StandardError @@ -552,13 +513,16 @@ def check_sort_order(entries) end relevant_entries.each_cons(2) do |left, right| - if !left.versionId.nil? && !right.versionId.nil? - assert (left.versionId > right.versionId), 'Result contains entries in the wrong order.' - elsif !left.lastUpdated.nil? && !right.lastUpdated.nil? - assert (left.lastUpdated >= right.lastUpdated), 'Result contains entries in the wrong order.' - else - raise AssertionException, 'Unable to determine if entries are in the correct order -- no meta.versionId or meta.lastUpdated' - end + left_version, right_version = + if left.versionId.present? && right.versionId.present? + [left.versionId, right.versionId] + elsif left.lastUpdated.present? && right.lastUpdated.present? + [left.lastUpdated, right.lastUpdated] + else + raise AssertionException, 'Unable to determine if entries are in the correct order -- no meta.versionId or meta.lastUpdated' + end + + assert (left_version > right_version), 'Result contains entries in the wrong order.' end end @@ -571,10 +535,10 @@ def validate_search_reply(klass, reply, search_params) assert_bundle_response(reply) entries = reply.resource.entry.select { |entry| entry.resource.class == klass } - assert !entries.empty?, 'No resources of this type were returned' + assert entries.present?, 'No resources of this type were returned' if klass == versioned_resource_class('Patient') - assert !reply.resource.get_by_id(@instance.patient_id).nil?, 'Server returned nil patient' + assert reply.resource.get_by_id(@instance.patient_id).present?, 'Server returned nil patient' assert reply.resource.get_by_id(@instance.patient_id).equals?(@patient, ['_id', 'text', 'meta', 'lastUpdated']), 'Server returned wrong patient' end @@ -591,18 +555,18 @@ def validate_search_reply(klass, reply, search_params) end def save_resource_ids_in_bundle(klass, reply) - return if reply.try(:resource).try(:entry).nil? + return if reply&.resource&.entry.blank? entries = reply.resource.entry.select { |entry| entry.resource.class == klass } entries.each do |entry| - @instance.post_resource_references(resource_type: klass.name.split(':').last, + @instance.post_resource_references(resource_type: klass.name.demodulize, resource_id: entry.resource.id) end end def validate_read_reply(resource, klass) - assert !resource.nil?, "No #{klass.name.split(':').last} resources available from search." + assert !resource.nil?, "No #{klass.name.demodulize} resources available from search." if resource.is_a? FHIR::DSTU2::Reference read_response = resource.read else @@ -617,7 +581,7 @@ def validate_read_reply(resource, klass) end def validate_history_reply(resource, klass) - assert !resource.nil?, "No #{klass.name.split(':').last} resources available from search." + assert !resource.nil?, "No #{klass.name.demodulize} resources available from search." id = resource.try(:id) assert !id.nil?, "#{klass} id not returned" history_response = @client.resource_instance_history(klass, id) @@ -627,11 +591,11 @@ def validate_history_reply(resource, klass) entries = history_response.try(:resource).try(:entry) assert entries, 'No bundle entries returned' assert entries.try(:length).positive?, 'No resources of this type were returned' - check_sort_order entries + validate_sort_order entries end def validate_vread_reply(resource, klass) - assert !resource.nil?, "No #{klass.name.split(':').last} resources available from search." + assert !resource.nil?, "No #{klass.name.demodulize} resources available from search." id = resource.try(:id) assert !id.nil?, "#{klass} id not returned" version_id = resource.try(:meta).try(:versionId) @@ -712,16 +676,6 @@ def validate_reference_resolutions(resource) assert(problems.empty?, problems.join("
\n")) end - def versioned_conformance_class - if @instance.fhir_version == 'dstu2' - FHIR::DSTU2::Conformance - elsif @instance.fhir_version == 'stu3' - FHIR::STU3::CapabilityStatement - else - FHIR::CapabilityStatement - end - end - def check_resource_against_profile(resource, resource_type, specified_profile = nil) assert resource.is_a?("FHIR::DSTU2::#{resource_type}".constantize), "Expected resource to be of type #{resource_type}" From 88986855342187a0d6f60aed1ec00f913c0c3d01 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Mon, 24 Jun 2019 12:24:34 -0400 Subject: [PATCH 26/89] refactor TestingInstance#save_resource_reference --- lib/app/models/testing_instance.rb | 16 +++++++++------- lib/app/sequence_base.rb | 13 ++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index fa2722c70..354ac11f3 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -182,7 +182,7 @@ def save_supported_resources(conformance) conformance .rest.first.resource .select { |resource| resources.include? resource.type } - .each_with_object({}) { |resource, hash| hash[resource.type] = resource } + .index_by(&:type) supported_resources.each(&:destroy) save! @@ -225,12 +225,14 @@ def conformance_supported?(resource, methods = []) end end - def post_resource_references(resource_type: nil, resource_id: nil) - resource_references.each do |ref| - ref.destroy if (ref.resource_type == resource_type) && (ref.resource_id == resource_id) - end - resource_references << ResourceReference.new(resource_type: resource_type, - resource_id: resource_id) + def save_resource_reference(type, id) + resource_references + .select { |ref| (ref.resource_type == type) && (ref.resource_id == id) } + .each(&:destroy) + + new_reference = ResourceReference.new(resource_type: type, resource_id: id) + resource_references << new_reference + save! # Ensure the instance resource references are accurate reload diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 1e04c532d..451995c03 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -555,14 +555,13 @@ def validate_search_reply(klass, reply, search_params) end def save_resource_ids_in_bundle(klass, reply) - return if reply&.resource&.entry.blank? + return if reply&.resource&.entry&.blank? - entries = reply.resource.entry.select { |entry| entry.resource.class == klass } - - entries.each do |entry| - @instance.post_resource_references(resource_type: klass.name.demodulize, - resource_id: entry.resource.id) - end + reply.resource.entry + .select { |entry| entry.resource.class == klass } + .each do |entry| + @instance.save_resource_reference(klass.name.demodulize, entry.resource.id) + end end def validate_read_reply(resource, klass) From d432dea9d81f977a4ddfe59d867a661d06fcdd66 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Mon, 24 Jun 2019 12:32:16 -0400 Subject: [PATCH 27/89] move #save_resource_ids_in_bundle to TestingInstance --- lib/app/models/testing_instance.rb | 10 ++++++++++ lib/app/sequence_base.rb | 11 +---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index 354ac11f3..9c84fc149 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -238,6 +238,16 @@ def save_resource_reference(type, id) reload end + def save_resource_ids_in_bundle(klass, reply) + return if reply&.resource&.entry&.blank? + + reply.resource.entry + .select { |entry| entry.resource.class == klass } + .each do |entry| + save_resource_reference(klass.name.demodulize, entry.resource.id) + end + end + def versioned_conformance_class if fhir_version == 'dstu2' FHIR::DSTU2::Conformance diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index 451995c03..d0a54615d 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -44,6 +44,7 @@ class SequenceBase delegate :versioned_resource_class, to: :@client delegate :versioned_conformance_class, to: :@instance + delegate :save_resource_ids_in_bundle, to: :@instance def initialize(instance, client, disable_tls_tests = false, sequence_result = nil, metadata_only = false) @client = client @@ -554,16 +555,6 @@ def validate_search_reply(klass, reply, search_params) end end - def save_resource_ids_in_bundle(klass, reply) - return if reply&.resource&.entry&.blank? - - reply.resource.entry - .select { |entry| entry.resource.class == klass } - .each do |entry| - @instance.save_resource_reference(klass.name.demodulize, entry.resource.id) - end - end - def validate_read_reply(resource, klass) assert !resource.nil?, "No #{klass.name.demodulize} resources available from search." if resource.is_a? FHIR::DSTU2::Reference From 8892f2b228099fde032ae1e14246d50724a89c57 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Wed, 26 Jun 2019 09:59:29 -0400 Subject: [PATCH 28/89] fix careteam/careplan issue --- lib/app/models/resource_reference.rb | 1 + lib/app/models/testing_instance.rb | 12 ++- .../argonaut/argonaut_careteam_sequence.rb | 12 ++- .../argonaut/argonaut_observation_sequence.rb | 13 ++- .../argonaut_smoking_status_sequence.rb | 10 +- ...gonaut_vital_signs_observation_sequence.rb | 10 +- lib/app/sequence_base.rb | 99 +++++++++++++------ .../argonaut_careteam_sequence_test.rb | 45 +++++++++ 8 files changed, 152 insertions(+), 50 deletions(-) diff --git a/lib/app/models/resource_reference.rb b/lib/app/models/resource_reference.rb index f8b03f5b2..39996dc54 100644 --- a/lib/app/models/resource_reference.rb +++ b/lib/app/models/resource_reference.rb @@ -7,6 +7,7 @@ class ResourceReference property :id, String, key: true, default: proc { SecureRandom.uuid } property :resource_type, String property :resource_id, String + property :profile, String belongs_to :testing_instance end diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index 9c84fc149..882a733f3 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -225,12 +225,16 @@ def conformance_supported?(resource, methods = []) end end - def save_resource_reference(type, id) + def save_resource_reference(type, id, profile = nil) resource_references .select { |ref| (ref.resource_type == type) && (ref.resource_id == id) } .each(&:destroy) - new_reference = ResourceReference.new(resource_type: type, resource_id: id) + new_reference = ResourceReference.new( + resource_type: type, + resource_id: id, + profile: profile + ) resource_references << new_reference save! @@ -238,13 +242,13 @@ def save_resource_reference(type, id) reload end - def save_resource_ids_in_bundle(klass, reply) + def save_resource_ids_in_bundle(klass, reply, profile = nil) return if reply&.resource&.entry&.blank? reply.resource.entry .select { |entry| entry.resource.class == klass } .each do |entry| - save_resource_reference(klass.name.demodulize, entry.resource.id) + save_resource_reference(klass.name.demodulize, entry.resource.id, profile) end end diff --git a/lib/app/modules/argonaut/argonaut_careteam_sequence.rb b/lib/app/modules/argonaut/argonaut_careteam_sequence.rb index e3e6fe187..d5dadf8b6 100644 --- a/lib/app/modules/argonaut/argonaut_careteam_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_careteam_sequence.rb @@ -3,6 +3,8 @@ module Inferno module Sequence class ArgonautCareTeamSequence < SequenceBase + PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:care_team] + group 'Argonaut Profile Conformance' title 'Care Team' @@ -73,10 +75,10 @@ def validate_resource_item(resource, property, value) resource_count = reply.try(:resource).try(:entry).try(:length) || 0 @resources_found = resource_count.positive? - skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found + skip_unless @resources_found, 'No resources appear to be available for this patient. Please use patients with more information.' @careteam = reply.try(:resource).try(:entry).try(:first).try(:resource) validate_search_reply(versioned_resource_class('CarePlan'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('CarePlan'), reply) + save_resource_ids_in_bundle(versioned_resource_class('CarePlan'), reply, PROFILE) end test 'CareTeam resources associated with Patient conform to Argonaut profiles' do @@ -88,9 +90,9 @@ def validate_resource_item(resource, property, value) ) versions :dstu2 end - test_resources_against_profile('CarePlan', Inferno::ValidationUtil::ARGONAUT_URIS[:care_team]) - skip_unless @profiles_encountered.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:care_team]), 'No CareTeams found.' - assert !@profiles_failed.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:care_team]), "CareTeams failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:care_team]]}" + test_resources_against_profile('CarePlan', PROFILE) + skip_unless @profiles_encountered.include?(PROFILE), 'No CareTeams found.' + assert !@profiles_failed.include?(PROFILE), "CareTeams failed validation.
#{@profiles_failed[PROFILE]}" end test 'All references can be resolved' do diff --git a/lib/app/modules/argonaut/argonaut_observation_sequence.rb b/lib/app/modules/argonaut/argonaut_observation_sequence.rb index 41ab67e7d..d20abc6c4 100644 --- a/lib/app/modules/argonaut/argonaut_observation_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_observation_sequence.rb @@ -3,6 +3,9 @@ module Inferno module Sequence class ArgonautObservationSequence < SequenceBase + SMOKING_STATUS_PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status] + OBSERVATION_RESULTS_PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results] + title 'Observation' description 'Verify that Observation resources on the FHIR server follow the Argonaut Data Query Implementation Guide' @@ -92,7 +95,7 @@ def validate_resource_item(resource, property, value) @observationresults = reply.try(:resource).try(:entry).try(:first).try(:resource) validate_search_reply(versioned_resource_class('Observation'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) + save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply, OBSERVATION_RESULTS_PROFILE) end test 'Server returns expected results from Observation Results search by patient + category + date' do @@ -198,7 +201,7 @@ def validate_resource_item(resource, property, value) search_params = { patient: @instance.patient_id, code: '72166-2' } reply = get_resource_by_params(versioned_resource_class('Observation'), search_params) validate_search_reply(versioned_resource_class('Observation'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) + save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply, SMOKING_STATUS_PROFILE) end test 'Observation read resource supported' do @@ -261,9 +264,9 @@ def validate_resource_item(resource, property, value) versions :dstu2 end - test_resources_against_profile('Observation', Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]) - skip_unless @profiles_encountered.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]), 'No Observation Results found.' - assert !@profiles_failed.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]), "Observation Results failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]]}" + test_resources_against_profile('Observation', OBSERVATION_RESULTS_PROFILE) + skip_unless @profiles_encountered.include?(OBSERVATION_RESULTS_PROFILE), 'No Observation Results found.' + assert !@profiles_failed.include?(OBSERVATION_RESULTS_PROFILE), "Observation Results failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]]}" end test 'All references can be resolved' do diff --git a/lib/app/modules/argonaut/argonaut_smoking_status_sequence.rb b/lib/app/modules/argonaut/argonaut_smoking_status_sequence.rb index 3d948fa33..908a22fd4 100644 --- a/lib/app/modules/argonaut/argonaut_smoking_status_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_smoking_status_sequence.rb @@ -3,6 +3,8 @@ module Inferno module Sequence class ArgonautSmokingStatusSequence < SequenceBase + PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status] + group 'Argonaut Profile Conformance' title 'Smoking Status' @@ -84,7 +86,7 @@ def validate_resource_item(resource, property, value) skip 'No resources appear to be available for this patient. Please use patients with more information.' unless @resources_found validate_search_reply(versioned_resource_class('Observation'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) + save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply, PROFILE) end test 'Smoking Status resources associated with Patient conform to Argonaut profiles' do @@ -96,9 +98,9 @@ def validate_resource_item(resource, property, value) ) versions :dstu2 end - test_resources_against_profile('Observation', Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status]) - skip_unless @profiles_encountered.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status]), 'No Smoking Status Observations found.' - assert !@profiles_failed.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status]), "Smoking Status Observations failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:smoking_status]]}" + test_resources_against_profile('Observation', PROFILE) + skip_unless @profiles_encountered.include?(PROFILE), 'No Smoking Status Observations found.' + assert !@profiles_failed.include?(PROFILE), "Smoking Status Observations failed validation.
#{@profiles_failed[PROFILE]}" end end end diff --git a/lib/app/modules/argonaut/argonaut_vital_signs_observation_sequence.rb b/lib/app/modules/argonaut/argonaut_vital_signs_observation_sequence.rb index ff2d925d0..588d44db3 100644 --- a/lib/app/modules/argonaut/argonaut_vital_signs_observation_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_vital_signs_observation_sequence.rb @@ -3,6 +3,8 @@ module Inferno module Sequence class ArgonautVitalSignsSequence < SequenceBase + PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:vital_signs] + title 'Vital Signs' description 'Verify that Vital Signs are collected on the FHIR server according to the Argonaut Data Query Implementation Guide' @@ -92,7 +94,7 @@ def validate_resource_item(resource, property, value) @vitalsigns = reply.try(:resource).try(:entry).try(:first).try(:resource) validate_search_reply(versioned_resource_class('Observation'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply) + save_resource_ids_in_bundle(versioned_resource_class('Observation'), reply, PROFILE) end test 'Server returns expected results from Vital Signs search by patient + category + date' do @@ -170,9 +172,9 @@ def validate_resource_item(resource, property, value) versions :dstu2 end - test_resources_against_profile('Observation', Inferno::ValidationUtil::ARGONAUT_URIS[:vital_signs]) - skip_unless @profiles_encountered.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:vital_signs]), 'No Vital Sign Observations found.' - assert !@profiles_failed.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:vital_signs]), "Vital Sign Observations failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:vital_signs]]}" + test_resources_against_profile('Observation', PROFILE) + skip_unless @profiles_encountered.include?(PROFILE), 'No Vital Sign Observations found.' + assert !@profiles_failed.include?(PROFILE), "Vital Sign Observations failed validation.
#{@profiles_failed[PROFILE]}" end end end diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index d0a54615d..b75e62cf9 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -42,6 +42,9 @@ class SequenceBase @@test_id_prefixes = {} + attr_accessor :profiles_encountered + attr_accessor :profiles_failed + delegate :versioned_resource_class, to: :@client delegate :versioned_conformance_class, to: :@instance delegate :save_resource_ids_in_bundle, to: :@instance @@ -479,6 +482,10 @@ def skip_unless(test, message = '', details = nil) raise SkipException.new message, details unless test end + def skip_if(test, message = '', details = nil) + raise SkipException.new message, details if test + end + def wait_at_endpoint(endpoint) raise WaitException, endpoint end @@ -596,47 +603,83 @@ def validate_vread_reply(resource, klass) assert vread_response.resource.is_a?(klass), "Expected resource to be valid #{klass}" end - attr_accessor :profiles_encountered - attr_accessor :profiles_failed + def validate_resource(resource_type, resource, profile) + errors = profile.validate_resource(resource) + @test_warnings.concat(profile.warnings.reject(&:empty?)) + errors.map! { |e| "#{resource_type}/#{resource.id}: #{e}" } + @profiles_failed[profile.url].concat(errors) unless errors.empty? + errors + end + + def fetch_resource(resource_type, resource_id) + response = @client.read(versioned_resource_class(resource_type), resource_id) + assert_response_ok response + resource = response.resource + assert resource.is_a?(versioned_resource_class(resource_type)), "Expected resource to be of type #{resource_type}" + resource + end + + def test_resources(resource_type) + references = @instance.resource_references.all(resource_type: resource_type) + skip_if( + references.empty?, + "Skip profile validation since no #{resource_type} resources found for Patient." + ) + + errors = references.map(&:resource_id).flat_map do |resource_id| + resource = fetch_resource(resource_type, resource_id) + p = Inferno::ValidationUtil.guess_profile(resource, @instance.fhir_version.to_sym) + if p + @profiles_encountered << p.url + validate_resource(resource_type, resource, p) + else + warn { assert false, 'No profiles found for this Resource' } + resource.validate + end + end + # TODO + # bundle = client.next_bundle + assert(errors.empty?, errors.join("
\n")) + end def test_resources_against_profile(resource_type, specified_profile = nil) @profiles_encountered ||= Set.new @profiles_failed ||= Hash.new { |hash, key| hash[key] = [] } - all_errors = [] + return test_resources(resource_type) if specified_profile.blank? - resources = @instance.resource_references.select { |r| r.resource_type == resource_type } - skip("Skip profile validation since no #{resource_type} resources found for Patient.") if resources.empty? + profile = Inferno::ValidationUtil::DEFINITIONS[specified_profile] + skip_if( + profile.blank?, + "Skip profile validation since profile #{specified_profile} is unknown." + ) - @instance.resource_references.select { |r| r.resource_type == resource_type }.map(&:resource_id).each do |resource_id| - resource_response = @client.read(versioned_resource_class(resource_type), resource_id) - assert_response_ok resource_response - resource = resource_response.resource - assert resource.is_a?(versioned_resource_class(resource_type)), "Expected resource to be of type #{resource_type}" - - p = Inferno::ValidationUtil.guess_profile(resource, @instance.fhir_version.to_sym) - if specified_profile - warn { assert false, "No #{specified_profile} found for this Resource" } - next unless p.url == specified_profile - end - if p - @profiles_encountered << p.url - errors = p.validate_resource(resource) - @test_warnings.concat(p.warnings.reject(&:empty?)) - unless errors.empty? - errors.map! { |e| "#{resource_type}/#{resource_id}: #{e}" } - @profiles_failed[p.url].concat(errors) + references = @instance.resource_references.all(profile: specified_profile) + resources = + if references.present? + references.map(&:resource_id).map do |resource_id| + fetch_resource(resource_type, resource_id) end - all_errors.concat(errors) else - warn { assert false, 'No profiles found for this Resource' } - errors = resource.validate - all_errors.concat(errors.values) + @instance.resource_references + .all(resource_type: resource_type) + .map { |reference| fetch_resource(resource_type, reference.resource_id) } + .select { |resource| resource.meta&.profile&.include? specified_profile } end + + skip_if( + resources.blank?, + "Skip profile validation since no #{resource_type} resources conforming to the #{specified_profile} profile found for Patient." + ) + + @profiles_encountered << profile.url + + errors = resources.flat_map do |resource| + validate_resource(resource_type, resource, profile) end # TODO # bundle = client.next_bundle - assert(all_errors.empty?, all_errors.join("
\n")) + assert(errors.empty?, errors.join("
\n")) end def validate_reference_resolutions(resource) diff --git a/test/sequence/argonaut/argonaut_careteam_sequence_test.rb b/test/sequence/argonaut/argonaut_careteam_sequence_test.rb index 89dfc6f33..511c04533 100644 --- a/test/sequence/argonaut/argonaut_careteam_sequence_test.rb +++ b/test/sequence/argonaut/argonaut_careteam_sequence_test.rb @@ -108,6 +108,37 @@ def full_sequence_stubs headers: { content_type: 'application/json+fhir; charset=UTF-8' }) end + def wrong_resource_stubs + # Return the wrong profile + uri_template = Addressable::Template.new "http://www.example.com/#{@resource_type}{?patient,category}" + wrong_resource = FHIR::DSTU2.from_contents(load_fixture('care_plan')) + + wrong_resource_bundle = wrap_resources_in_bundle(wrong_resource) + + wrong_resource_bundle.entry.each do |entry| + entry.resource.meta = FHIR::DSTU2::Meta.new unless entry.resource.meta + entry.resource.meta.versionId = '1' + end + + stub_request(:get, uri_template) + .with(headers: @request_headers) + .to_return( + status: 200, body: wrong_resource_bundle.to_json, headers: @response_headers + ) + + stub_request(:get, "http://www.example.com/#{@resource_type}/#{@resource.id}") + .with(headers: @request_headers) + .to_return(status: 200, + body: wrong_resource.to_json, + headers: { content_type: 'application/json+fhir; charset=UTF-8' }) + + stub_request(:get, %r{example.com/Patient/}) + .with(headers: { 'Authorization' => "Bearer #{@instance.token}" }) + .to_return(status: 200, + body: @patient_resource.to_json, + headers: { content_type: 'application/json+fhir; charset=UTF-8' }) + end + def test_all_pass full_sequence_stubs @@ -121,4 +152,18 @@ def test_all_pass assert sequence_result.pass?, "The sequence should be marked as pass. #{sequence_result.result}" assert sequence_result.test_results.all? { |r| r.test_warnings.empty? }, 'There should not be any warnings.' end + + # Return a careplan profiled resource even though we are asking for a careteam profile + # This should have at least one failure + def test_fail_on_wrong_profile + wrong_resource_stubs + + sequence_result = @sequence.start + + failures = sequence_result.test_results.select(&:fail?) + + assert failures.present?, 'Expecting at least one failure because we are returning a resource stating conformance to the wrong profile' + assert sequence_result.result == 'fail', "The sequence should be marked as fail. #{sequence_result.result}" + assert sequence_result.test_results.all? { |r| r.test_warnings.empty? }, 'There should not be any warnings.' + end end From a3368819d7adafc7d92d9cc1aa31e37da53f2544 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Mon, 1 Jul 2019 07:56:00 -0400 Subject: [PATCH 29/89] add sequence_result attr_accessor --- lib/app/sequence_base.rb | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/app/sequence_base.rb b/lib/app/sequence_base.rb index b75e62cf9..43f21570b 100644 --- a/lib/app/sequence_base.rb +++ b/lib/app/sequence_base.rb @@ -44,6 +44,7 @@ class SequenceBase attr_accessor :profiles_encountered attr_accessor :profiles_failed + attr_accessor :sequence_result delegate :versioned_resource_class, to: :@client delegate :versioned_conformance_class, to: :@instance @@ -63,15 +64,15 @@ def initialize(instance, client, disable_tls_tests = false, sequence_result = ni def resume(request = nil, headers = nil, params = nil, fail_message = nil, &block) @params = params unless params.nil? - @sequence_result.test_results.last.pass! + sequence_result.test_results.last.pass! if fail_message.present? - @sequence_result.test_results.last.fail! - @sequence_result.test_results.last.message = fail_message + sequence_result.test_results.last.fail! + sequence_result.test_results.last.message = fail_message end unless request.nil? - @sequence_result.test_results.last.request_responses << Models::RequestResponse.new( + sequence_result.test_results.last.request_responses << Models::RequestResponse.new( direction: 'inbound', request_method: request.request_method.downcase, request_url: request.url, @@ -81,18 +82,18 @@ def resume(request = nil, headers = nil, params = nil, fail_message = nil, &bloc ) end - @sequence_result.pass! - @sequence_result.wait_at_endpoint = nil - @sequence_result.redirect_to_url = nil + sequence_result.pass! + sequence_result.wait_at_endpoint = nil + sequence_result.redirect_to_url = nil - @sequence_result.save! + sequence_result.save! start(&block) end def start(test_set_id = nil, test_case_id = nil, &block) - if @sequence_result.nil? - @sequence_result = Models::SequenceResult.new( + if sequence_result.nil? + self.sequence_result = Models::SequenceResult.new( name: sequence_name, result: ResultStatuses::PASS, testing_instance: @instance, @@ -101,10 +102,10 @@ def start(test_set_id = nil, test_case_id = nil, &block) test_case_id: test_case_id, app_version: VERSION ) - @sequence_result.save! + sequence_result.save! end - start_at = @sequence_result.result_count + start_at = sequence_result.result_count load_input_params(sequence_name) @@ -116,7 +117,7 @@ def start(test_set_id = nil, test_case_id = nil, &block) update_output(sequence_name, output_results) - @sequence_result.tap do |result| + sequence_result.tap do |result| result.output_results = output_results.to_json if output_results.present? result.reset! @@ -135,7 +136,7 @@ def load_input_params(sequence_name) input_value = 'none' if input_value.empty? input_parameters[requirement.to_sym] = input_value end - @sequence_result.input_params = input_parameters.to_json + sequence_result.input_params = input_parameters.to_json end def save_output(sequence_name) @@ -196,12 +197,12 @@ def run_tests(methods) yield result if block_given? - @sequence_result.test_results << result + sequence_result.test_results << result next unless result.wait? - @sequence_result.redirect_to_url = result.redirect_to_url - @sequence_result.wait_at_endpoint = result.wait_at_endpoint + sequence_result.redirect_to_url = result.redirect_to_url + sequence_result.wait_at_endpoint = result.wait_at_endpoint break end end From 967a24e4b2d763c76b18c9cbf8c8338a2c3634ca Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Mon, 1 Jul 2019 14:54:21 -0400 Subject: [PATCH 30/89] specify careplan profile --- lib/app/modules/argonaut/argonaut_careplan_sequence.rb | 10 ++++++---- .../modules/argonaut/argonaut_observation_sequence.rb | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/app/modules/argonaut/argonaut_careplan_sequence.rb b/lib/app/modules/argonaut/argonaut_careplan_sequence.rb index 15af8d612..cc9659ee2 100644 --- a/lib/app/modules/argonaut/argonaut_careplan_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_careplan_sequence.rb @@ -3,6 +3,8 @@ module Inferno module Sequence class ArgonautCarePlanSequence < SequenceBase + PROFILE = Inferno::ValidationUtil::ARGONAUT_URIS[:care_plan] + group 'Argonaut Profile Conformance' title 'Care Plan' @@ -102,7 +104,7 @@ def validate_resource_item(resource, property, value) @careplan = reply.try(:resource).try(:entry).try(:first).try(:resource) validate_search_reply(versioned_resource_class('CarePlan'), reply, search_params) - save_resource_ids_in_bundle(versioned_resource_class('CarePlan'), reply) + save_resource_ids_in_bundle(versioned_resource_class('CarePlan'), reply, PROFILE) end test 'Server returns expected results from CarePlan search by patient + category + date' do @@ -228,9 +230,9 @@ def validate_resource_item(resource, property, value) ) versions :dstu2 end - test_resources_against_profile('CarePlan', Inferno::ValidationUtil::ARGONAUT_URIS[:care_plan]) - skip_unless @profiles_encountered.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:care_plan]), 'No CarePlans found.' - assert !@profiles_failed.include?(Inferno::ValidationUtil::ARGONAUT_URIS[:care_plan]), "CarePlans failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:care_plan]]}" + test_resources_against_profile('CarePlan', PROFILE) + skip_unless @profiles_encountered.include?(PROFILE), 'No CarePlans found.' + assert !@profiles_failed.include?(PROFILE), "CarePlans failed validation.
#{@profiles_failed[PROFILE]}" end test 'All references can be resolved' do diff --git a/lib/app/modules/argonaut/argonaut_observation_sequence.rb b/lib/app/modules/argonaut/argonaut_observation_sequence.rb index d20abc6c4..e78f9ac83 100644 --- a/lib/app/modules/argonaut/argonaut_observation_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_observation_sequence.rb @@ -266,7 +266,7 @@ def validate_resource_item(resource, property, value) test_resources_against_profile('Observation', OBSERVATION_RESULTS_PROFILE) skip_unless @profiles_encountered.include?(OBSERVATION_RESULTS_PROFILE), 'No Observation Results found.' - assert !@profiles_failed.include?(OBSERVATION_RESULTS_PROFILE), "Observation Results failed validation.
#{@profiles_failed[Inferno::ValidationUtil::ARGONAUT_URIS[:observation_results]]}" + assert !@profiles_failed.include?(OBSERVATION_RESULTS_PROFILE), "Observation Results failed validation.
#{@profiles_failed[OBSERVATION_RESULTS_PROFILE]}" end test 'All references can be resolved' do From e7bd59d773acba92a65c4969abaa7fa25e378a62 Mon Sep 17 00:00:00 2001 From: hershilpatel <51918208+hershilpatel@users.noreply.github.com> Date: Mon, 1 Jul 2019 15:05:05 -0400 Subject: [PATCH 31/89] Update lib/app/modules/core/capability_statement_sequence.rb Co-Authored-By: Reece Adamson <41651655+radamson@users.noreply.github.com> --- lib/app/modules/core/capability_statement_sequence.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index 638af1ea2..8b2c0eead 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -76,7 +76,8 @@ class CapabilityStatementSequence < SequenceBase id '02' link 'http://www.hl7.org/fhir/directory.cfml' desc %( - Testing that the FHIR client is the same version that was version as the testing instance that was selected. + Checks that the FHIR version of the server matches the FHIR version expected by the tests. + This test will inspect the CapabilityStatement returned by the server to verify the FHIR version of the server. ) end From 9c02380bf7dcafd7b3cdddc2d99550f3e22f40ea Mon Sep 17 00:00:00 2001 From: hershilpatel <51918208+hershilpatel@users.noreply.github.com> Date: Mon, 1 Jul 2019 15:05:18 -0400 Subject: [PATCH 32/89] Update lib/app/modules/core/capability_statement_sequence.rb Co-Authored-By: Reece Adamson <41651655+radamson@users.noreply.github.com> --- lib/app/modules/core/capability_statement_sequence.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index 8b2c0eead..076f22fdf 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -71,7 +71,7 @@ class CapabilityStatementSequence < SequenceBase end end - test 'Test FHIR version' do + test 'FHIR version of the server matches the FHIR version expected by tests' do metadata do id '02' link 'http://www.hl7.org/fhir/directory.cfml' From 5437d7bcc7b0d57920090b269d7cf4a01236e7fb Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Tue, 2 Jul 2019 13:10:07 -0400 Subject: [PATCH 33/89] updated test version to check for nil values, and uppercased the values for the version --- lib/app/modules/core/capability_statement_sequence.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/app/modules/core/capability_statement_sequence.rb b/lib/app/modules/core/capability_statement_sequence.rb index 076f22fdf..de4729dfe 100644 --- a/lib/app/modules/core/capability_statement_sequence.rb +++ b/lib/app/modules/core/capability_statement_sequence.rb @@ -81,8 +81,10 @@ class CapabilityStatementSequence < SequenceBase ) end + pass 'Tests are not version dependent' if @instance.fhir_version.blank? + # @client.detect_version is a symbol - assert_equal(@instance.fhir_version, @client.detect_version.to_s, 'FHIR client version does not match with instance version') + assert_equal(@instance.fhir_version.upcase, @client.detect_version.to_s.upcase, 'FHIR client version does not match with instance version') end test 'FHIR server supports the conformance interaction that defines how it supports resources' do From e69e2058a8125c31f00a85abdffbd8d5b6ddd41f Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Tue, 2 Jul 2019 13:18:37 -0400 Subject: [PATCH 34/89] updated version on Gemfile.lock to be 2.0.2 instead of 1.16.1 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index d1fb44c02..1330df39c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -253,4 +253,4 @@ DEPENDENCIES webmock BUNDLED WITH - 1.16.1 + 2.0.2 From 7abc3fc1906fe5035ff523fa2c3c67a573d0e1e8 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Tue, 2 Jul 2019 14:25:19 -0400 Subject: [PATCH 35/89] Apply patient_id save hotfix to development. --- lib/app/models/testing_instance.rb | 2 ++ lib/version.rb | 2 +- test/model/testing_instance_test.rb | 10 ++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/app/models/testing_instance.rb b/lib/app/models/testing_instance.rb index e0346ecdd..f71931a26 100644 --- a/lib/app/models/testing_instance.rb +++ b/lib/app/models/testing_instance.rb @@ -154,6 +154,8 @@ def patient_id=(patient_id) resource_id: patient_id ) + save! + reload end diff --git a/lib/version.rb b/lib/version.rb index 143e67645..6ed74ae6f 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Inferno - VERSION = '2.3.0' + VERSION = '2.3.1' end diff --git a/test/model/testing_instance_test.rb b/test/model/testing_instance_test.rb index a246be7fc..f8e7bb985 100644 --- a/test/model/testing_instance_test.rb +++ b/test/model/testing_instance_test.rb @@ -5,8 +5,8 @@ class TestingInstanceTest < MiniTest::Test def setup - @patient_id1 = 1 - @patient_id2 = 2 + @patient_id1 = '1' + @patient_id2 = '2' @testing_instance = Inferno::Models::TestingInstance.new @testing_instance.resource_references << Inferno::Models::ResourceReference.new( resource_type: 'Patient', @@ -20,7 +20,9 @@ def test_patient_id_assignment @testing_instance.patient_id = @patient_id2 - assert(@testing_instance.resource_references.empty?) + assert(@testing_instance.patient_id == @patient_id2) + assert(@testing_instance.resource_references.length == 1) + assert(@testing_instance.resource_references.first.resource_id == @patient_id2) end def test_patient_id_reassignment @@ -31,4 +33,4 @@ def test_patient_id_reassignment assert(@testing_instance.resource_references == resource_references) end -end +end \ No newline at end of file From ec44d26c2f640b3ed5443a39496efbd7525bd8cf Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Tue, 2 Jul 2019 17:01:33 -0400 Subject: [PATCH 36/89] Fix newline issue for rubocop. --- test/model/testing_instance_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model/testing_instance_test.rb b/test/model/testing_instance_test.rb index f8e7bb985..aa08bb35a 100644 --- a/test/model/testing_instance_test.rb +++ b/test/model/testing_instance_test.rb @@ -33,4 +33,4 @@ def test_patient_id_reassignment assert(@testing_instance.resource_references == resource_references) end -end \ No newline at end of file +end From df6f59a7109418c7a7712d90c577111aa2909f3d Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Wed, 10 Jul 2019 17:08:15 -0400 Subject: [PATCH 37/89] added an assert to check if uri is valid, and updated test to not redirect to an invalid url. Also updated tests to check for invalid redirect and tokens cause them to fail with prettier error message rather than code failure --- .../smart/standalone_launch_sequence.rb | 27 ++++++++++++++++++- lib/app/utils/assertions.rb | 7 ++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/app/modules/smart/standalone_launch_sequence.rb b/lib/app/modules/smart/standalone_launch_sequence.rb index bef06f67e..100efddf0 100644 --- a/lib/app/modules/smart/standalone_launch_sequence.rb +++ b/lib/app/modules/smart/standalone_launch_sequence.rb @@ -35,6 +35,9 @@ class StandaloneLaunchSequence < SequenceBase !@instance.client_id.nil? end + OAUTH_REDIRECT_FAILED = "Redirect to OAuth server failed" + NO_TOKEN = "No valid token" + test 'OAuth 2.0 authorize endpoint secured by transport layer security' do metadata do id '01' @@ -72,7 +75,13 @@ class StandaloneLaunchSequence < SequenceBase 'aud' => @instance.url } - oauth2_auth_query = @instance.oauth_authorize_endpoint + + oauth_authorize_endpoint = @instance.oauth_authorize_endpoint + + # Confirm that oauth2_auth_endpoint is valid before moving forward + assert_is_valid_uri oauth_authorize_endpoint + + oauth2_auth_query = oauth_authorize_endpoint oauth2_auth_query += if @instance.oauth_authorize_endpoint.include? '?' '&' @@ -96,6 +105,9 @@ class StandaloneLaunchSequence < SequenceBase ) end + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED + assert @params['error'].nil?, "Error returned from authorization server: code #{@params['error']}, description: #{@params['error_description']}" assert @params['state'] == @instance.state, "OAuth server state querystring parameter (#{@params['state']}) did not match state from app #{@instance.state}" assert !@params['code'].nil?, 'Expected code to be submitted in request' @@ -138,6 +150,10 @@ class StandaloneLaunchSequence < SequenceBase token_response = LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params.to_json, headers) assert_response_bad_or_unauthorized token_response + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED + + oauth2_params = { 'grant_type' => 'authorization_code', 'code' => @params['code'], @@ -158,6 +174,9 @@ class StandaloneLaunchSequence < SequenceBase ) end + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED + oauth2_params = { 'grant_type' => 'authorization_code', 'code' => @params['code'], @@ -185,6 +204,9 @@ class StandaloneLaunchSequence < SequenceBase ) end + # Confirm that there is valid token + assert !@token_response.nil?, NO_TOKEN + @token_response_headers = @token_response.headers assert_valid_json(@token_response.body) @token_response_body = JSON.parse(@token_response.body) @@ -242,6 +264,9 @@ class StandaloneLaunchSequence < SequenceBase ) end + # Confirm that there is valid token + assert !@token_response.nil?, NO_TOKEN + [:cache_control, :pragma].each do |key| assert @token_response_headers.key?(key), "Token response headers did not contain #{key} as is required in the SMART App Launch Guide." end diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 75cf6a1ff..7fb3a15b0 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true - require_relative 'assertions.rb' +require 'uri' module Inferno module Assertions def assert(test, message = 'assertion failed, no message', data = '') @@ -260,5 +260,10 @@ def assert_deny_previous_tls(uri) ) end end + + def assert_is_valid_uri(uri) + assert uri =~ URI::regexp, "\"#{uri}\" is not a valid URI" + end + end end From 9eee6d8342ebe29a8130da10107d723bd513645a Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Wed, 10 Jul 2019 17:37:17 -0400 Subject: [PATCH 38/89] updated assert to accept a message as a param --- lib/app/modules/smart/standalone_launch_sequence.rb | 2 +- lib/app/utils/assertions.rb | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/app/modules/smart/standalone_launch_sequence.rb b/lib/app/modules/smart/standalone_launch_sequence.rb index 100efddf0..a89a6f3f5 100644 --- a/lib/app/modules/smart/standalone_launch_sequence.rb +++ b/lib/app/modules/smart/standalone_launch_sequence.rb @@ -79,7 +79,7 @@ class StandaloneLaunchSequence < SequenceBase oauth_authorize_endpoint = @instance.oauth_authorize_endpoint # Confirm that oauth2_auth_endpoint is valid before moving forward - assert_is_valid_uri oauth_authorize_endpoint + assert_is_valid_uri oauth_authorize_endpoint, "OAuth2 Authorization Endpoint: \"#{oauth_authorize_endpoint}\" is not a valid URI" oauth2_auth_query = oauth_authorize_endpoint diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 7fb3a15b0..994a0849a 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -261,8 +261,12 @@ def assert_deny_previous_tls(uri) end end - def assert_is_valid_uri(uri) - assert uri =~ URI::regexp, "\"#{uri}\" is not a valid URI" + def assert_is_valid_uri(uri, message = nil) + + if message == nil + message = "\"#{uri}\" is not a valid URI" + end + assert uri =~ URI::regexp, message end end From e265952f1b93ece4144701d44031145cc22e6445 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Thu, 11 Jul 2019 11:58:44 -0400 Subject: [PATCH 39/89] updated formatting to pass rubocop --- .../smart/standalone_launch_sequence.rb | 26 +++++++++---------- lib/app/utils/assertions.rb | 14 +++++----- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/lib/app/modules/smart/standalone_launch_sequence.rb b/lib/app/modules/smart/standalone_launch_sequence.rb index a89a6f3f5..71cae254a 100644 --- a/lib/app/modules/smart/standalone_launch_sequence.rb +++ b/lib/app/modules/smart/standalone_launch_sequence.rb @@ -35,8 +35,8 @@ class StandaloneLaunchSequence < SequenceBase !@instance.client_id.nil? end - OAUTH_REDIRECT_FAILED = "Redirect to OAuth server failed" - NO_TOKEN = "No valid token" + OAUTH_REDIRECT_FAILED = 'Redirect to OAuth server failed' + NO_TOKEN = 'No valid token' test 'OAuth 2.0 authorize endpoint secured by transport layer security' do metadata do @@ -75,7 +75,6 @@ class StandaloneLaunchSequence < SequenceBase 'aud' => @instance.url } - oauth_authorize_endpoint = @instance.oauth_authorize_endpoint # Confirm that oauth2_auth_endpoint is valid before moving forward @@ -105,8 +104,8 @@ class StandaloneLaunchSequence < SequenceBase ) end - # Confirm that there is a @params object from the redirect - assert !@params.nil?, OAUTH_REDIRECT_FAILED + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED assert @params['error'].nil?, "Error returned from authorization server: code #{@params['error']}, description: #{@params['error_description']}" assert @params['state'] == @instance.state, "OAuth server state querystring parameter (#{@params['state']}) did not match state from app #{@instance.state}" @@ -150,9 +149,8 @@ class StandaloneLaunchSequence < SequenceBase token_response = LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params.to_json, headers) assert_response_bad_or_unauthorized token_response - # Confirm that there is a @params object from the redirect - assert !@params.nil?, OAUTH_REDIRECT_FAILED - + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED oauth2_params = { 'grant_type' => 'authorization_code', @@ -174,8 +172,8 @@ class StandaloneLaunchSequence < SequenceBase ) end - # Confirm that there is a @params object from the redirect - assert !@params.nil?, OAUTH_REDIRECT_FAILED + # Confirm that there is a @params object from the redirect + assert !@params.nil?, OAUTH_REDIRECT_FAILED oauth2_params = { 'grant_type' => 'authorization_code', @@ -204,8 +202,8 @@ class StandaloneLaunchSequence < SequenceBase ) end - # Confirm that there is valid token - assert !@token_response.nil?, NO_TOKEN + # Confirm that there is valid token + assert !@token_response.nil?, NO_TOKEN @token_response_headers = @token_response.headers assert_valid_json(@token_response.body) @@ -264,8 +262,8 @@ class StandaloneLaunchSequence < SequenceBase ) end - # Confirm that there is valid token - assert !@token_response.nil?, NO_TOKEN + # Confirm that there is valid token + assert !@token_response.nil?, NO_TOKEN [:cache_control, :pragma].each do |key| assert @token_response_headers.key?(key), "Token response headers did not contain #{key} as is required in the SMART App Launch Guide." diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 994a0849a..11ed11fdd 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true + require_relative 'assertions.rb' require 'uri' + module Inferno module Assertions def assert(test, message = 'assertion failed, no message', data = '') @@ -261,13 +263,11 @@ def assert_deny_previous_tls(uri) end end - def assert_is_valid_uri(uri, message = nil) - - if message == nil - message = "\"#{uri}\" is not a valid URI" - end - assert uri =~ URI::regexp, message + def assert_is_valid_uri(uri, message = nil) + if message.nil? + message = "\"#{uri}\" is not a valid URI" + end + assert uri =~ URI::DEFAULT_PARSER.make_regexp, message end - end end From 5caf3d4d3a45cde834edda70f287fcc9dc7c2278 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Thu, 11 Jul 2019 12:31:47 -0400 Subject: [PATCH 40/89] updated formatting to pass rubocop --- lib/app/utils/assertions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 11ed11fdd..6b9fb8df1 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -263,7 +263,7 @@ def assert_deny_previous_tls(uri) end end - def assert_is_valid_uri(uri, message = nil) + def assert_is_valid_uri(uri, message = nil) if message.nil? message = "\"#{uri}\" is not a valid URI" end From 5bc175fe01a8cd42ad6d4579cf5ede28bfb9ddc6 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Thu, 11 Jul 2019 14:48:56 -0400 Subject: [PATCH 41/89] refactored assertion to be assert_valid_http_uri, and replaced instances that were manually testing the uri --- lib/app/modules/smart/smart_discovery_sequence.rb | 6 +++--- lib/app/modules/smart/standalone_launch_sequence.rb | 2 +- lib/app/utils/assertions.rb | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/app/modules/smart/smart_discovery_sequence.rb b/lib/app/modules/smart/smart_discovery_sequence.rb index 1c56865e8..b4306f5d7 100644 --- a/lib/app/modules/smart/smart_discovery_sequence.rb +++ b/lib/app/modules/smart/smart_discovery_sequence.rb @@ -84,9 +84,9 @@ class SMARTDiscoverySequence < SequenceBase @conformance_authorize_url = oauth_metadata[:authorize_url] @conformance_token_url = oauth_metadata[:token_url] assert !@conformance_authorize_url.blank?, 'No authorize URI provided in Conformance/CapabilityStatement resource' - assert (@conformance_authorize_url =~ /\A#{URI.regexp(['http', 'https'])}\z/).zero?, "Invalid authorize url: '#{@conformance_authorize_url}'" + assert_valid_http_uri @conformance_authorize_url, "Invalid authorize url: '#{@conformance_authorize_url}'" assert !@conformance_token_url.blank?, 'No token URI provided in conformance statement.' - assert (@conformance_token_url =~ /\A#{URI.regexp(['http', 'https'])}\z/).zero?, "Invalid token url: '#{@conformance_token_url}'" + assert_valid_http_uri @conformance_token_url, "Invalid token url: '#{@conformance_token_url}'" warning do service = [] @@ -109,7 +109,7 @@ class SMARTDiscoverySequence < SequenceBase registration_url = security_info.extension.find { |x| x.url == 'register' } registration_url = registration_url.value if registration_url assert !registration_url.blank?, 'No dynamic registration endpoint in conformance.' - assert (registration_url =~ /\A#{URI.regexp(['http', 'https'])}\z/).zero?, "Invalid registration url: '#{registration_url}'" + assert_valid_http_uri registration_url, "Invalid registration url: '#{registration_url}'" manage_url = security_info.extension.find { |x| x.url == 'manage' } manage_url = manage_url.value if manage_url diff --git a/lib/app/modules/smart/standalone_launch_sequence.rb b/lib/app/modules/smart/standalone_launch_sequence.rb index 71cae254a..ad9fc17a4 100644 --- a/lib/app/modules/smart/standalone_launch_sequence.rb +++ b/lib/app/modules/smart/standalone_launch_sequence.rb @@ -78,7 +78,7 @@ class StandaloneLaunchSequence < SequenceBase oauth_authorize_endpoint = @instance.oauth_authorize_endpoint # Confirm that oauth2_auth_endpoint is valid before moving forward - assert_is_valid_uri oauth_authorize_endpoint, "OAuth2 Authorization Endpoint: \"#{oauth_authorize_endpoint}\" is not a valid URI" + assert_valid_http_uri oauth_authorize_endpoint, "OAuth2 Authorization Endpoint: \"#{oauth_authorize_endpoint}\" is not a valid URI" oauth2_auth_query = oauth_authorize_endpoint diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 6b9fb8df1..4bfe8a39b 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -263,11 +263,11 @@ def assert_deny_previous_tls(uri) end end - def assert_is_valid_uri(uri, message = nil) + def assert_valid_http_uri(uri, message = nil) if message.nil? message = "\"#{uri}\" is not a valid URI" end - assert uri =~ URI::DEFAULT_PARSER.make_regexp, message + assert (uri =~ /\A#{URI.regexp(['http', 'https'])}\z/), message end end end From 2fc2e3140f73e1487a66f0d32c836713f24d623b Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Fri, 12 Jul 2019 08:56:23 -0400 Subject: [PATCH 42/89] updated assert_valid_http_uri to no change the input argument (to avoid side effects) and instead have a new error_message variable --- lib/app/utils/assertions.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 4bfe8a39b..a14d628ae 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -264,10 +264,11 @@ def assert_deny_previous_tls(uri) end def assert_valid_http_uri(uri, message = nil) - if message.nil? - message = "\"#{uri}\" is not a valid URI" + error_message = message; + if error_message.nil? + error_message = "\"#{uri}\" is not a valid URI" end - assert (uri =~ /\A#{URI.regexp(['http', 'https'])}\z/), message + assert (uri =~ /\A#{URI.regexp(['http', 'https'])}\z/), error_message end end end From 3954ebd77abe7ede28608743aa2f7766e34d2482 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Fri, 12 Jul 2019 09:07:10 -0400 Subject: [PATCH 43/89] removed unecessary semicolon --- lib/app/utils/assertions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index a14d628ae..c55d57db1 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -264,7 +264,7 @@ def assert_deny_previous_tls(uri) end def assert_valid_http_uri(uri, message = nil) - error_message = message; + error_message = message if error_message.nil? error_message = "\"#{uri}\" is not a valid URI" end From 96591d7f05255f5e38ee567fcacd1ee7f7b4088e Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Mon, 15 Jul 2019 09:59:18 -0400 Subject: [PATCH 44/89] condensed code into simpler line --- lib/app/utils/assertions.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index c55d57db1..99cbd96fe 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -263,11 +263,8 @@ def assert_deny_previous_tls(uri) end end - def assert_valid_http_uri(uri, message = nil) - error_message = message - if error_message.nil? - error_message = "\"#{uri}\" is not a valid URI" - end + def assert_valid_http_uri(uri, message = nil) + error_message = message || "\"#{uri}\" is not a valid URI" assert (uri =~ /\A#{URI.regexp(['http', 'https'])}\z/), error_message end end From f1068d26261c3855f3f587c470729eede93c9947 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Mon, 15 Jul 2019 11:30:31 -0400 Subject: [PATCH 45/89] removed spaces --- lib/app/utils/assertions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/utils/assertions.rb b/lib/app/utils/assertions.rb index 99cbd96fe..dcd67cea7 100644 --- a/lib/app/utils/assertions.rb +++ b/lib/app/utils/assertions.rb @@ -263,7 +263,7 @@ def assert_deny_previous_tls(uri) end end - def assert_valid_http_uri(uri, message = nil) + def assert_valid_http_uri(uri, message = nil) error_message = message || "\"#{uri}\" is not a valid URI" assert (uri =~ /\A#{URI.regexp(['http', 'https'])}\z/), error_message end From c1cf7de6dac47a1655ad1bcf9f29790b5c172cd2 Mon Sep 17 00:00:00 2001 From: Nicole Kennedy Date: Tue, 16 Jul 2019 09:35:30 -0400 Subject: [PATCH 46/89] update background --- lib/app/endpoint/home.rb | 6 ++++-- lib/app/views/guided.erb | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/app/endpoint/home.rb b/lib/app/endpoint/home.rb index b25c50cd3..bd0938588 100644 --- a/lib/app/endpoint/home.rb +++ b/lib/app/endpoint/home.rb @@ -125,7 +125,8 @@ class Home < Endpoint instance: instance, test_set: test_set, sequence_results: instance.latest_results_by_case, - tests_running: true) + tests_running: true, + test_group: test_group.id) out << js_hide_wait_modal out << js_show_test_modal @@ -442,7 +443,8 @@ class Home < Endpoint out << erb(instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, test_set: test_set, sequence_results: instance.latest_results_by_case, - tests_running: true) + tests_running: true, + test_group: test_group.id) next_test_case = submitted_test_cases.shift finished = next_test_case.nil? diff --git a/lib/app/views/guided.erb b/lib/app/views/guided.erb index 2dd916010..75f6004e2 100644 --- a/lib/app/views/guided.erb +++ b/lib/app/views/guided.erb @@ -80,9 +80,10 @@ <% end %>
- \ No newline at end of file + From dc8c774902020edf3e114de2aaabe0bf6aa4eeea Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Fri, 12 Jul 2019 14:52:45 -0400 Subject: [PATCH 50/89] move test set endpoints out of home, update routing strategy --- lib/app/endpoint.rb | 1 - lib/app/endpoint/home.rb | 217 +-------------- lib/app/endpoint/oauth2_endpoints.rb | 349 +++++++++++++------------ lib/app/endpoint/test_set_endpoints.rb | 218 +++++++++++++++ 4 files changed, 399 insertions(+), 386 deletions(-) create mode 100644 lib/app/endpoint/test_set_endpoints.rb diff --git a/lib/app/endpoint.rb b/lib/app/endpoint.rb index c55e0e54f..03e71dabc 100644 --- a/lib/app/endpoint.rb +++ b/lib/app/endpoint.rb @@ -76,4 +76,3 @@ def render_index require_relative 'endpoint/landing' require_relative 'endpoint/home' -require_relative 'endpoint/oauth2_endpoints' diff --git a/lib/app/endpoint/home.rb b/lib/app/endpoint/home.rb index d89be40b3..3dd157a3f 100644 --- a/lib/app/endpoint/home.rb +++ b/lib/app/endpoint/home.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +require_relative 'oauth2_endpoints' +require_relative 'test_set_endpoints' + module Inferno class App class Endpoint @@ -10,6 +13,9 @@ class Home < Endpoint # Set the url prefix these routes will map to set :prefix, "/#{base_path}" + include OAuth2Endpoints + include TestSetEndpoints + # Return the index page of the application get '/?' do render_index @@ -49,9 +55,6 @@ class Home < Endpoint cookies[:instance_id_test_set] = "#{@instance.id}/test_sets/#{inferno_module.default_test_set}" @instance.save! - print "redirecting to: " - puts "#{base_path}/#{@instance.id}/#{'?autoRun=CapabilityStatementSequence' if - settings.autorun_capability}" redirect "#{base_path}/#{@instance.id}/#{'?autoRun=CapabilityStatementSequence' if settings.autorun_capability}" end @@ -69,214 +72,6 @@ class Home < Endpoint redirect "#{base_path}/#{instance.id}/test_sets/#{instance.module.default_test_set}/#{'?error=' + params[:error] unless params[:error].nil?}" end - # Returns a specific testing instance test page - get '/:id/test_sets/:test_set/?' do - instance = Inferno::Models::TestingInstance.get(params[:id]) - halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] - halt 404 if test_set.nil? - sequence_results = instance.latest_results_by_case - - erb instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, - test_set: test_set, - sequence_results: sequence_results, - error_code: params[:error] - end - - get '/:id/test_sets/:test_set/report?' do - instance = Inferno::Models::TestingInstance.get(params[:id]) - halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] - halt 404 if test_set.nil? - sequence_results = instance.latest_results_by_case - - request_response_count = Inferno::Models::RequestResponse.all(instance_id: instance.id).count - latest_sequence_time = - if instance.sequence_results.count.positive? - Inferno::Models::SequenceResult.first(testing_instance: instance).created_at.strftime('%m/%d/%Y %H:%M') - else - 'No tests ran' - end - - report_summary = { - fhir_version: instance.fhir_version, - app_version: VERSION, - resource_references: instance.resource_references.count, - supported_resources: instance.supported_resources.count, - request_response: request_response_count, - latest_sequence_time: latest_sequence_time, - final_result: instance.final_result(params[:test_set]), - inferno_url: "#{request.base_url}#{base_path}/#{instance.id}/test_sets/#{params[:test_set]}/" - } - - erb( - :report, - { layout: false }, - instance: instance, - test_set: test_set, - show_button: false, - sequence_results: sequence_results, - report_summary: report_summary - ) - end - - # Cancels the currently running test - get '/:id/test_sets/:test_set/sequence_result/:sequence_result_id/cancel' do - sequence_result = Inferno::Models::SequenceResult.get(params[:sequence_result_id]) - halt 404 if sequence_result.testing_instance.id != params[:id] - test_set = sequence_result.testing_instance.module.test_sets[params[:test_set].to_sym] - halt 404 if test_set.nil? - - sequence_result.result = 'cancel' - cancel_message = 'Test cancelled by user.' - - unless sequence_result.test_results.empty? - last_result = sequence_result.test_results.last - last_result.result = 'cancel' - last_result.message = cancel_message - end - - sequence = sequence_result.testing_instance.module.sequences.find do |x| - x.sequence_name == sequence_result.name - end - - current_test_count = sequence_result.result_count - - sequence.tests.each_with_index do |test, index| - next if index < current_test_count - - sequence_result.test_results << Inferno::Models::TestResult.new(test_id: test[:test_id], - name: test[:name], - result: 'cancel', - url: test[:url], - description: test[:description], - test_index: test[:test_index], - message: cancel_message) - end - - sequence_result.save! - - test_group = test_set.test_case_by_id(sequence_result.test_case_id).test_group - - query_target = sequence_result.test_case_id - query_target = "#{test_group.id}/#{sequence_result.test_case_id}" unless test_group.nil? - - redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}" - end - - get '/:id/test_sets/:test_set/sequence_result?' do - redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/" - end - - # Run a sequence and get the results - post '/:id/test_sets/:test_set/sequence_result?' do - instance = Inferno::Models::TestingInstance.get(params[:id]) - halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] - halt 404 if test_set.nil? - - cookies[:instance_id_test_set] = "#{instance.id}/test_sets/#{params[:test_set]}" - - # Save params - params[:required_fields].split(',').each do |field| - instance.send("#{field}=", params[field]) if instance.respond_to? field - end - - instance.save! - - client = FHIR::Client.new(instance.url) - case instance.fhir_version - when 'stu3' - client.use_stu3 - when 'dstu2' - client.use_dstu2 - else - client.use_r4 - end - client.default_json - submitted_test_cases = params[:test_case].split(',') - - instance.reload # ensure that we have all the latest data - - total_tests = submitted_test_cases.reduce(0) do |total, set| - sequence_test_count = test_set.test_case_by_id(set).sequence.test_count - total + sequence_test_count - end - - test_group = nil - test_group = test_set.test_case_by_id(submitted_test_cases.first).test_group - failed_test_cases = [] - all_test_cases = [] - - timer_count = 0 - stayalive_timer_seconds = 20 - - finished = false - stream :keep_open do |out| - EventMachine::PeriodicTimer.new(stayalive_timer_seconds) do - timer_count += 1 - out << js_stayalive(timer_count * stayalive_timer_seconds) - end - - out << erb(instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, - test_set: test_set, - sequence_results: instance.latest_results_by_case, - tests_running: true, - test_group: test_group.id) - - next_test_case = submitted_test_cases.shift - finished = next_test_case.nil? - - test_count = 0 - until next_test_case.nil? - test_case = test_set.test_case_by_id(next_test_case) - - next_test_case = submitted_test_cases.shift - if test_case.nil? - finished = next_test_case.nil? - next - end - - out << js_show_test_modal - - instance.reload # ensure that we have all the latest data - sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests) - count = 0 - sequence_result = sequence.start(test_set.id, test_case.id) do |result| - count += 1 - test_count += 1 - out << js_update_result(sequence, test_set, result, count, sequence.test_count, test_count, total_tests) - end - - sequence_result.next_test_cases = ([next_test_case] + submitted_test_cases).join(',') - - all_test_cases << test_case.id - failed_test_cases << test_case.id if sequence_result.fail? - - sequence_result.save! - if sequence_result.redirect_to_url - out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) - next_test_case = nil - finished = false - elsif sequence_result.wait_at_endpoint - next_test_case = nil - finished = true - elsif !submitted_test_cases.empty? - out << js_next_sequence(sequence_result.next_test_cases) - else - finished = true - end - end - - query_target = failed_test_cases.join(',') - query_target = all_test_cases.join(',') if all_test_cases.length == 1 - - query_target = "#{test_group.id}/#{query_target}" unless test_group.nil? - - out << js_redirect("#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}") if finished - end - end - # Returns test details for a specific test including any applicable requests and responses. # This route is typically used for retrieving test metadata before the test has been run get '/test_details/:module/:sequence_name/:test_index?' do diff --git a/lib/app/endpoint/oauth2_endpoints.rb b/lib/app/endpoint/oauth2_endpoints.rb index dd572c189..f1e5b4dd5 100644 --- a/lib/app/endpoint/oauth2_endpoints.rb +++ b/lib/app/endpoint/oauth2_endpoints.rb @@ -1,23 +1,22 @@ # frozen_string_literal: true -require_relative '../endpoint' - module Inferno class App - class OAuth2Endpoints < Endpoint - set :prefix, "/#{base_path}/oauth2/" - # Resume oauth2 flow - # This must be early so it doesn't get picked up by the other routes - get '/:key/:endpoint/?' do - instance = nil - error_message = nil - - if params[:endpoint] == 'redirect' - instance = Inferno::Models::TestingInstance.first(state: params[:state]) - if instance.nil? - instance = Inferno::Models::TestingInstance.get(cookies[:instance_id_test_set]&.split('/')&.first) - if instance.nil? - error_message = %( + module OAuth2Endpoints + def self.included(klass) + klass.class_eval do + # Resume oauth2 flow + # This must be early so it doesn't get picked up by the other routes + get '/oauth2/:key/:endpoint/?' do + instance = nil + error_message = nil + + if params[:endpoint] == 'redirect' + instance = Inferno::Models::TestingInstance.first(state: params[:state]) + if instance.nil? + instance = Inferno::Models::TestingInstance.get(cookies[:instance_id_test_set]&.split('/')&.first) + if instance.nil? + error_message = %(

Inferno has detected an issue with the SMART launch. No actively running launch sequences found with a state of #{params[:state]}. @@ -28,178 +27,180 @@ class OAuth2Endpoints < Endpoint

) - error_message += "

Error returned by server: #{params[:error]}.

" if params[:error].present? - - error_message += "

Error description returned by server: #{params[:error_description]}.

" unless params[:error_description].nil? - - halt 500, error_message - elsif instance&.waiting_on_sequence&.wait? - error_message = "State provided in redirect (#{params[:state]}) does not match expected state (#{instance.state})." - else - redirect "#{base_path}/#{cookies[:instance_id_test_set]}/?error=no_state&state=#{params[:state]}" - end - end - end + error_message += "

Error returned by server: #{params[:error]}.

" if params[:error].present? - if params[:endpoint] == 'launch' - recent_results = Inferno::Models::SequenceResult.all( - :created_at.gte => 5.minutes.ago, - :result => 'wait', - :order => [:created_at.desc] - ) - iss_url = params[:iss]&.downcase&.split('://')&.last&.chomp('/') - - matching_results = recent_results.select do |sr| - testing_instance_url = sr.testing_instance.url.downcase.split('://').last.chomp('/') - testing_instance_url == iss_url - end + error_message += "

Error description returned by server: #{params[:error_description]}.

" unless params[:error_description].nil? - instance = matching_results&.first&.testing_instance - if instance.nil? - instance = Inferno::Models::TestingInstance.get(cookies[:instance_id_test_set]&.split('/')&.first) - if instance.nil? - message = "Error: No actively running launch sequences found for iss #{params[:iss]}. " \ - 'Please ensure that the EHR launch test is actively running before attempting to launch Inferno from the EHR.' - halt 500, message - elsif instance&.waiting_on_sequence&.wait? - error_message = 'No iss for redirect' - else - redirect "#{base_path}/#{cookies[:instance_id_test_set]}/?error=no_ehr_launch&iss=#{params[:iss]}" + halt 500, error_message + elsif instance&.waiting_on_sequence&.wait? + error_message = "State provided in redirect (#{params[:state]}) does not match expected state (#{instance.state})." + else + redirect "#{base_path}/#{cookies[:instance_id_test_set]}/?error=no_state&state=#{params[:state]}" + end + end end - end - end - halt 500, 'Error: Could not find a running test that match this set of critera' unless !instance.nil? && - instance.client_endpoint_key == params[:key] && - %w[launch redirect].include?(params[:endpoint]) - - sequence_result = instance.waiting_on_sequence - if sequence_result&.wait? - test_set = instance.module.test_sets[sequence_result.test_set_id.to_sym] - failed_test_cases = [] - all_test_cases = [] - test_case = test_set.test_case_by_id(sequence_result.test_case_id) - test_group = test_case.test_group - - client = FHIR::Client.new(instance.url) - case instance.fhir_version - when 'stu3' - client.use_stu3 - when 'dstu2' - client.use_dstu2 - else - client.use_r4 - end - client.default_json - sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests, sequence_result) - first_test_count = sequence.test_count - timer_count = 0 - stayalive_timer_seconds = 20 - - finished = false + if params[:endpoint] == 'launch' + recent_results = Inferno::Models::SequenceResult.all( + :created_at.gte => 5.minutes.ago, + :result => 'wait', + :order => [:created_at.desc] + ) + iss_url = params[:iss]&.downcase&.split('://')&.last&.chomp('/') + + matching_results = recent_results.select do |sr| + testing_instance_url = sr.testing_instance.url.downcase.split('://').last.chomp('/') + testing_instance_url == iss_url + end - stream :keep_open do |out| - EventMachine::PeriodicTimer.new(stayalive_timer_seconds) do - timer_count += 1 - out << js_stayalive(timer_count * stayalive_timer_seconds) + instance = matching_results&.first&.testing_instance + if instance.nil? + instance = Inferno::Models::TestingInstance.get(cookies[:instance_id_test_set]&.split('/')&.first) + if instance.nil? + message = "Error: No actively running launch sequences found for iss #{params[:iss]}. " \ + 'Please ensure that the EHR launch test is actively running before attempting to launch Inferno from the EHR.' + halt 500, message + elsif instance&.waiting_on_sequence&.wait? + error_message = 'No iss for redirect' + else + redirect "#{base_path}/#{cookies[:instance_id_test_set]}/?error=no_ehr_launch&iss=#{params[:iss]}" + end + end end + halt 500, 'Error: Could not find a running test that match this set of critera' unless !instance.nil? && + instance.client_endpoint_key == params[:key] && + %w[launch redirect].include?(params[:endpoint]) + + sequence_result = instance.waiting_on_sequence + if sequence_result&.wait? + test_set = instance.module.test_sets[sequence_result.test_set_id.to_sym] + failed_test_cases = [] + all_test_cases = [] + test_case = test_set.test_case_by_id(sequence_result.test_case_id) + test_group = test_case.test_group + + client = FHIR::Client.new(instance.url) + case instance.fhir_version + when 'stu3' + client.use_stu3 + when 'dstu2' + client.use_dstu2 + else + client.use_r4 + end + client.default_json + sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests, sequence_result) + first_test_count = sequence.test_count - # finish the inprocess stream - - out << erb(instance.module.view_by_test_set(test_set.id), - {}, - instance: instance, - test_set: test_set, - sequence_results: instance.latest_results_by_case, - tests_running: true, - test_group: test_group.id) - - out << js_hide_wait_modal - out << js_show_test_modal - count = sequence_result.result_count - - submitted_test_cases_count = sequence_result.next_test_cases.split(',') - total_tests = submitted_test_cases_count.reduce(first_test_count) do |total, set| - sequence_test_count = test_set.test_case_by_id(set).sequence.test_count - total + sequence_test_count - end + timer_count = 0 + stayalive_timer_seconds = 20 - sequence_result = sequence.resume(request, headers, request.params, error_message) do |result| - count += 1 - out << js_update_result(sequence, test_set, result, count, sequence.test_count, count, total_tests) - instance.save! - end - all_test_cases << test_case.id - failed_test_cases << test_case.id if sequence_result.fail? - instance.sequence_results.push(sequence_result) - instance.save! - - submitted_test_cases = sequence_result.next_test_cases.split(',') - - next_test_case = submitted_test_cases.shift - finished = next_test_case.nil? - if sequence_result.redirect_to_url - out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) - next_test_case = nil finished = false - elsif !submitted_test_cases.empty? - out << js_next_sequence(sequence_result.next_test_cases) - else - finished = true - end - # continue processesing any afterwards - - test_count = first_test_count - until next_test_case.nil? - test_case = test_set.test_case_by_id(next_test_case) - - next_test_case = submitted_test_cases.shift - if test_case.nil? + stream :keep_open do |out| + EventMachine::PeriodicTimer.new(stayalive_timer_seconds) do + timer_count += 1 + out << js_stayalive(timer_count * stayalive_timer_seconds) + end + + # finish the inprocess stream + + out << erb(instance.module.view_by_test_set(test_set.id), + {}, + instance: instance, + test_set: test_set, + sequence_results: instance.latest_results_by_case, + tests_running: true, + test_group: test_group.id) + + out << js_hide_wait_modal + out << js_show_test_modal + count = sequence_result.result_count + + submitted_test_cases_count = sequence_result.next_test_cases.split(',') + total_tests = submitted_test_cases_count.reduce(first_test_count) do |total, set| + sequence_test_count = test_set.test_case_by_id(set).sequence.test_count + total + sequence_test_count + end + + sequence_result = sequence.resume(request, headers, request.params, error_message) do |result| + count += 1 + out << js_update_result(sequence, test_set, result, count, sequence.test_count, count, total_tests) + instance.save! + end + all_test_cases << test_case.id + failed_test_cases << test_case.id if sequence_result.fail? + instance.sequence_results.push(sequence_result) + instance.save! + + submitted_test_cases = sequence_result.next_test_cases.split(',') + + next_test_case = submitted_test_cases.shift finished = next_test_case.nil? - next - end - - out << js_show_test_modal - - instance.reload # ensure that we have all the latest data - sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests) - count = 0 - sequence_result = sequence.start do |result| - test_count += 1 - count += 1 - out << js_update_result(sequence, test_set, result, count, sequence.test_count, test_count, total_tests) - end - all_test_cases << test_case.id - failed_test_cases << test_case.id if sequence_result.fail? - - sequence_result.test_set_id = test_set.id - sequence_result.test_case_id = test_case.id - - sequence_result.next_test_cases = ([next_test_case] + submitted_test_cases).join(',') - - sequence_result.save! - if sequence_result.redirect_to_url - out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) - finished = false - elsif !submitted_test_cases.empty? - out << js_next_sequence(sequence_result.next_test_cases) - else - finished = true + if sequence_result.redirect_to_url + out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) + next_test_case = nil + finished = false + elsif !submitted_test_cases.empty? + out << js_next_sequence(sequence_result.next_test_cases) + else + finished = true + end + + # continue processesing any afterwards + + test_count = first_test_count + until next_test_case.nil? + test_case = test_set.test_case_by_id(next_test_case) + + next_test_case = submitted_test_cases.shift + if test_case.nil? + finished = next_test_case.nil? + next + end + + out << js_show_test_modal + + instance.reload # ensure that we have all the latest data + sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests) + count = 0 + sequence_result = sequence.start do |result| + test_count += 1 + count += 1 + out << js_update_result(sequence, test_set, result, count, sequence.test_count, test_count, total_tests) + end + all_test_cases << test_case.id + failed_test_cases << test_case.id if sequence_result.fail? + + sequence_result.test_set_id = test_set.id + sequence_result.test_case_id = test_case.id + + sequence_result.next_test_cases = ([next_test_case] + submitted_test_cases).join(',') + + sequence_result.save! + if sequence_result.redirect_to_url + out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) + finished = false + elsif !submitted_test_cases.empty? + out << js_next_sequence(sequence_result.next_test_cases) + else + finished = true + end + end + + query_target = failed_test_cases.join(',') + query_target = all_test_cases.join(',') if all_test_cases.length == 1 + + query_target = "#{test_group.id}/#{query_target}" unless test_group.nil? + + out << js_redirect("#{base_path}/#{instance.id}/test_sets/#{test_set.id}/##{query_target}") if finished end + else + latest_sequence_result = Inferno::Models::SequenceResult.first(testing_instance: instance) + test_set_id = latest_sequence_result&.test_set_id || instance.module.default_test_set + redirect "#{BASE_PATH}/#{instance.id}/#{test_set_id}/?error=no_#{params[:endpoint]}" end - - query_target = failed_test_cases.join(',') - query_target = all_test_cases.join(',') if all_test_cases.length == 1 - - query_target = "#{test_group.id}/#{query_target}" unless test_group.nil? - - out << js_redirect("#{base_path}/#{instance.id}/test_sets/#{test_set.id}/##{query_target}") if finished end - else - latest_sequence_result = Inferno::Models::SequenceResult.first(testing_instance: instance) - test_set_id = latest_sequence_result&.test_set_id || instance.module.default_test_set - redirect "#{BASE_PATH}/#{instance.id}/#{test_set_id}/?error=no_#{params[:endpoint]}" end end end diff --git a/lib/app/endpoint/test_set_endpoints.rb b/lib/app/endpoint/test_set_endpoints.rb new file mode 100644 index 000000000..492a8ae62 --- /dev/null +++ b/lib/app/endpoint/test_set_endpoints.rb @@ -0,0 +1,218 @@ +module Inferno + class App + module TestSetEndpoints + def self.included(klass) + klass.class_eval do + # Returns a specific testing instance test page + get '/:id/test_sets/:test_set/?' do + instance = Inferno::Models::TestingInstance.get(params[:id]) + halt 404 if instance.nil? + test_set = instance.module.test_sets[params[:test_set].to_sym] + halt 404 if test_set.nil? + sequence_results = instance.latest_results_by_case + + erb instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, + test_set: test_set, + sequence_results: sequence_results, + error_code: params[:error] + end + + get '/:id/test_sets/:test_set/report?' do + instance = Inferno::Models::TestingInstance.get(params[:id]) + halt 404 if instance.nil? + test_set = instance.module.test_sets[params[:test_set].to_sym] + halt 404 if test_set.nil? + sequence_results = instance.latest_results_by_case + + request_response_count = Inferno::Models::RequestResponse.all(instance_id: instance.id).count + latest_sequence_time = + if instance.sequence_results.count.positive? + Inferno::Models::SequenceResult.first(testing_instance: instance).created_at.strftime('%m/%d/%Y %H:%M') + else + 'No tests ran' + end + + report_summary = { + fhir_version: instance.fhir_version, + app_version: VERSION, + resource_references: instance.resource_references.count, + supported_resources: instance.supported_resources.count, + request_response: request_response_count, + latest_sequence_time: latest_sequence_time, + final_result: instance.final_result(params[:test_set]), + inferno_url: "#{request.base_url}#{base_path}/#{instance.id}/test_sets/#{params[:test_set]}/" + } + + erb( + :report, + { layout: false }, + instance: instance, + test_set: test_set, + show_button: false, + sequence_results: sequence_results, + report_summary: report_summary + ) + end + + # Cancels the currently running test + get '/:id/test_sets/:test_set/sequence_result/:sequence_result_id/cancel' do + sequence_result = Inferno::Models::SequenceResult.get(params[:sequence_result_id]) + halt 404 if sequence_result.testing_instance.id != params[:id] + test_set = sequence_result.testing_instance.module.test_sets[params[:test_set].to_sym] + halt 404 if test_set.nil? + + sequence_result.result = 'cancel' + cancel_message = 'Test cancelled by user.' + + unless sequence_result.test_results.empty? + last_result = sequence_result.test_results.last + last_result.result = 'cancel' + last_result.message = cancel_message + end + + sequence = sequence_result.testing_instance.module.sequences.find do |x| + x.sequence_name == sequence_result.name + end + + current_test_count = sequence_result.result_count + + sequence.tests.each_with_index do |test, index| + next if index < current_test_count + + sequence_result.test_results << Inferno::Models::TestResult.new(test_id: test[:test_id], + name: test[:name], + result: 'cancel', + url: test[:url], + description: test[:description], + test_index: test[:test_index], + message: cancel_message) + end + + sequence_result.save! + + test_group = test_set.test_case_by_id(sequence_result.test_case_id).test_group + + query_target = sequence_result.test_case_id + query_target = "#{test_group.id}/#{sequence_result.test_case_id}" unless test_group.nil? + + redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}" + end + + get '/:id/test_sets/:test_set/sequence_result?' do + redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/" + end + + # Run a sequence and get the results + post '/:id/test_sets/:test_set/sequence_result?' do + instance = Inferno::Models::TestingInstance.get(params[:id]) + halt 404 if instance.nil? + test_set = instance.module.test_sets[params[:test_set].to_sym] + halt 404 if test_set.nil? + + cookies[:instance_id_test_set] = "#{instance.id}/test_sets/#{params[:test_set]}" + + # Save params + params[:required_fields].split(',').each do |field| + instance.send("#{field}=", params[field]) if instance.respond_to? field + end + + instance.save! + + client = FHIR::Client.new(instance.url) + case instance.fhir_version + when 'stu3' + client.use_stu3 + when 'dstu2' + client.use_dstu2 + else + client.use_r4 + end + client.default_json + submitted_test_cases = params[:test_case].split(',') + + instance.reload # ensure that we have all the latest data + + total_tests = submitted_test_cases.reduce(0) do |total, set| + sequence_test_count = test_set.test_case_by_id(set).sequence.test_count + total + sequence_test_count + end + + test_group = nil + test_group = test_set.test_case_by_id(submitted_test_cases.first).test_group + failed_test_cases = [] + all_test_cases = [] + + timer_count = 0 + stayalive_timer_seconds = 20 + + finished = false + stream :keep_open do |out| + EventMachine::PeriodicTimer.new(stayalive_timer_seconds) do + timer_count += 1 + out << js_stayalive(timer_count * stayalive_timer_seconds) + end + + out << erb(instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, + test_set: test_set, + sequence_results: instance.latest_results_by_case, + tests_running: true, + test_group: test_group.id + ) + + next_test_case = submitted_test_cases.shift + finished = next_test_case.nil? + + test_count = 0 + until next_test_case.nil? + test_case = test_set.test_case_by_id(next_test_case) + + next_test_case = submitted_test_cases.shift + if test_case.nil? + finished = next_test_case.nil? + next + end + + out << js_show_test_modal + + instance.reload # ensure that we have all the latest data + sequence = test_case.sequence.new(instance, client, settings.disable_tls_tests) + count = 0 + sequence_result = sequence.start(test_set.id, test_case.id) do |result| + count += 1 + test_count += 1 + out << js_update_result(sequence, test_set, result, count, sequence.test_count, test_count, total_tests) + end + + sequence_result.next_test_cases = ([next_test_case] + submitted_test_cases).join(',') + + all_test_cases << test_case.id + failed_test_cases << test_case.id if sequence_result.fail? + + sequence_result.save! + if sequence_result.redirect_to_url + out << js_redirect_modal(sequence_result.redirect_to_url, sequence_result, instance) + next_test_case = nil + finished = false + elsif sequence_result.wait_at_endpoint + next_test_case = nil + finished = true + elsif !submitted_test_cases.empty? + out << js_next_sequence(sequence_result.next_test_cases) + else + finished = true + end + end + + query_target = failed_test_cases.join(',') + query_target = all_test_cases.join(',') if all_test_cases.length == 1 + + query_target = "#{test_group.id}/#{query_target}" unless test_group.nil? + + out << js_redirect("#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}") if finished + end + end + end + end + end + end +end From 53ad26161ef17536b75f430c17371bb744999176 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Fri, 12 Jul 2019 14:55:54 -0400 Subject: [PATCH 51/89] rename test_set param --- lib/app/endpoint/test_set_endpoints.rb | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/app/endpoint/test_set_endpoints.rb b/lib/app/endpoint/test_set_endpoints.rb index 492a8ae62..b19963a41 100644 --- a/lib/app/endpoint/test_set_endpoints.rb +++ b/lib/app/endpoint/test_set_endpoints.rb @@ -4,23 +4,23 @@ module TestSetEndpoints def self.included(klass) klass.class_eval do # Returns a specific testing instance test page - get '/:id/test_sets/:test_set/?' do + get '/:id/test_sets/:test_set_id/?' do instance = Inferno::Models::TestingInstance.get(params[:id]) halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] + test_set = instance.module.test_sets[params[:test_set_id].to_sym] halt 404 if test_set.nil? sequence_results = instance.latest_results_by_case - erb instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, + erb instance.module.view_by_test_set(params[:test_set_id]), {}, instance: instance, test_set: test_set, sequence_results: sequence_results, error_code: params[:error] end - get '/:id/test_sets/:test_set/report?' do + get '/:id/test_sets/:test_set_id/report?' do instance = Inferno::Models::TestingInstance.get(params[:id]) halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] + test_set = instance.module.test_sets[params[:test_set_id].to_sym] halt 404 if test_set.nil? sequence_results = instance.latest_results_by_case @@ -39,8 +39,8 @@ def self.included(klass) supported_resources: instance.supported_resources.count, request_response: request_response_count, latest_sequence_time: latest_sequence_time, - final_result: instance.final_result(params[:test_set]), - inferno_url: "#{request.base_url}#{base_path}/#{instance.id}/test_sets/#{params[:test_set]}/" + final_result: instance.final_result(params[:test_set_id]), + inferno_url: "#{request.base_url}#{base_path}/#{instance.id}/test_sets/#{params[:test_set_id]}/" } erb( @@ -55,10 +55,10 @@ def self.included(klass) end # Cancels the currently running test - get '/:id/test_sets/:test_set/sequence_result/:sequence_result_id/cancel' do + get '/:id/test_sets/:test_set_id/sequence_result/:sequence_result_id/cancel' do sequence_result = Inferno::Models::SequenceResult.get(params[:sequence_result_id]) halt 404 if sequence_result.testing_instance.id != params[:id] - test_set = sequence_result.testing_instance.module.test_sets[params[:test_set].to_sym] + test_set = sequence_result.testing_instance.module.test_sets[params[:test_set_id].to_sym] halt 404 if test_set.nil? sequence_result.result = 'cancel' @@ -95,21 +95,21 @@ def self.included(klass) query_target = sequence_result.test_case_id query_target = "#{test_group.id}/#{sequence_result.test_case_id}" unless test_group.nil? - redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}" + redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set_id]}/##{query_target}" end - get '/:id/test_sets/:test_set/sequence_result?' do - redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/" + get '/:id/test_sets/:test_set_id/sequence_result?' do + redirect "#{base_path}/#{params[:id]}/test_sets/#{params[:test_set_id]}/" end # Run a sequence and get the results - post '/:id/test_sets/:test_set/sequence_result?' do + post '/:id/test_sets/:test_set_id/sequence_result?' do instance = Inferno::Models::TestingInstance.get(params[:id]) halt 404 if instance.nil? - test_set = instance.module.test_sets[params[:test_set].to_sym] + test_set = instance.module.test_sets[params[:test_set_id].to_sym] halt 404 if test_set.nil? - cookies[:instance_id_test_set] = "#{instance.id}/test_sets/#{params[:test_set]}" + cookies[:instance_id_test_set] = "#{instance.id}/test_sets/#{params[:test_set_id]}" # Save params params[:required_fields].split(',').each do |field| @@ -152,7 +152,7 @@ def self.included(klass) out << js_stayalive(timer_count * stayalive_timer_seconds) end - out << erb(instance.module.view_by_test_set(params[:test_set]), {}, instance: instance, + out << erb(instance.module.view_by_test_set(params[:test_set_id]), {}, instance: instance, test_set: test_set, sequence_results: instance.latest_results_by_case, tests_running: true, @@ -208,7 +208,7 @@ def self.included(klass) query_target = "#{test_group.id}/#{query_target}" unless test_group.nil? - out << js_redirect("#{base_path}/#{params[:id]}/test_sets/#{params[:test_set]}/##{query_target}") if finished + out << js_redirect("#{base_path}/#{params[:id]}/test_sets/#{params[:test_set_id]}/##{query_target}") if finished end end end From d893368eb210dd77d4853093f62734e18518c503 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Fri, 12 Jul 2019 15:05:28 -0400 Subject: [PATCH 52/89] appease rubocop --- .rubocop.yml | 14 +++++++++++++ lib/app/endpoint/test_set_endpoints.rb | 29 +++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index df5df76c2..faef60521 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -21,3 +21,17 @@ Metrics/LineLength: Exclude: - 'lib/app/modules/**/*' - 'lib/app/helpers/browser_logic.rb' + +Metrics/AbcSize: + Exclude: + - 'lib/app/endpoint/oauth2_endpoints.rb' + - 'lib/app/endpoint/test_set_endpoints.rb' + +Metrics/MethodLength: + Exclude: + - 'lib/app/endpoint/oauth2_endpoints.rb' + - 'lib/app/endpoint/test_set_endpoints.rb' + +Metrics/PerceivedComplexity: + Exclude: + - 'lib/app/endpoint/oauth2_endpoints.rb' diff --git a/lib/app/endpoint/test_set_endpoints.rb b/lib/app/endpoint/test_set_endpoints.rb index b19963a41..c58ef8cdf 100644 --- a/lib/app/endpoint/test_set_endpoints.rb +++ b/lib/app/endpoint/test_set_endpoints.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Inferno class App module TestSetEndpoints @@ -11,10 +13,14 @@ def self.included(klass) halt 404 if test_set.nil? sequence_results = instance.latest_results_by_case - erb instance.module.view_by_test_set(params[:test_set_id]), {}, instance: instance, - test_set: test_set, - sequence_results: sequence_results, - error_code: params[:error] + erb( + instance.module.view_by_test_set(params[:test_set_id]), + {}, + instance: instance, + test_set: test_set, + sequence_results: sequence_results, + error_code: params[:error] + ) end get '/:id/test_sets/:test_set_id/report?' do @@ -152,12 +158,15 @@ def self.included(klass) out << js_stayalive(timer_count * stayalive_timer_seconds) end - out << erb(instance.module.view_by_test_set(params[:test_set_id]), {}, instance: instance, - test_set: test_set, - sequence_results: instance.latest_results_by_case, - tests_running: true, - test_group: test_group.id - ) + out << erb( + instance.module.view_by_test_set(params[:test_set_id]), + {}, + instance: instance, + test_set: test_set, + sequence_results: instance.latest_results_by_case, + tests_running: true, + test_group: test_group.id + ) next_test_case = submitted_test_cases.shift finished = next_test_case.nil? From 46c3b0e39479647c4dcf27d173d46230e4672bd5 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Fri, 12 Jul 2019 15:09:36 -0400 Subject: [PATCH 53/89] fix tests --- test/integration/instance_page_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/instance_page_test.rb b/test/integration/instance_page_test.rb index 3cc250b71..874c5173a 100644 --- a/test/integration/instance_page_test.rb +++ b/test/integration/instance_page_test.rb @@ -15,7 +15,7 @@ def setup follow_redirect! while last_response.status == 302 assert last_response.ok? @instance_path = last_request.url - instance_id = @instance_path.split('/').last(2).first # second to last + instance_id = @instance_path.split('/').last(3).first # third to last @instance = Inferno::Models::TestingInstance.get(instance_id) assert !@instance.nil?, "No instance id #{instance_id}" end From c1bbd21294abcba6560a2611461e63636abc4e72 Mon Sep 17 00:00:00 2001 From: Hershil Patel Date: Fri, 19 Jul 2019 13:01:59 -0400 Subject: [PATCH 54/89] updated test ids for sequences that inherit from capability statement sequence --- lib/app/modules/argonaut/argonaut_conformance_sequence.rb | 4 ++-- .../us_core_r4/us_core_r4_capability_statement_sequence.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/app/modules/argonaut/argonaut_conformance_sequence.rb b/lib/app/modules/argonaut/argonaut_conformance_sequence.rb index a92b2becc..8e8b5a265 100644 --- a/lib/app/modules/argonaut/argonaut_conformance_sequence.rb +++ b/lib/app/modules/argonaut/argonaut_conformance_sequence.rb @@ -59,7 +59,7 @@ class ArgonautConformanceSequence < CapabilityStatementSequence test 'FHIR server conformance states JSON support' do metadata do - id '03' + id '04' link 'http://www.fhir.org/guides/argonaut/r2/Conformance-server.html' desc %( @@ -93,7 +93,7 @@ class ArgonautConformanceSequence < CapabilityStatementSequence test 'Conformance Statement describes SMART on FHIR core capabilities' do metadata do - id '04' + id '05' link 'http://www.hl7.org/fhir/smart-app-launch/conformance/' optional desc %( diff --git a/lib/app/modules/us_core_r4/us_core_r4_capability_statement_sequence.rb b/lib/app/modules/us_core_r4/us_core_r4_capability_statement_sequence.rb index 4c9482969..c9b100d80 100644 --- a/lib/app/modules/us_core_r4/us_core_r4_capability_statement_sequence.rb +++ b/lib/app/modules/us_core_r4/us_core_r4_capability_statement_sequence.rb @@ -59,7 +59,7 @@ class UsCoreR4CapabilityStatementSequence < CapabilityStatementSequence test 'FHIR server capability states JSON support' do metadata do - id '03' + id '04' link 'http://hl7.org/fhir/us/core/2019Jan/CapabilityStatement-us-core-server.html' desc %( @@ -93,7 +93,7 @@ class UsCoreR4CapabilityStatementSequence < CapabilityStatementSequence test 'Capability Statement describes SMART on FHIR core capabilities' do metadata do - id '04' + id '05' link 'http://www.hl7.org/fhir/smart-app-launch/conformance/' optional desc %( @@ -128,7 +128,7 @@ class UsCoreR4CapabilityStatementSequence < CapabilityStatementSequence test 'Capability Statement lists supported Argonaut profiles, operations and search parameters' do metadata do - id '05' + id '06' link 'http://hl7.org/fhir/us/core/2019Jan/CapabilityStatement-us-core-server.html' desc %( The Argonaut Data Query Implementation Guide states: From 4baff3c51e034f011d649ce24d29a53bcf66253c Mon Sep 17 00:00:00 2001 From: yunwwang Date: Mon, 22 Jul 2019 15:30:30 -0400 Subject: [PATCH 55/89] FI-271 clinical notes (#242) * comming new test to check version * commiting before merge * updated link to documentation for the FHIR version test * fixed formatting issues * Update lib/app/modules/core/capability_statement_sequence.rb Co-Authored-By: Reece Adamson <41651655+radamson@users.noreply.github.com> * Update lib/app/modules/core/capability_statement_sequence.rb Co-Authored-By: Reece Adamson <41651655+radamson@users.noreply.github.com> * updated test version to check for nil values, and uppercased the values for the version * updated version on Gemfile.lock to be 2.0.2 instead of 1.16.1 * Apply patient_id save hotfix to development. * Fix newline issue for rubocop. * added an assert to check if uri is valid, and updated test to not redirect to an invalid url. Also updated tests to check for invalid redirect and tokens cause them to fail with prettier error message rather than code failure * updated assert to accept a message as a param * updated formatting to pass rubocop * updated formatting to pass rubocop * refactored assertion to be assert_valid_http_uri, and replaced instances that were manually testing the uri * Add Sequence and tests for US Core R4 Clinical Notes * Fix lint styling * Fix more styling errors * updated assert_valid_http_uri to no change the input argument (to avoid side effects) and instead have a new error_message variable * removed unecessary semicolon * condensed code into simpler line * removed spaces * Fix PR comments * update background * Add period to end of sentence. * Update clinicalnotes_sequence.rb Fix PR comments. Add function assert_attachment_match for comparing attachment urls. Add class ClinicalNoteAttachment * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * updated test ids for sequences that inherit from capability statement sequence * Add Sequence and tests for US Core R4 Clinical Notes * Fix lint styling * Fix more styling errors * Fix PR comments * Update clinicalnotes_sequence.rb Fix PR comments. Add function assert_attachment_match for comparing attachment urls. Add class ClinicalNoteAttachment * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * Update lib/app/modules/us_core_r4/clinicalnotes_sequence.rb Co-Authored-By: Rob Scanlon * fix review comment that not working with open endpoint. Add set_no_auth if token is blank --- .gitignore | 3 +- lib/app/modules/us_core_module.yml | 1 + .../us_core_r4/clinicalnotes_sequence.rb | 234 ++++++++++++++++++ ..._core_r4_clinicalnotes_diagrpt_bundle.json | 177 +++++++++++++ ...s_core_r4_clinicalnotes_docref_bundle.json | 162 ++++++++++++ .../us_core_r4/clinicalnotes_sequence_test.rb | 103 ++++++++ 6 files changed, 679 insertions(+), 1 deletion(-) create mode 100644 lib/app/modules/us_core_r4/clinicalnotes_sequence.rb create mode 100644 test/fixtures/us_core_r4_clinicalnotes_diagrpt_bundle.json create mode 100644 test/fixtures/us_core_r4_clinicalnotes_docref_bundle.json create mode 100644 test/sequence/us_core_r4/clinicalnotes_sequence_test.rb diff --git a/.gitignore b/.gitignore index e1bd7d268..26674d9c3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ data/* coverage tmp/* .vscode/* -resources/terminology/* \ No newline at end of file +resources/terminology/* +.ruby-version diff --git a/lib/app/modules/us_core_module.yml b/lib/app/modules/us_core_module.yml index e057e7584..7709101b5 100644 --- a/lib/app/modules/us_core_module.yml +++ b/lib/app/modules/us_core_module.yml @@ -46,3 +46,4 @@ test_sets: - UsCoreR4PractitionerroleSequence - UsCoreR4ProcedureSequence - R4ProvenanceSequence + - UsCoreR4ClinicalNotesSequence diff --git a/lib/app/modules/us_core_r4/clinicalnotes_sequence.rb b/lib/app/modules/us_core_r4/clinicalnotes_sequence.rb new file mode 100644 index 000000000..ed7b20e23 --- /dev/null +++ b/lib/app/modules/us_core_r4/clinicalnotes_sequence.rb @@ -0,0 +1,234 @@ +# frozen_string_literal: true + +module Inferno + module Sequence + class UsCoreR4ClinicalNotesSequence < SequenceBase + group 'US Core R4 Profile Conformance' + + title 'Clinical Notes Guideline Tests' + + description 'Verify that DocumentReference and DiagnosticReport resources on the FHIR server follow the US Core R4 Clinical Notes Guideline' + + test_id_prefix 'ClinicalNotes' + + requires :token, :patient_id + conformance_supports :DocumentReference, :DiagnosticReport + + details %( + + The #{title} Sequence tests DiagnosticReport and DocumentReference resources associated with the provided patient. The resources + returned will be checked for consistency against the [US Core Clinical Notes Guidance](https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html) + + ) + + @clinical_notes_found = false + + def test_clinical_notes_document_reference(type_code) + skip 'No Clinical Notes appear to be available for this patient. Please use patients with more information.' unless @clinical_notes_found + + assert @actual_type_codes.include?(type_code), "Clinical Notes shall have at least one DocumentReference with type #{type_code}" + end + + def test_clinical_notes_diagnostic_report(category_code) + skip 'No Clinical Notes appear to be available for this patient. Please use patients with more information.' unless @clinical_notes_found + + search_params = { 'patient': @instance.patient_id, 'category': category_code } + resource_class = 'DiagnosticReport' + @report_attachments = ClinicalNoteAttachment.new(resource_class) + + reply = get_resource_by_params(versioned_resource_class(resource_class), search_params) + assert_response_ok(reply) + assert_bundle_response(reply) + + resource_count = reply&.resource&.entry&.length || 0 + @resources_found = true if resource_count.positive? + + assert @resources_found, "Clinical Notes shall have at least one DiagnosticReport with category #{category_code}" + + diagnostic_reports = reply&.resource&.entry&.map { |entry| entry&.resource } + + diagnostic_reports&.each do |report| + report&.presentedForm&.select { |attachment| !@report_attachments.attachment.key?(attachment&.url) }&.each do |attachment| + @report_attachments.attachment[attachment.url] = report.id + end + end + end + + test 'Server returns expected results from DocumentReference search by patient+clinicalnotes' do + metadata do + id '01' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + @client.set_no_auth if @instance.token.blank? + + search_params = { 'patient': @instance.patient_id, 'category': 'clinical-note' } + resource_class = 'DocumentReference' + + @document_attachments = ClinicalNoteAttachment.new(resource_class) + + reply = get_resource_by_params(versioned_resource_class(resource_class), search_params) + assert_response_ok(reply) + assert_bundle_response(reply) + + resource_count = reply&.resource&.entry&.length || 0 + @clinical_notes_found = true if resource_count.positive? + + skip 'No Clinical Notes appear to be available for this patient. Please use patients with more information.' unless @clinical_notes_found + + document_references = reply&.resource&.entry&.map { |entry| entry&.resource } + + @required_type_codes = Set[ + '11488-4', # Consultation Note + '18842-5', # Dischard Summary + '34117-2', # History and physical note + '28570-0', # Procedure note + '11506-3' # Progress note + ] + + @actual_type_codes = Set[] + + document_references&.select { |document| document&.type&.coding&.present? }&.each do |document| + document.type.coding.select { |coding| coding&.system == 'http://loinc.org' && @required_type_codes.include?(coding&.code) }&.each do |coding| + @actual_type_codes << coding.code + + document&.content&.select { |content| !@document_attachments.attachment.key?(content&.attachment&.url) }&.each do |content| + @document_attachments.attachment[content.attachment.url] = document.id + end + end + end + end + + test 'Server shall have Consultation Notes' do + metadata do + id '02' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_document_reference('11488-4') + end + + test 'Server shall have Discharge Summary' do + metadata do + id '03' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_document_reference('18842-5') + end + + test 'Server shall have History and Physical Note' do + metadata do + id '04' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_document_reference('34117-2') + end + + test 'Server shall have Procedures Note' do + metadata do + id '05' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_document_reference('28570-0') + end + + test 'Server shall have Progress Note' do + metadata do + id '06' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_document_reference('11506-3') + end + + test 'Server returns Cardiology report from DiagnosticReport search by patient+category' do + metadata do + id '07' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_diagnostic_report('http://loinc.org|LP29708-2') + end + + test 'Server returns Pathology report from DiagnosticReport search by patient+category' do + metadata do + id '08' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_diagnostic_report('http://loinc.org|LP7839-6') + end + + test 'Server returns Radiology report from DiagnosticReport search by patient+category' do + metadata do + id '09' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + test_clinical_notes_diagnostic_report('http://loinc.org|LP29684-5') + end + + test 'DiagnosticReport and DocumentReference reference the same attachment' do + metadata do + id '10' + link 'https://www.hl7.org/fhir/us/core/clinical-notes-guidance.html' + desc %( + ) + versions :r4 + end + + skip 'No Clinical Notes appear to be available for this patient. Please use patients with more information.' unless @clinical_notes_found + + assert_attachment_matched(@document_attachments, @report_attachments) + assert_attachment_matched(@report_attachments, @document_attachments) + end + + def assert_attachment_matched(source_attachments, target_attachments) + not_matched_urls = source_attachments.attachment.keys - target_attachments.attachment.keys + not_matched_attachments = not_matched_urls.map { |url| "#{url} in #{source_attachments.resource_class}/#{source_attachments.attachment[url]}" } + + assert not_matched_attachments.empty?, "Attachments #{not_matched_attachments.join(', ')} are not referenced in any #{target_attachments.resource_class}." + end + end + + class ClinicalNoteAttachment + attr_reader :resource_class + attr_reader :attachment + + def initialize(resource_class) + @resource_class = resource_class + @attachment = {} + end + end + end +end diff --git a/test/fixtures/us_core_r4_clinicalnotes_diagrpt_bundle.json b/test/fixtures/us_core_r4_clinicalnotes_diagrpt_bundle.json new file mode 100644 index 000000000..96962992e --- /dev/null +++ b/test/fixtures/us_core_r4_clinicalnotes_diagrpt_bundle.json @@ -0,0 +1,177 @@ +{ + "resourceType": "Bundle", + "id": "9d89bb92-1bac-498e-99ac-d2dbaa75caed", + "type": "searchset", + "entry": [ + { + "resource": { + "resourceType": "DiagnosticReport", + "id": "SMART-DiagnosticReport-1-note", + "status": "final", + "category": { + "coding": [ + { + "system": "http://loinc.org", + "code": "LP29708-2", + "display": "Cardiology" + } + ] + }, + "code": { + "coding": [ + { + "system": "http://loinc.org", + "code": "57698-3", + "display": "Lipid Panel" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "presentedForm": [ + { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-1-note" + } + ] + } + }, + { + "resource": { + "resourceType": "DiagnosticReport", + "id": "SMART-DiagnosticReport-2-note", + "status": "final", + "category": { + "coding": [ + { + "system": "http://loinc.org", + "code": "LP7839-6", + "display": "Pathology" + } + ] + }, + "code": { + "coding": [ + { + "system": "http://loinc.org", + "code": "57698-3", + "display": "Lipid Panel" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "presentedForm": [ + { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-2-note" + } + ] + } + }, + { + "resource": { + "resourceType": "DiagnosticReport", + "id": "SMART-DiagnosticReport-3-note", + "status": "final", + "category": { + "coding": [ + { + "system": "http://loinc.org", + "code": "LP29684-5", + "display": "Radiology" + } + ] + }, + "code": { + "coding": [ + { + "system": "http://loinc.org", + "code": "57698-3", + "display": "Lipid Panel" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "presentedForm": [ + { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-3-note" + } + ] + } + }, + { + "resource": { + "resourceType": "DiagnosticReport", + "id": "SMART-DiagnosticReport-4-note", + "status": "final", + "category": { + "coding": [ + { + "system": "http://loinc.org", + "code": "LP29708-2", + "display": "Cardiology" + } + ] + }, + "code": { + "coding": [ + { + "system": "http://loinc.org", + "code": "57698-3", + "display": "Lipid Panel" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "presentedForm": [ + { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-4-note" + } + ] + } + }, + { + "resource": { + "resourceType": "DiagnosticReport", + "id": "SMART-DiagnosticReport-5-note", + "status": "final", + "category": { + "coding": [ + { + "system": "http://loinc.org", + "code": "LP29708-2", + "display": "Cardiology" + } + ] + }, + "code": { + "coding": [ + { + "system": "http://loinc.org", + "code": "57698-3", + "display": "Lipid Panel" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "presentedForm": [ + { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-5-note" + } + ] + } + } + ] + } \ No newline at end of file diff --git a/test/fixtures/us_core_r4_clinicalnotes_docref_bundle.json b/test/fixtures/us_core_r4_clinicalnotes_docref_bundle.json new file mode 100644 index 000000000..4c3889c0c --- /dev/null +++ b/test/fixtures/us_core_r4_clinicalnotes_docref_bundle.json @@ -0,0 +1,162 @@ +{ + "resourceType": "Bundle", + "id": "9d89bb92-1bac-498e-99ac-d2dbaa75caed", + "type": "searchset", + "entry": [ + { + "resource": { + "resourceType": "DocumentReference", + "id": "SMART-DocumentReference-1-note", + "status": "current", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "11488-4", + "display": "Consultation Note" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "content": [ + { + "attachment": { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-1-note" + } + } + ] + } + }, + { + "resource": { + "resourceType": "DocumentReference", + "id": "SMART-DocumentReference-2-note", + "status": "current", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "18842-5", + "display": "Discharge Summary" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "content": [ + { + "attachment": { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-2-note" + } + } + ] + } + }, + { + "fullUrl": "https://api.logicahealth.org/InfernoR4yw/open/DocumentReference/SMART-DocumentReference-3-note", + "resource": { + "resourceType": "DocumentReference", + "id": "SMART-DocumentReference-3-note", + "meta": { + "versionId": "1", + "lastUpdated": "2019-03-07T08:52:17.000+00:00" + }, + "text": { + "status": "generated", + "div": "
Emergency Department Note
" + }, + "status": "current", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "34117-2", + "display": "History & Physical Note" + } + ], + "text": "Note" + }, + "subject": { + "reference": "Patient/SMART-2169591" + }, + "date": "2006-08-30T00:00:00.000-06:00", + "description": "Emergency Department Note", + "content": [ + { + "attachment": { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-3-note", + "size": 0 + } + } + ] + }, + "search": { + "mode": "match" + }, + "response": { + "status": "201 Created", + "etag": "W/\"1\"" + } + }, + { + "resource": { + "resourceType": "DocumentReference", + "id": "SMART-DocumentReference-4-note", + "status": "current", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "28570-0", + "display": "Procedures Note" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "content": [ + { + "attachment": { + "contentType": "text/plain", + "url": "/Binary/SMART-Binary-4-note" + } + } + ] + } + }, + { + "resource": { + "resourceType": "DocumentReference", + "id": "SMART-DocumentReference-5-document", + "status": "current", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "11506-3", + "display": "Progress Note" + } + ] + }, + "subject": { + "reference": "Patient/1234" + }, + "content": [ + { + "attachment": { + "contentType": "application/pdf", + "url": "/Binary/SMART-Binary-5-note" + } + } + ] + } + } + ] + } \ No newline at end of file diff --git a/test/sequence/us_core_r4/clinicalnotes_sequence_test.rb b/test/sequence/us_core_r4/clinicalnotes_sequence_test.rb new file mode 100644 index 000000000..b94848857 --- /dev/null +++ b/test/sequence/us_core_r4/clinicalnotes_sequence_test.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require_relative '../../test_helper' + +class UsCoreR4ClinicalNotesSequenceTest < MiniTest::Test + def setup + @patient_id = 1234 + @docref_bundle = FHIR.from_contents(load_fixture(:us_core_r4_clinicalnotes_docref_bundle)) + @diagrpt_bundle = FHIR.from_contents(load_fixture(:us_core_r4_clinicalnotes_diagrpt_bundle)) + + @instance = Inferno::Models::TestingInstance.new( + url: 'http://www.example.com', + client_name: 'Inferno', + base_url: 'http://localhost:4567', + client_endpoint_key: Inferno::SecureRandomBase62.generate(32), + client_id: SecureRandom.uuid, + selected_module: 'us_core_r4', + oauth_authorize_endpoint: 'http://oauth_reg.example.com/authorize', + oauth_token_endpoint: 'http://oauth_reg.example.com/token', + scopes: 'launch openid patient/*.* profile', + token: 99_897_979 + ) + + @instance.save! + + @instance.resource_references << Inferno::Models::ResourceReference.new( + resource_type: 'Patient', + resource_id: @patient_id + ) + + @instance.supported_resources << Inferno::Models::SupportedResource.create( + resource_type: 'DocumentReference', + testing_instance_id: @instance.id, + supported: true, + read_supported: true + ) + + @request_headers = { + 'Accept' => 'application/fhir+json', + 'Accept-Charset' => 'utf-8', + 'Accept-Encoding' => 'gzip, deflate', + 'Authorization' => 'Bearer 99897979', + 'Host' => 'www.example.com', + 'User-Agent' => 'Ruby FHIR Client' + } + + client = FHIR::Client.new(@instance.url) + client.use_r4 + client.default_json + @sequence = Inferno::Sequence::UsCoreR4ClinicalNotesSequence.new(@instance, client, true) + end + + def full_sequence_stubs + WebMock.reset! + + # Search Clincal Notes + stub_request(:get, "http://www.example.com/DocumentReference?category=clinical-note&patient=#{@patient_id}") + .with(headers: @request_headers) + .to_return( + status: 200, + body: @docref_bundle.to_json, + headers: { content_type: 'application/fhir+json; charset=UTF-8' } + ) + + # Search Cardiology report + stub_request(:get, "http://www.example.com/DiagnosticReport?category=http://loinc.org|LP29708-2&patient=#{@patient_id}") + .with(headers: @request_headers) + .to_return( + status: 200, + body: @diagrpt_bundle.to_json, + headers: { content_type: 'application/fhir+json; charset=UTF-8' } + ) + + # Search Pathology report + stub_request(:get, "http://www.example.com/DiagnosticReport?category=http://loinc.org|LP7839-6&patient=#{@patient_id}") + .with(headers: @request_headers) + .to_return( + status: 200, + body: @diagrpt_bundle.to_json, + headers: { content_type: 'application/fhir+json; charset=UTF-8' } + ) + + # Search Cardiology report + stub_request(:get, "http://www.example.com/DiagnosticReport?category=http://loinc.org|LP29684-5&patient=#{@patient_id}") + .with(headers: @request_headers) + .to_return( + status: 200, + body: @diagrpt_bundle.to_json, + headers: { content_type: 'application/fhir+json; charset=UTF-8' } + ) + end + + def test_all_pass + full_sequence_stubs + + sequence_result = @sequence.start + + failures = sequence_result.failures + assert failures.empty?, "All tests should pass. First error: #{failures&.first&.message}" + assert !sequence_result.skip?, 'No tests should be skipped.' + assert sequence_result.pass?, 'The sequence should be marked as pass.' + end +end From f76d627ab8b8472d89e7caa9831a125b647b78a2 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Tue, 23 Jul 2019 09:31:40 -0400 Subject: [PATCH 56/89] update url --- lib/app/endpoint/oauth2_endpoints.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app/endpoint/oauth2_endpoints.rb b/lib/app/endpoint/oauth2_endpoints.rb index f1e5b4dd5..ce7d560a1 100644 --- a/lib/app/endpoint/oauth2_endpoints.rb +++ b/lib/app/endpoint/oauth2_endpoints.rb @@ -198,7 +198,7 @@ def self.included(klass) else latest_sequence_result = Inferno::Models::SequenceResult.first(testing_instance: instance) test_set_id = latest_sequence_result&.test_set_id || instance.module.default_test_set - redirect "#{BASE_PATH}/#{instance.id}/#{test_set_id}/?error=no_#{params[:endpoint]}" + redirect "#{BASE_PATH}/#{instance.id}/test_sets/#{test_set_id}/?error=no_#{params[:endpoint]}" end end end From d60c3aa6b553db6d672df62c2246338fb96f7926 Mon Sep 17 00:00:00 2001 From: Stephen MacVicar Date: Tue, 23 Jul 2019 13:47:18 -0400 Subject: [PATCH 57/89] refactor token refresh tests --- test/sequence/token_refresh_sequence_test.rb | 84 ++++++++++---------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/test/sequence/token_refresh_sequence_test.rb b/test/sequence/token_refresh_sequence_test.rb index 0a69e10da..cab89d263 100644 --- a/test/sequence/token_refresh_sequence_test.rb +++ b/test/sequence/token_refresh_sequence_test.rb @@ -7,18 +7,20 @@ class TokenRefreshSequenceTest < MiniTest::Test def setup refresh_token = JSON::JWT.new(iss: 'foo_refresh') - @instance = Inferno::Models::TestingInstance.new(url: 'http://www.example.com', - client_name: 'Inferno', - base_url: 'http://localhost:4567', - client_endpoint_key: Inferno::SecureRandomBase62.generate(32), - client_id: SecureRandom.uuid, - selected_module: 'argonaut', - oauth_authorize_endpoint: 'http://oauth_reg.example.com/authorize', - oauth_token_endpoint: 'http://oauth_reg.example.com/token', - initiate_login_uri: 'http://localhost:4567/launch', - redirect_uris: 'http://localhost:4567/redirect', - scopes: 'launch openid patient/*.* profile', - refresh_token: refresh_token) + @instance = Inferno::Models::TestingInstance.new( + url: 'http://www.example.com', + client_name: 'Inferno', + base_url: 'http://localhost:4567', + client_endpoint_key: Inferno::SecureRandomBase62.generate(32), + client_id: SecureRandom.uuid, + selected_module: 'argonaut', + oauth_authorize_endpoint: 'http://oauth_reg.example.com/authorize', + oauth_token_endpoint: 'http://oauth_reg.example.com/token', + initiate_login_uri: 'http://localhost:4567/launch', + redirect_uris: 'http://localhost:4567/redirect', + scopes: 'launch openid patient/*.* profile', + refresh_token: refresh_token + ) @instance.save! # this is for convenience. we could rewrite to ensure nothing gets saved within tests. client = FHIR::Client.new(@instance.url) @@ -28,47 +30,41 @@ def setup @standalone_token_exchange = load_json_fixture(:standalone_token_exchange) end - def all_pass(confidential) + def setup_mocks WebMock.reset! - if confidential - # Responses Must Contain Authorization Header - stub_request(:post, @instance.oauth_token_endpoint) - .with(headers: { 'Content-Type' => 'application/x-www-form-urlencoded', - 'Authorization' => - "Basic #{Base64.strict_encode64(@instance.client_id + - ':' + - @instance.client_secret)}" }, - body: { 'grant_type' => 'refresh_token', - 'refresh_token' => @instance.refresh_token }) - .to_return(status: 200, - body: @standalone_token_exchange.to_json, - headers: { content_type: 'application/json; charset=UTF-8', - cache_control: 'no-store', - pragma: 'no-cache' }) - # Responses must NOT contain client_id in the body or the client secret in any situation - stub_request(:post, @instance.oauth_token_endpoint) - .with(body: /client_id|client_secret/) - .to_return(status: 401) + headers = { + 'Content-Type' => 'application/x-www-form-urlencoded', + } + body = { + 'grant_type' => 'refresh_token', + 'refresh_token' => @instance.refresh_token + } + + if @instance.client_secret.present? + headers['Authorization'] = "Basic #{Base64.strict_encode64(@instance.client_id + ':' + @instance.client_secret)}" else - stub_request(:post, @instance.oauth_token_endpoint) - .with(headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }, - body: { 'client_id' => @instance.client_id, - 'grant_type' => 'refresh_token', - 'refresh_token' => @instance.refresh_token }) - .to_return(status: 200, - body: @standalone_token_exchange.to_json, - headers: { content_type: 'application/json; charset=UTF-8', - cache_control: 'no-store', - pragma: 'no-cache' }) + body['client_id'] = @instance.client_id end + stub_request(:post, @instance.oauth_token_endpoint) + .with(headers: headers, + body: body) + .to_return(status: 200, + body: @standalone_token_exchange.to_json, + headers: { content_type: 'application/json; charset=UTF-8', + cache_control: 'no-store', + pragma: 'no-cache' }) + # To test rejection of invalid client_id stub_request(:post, @instance.oauth_token_endpoint) .with(body: /INVALID/, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }) .to_return(status: 401) + end + def all_pass + setup_mocks sequence_result = @sequence.start assert sequence_result.pass?, 'The sequence should be marked as pass.' @@ -77,12 +73,12 @@ def all_pass(confidential) def test_all_pass_confidential_client @instance.client_secret = SecureRandom.uuid @instance.confidential_client = true - all_pass(true) + all_pass end def test_all_pass_public_client @instance.client_secret = nil @instance.confidential_client = nil - all_pass(false) + all_pass end end From 1754b2cc244d63c2da241f0c154e2e252919fb56 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 00:54:08 -0400 Subject: [PATCH 58/89] Reorganize token refresh tests to check for failure on optional param. --- .../modules/smart/token_refresh_sequence.rb | 156 ++++++++++-------- test/sequence/token_refresh_sequence_test.rb | 106 ++++++++++-- 2 files changed, 184 insertions(+), 78 deletions(-) diff --git a/lib/app/modules/smart/token_refresh_sequence.rb b/lib/app/modules/smart/token_refresh_sequence.rb index 3b2e3605b..9f7562f6d 100644 --- a/lib/app/modules/smart/token_refresh_sequence.rb +++ b/lib/app/modules/smart/token_refresh_sequence.rb @@ -17,144 +17,166 @@ class TokenRefreshSequence < SequenceBase Refresh tokens are typically longer lived than access tokens and allow client applications to obtain a new access token Refresh tokens themselves cannot provide access to resources on the server. + Token refreshes are accomplished through a `POST` request to the token exchange endpoint as described in the + [SMART App Launch Framework](http://www.hl7.org/fhir/smart-app-launch/#step-5-later-app-uses-a-refresh-token-to-obtain-a-new-access-token) + # Test Methodology - Inferno will attempt to exchange the refresh token for a new access token and verify that the information returned + This test attempt to exchange the refresh token for a new access token and verify that the information returned contains the required fields and uses the proper headers. + This test + For more information see: * [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749) * [Using a refresh token to obtain a new access token](http://hl7.org/fhir/smart-app-launch/#step-5-later-app-uses-a-refresh-token-to-obtain-a-new-access-token) ) - test 'Refresh token exchange fails when supplied invalid Refresh Token or Client ID.' do - metadata do - id '01' - link 'https://tools.ietf.org/html/rfc6749' - desc %( - If the request failed verification or is invalid, the authorization server returns an error response. ) - end + INVALID_CLIENT_ID = 'INVALID_CLIENT_ID' + INVALID_REFRESH_TOKEN = 'INVALID_REFRESH_TOKEN' + def encoded_secret(client_id, client_secret) + "Basic #{Base64.strict_encode64(client_id + ':' + client_secret)}" + end + + def perform_refresh_request(client_id, refresh_token, provide_scope = false) oauth2_params = { 'grant_type' => 'refresh_token', - 'refresh_token' => 'INVALID REFRESH TOKEN', - 'client_id' => @instance.client_id + 'refresh_token' => refresh_token } + oauth2_headers = { 'Content-Type' => 'application/x-www-form-urlencoded' } - token_response = LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params) - assert_response_bad_or_unauthorized token_response + if @instance.confidential_client + oauth2_headers['Authorization'] = encoded_secret(client_id, @instance.client_secret) + else + oauth2_params['client_id'] = client_id + end - oauth2_params = { - 'grant_type' => 'refresh_token', - 'refresh_token' => @instance.refresh_token, - 'client_id' => 'INVALID_CLIENT_ID' - } + oauth2_params['scope'] = @instance.scopes if provide_scope - token_response = LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params) - assert_response_bad_or_unauthorized token_response + LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params, oauth2_headers) end - test 'Server successfully exchanges refresh token at OAuth token endpoint.' do + test 'Refresh token exchange fails when provided invalid Refresh Token.' do metadata do - id '02' + id '01' link 'https://tools.ietf.org/html/rfc6749' desc %( - Server successfully exchanges refresh token at OAuth token endpoint. - ) - end - - oauth2_params = { - 'grant_type' => 'refresh_token', - 'refresh_token' => @instance.refresh_token - } - oauth2_headers = { 'Content-Type' => 'application/x-www-form-urlencoded' } - - if @instance.confidential_client - oauth2_headers['Authorization'] = "Basic #{Base64.strict_encode64(@instance.client_id + - ':' + - @instance.client_secret)}" - else - oauth2_params['client_id'] = @instance.client_id + If the request failed verification or is invalid, the authorization server returns an error response. ) end - @token_response = LoggedRestClient.post(@instance.oauth_token_endpoint, oauth2_params, oauth2_headers) - assert_response_ok(@token_response) + token_response = perform_refresh_request(@instance.client_id, INVALID_REFRESH_TOKEN) + assert_response_bad_or_unauthorized token_response end - test 'Data returned from refresh token exchange contains required information encoded in JSON.' do + test 'Refresh token exchange fails when provided invalid Client ID.' do metadata do - id '03' - link 'http://www.hl7.org/fhir/smart-app-launch/' + id '02' + link 'https://tools.ietf.org/html/rfc6749' desc %( - The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. - access_token, token_type, and scope are required. access_token must be Bearer. - ) + If the request failed verification or is invalid, the authorization server returns an error response. ) end - @token_response_headers = @token_response.headers - assert_valid_json(@token_response.body) - @token_response_body = JSON.parse(@token_response.body) + token_response = perform_refresh_request(INVALID_CLIENT_ID, @instance.refresh_token) + assert_response_bad_or_unauthorized token_response + end - assert @token_response_body.key?('access_token'), 'Token response did not contain access_token as required' + def validate_and_save_refresh_response(token_response) + assert_response_ok(token_response) + assert_valid_json(token_response.body) + token_response_body = JSON.parse(token_response.body) + + assert token_response_body.key?('access_token'), 'Token response did not contain access_token as required' token_retrieved_at = DateTime.now @instance.resource_references.each(&:destroy) - @instance.resource_references << Inferno::Models::ResourceReference.new(resource_type: 'Patient', resource_id: @token_response_body['patient']) if @token_response_body.key?('patient') + @instance.resource_references << Inferno::Models::ResourceReference.new(resource_type: 'Patient', resource_id: token_response_body['patient']) if token_response_body.key?('patient') @instance.save! - @instance.update(token: @token_response_body['access_token'], token_retrieved_at: token_retrieved_at) + @instance.update(token: token_response_body['access_token'], token_retrieved_at: token_retrieved_at) ['token_type', 'scope'].each do |key| - assert @token_response_body.key?(key), "Token response did not contain #{key} as required" + assert token_response_body.key?(key), "Token response did not contain #{key} as required" end # case insentitive per https://tools.ietf.org/html/rfc6749#section-5.1 - assert @token_response_body['token_type'].casecmp('bearer').zero?, 'Token type must be Bearer.' + assert token_response_body['token_type'].casecmp('bearer').zero?, 'Token type must be Bearer.' expected_scopes = @instance.scopes.split(' ') - actual_scopes = @token_response_body['scope'].split(' ') + actual_scopes = token_response_body['scope'].split(' ') warning do missing_scopes = (expected_scopes - actual_scopes) assert missing_scopes.empty?, "Token exchange response did not include expected scopes: #{missing_scopes}" - assert @token_response_body.key?('patient'), 'No patient id provided in token exchange.' + assert token_response_body.key?('patient'), 'No patient id provided in token exchange.' end - scopes = @token_response_body['scope'] || @instance.scopes + scopes = token_response_body['scope'] || @instance.scopes @instance.save! @instance.update(scopes: scopes) - if @token_response_body.key?('id_token') + if token_response_body.key?('id_token') @instance.save! - @instance.update(id_token: @token_response_body['id_token']) + @instance.update(id_token: token_response_body['id_token']) end - if @token_response_body.key?('refresh_token') + if token_response_body.key?('refresh_token') @instance.save! - @instance.update(refresh_token: @token_response_body['refresh_token']) + @instance.update(refresh_token: token_response_body['refresh_token']) end + [:cache_control, :pragma].each do |key| + assert token_response.headers.key?(key), "Token response headers did not contain #{key} as is required in the SMART App Launch Guide." + end + + assert token_response.headers[:cache_control].downcase.include?('no-store'), 'Token response header must have cache_control containing no-store.' + assert token_response.headers[:pragma].downcase.include?('no-cache'), 'Token response header must have pragma containing no-cache.' end - test 'Response includes correct HTTP Cache-Control and Pragma headers' do + test 'Server successfully refreshes the access token when optional scope parameter omitted.' do metadata do - id '04' - link 'http://www.hl7.org/fhir/smart-app-launch/' + id '03' + link 'https://tools.ietf.org/html/rfc6749' desc %( + Server successfully exchanges refresh token at OAuth token endpoint without providing scope in + the body of the request. + + The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. + access_token, token_type, and scope are required. access_token must be Bearer. + The authorization servers response must include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache. ) end - [:cache_control, :pragma].each do |key| - assert @token_response_headers.key?(key), "Token response headers did not contain #{key} as is required in the SMART App Launch Guide." + specify_scopes = false + + token_response = perform_refresh_request(@instance.client_id, @instance.refresh_token, specify_scopes) + validate_and_save_refresh_response(token_response) + end + + test 'Server successfully refreshes the access token when optional scope parameter provided.' do + metadata do + id '05' + link 'https://tools.ietf.org/html/rfc6749' + desc %( + Server successfully exchanges refresh token at OAuth token endpoint while providing scope in + the body of the request. + + The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. + access_token, token_type, and scope are required. access_token must be Bearer. + + The authorization servers response must include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache. + ) end - assert @token_response_headers[:cache_control].downcase.include?('no-store'), 'Token response header must have cache_control containing no-store.' - assert @token_response_headers[:pragma].downcase.include?('no-cache'), 'Token response header must have pragma containing no-cache.' + specify_scopes = true + + token_response = perform_refresh_request(@instance.client_id, @instance.refresh_token, specify_scopes) + validate_and_save_refresh_response(token_response) end end end diff --git a/test/sequence/token_refresh_sequence_test.rb b/test/sequence/token_refresh_sequence_test.rb index cab89d263..888b385c0 100644 --- a/test/sequence/token_refresh_sequence_test.rb +++ b/test/sequence/token_refresh_sequence_test.rb @@ -18,7 +18,7 @@ def setup oauth_token_endpoint: 'http://oauth_reg.example.com/token', initiate_login_uri: 'http://localhost:4567/launch', redirect_uris: 'http://localhost:4567/redirect', - scopes: 'launch openid patient/*.* profile', + scopes: 'launch/patient online_access openid profile launch user/*.* patient/*.*', refresh_token: refresh_token ) @@ -28,39 +28,74 @@ def setup client.default_json @sequence = Inferno::Sequence::TokenRefreshSequence.new(@instance, client, true) @standalone_token_exchange = load_json_fixture(:standalone_token_exchange) + @confidential_client_secret = SecureRandom.uuid end - def setup_mocks + def setup_mocks(failure_mode = nil) WebMock.reset! headers = { - 'Content-Type' => 'application/x-www-form-urlencoded', + 'Content-Type' => 'application/x-www-form-urlencoded' } body = { 'grant_type' => 'refresh_token', 'refresh_token' => @instance.refresh_token } + body_with_scope = { + 'grant_type' => 'refresh_token', + 'refresh_token' => @instance.refresh_token, + 'scope' => @instance.scopes + } + + exchange_response = @standalone_token_exchange.dup + + exchange_response['token_type'] = 'unknown' if failure_mode == :bad_token_type + exchange_response.delete('scope') if failure_mode == :no_scope + exchange_response.delete('access_token') if failure_mode == :no_access_token + if @instance.client_secret.present? headers['Authorization'] = "Basic #{Base64.strict_encode64(@instance.client_id + ':' + @instance.client_secret)}" else - body['client_id'] = @instance.client_id + body['client_id'] = body_with_scope['client_id'] = @instance.client_id end + response_headers = { content_type: 'application/json; charset=UTF-8', + cache_control: 'no-store', + pragma: 'no-cache' } + + response_headers.delete(:cache_control) if failure_mode == :cache_control_off + response_headers.delete(:pragma) if failure_mode == :pragma_off + + exchange_response_json = exchange_response.to_json + exchange_response_json = '' if failure_mode == :bad_json_response + stub_request(:post, @instance.oauth_token_endpoint) .with(headers: headers, body: body) + .to_return(status: failure_mode == :requires_scope ? 400 : 200, + body: exchange_response_json, + headers: response_headers) + + stub_request(:post, @instance.oauth_token_endpoint) + .with(headers: headers, + body: body_with_scope) .to_return(status: 200, - body: @standalone_token_exchange.to_json, - headers: { content_type: 'application/json; charset=UTF-8', - cache_control: 'no-store', - pragma: 'no-cache' }) + body: exchange_response_json, + headers: response_headers) - # To test rejection of invalid client_id + # To test rejection of invalid client_id for public client stub_request(:post, @instance.oauth_token_endpoint) .with(body: /INVALID/, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }) .to_return(status: 401) + + # To test rejection of invalid client_id for confidential client + auth_header = "Basic #{Base64.strict_encode64('INVALID_CLIENT_ID:' + @confidential_client_secret)}" + stub_request(:post, @instance.oauth_token_endpoint) + .with(headers: { 'Content-Type' => 'application/x-www-form-urlencoded', + 'Authorization' => auth_header }) + .to_return(status: 401) end def all_pass @@ -71,14 +106,63 @@ def all_pass end def test_all_pass_confidential_client - @instance.client_secret = SecureRandom.uuid + @instance.client_secret = @confidential_client_secret @instance.confidential_client = true all_pass end def test_all_pass_public_client @instance.client_secret = nil - @instance.confidential_client = nil + @instance.confidential_client = false all_pass end + + def test_fail_if_bad_token_type + setup_mocks(:bad_token_type) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_cache_control_off + setup_mocks(:cache_control_off) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_pragma_off + setup_mocks(:pragma_off) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_no_scope_returned + setup_mocks(:no_scope) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_no_access_token + setup_mocks(:no_access_token) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_bad_json_response + setup_mocks(:bad_json_response) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + + def test_fail_if_scope_must_be_in_payload + setup_mocks(:requires_scope) + + sequence_result = @sequence.start + assert sequence_result.fail? + end end From 66af729bb8017c6fb7b28f749d2319c767c5946e Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 01:10:13 -0400 Subject: [PATCH 59/89] Fix description and bad id. --- lib/app/modules/smart/token_refresh_sequence.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/app/modules/smart/token_refresh_sequence.rb b/lib/app/modules/smart/token_refresh_sequence.rb index 9f7562f6d..dc6ede2dc 100644 --- a/lib/app/modules/smart/token_refresh_sequence.rb +++ b/lib/app/modules/smart/token_refresh_sequence.rb @@ -25,8 +25,6 @@ class TokenRefreshSequence < SequenceBase This test attempt to exchange the refresh token for a new access token and verify that the information returned contains the required fields and uses the proper headers. - This test - For more information see: * [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749) @@ -160,7 +158,7 @@ def validate_and_save_refresh_response(token_response) test 'Server successfully refreshes the access token when optional scope parameter provided.' do metadata do - id '05' + id '04' link 'https://tools.ietf.org/html/rfc6749' desc %( Server successfully exchanges refresh token at OAuth token endpoint while providing scope in From c491c420881a058dd0cec790d098e728ebb07446 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 11:58:56 -0400 Subject: [PATCH 60/89] Various token refresh test updates reflecting PR commits. --- .../modules/smart/token_refresh_sequence.rb | 21 ++--- test/sequence/token_refresh_sequence_test.rb | 83 +++++++++++++------ 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/lib/app/modules/smart/token_refresh_sequence.rb b/lib/app/modules/smart/token_refresh_sequence.rb index dc6ede2dc..41f73d84d 100644 --- a/lib/app/modules/smart/token_refresh_sequence.rb +++ b/lib/app/modules/smart/token_refresh_sequence.rb @@ -22,7 +22,7 @@ class TokenRefreshSequence < SequenceBase # Test Methodology - This test attempt to exchange the refresh token for a new access token and verify that the information returned + This test attempts to exchange the refresh token for a new access token and verify that the information returned contains the required fields and uses the proper headers. For more information see: @@ -85,6 +85,10 @@ def validate_and_save_refresh_response(token_response) assert_valid_json(token_response.body) token_response_body = JSON.parse(token_response.body) + # The minimum we need to 'progress' is the access token, + # so first just check and save access token, before validating rest of payload. + # This is done to make things easier for developers. + assert token_response_body.key?('access_token'), 'Token response did not contain access_token as required' token_retrieved_at = DateTime.now @@ -96,7 +100,7 @@ def validate_and_save_refresh_response(token_response) @instance.update(token: token_response_body['access_token'], token_retrieved_at: token_retrieved_at) - ['token_type', 'scope'].each do |key| + ['expires_in', 'token_type', 'scope'].each do |key| assert token_response_body.key?(key), "Token response did not contain #{key} as required" end @@ -127,12 +131,7 @@ def validate_and_save_refresh_response(token_response) @instance.save! @instance.update(refresh_token: token_response_body['refresh_token']) end - [:cache_control, :pragma].each do |key| - assert token_response.headers.key?(key), "Token response headers did not contain #{key} as is required in the SMART App Launch Guide." - end - assert token_response.headers[:cache_control].downcase.include?('no-store'), 'Token response header must have cache_control containing no-store.' - assert token_response.headers[:pragma].downcase.include?('no-cache'), 'Token response header must have pragma containing no-cache.' end test 'Server successfully refreshes the access token when optional scope parameter omitted.' do @@ -144,9 +143,7 @@ def validate_and_save_refresh_response(token_response) the body of the request. The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. - access_token, token_type, and scope are required. access_token must be Bearer. - - The authorization servers response must include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache. + access_token, expires_in, token_type, and scope are required. access_token must be Bearer. ) end @@ -165,9 +162,7 @@ def validate_and_save_refresh_response(token_response) the body of the request. The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. - access_token, token_type, and scope are required. access_token must be Bearer. - - The authorization servers response must include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache. + access_token, token_type, expires_in, and scope are required. access_token must be Bearer. ) end diff --git a/test/sequence/token_refresh_sequence_test.rb b/test/sequence/token_refresh_sequence_test.rb index 888b385c0..56d8a19e6 100644 --- a/test/sequence/token_refresh_sequence_test.rb +++ b/test/sequence/token_refresh_sequence_test.rb @@ -37,50 +37,68 @@ def setup_mocks(failure_mode = nil) headers = { 'Content-Type' => 'application/x-www-form-urlencoded' } + body = { 'grant_type' => 'refresh_token', 'refresh_token' => @instance.refresh_token } + body_response_code = 200 + body_with_scope = { 'grant_type' => 'refresh_token', 'refresh_token' => @instance.refresh_token, 'scope' => @instance.scopes } - exchange_response = @standalone_token_exchange.dup + body_with_scope_response_code = 200 - exchange_response['token_type'] = 'unknown' if failure_mode == :bad_token_type - exchange_response.delete('scope') if failure_mode == :no_scope - exchange_response.delete('access_token') if failure_mode == :no_access_token - - if @instance.client_secret.present? - headers['Authorization'] = "Basic #{Base64.strict_encode64(@instance.client_id + ':' + @instance.client_secret)}" - else - body['client_id'] = body_with_scope['client_id'] = @instance.client_id - end + exchange_response = @standalone_token_exchange.dup response_headers = { content_type: 'application/json; charset=UTF-8', cache_control: 'no-store', pragma: 'no-cache' } - response_headers.delete(:cache_control) if failure_mode == :cache_control_off - response_headers.delete(:pragma) if failure_mode == :pragma_off + case failure_mode + when :bad_token_type + exchange_response['token_type'] = 'unknown' + when :no_scope + exchange_response.delete('scope') + when :no_access_token + exchange_response.delete('access_token') + when :no_expires_in + exchange_response.delete('expires_in') + when :cache_control_off + response_headers.delete(:cache_control) + when :pragma_off + response_headers.delete(:pragma) + when :requires_scope + body_response_code = 400 + when :disallows_scope + body_with_scope_response_code = 400 + end + # can't do this above because we are altering the content of hash in other error modes exchange_response_json = exchange_response.to_json exchange_response_json = '' if failure_mode == :bad_json_response + if @instance.client_secret.present? + headers['Authorization'] = "Basic #{Base64.strict_encode64(@instance.client_id + ':' + @instance.client_secret)}" + else + body['client_id'] = body_with_scope['client_id'] = @instance.client_id + end + stub_request(:post, @instance.oauth_token_endpoint) .with(headers: headers, body: body) - .to_return(status: failure_mode == :requires_scope ? 400 : 200, + .to_return(status: body_response_code, body: exchange_response_json, headers: response_headers) stub_request(:post, @instance.oauth_token_endpoint) .with(headers: headers, body: body_with_scope) - .to_return(status: 200, + .to_return(status: body_with_scope_response_code, body: exchange_response_json, headers: response_headers) @@ -105,34 +123,37 @@ def all_pass assert sequence_result.pass?, 'The sequence should be marked as pass.' end - def test_all_pass_confidential_client + def test_pass_if_confidential_client @instance.client_secret = @confidential_client_secret @instance.confidential_client = true all_pass end - def test_all_pass_public_client + def test_pass_if_public_client @instance.client_secret = nil @instance.confidential_client = false all_pass end - def test_fail_if_bad_token_type - setup_mocks(:bad_token_type) + # Initial token exchange requires cache control and pragma headers + # But token exchange does not according to the letter of the smart spec + # Check that the next two tests pass + def test_pass_if_cache_control_off + setup_mocks(:cache_control_off) sequence_result = @sequence.start - assert sequence_result.fail? + assert sequence_result.pass? end - def test_fail_if_cache_control_off - setup_mocks(:cache_control_off) + def test_pass_if_pragma_off + setup_mocks(:pragma_off) sequence_result = @sequence.start - assert sequence_result.fail? + assert sequence_result.pass? end - def test_fail_if_pragma_off - setup_mocks(:pragma_off) + def test_fail_if_bad_token_type + setup_mocks(:bad_token_type) sequence_result = @sequence.start assert sequence_result.fail? @@ -152,6 +173,13 @@ def test_fail_if_no_access_token assert sequence_result.fail? end + def test_fail_if_no_expires_in + setup_mocks(:no_expires_in) + + sequence_result = @sequence.start + assert sequence_result.fail? + end + def test_fail_if_bad_json_response setup_mocks(:bad_json_response) @@ -165,4 +193,11 @@ def test_fail_if_scope_must_be_in_payload sequence_result = @sequence.start assert sequence_result.fail? end + + def test_fail_if_scope_cannot_be_in_payload + setup_mocks(:disallows_scope) + + sequence_result = @sequence.start + assert sequence_result.fail? + end end From 150b8dfcb4542b0c595bc2034233d0e833140178 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 12:23:25 -0400 Subject: [PATCH 61/89] Change missing headers in token refresh to warnings. --- .../modules/smart/token_refresh_sequence.rb | 21 ++++++++++++++++++- test/sequence/token_refresh_sequence_test.rb | 12 +++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/app/modules/smart/token_refresh_sequence.rb b/lib/app/modules/smart/token_refresh_sequence.rb index 41f73d84d..81b262f04 100644 --- a/lib/app/modules/smart/token_refresh_sequence.rb +++ b/lib/app/modules/smart/token_refresh_sequence.rb @@ -132,6 +132,16 @@ def validate_and_save_refresh_response(token_response) @instance.update(refresh_token: token_response_body['refresh_token']) end + warning do + # These should be required but due to a gap in the SMART App Launch Guide they are not currently required + # See https://github.com/HL7/smart-app-launch/issues/293 + [:cache_control, :pragma].each do |key| + assert token_response.headers.key?(key), "Token response headers did not contain #{key} as is recommended for token exchanges." + end + + assert token_response.headers[:cache_control].downcase.include?('no-store'), 'Token response header should have cache_control containing no-store.' + assert token_response.headers[:pragma].downcase.include?('no-cache'), 'Token response header should have pragma containing no-cache.' + end end test 'Server successfully refreshes the access token when optional scope parameter omitted.' do @@ -144,6 +154,11 @@ def validate_and_save_refresh_response(token_response) The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. access_token, expires_in, token_type, and scope are required. access_token must be Bearer. + + Although not required in the token refresh portion of the SMART App Launch Guide, + the token refresh response should include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache + to be consistent with the requirements of the inital access token exchange. + ) end @@ -162,7 +177,11 @@ def validate_and_save_refresh_response(token_response) the body of the request. The EHR authorization server SHALL return a JSON structure that includes an access token or a message indicating that the authorization request has been denied. - access_token, token_type, expires_in, and scope are required. access_token must be Bearer. + access_token, token_type, and scope are required. access_token must be Bearer. + + Although not required in the token refresh portion of the SMART App Launch Guide, + the token refresh response should include the HTTP Cache-Control response header field with a value of no-store, as well as the Pragma response header field with a value of no-cache + to be consistent with the requirements of the inital access token exchange. ) end diff --git a/test/sequence/token_refresh_sequence_test.rb b/test/sequence/token_refresh_sequence_test.rb index 56d8a19e6..b0b0eead9 100644 --- a/test/sequence/token_refresh_sequence_test.rb +++ b/test/sequence/token_refresh_sequence_test.rb @@ -120,7 +120,8 @@ def all_pass setup_mocks sequence_result = @sequence.start - assert sequence_result.pass?, 'The sequence should be marked as pass.' + assert sequence_result.pass? + assert(sequence_result.test_results.none? { |result| result.test_warnings.present? }) end def test_pass_if_confidential_client @@ -137,19 +138,22 @@ def test_pass_if_public_client # Initial token exchange requires cache control and pragma headers # But token exchange does not according to the letter of the smart spec - # Check that the next two tests pass - def test_pass_if_cache_control_off + # This may be updated in future versions of the spec + # See https://github.com/HL7/smart-app-launch/issues/293 + def test_warning_if_cache_control_off setup_mocks(:cache_control_off) sequence_result = @sequence.start assert sequence_result.pass? + assert(sequence_result.test_results.any? { |result| result.test_warnings.present? }) end - def test_pass_if_pragma_off + def test_warning_if_pragma_off setup_mocks(:pragma_off) sequence_result = @sequence.start assert sequence_result.pass? + assert(sequence_result.test_results.any? { |result| result.test_warnings.present? }) end def test_fail_if_bad_token_type From 6009d0f58045b51c2b47392bedf57916a82778d7 Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 12:33:43 -0400 Subject: [PATCH 62/89] Stylistic fix in refresh token seqence. --- test/sequence/token_refresh_sequence_test.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/sequence/token_refresh_sequence_test.rb b/test/sequence/token_refresh_sequence_test.rb index b0b0eead9..30183a1b8 100644 --- a/test/sequence/token_refresh_sequence_test.rb +++ b/test/sequence/token_refresh_sequence_test.rb @@ -45,11 +45,7 @@ def setup_mocks(failure_mode = nil) body_response_code = 200 - body_with_scope = { - 'grant_type' => 'refresh_token', - 'refresh_token' => @instance.refresh_token, - 'scope' => @instance.scopes - } + body_with_scope = body.merge('scope' => @instance.scopes) body_with_scope_response_code = 200 From 85ac089fffe8879c54d141f62a9874bfa4a9d33e Mon Sep 17 00:00:00 2001 From: Rob Scanlon Date: Wed, 24 Jul 2019 13:23:07 -0400 Subject: [PATCH 63/89] Update GitHub urls to new onc-healthit organization. --- README.md | 18 +++++++++--------- deployment-configuration.md | 6 +++--- lib/app/views/default.erb | 2 +- lib/app/views/guided.erb | 2 +- lib/app/views/index.erb | 2 +- lib/app/views/layout.erb | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 0a9f5cd62..5b59878a9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ - + -[![Build Status](https://travis-ci.org/siteadmin/inferno.svg?branch=master)](https://travis-ci.org/siteadmin/inferno) +[![Build Status](https://travis-ci.org/onc-healthit/inferno.svg?branch=master)](https://travis-ci.org/onc-healthit/inferno) Inferno is an open source tool that tests whether patients can access their health data through a standard interface. It makes HTTP(S) requests to test your server's conformance to authentication, authorization, and FHIR content standards and reports the results back to you. @@ -9,7 +9,7 @@ This application creates test clients that exercise the range of requirements of ## Using Inferno -If you are new to FHIR or SMART-on-FHIR, you may want to review the [Inferno Quick Start Guide](https://github.com/siteadmin/inferno/wiki/Quick-Start-Guide). +If you are new to FHIR or SMART-on-FHIR, you may want to review the [Inferno Quick Start Guide](https://github.com/onc-healthit/inferno/wiki/Quick-Start-Guide). ## Installation and Deployment @@ -18,14 +18,14 @@ If you are new to FHIR or SMART-on-FHIR, you may want to review the [Inferno Qui Docker is the recommended installation method for Windows devices and can also be used on Linux and MacOS hosts. 1. Install [Docker](https://www.docker.com/) for the host platform as well as the [docker-compose](https://docs.docker.com/compose/install/) tool (which may be included in the distribution, as is the case for Windows and MacOS). -2. Download the [latest release of the `inferno` project](https://github.com/siteadmin/inferno/releases) to your local computer on a directory of your choice. +2. Download the [latest release of the `inferno` project](https://github.com/onc-healthit/inferno/releases) to your local computer on a directory of your choice. 3. Open a terminal in the directory where the project was downloaded (above). 4. Run the command `docker-compose up` to start the server. This will automatically build the Docker image and launch both the ruby server (using unicorn) and an NGINX web server. 5. Navigate to http://localhost:8080 to find the running application. If the docker image gets out of sync with the underlying system, such as when new dependencies are added to the application, you need to run `docker-compose up --build` to rebuild the containers. -Check out the [Troubleshooting Documentation](https://github.com/siteadmin/inferno/wiki/Troubleshooting) for help. +Check out the [Troubleshooting Documentation](https://github.com/onc-healthit/inferno/wiki/Troubleshooting) for help. ### Native Installation @@ -39,7 +39,7 @@ And run the following commands from the terminal: ```sh # MacOS or Linux -git clone https://github.com/siteadmin/inferno +git clone https://github.com/onc-healthit/inferno cd inferno bundle install bundle exec rackup @@ -59,7 +59,7 @@ Inferno can also be deployed onto a server to test many different instances of t Deployment on a remote server can be done by using a modified form of the Docker containers provided (see above) or by direct installation on the remote host. -Please see the file [deployment-configuration.md](https://github.com/siteadmin/inferno/blob/master/deployment-configuration.md) for details. +Please see the file [deployment-configuration.md](https://github.com/onc-healthit/inferno/blob/master/deployment-configuration.md) for details. ### Reference Implementation @@ -82,7 +82,7 @@ bundle exec rake test ## Inspecting and Exporting Tests Tests are written to be easily understood, even by those who aren't familiar with Ruby. They can be -viewed directly [in this repository](https://github.com/siteadmin/inferno/tree/master/lib/app/sequences). +viewed directly [in this repository](https://github.com/onc-healthit/inferno/tree/master/lib/app/sequences). Tests contain metadata that provide additional details and traceability to standards. The active tests and related metadata can be exported into CSV format and saved to a file named `testlist.csv` with the following command: @@ -134,7 +134,7 @@ bundle exec rake inferno:generate_script[https://my-server.org/data,onc] * The `confidential_client` field is a boolean and must be provided as `true` or `false` ## Using with Continuous Integration Systems -Instructions and examples are available in the [Continuous Integration Section of the Wiki](https://github.com/siteadmin/inferno/wiki/Using-with-Continuous-Integration-Systems). +Instructions and examples are available in the [Continuous Integration Section of the Wiki](https://github.com/onc-healthit/inferno/wiki/Using-with-Continuous-Integration-Systems). ## Contact Us The Inferno development team can be reached by email at inferno@groups.mitre.org. Inferno also has a dedicated [HL7 FHIR chat channel](https://chat.fhir.org/#narrow/stream/153-inferno). diff --git a/deployment-configuration.md b/deployment-configuration.md index c64c41f9b..f89f972dd 100644 --- a/deployment-configuration.md +++ b/deployment-configuration.md @@ -23,7 +23,7 @@ It is important to open port `80` for HTTP and port `22` for SSH if you need to "Review and Launch" button, click next button until you get to the Security Groups option. Ensure 80 is accessible from anywhere and 22 is available from an IP range from which you will connect. Below is an example: -![Security Groups Configuration](https://raw.githubusercontent.com/siteadmin/inferno/master/deployment-files/security-groups.png "Security Groups Configuration") +![Security Groups Configuration](https://raw.githubusercontent.com/onc-healthit/inferno/master/deployment-files/security-groups.png "Security Groups Configuration") After this step is done, launch the instance. Obtain your instance's IP or host name from the AWS console. Point a web browser to the instance using the IP address or host name. @@ -70,7 +70,7 @@ Now, issue the following commands to setup Inferno. sudo apt-get install git ruby-bundler ruby-dev sudo apt-get install sqlite3 libsqlite3-dev sudo apt-get install build-essential patch zlib1g-dev liblzma-dev - git clone https://github.com/siteadmin/inferno.git + git clone https://github.com/onc-healthit/inferno.git cd inferno bundle install @@ -183,7 +183,7 @@ This section describes how to setup the tool using Apache2 using Passenger. sudo apt-get install apache2 git ruby-bundler ruby-dev sudo apt-get install sqlite3 libsqlite3-dev sudo apt-get install build-essential patch zlib1g-dev liblzma-dev - git clone https://github.com/siteadmin/inferno.git + git clone https://github.com/onc-healthit/inferno.git cd inferno bundle install diff --git a/lib/app/views/default.erb b/lib/app/views/default.erb index c4a6984a6..be834ea43 100644 --- a/lib/app/views/default.erb +++ b/lib/app/views/default.erb @@ -434,7 +434,7 @@ Incoming HTTP(S) This test contains incoming HTTP(S) requests -

For more information, see the Inferno README and the Inferno wiki.

+

For more information, see the Inferno README and the Inferno wiki.

diff --git a/lib/app/views/guided.erb b/lib/app/views/guided.erb index c85a9def6..1ab37188a 100644 --- a/lib/app/views/guided.erb +++ b/lib/app/views/guided.erb @@ -602,7 +602,7 @@ Incoming HTTP(S) This test contains incoming HTTP(S) requests -

For more information, see the Inferno README and the Inferno wiki.

+

For more information, see the Inferno README and the Inferno wiki.

diff --git a/lib/app/views/index.erb b/lib/app/views/index.erb index 3648973ab..4aceecb79 100644 --- a/lib/app/views/index.erb +++ b/lib/app/views/index.erb @@ -56,7 +56,7 @@
- This software is under active development. Please report bugs and submit feature requests as GitHub issues. + This software is under active development. Please report bugs and submit feature requests as GitHub issues.
diff --git a/lib/app/views/layout.erb b/lib/app/views/layout.erb index 3f421faf9..e37fd6097 100644 --- a/lib/app/views/layout.erb +++ b/lib/app/views/layout.erb @@ -28,7 +28,7 @@ Home %> @@ -42,10 +42,10 @@