Module: Assertion
- Included in:
- TestScriptRunnable
- Defined in:
- lib/testscript_engine/assertion.rb
Defined Under Namespace
Classes: AssertionException
Constant Summary collapse
- ASSERT_TYPES_MATCHER =
/(?<=\p{Ll})(?=\p{Lu})|(?<=\p{Lu})(?=\p{Lu}\p{Ll})/
- ASSERT_TYPES =
[ "contentType", "expression", "headerField", "minimumId", "navigationLinks", "path", "requestMethod", "resource", "responseCode", "response", "validateProfileId", "requestURL" ]
- CODE_MAP =
{ '200' => 'okay', '201' => 'created', '204' => 'noContent', '304' => 'notModified', '400' => 'bad', '403' => 'forbidden', '404' => 'notFound', '405' => 'methodNotAllowed', '409' => 'conflict', '410' => 'gone', '412' => 'preconditionFailed', '422' => 'unprocessable' }
Instance Method Summary collapse
- #compare(assert_type, received, operator, expected = nil) ⇒ Object
- #content_type(assert) ⇒ Object
- #determine_assert_type(all_elements) ⇒ Object
- #determine_expected_value(assert) ⇒ Object
- #direction ⇒ Object
- #evaluate(assert) ⇒ Object
- #evaluate_path(path, resource) ⇒ Object
- #expression(assert) ⇒ Object
- #extract_xpath_value(resource_xml, resource_xpath) ⇒ Object
- #fail_message(assert_type, received, operator, expected) ⇒ Object
- #get_request(id) ⇒ Object
-
#get_resource(id) ⇒ Object
<— TO DO: MOVE TO UTILITIES MODULE —>.
- #get_response(id) ⇒ Object
- #header_field(assert) ⇒ Object
- #minimum_id(assert) ⇒ Object
- #navigation_links(assert) ⇒ Object
- #pass_message(assert_type, received, operator, expected) ⇒ Object
- #path(assert) ⇒ Object
- #request_header(requestId = nil, header_name = nil) ⇒ Object
- #request_method(assert) ⇒ Object
- #request_url(assert) ⇒ Object
- #resource(assert) ⇒ Object
- #response(assert) ⇒ Object
- #response_code(assert) ⇒ Object
- #response_header(responseId = nil, header_name = nil) ⇒ Object
- #validate_profile_id(assert) ⇒ Object
Instance Method Details
#compare(assert_type, received, operator, expected = nil) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/testscript_engine/assertion.rb', line 78 def compare(assert_type, received, operator, expected = nil) operator = 'equals' unless operator outcome = begin case operator when 'equals' expected == received when 'notEquals' expected != received when 'in' expected.split(',').include? received when 'notIn' !expected.split(',').include? received when 'greaterThan' received.to_i > expected.to_i when 'lessThan' received.to_i < expected.to_i when 'empty' received.blank? when 'notEmpty' received.present? when 'contains' received&.include? expected when 'notContains' !received&.include? expected end end if outcome (assert_type, received, operator, expected) else = (assert_type, received, operator, expected) raise AssertionException.new(, :fail) end end |
#content_type(assert) ⇒ Object
129 130 131 132 |
# File 'lib/testscript_engine/assertion.rb', line 129 def content_type(assert) received = request_header(assert.sourceId, 'Content-Type') compare("Content-Type", received, assert.operator, assert.contentType) end |
#determine_assert_type(all_elements) ⇒ Object
57 58 59 60 |
# File 'lib/testscript_engine/assertion.rb', line 57 def determine_assert_type(all_elements) assert_type = all_elements.detect { |elem| ASSERT_TYPES.include? elem } return assert_type.split(ASSERT_TYPES_MATCHER).map(&:downcase).join('_') end |
#determine_expected_value(assert) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/testscript_engine/assertion.rb', line 66 def determine_expected_value(assert) if assert.value assert.value elsif assert.compareToSourceExpression FHIRPath.evaluate(assert.compareToSourceExpression, get_resource(assert.compareToSourceId).to_hash) elsif assert.compareToSourcePath evaluate_path(assert.compareToSourcePath, get_resource(assert.compareToSourceId)) end end |
#direction ⇒ Object
62 63 64 |
# File 'lib/testscript_engine/assertion.rb', line 62 def direction @direction ||= 'response' end |
#evaluate(assert) ⇒ Object
47 48 49 50 51 52 53 54 55 |
# File 'lib/testscript_engine/assertion.rb', line 47 def evaluate(assert) @direction = assert.direction assert_elements = assert.to_hash.keys assert_type = determine_assert_type(assert_elements) = send(assert_type.to_sym, assert) pass(:eval_assert_result, ) end |
#evaluate_path(path, resource) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/testscript_engine/assertion.rb', line 256 def evaluate_path(path, resource) return unless path and resource begin # Then, try xpath if necessary result = extract_xpath_value(resource.to_xml, path) rescue # If xpath fails, see if JSON path will work... result = JsonPath.new(path).first(resource.to_json) end return result end |
#expression(assert) ⇒ Object
134 135 136 137 138 139 140 141 |
# File 'lib/testscript_engine/assertion.rb', line 134 def expression(assert) resource = get_resource(assert.sourceId) raise AssertionException.new('No resource given by sourceId.', :fail) unless resource received = FHIRPath.evaluate(assert.expression, resource.to_hash) expected = determine_expected_value(assert) compare("Expression", received, assert.operator, expected) end |
#extract_xpath_value(resource_xml, resource_xpath) ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/testscript_engine/assertion.rb', line 269 def extract_xpath_value(resource_xml, resource_xpath) # Massage the xpath if it doesn't have fhir: namespace or if doesn't end in @value # Also make it look in the entire xml document instead of just starting at the root xpath = resource_xpath.split('/').map do |s| s.start_with?('fhir:') || s.length.zero? || s.start_with?('@') ? s : "fhir:#{s}" end.join('/') xpath = "#{xpath}/@value" unless xpath.end_with? '@value' xpath = "//#{xpath}" resource_doc = Nokogiri::XML(resource_xml) resource_doc.root.add_namespace_definition('fhir', 'http://hl7.org/fhir') resource_element = resource_doc.xpath(xpath) # This doesn't work on warningOnly; consider putting back in place # raise AssertionException.new("[#{resource_xpath}] resolved to multiple values instead of a single value", resource_element.to_s) if resource_element.length>1 resource_element.first.value end |
#fail_message(assert_type, received, operator, expected) ⇒ Object
121 122 123 124 125 126 127 |
# File 'lib/testscript_engine/assertion.rb', line 121 def (assert_type, received, operator, expected) received = Array(received) expected = Array(expected) = "#{assert_type}: Expected #{assert_type} #{operator}" = + " #{expected}" if expected + ", but found #{received}." end |
#get_request(id) ⇒ Object
229 230 231 232 |
# File 'lib/testscript_engine/assertion.rb', line 229 def get_request(id) return request_map[id] if id reply&.request end |
#get_resource(id) ⇒ Object
<— TO DO: MOVE TO UTILITIES MODULE —>
216 217 218 219 220 221 222 |
# File 'lib/testscript_engine/assertion.rb', line 216 def get_resource(id) if direction == 'request' get_request(id)&.[](:payload) else get_response(id)&.[](:body) || fixtures[id] end end |
#get_response(id) ⇒ Object
224 225 226 227 |
# File 'lib/testscript_engine/assertion.rb', line 224 def get_response(id) return response_map[id] if id reply&.response end |
#header_field(assert) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/testscript_engine/assertion.rb', line 143 def header_field(assert) received = begin if direction == 'request' request_header(assert.sourceId, assert.headerField) else response_header(assert.sourceId, assert.headerField) end end expected = determine_expected_value(assert) compare("Header #{assert.headerField}", received, assert.operator, expected) end |
#minimum_id(assert) ⇒ Object
156 157 158 159 160 161 |
# File 'lib/testscript_engine/assertion.rb', line 156 def minimum_id(assert) received = get_resource(assert.sourceId) raise AssertionException.new('minimumId assert not yet supported.', :skip) # result = client.validate(received, { profile_uri: assert.validateProfileId }) end |
#navigation_links(assert) ⇒ Object
163 164 165 166 167 168 169 170 |
# File 'lib/testscript_engine/assertion.rb', line 163 def (assert) received = get_resource(assert.sourceId) result = received&.first_link && received&.last_link && received&.next_link return "Navigation Links: As expected, all navigation links found." if result raise AssertionException.new("Navigation Links: Expected all navigation links, but did not receive.", :fail) end |
#pass_message(assert_type, received, operator, expected) ⇒ Object
113 114 115 116 117 118 119 |
# File 'lib/testscript_engine/assertion.rb', line 113 def (assert_type, received, operator, expected) received = Array(received) expected = Array(expected) = "#{assert_type}: As expected, #{assert_type} #{operator}" = + (expected ? " #{expected}." : '.') + " Found #{received}." if received end |
#path(assert) ⇒ Object
172 173 174 175 176 177 |
# File 'lib/testscript_engine/assertion.rb', line 172 def path(assert) resource = get_resource(assert.sourceId) received = evaluate_path(assert.path, resource) expected = determine_expected_value(assert) compare("Path", received, assert.operator, expected) end |
#request_header(requestId = nil, header_name = nil) ⇒ Object
245 246 247 248 249 250 251 252 253 254 |
# File 'lib/testscript_engine/assertion.rb', line 245 def request_header(requestId = nil, header_name = nil) request = requestId ? request_map[requestId] : reply&.request return unless request headers = request[:headers] return unless headers headers.transform_keys!(&:downcase) header_name ? headers[header_name.downcase] : headers end |
#request_method(assert) ⇒ Object
179 180 181 182 183 184 |
# File 'lib/testscript_engine/assertion.rb', line 179 def request_method(assert) request = assert.sourceId ? request_map[assert.sourceId] : reply.request received = request[:method] expected = determine_expected_value(assert) compare("Request Method", received, assert.operator, expected) end |
#request_url(assert) ⇒ Object
209 210 211 212 |
# File 'lib/testscript_engine/assertion.rb', line 209 def request_url(assert) received = get_request(assert.sourceId)[:url] compare("RequestURL", received, assert.operator, assert.requestURL) end |
#resource(assert) ⇒ Object
186 187 188 189 |
# File 'lib/testscript_engine/assertion.rb', line 186 def resource(assert) received = get_resource(assert.sourceId) compare("Resource", received&.resourceType, assert.operator, assert.resource) end |
#response(assert) ⇒ Object
196 197 198 199 200 |
# File 'lib/testscript_engine/assertion.rb', line 196 def response(assert) received_code = get_response(assert.sourceId)&.[](:code).to_s received = CODE_MAP[received_code] compare("Response", received, assert.operator, assert.response) end |
#response_code(assert) ⇒ Object
191 192 193 194 |
# File 'lib/testscript_engine/assertion.rb', line 191 def response_code(assert) received = get_response(assert.sourceId)&.[](:code).to_s compare("Response Code", received, assert.operator, assert.responseCode) end |
#response_header(responseId = nil, header_name = nil) ⇒ Object
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/testscript_engine/assertion.rb', line 234 def response_header(responseId = nil, header_name = nil) response = responseId ? response_map[responseId] : reply&.response return unless response headers = response[:headers] return unless headers headers.transform_keys!(&:downcase) header_name ? headers[header_name.downcase] : headers end |
#validate_profile_id(assert) ⇒ Object
202 203 204 205 206 207 |
# File 'lib/testscript_engine/assertion.rb', line 202 def validate_profile_id(assert) received = get_resource(assert.sourceId) raise AssertionException.new('validateProfileId assert not yet supported.', :skip) # result = client.validate(received, { profile_uri: assert.validateProfileId }) end |