Module: Inferno::DSL::Assertions

Included in:
Entities::TestGroup, Entities::TestSuite
Defined in:
lib/inferno/dsl/assertions.rb

Overview

This module contains the assertions used within tests to verify the behavior of the systems under test. Failing an assertion causes a test to immediately stop execution and receive a ‘fail` result. Additional assertions added to this module will be available in all tests.

Instance Method Summary collapse

Instance Method Details

#assert(test, message = '') ⇒ void

This method returns an undefined value.

Make an assertion

Parameters:

  • test

    a value whose truthiness will determine whether the assertion passes or fails

  • message (String) (defaults to: '')

    failure message

Raises:



16
17
18
# File 'lib/inferno/dsl/assertions.rb', line 16

def assert(test, message = '')
  raise Exceptions::AssertionException, message unless test
end

#assert_resource_type(resource_type, resource: self.resource) ⇒ void

This method returns an undefined value.

Check a FHIR resource’s type

Examples:

# The resource type can be a symbol, String, or FHIR::Model class
assert_resource_type(:capability_statement)
assert_resource_type('CapabilityStatement')
assert_resource_type(FHIR::CapabilityStatement)

Parameters:

  • resource_type (String, Symbol, Class)
  • resource (FHIR::Model) (defaults to: self.resource)


52
53
54
55
56
57
# File 'lib/inferno/dsl/assertions.rb', line 52

def assert_resource_type(resource_type, resource: self.resource)
  resource_type_name = normalize_resource_type(resource_type)

  assert resource&.resourceType == resource_type_name,
         bad_resource_type_message(resource_type_name, resource&.resourceType)
end

#assert_response_content_type(type, request: self.request) ⇒ void

This method returns an undefined value.

Check the Content-Type header of a response. This assertion will fail if the response’s content type does not begin with the provided type.

Parameters:



184
185
186
187
188
189
# File 'lib/inferno/dsl/assertions.rb', line 184

def assert_response_content_type(type, request: self.request)
  header = request.response_header('Content-Type')
  assert header.present?, no_content_type_message

  assert header.value.start_with?(type), bad_content_type_message(type, header.value)
end

#assert_response_status(status, request: self.request, response: nil) ⇒ void

This method returns an undefined value.

Check a response’s status

Parameters:

  • status (Integer, Array<Integer>)

    a single integer or an array of integer status codes

  • request (Inferno::Entities::Request) (defaults to: self.request)
  • response (Hash) (defaults to: nil)


32
33
34
35
# File 'lib/inferno/dsl/assertions.rb', line 32

def assert_response_status(status, request: self.request, response: nil)
  response ||= request&.response
  assert Array.wrap(status).include?(response[:status]), bad_response_status_message(status, response[:status])
end

#assert_valid_bundle_entries(bundle: resource, resource_types: {}) ⇒ void

This method returns an undefined value.

Validate each entry of a Bundle

String,Symbol,FHIR::Model,Array<String,Symbol,FHIR::Model>,Hash

If a

string, symbol, or FHIR::Model is provided, only that resource type
will be validated. If an array of strings is provided, only those
resource types will be validated. If a hash is provided with resource
types as keys and profile urls (or nil) as values, only those resource
types will be validated against the provided profile url or the base
resource if nil.

Examples:

# Only validate Patient bundle entries
assert_valid_bundle_entries(resource_types: 'Patient')

# Only valiadte Patient and Condition bundle entries
assert_valid_bundle_entries(resource_types: ['Patient', 'Condition'])

# Only validate Patient and Condition bundle entries. Validate Patient
# resources against the given profile, and Codition resources against the
# base FHIR Condition resource.
assert_valid_bundle_entries(
  resource_types: {
    'Patient': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient',
    'Condition': nil
  }
)

Parameters:

  • bundle (FHIR::Bundle) (defaults to: resource)
  • resource_types (defaults to: {})


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/inferno/dsl/assertions.rb', line 106

def assert_valid_bundle_entries(bundle: resource, resource_types: {})
  assert_resource_type('Bundle', resource: bundle)

  types_to_check = normalize_types_to_check(resource_types)

  invalid_resources =
    bundle
      .entry
      .map(&:resource)
      .select { |resource| types_to_check.empty? || types_to_check.include?(resource.resourceType) }
      .reject do |resource|
        validation_params = { resource: }
        profile = types_to_check[resource.resourceType]
        validation_params[:profile_url] = profile if profile

        resource_is_valid?(**validation_params)
      end

  assert invalid_resources.empty?, invalid_bundle_entries_message(invalid_resources)
end

#assert_valid_http_uri(uri, message = '') ⇒ void

This method returns an undefined value.

Check for a valid http/https uri

Parameters:

  • uri (String)
  • message (String) (defaults to: '')

    custom failure message



173
174
175
176
# File 'lib/inferno/dsl/assertions.rb', line 173

def assert_valid_http_uri(uri, message = '')
  error_message = message.presence || "\"#{uri}\" is not a valid URI"
  assert uri =~ /\A#{URI::DEFAULT_PARSER.make_regexp(['http', 'https'])}\z/, error_message
end

#assert_valid_json(maybe_json_string, message = '') ⇒ void

This method returns an undefined value.

Check for valid JSON

Parameters:

  • maybe_json_string (String)
  • message (String) (defaults to: '')

    extra failure message



162
163
164
165
166
# File 'lib/inferno/dsl/assertions.rb', line 162

def assert_valid_json(maybe_json_string, message = '')
  assert JSON.parse(maybe_json_string)
rescue JSON::ParserError
  assert false, "Invalid JSON. #{message}"
end

#assert_valid_resource(resource: self.resource, profile_url: nil, validator: :default) ⇒ void

This method returns an undefined value.

Validate a FHIR resource

Parameters:

  • resource (FHIR::Model) (defaults to: self.resource)
  • profile_url (String) (defaults to: nil)

    url of the profile to validate against, defaults to validating against the base FHIR resource

  • validator (Symbol) (defaults to: :default)

    the name of the validator to use



73
74
75
76
# File 'lib/inferno/dsl/assertions.rb', line 73

def assert_valid_resource(resource: self.resource, profile_url: nil, validator: :default)
  assert resource_is_valid?(resource:, profile_url:, validator:),
         invalid_resource_message(resource, profile_url)
end

#bad_content_type_message(expected, received) ⇒ Object



197
198
199
# File 'lib/inferno/dsl/assertions.rb', line 197

def bad_content_type_message(expected, received)
  "Expected `Content-Type` to be `#{expected}`, but found `#{received}`"
end

#bad_resource_type_message(expected, received) ⇒ Object



38
39
40
# File 'lib/inferno/dsl/assertions.rb', line 38

def bad_resource_type_message(expected, received)
  "Unexpected resource type: expected #{expected}, but received #{received}"
end

#bad_response_status_message(expected, received) ⇒ Object



21
22
23
# File 'lib/inferno/dsl/assertions.rb', line 21

def bad_response_status_message(expected, received)
  "Unexpected response status: expected #{Array.wrap(expected).join(', ')}, but received #{received}"
end

#invalid_bundle_entries_message(invalid_resources) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/inferno/dsl/assertions.rb', line 128

def invalid_bundle_entries_message(invalid_resources)
  identifier_strings =
    invalid_resources
      .map { |resource| "#{resource.resourceType}##{resource.id}" }
      .join(', ')
  "The following bundle entries are invalid: #{identifier_strings}"
end

#invalid_resource_message(resource, profile_url) ⇒ Object



60
61
62
63
64
# File 'lib/inferno/dsl/assertions.rb', line 60

def invalid_resource_message(resource, profile_url)
  return "Resource does not conform to the profile: #{profile_url}" if profile_url.present?

  "Resource does not conform to the base #{resource&.resourceType} profile."
end

#no_content_type_messageObject



192
193
194
# File 'lib/inferno/dsl/assertions.rb', line 192

def no_content_type_message
  'Response did not contain a `Content-Type` header.'
end

#normalize_resource_type(resource_type) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/inferno/dsl/assertions.rb', line 137

def normalize_resource_type(resource_type)
  if resource_type.is_a? Class
    resource_type.name.demodulize
  else
    resource_type.to_s.camelize
  end
end

#normalize_types_to_check(resource_types) ⇒ Object



146
147
148
149
150
151
152
153
154
155
# File 'lib/inferno/dsl/assertions.rb', line 146

def normalize_types_to_check(resource_types)
  case resource_types
  when Hash
    resource_types.transform_keys { |type| normalize_resource_type(type) }
  when String
    { normalize_resource_type(resource_types) => nil }
  when Array
    resource_types.each_with_object({}) { |type, types| types[normalize_resource_type(type)] = nil }
  end
end