inferno_core 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/inferno +7 -0
- data/lib/inferno/apps/cli/console.rb +12 -0
- data/lib/inferno/apps/cli/main.rb +18 -0
- data/lib/inferno/apps/cli/migration.rb +14 -0
- data/lib/inferno/apps/cli.rb +8 -0
- data/lib/inferno/apps/web/index.html.erb +1 -0
- data/lib/inferno/config/application.rb +3 -0
- data/lib/inferno/config/boot/db.rb +1 -9
- data/lib/inferno/config/boot/logging.rb +2 -0
- data/lib/inferno/db/migrations/001_create_initial_structure.rb +1 -1
- data/lib/inferno/db/schema.rb +1 -1
- data/lib/inferno/dsl/assertions.rb +66 -1
- data/lib/inferno/dsl/configurable.rb +1 -1
- data/lib/inferno/dsl/fhir_client.rb +22 -18
- data/lib/inferno/dsl/fhir_client_builder.rb +3 -3
- data/lib/inferno/dsl/fhir_validation.rb +105 -1
- data/lib/inferno/dsl/http_client.rb +4 -4
- data/lib/inferno/dsl/http_client_builder.rb +3 -3
- data/lib/inferno/dsl/request_storage.rb +8 -8
- data/lib/inferno/dsl/results.rb +1 -1
- data/lib/inferno/dsl/resume_test_route.rb +9 -9
- data/lib/inferno/dsl/runnable.rb +36 -18
- data/lib/inferno/entities/header.rb +14 -7
- data/lib/inferno/entities/message.rb +16 -8
- data/lib/inferno/entities/request.rb +32 -19
- data/lib/inferno/entities/result.rb +36 -29
- data/lib/inferno/entities/session_data.rb +12 -6
- data/lib/inferno/entities/test.rb +13 -0
- data/lib/inferno/entities/test_run.rb +29 -6
- data/lib/inferno/entities/test_session.rb +16 -10
- data/lib/inferno/public/217.bundle.js +1 -1
- data/lib/inferno/public/bundle.js +154 -1
- data/lib/inferno/public/bundle.js.LICENSE.txt +15 -0
- data/lib/inferno/repositories/in_memory_repository.rb +1 -1
- data/lib/inferno/repositories/results.rb +1 -1
- data/lib/inferno/spec_support.rb +1 -1
- data/lib/inferno/test_runner.rb +1 -1
- data/lib/inferno/utils/markdown_formatter.rb +1 -1
- data/lib/inferno/utils/middleware/request_logger.rb +9 -3
- data/lib/inferno/utils/migration.rb +17 -0
- data/lib/inferno/version.rb +1 -1
- data/lib/inferno.rb +0 -4
- metadata +41 -8
- data/bin/inferno-console +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef5b26a5633a33054fd378a523bc3a768e1a77ef572180db26ea792899cfc86a
|
4
|
+
data.tar.gz: b08e8c22c830ab2547d02e89d08e97bfc8248ce1fd8705d95b25d25df1925565
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a22e65c16f1b80abec1c1e182a91ffa44cdb4e78cfad7ec6233c07cbcbfcdf221a5444aa7bec88c4a6bdb99ad95623926d88f6ed60b3888fa0b7bfc1b5a32793
|
7
|
+
data.tar.gz: d9717b4a08e8650071bb679ff964f85efd9d771a8f361a4b0a0781d7e9e91ea9ff764e6c8760a34f063e97944fedfb06b86349cd95cb29561844dc20a37401c1
|
data/bin/inferno
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'console'
|
2
|
+
require_relative 'migration'
|
3
|
+
|
4
|
+
module Inferno
|
5
|
+
module CLI
|
6
|
+
class Main < Thor
|
7
|
+
desc 'console', 'Start an interactive console session with Inferno'
|
8
|
+
def console
|
9
|
+
Console.new.run
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'migrate', 'Run database migrations'
|
13
|
+
def migrate
|
14
|
+
Migration.new.run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -12,6 +12,7 @@ Inferno::Application.boot(:db) do
|
|
12
12
|
config = YAML.load_file(config_path)[ENV['APP_ENV']]
|
13
13
|
.merge(logger: Inferno::Application['logger'])
|
14
14
|
connection = Sequel.connect(config)
|
15
|
+
connection.sql_log_level = :debug
|
15
16
|
|
16
17
|
register('db.config', config)
|
17
18
|
register('db.connection', connection)
|
@@ -19,14 +20,5 @@ Inferno::Application.boot(:db) do
|
|
19
20
|
|
20
21
|
start do
|
21
22
|
Sequel.extension :migration
|
22
|
-
db = Inferno::Application['db.connection']
|
23
|
-
migration_path = File.join(Inferno::Application.root, 'lib', 'inferno', 'db', 'migrations')
|
24
|
-
Sequel::Migrator.run(db, migration_path)
|
25
|
-
|
26
|
-
if ENV['APP_ENV'] == 'development'
|
27
|
-
schema_path = File.join(Inferno::Application.root, 'lib', 'inferno', 'db', 'schema.rb')
|
28
|
-
db.extension :schema_dumper
|
29
|
-
File.open(schema_path, 'w') { |f| f.print(db.dump_schema_migration) }
|
30
|
-
end
|
31
23
|
end
|
32
24
|
end
|
@@ -116,7 +116,7 @@ Sequel.migration do
|
|
116
116
|
# Requires requests to be a part of tests now.
|
117
117
|
foreign_key :result_id, :results, index: true, type: String
|
118
118
|
foreign_key :test_session_id, :test_sessions, index: true, type: String
|
119
|
-
|
119
|
+
index [:test_session_id, :name], concurrently: true
|
120
120
|
|
121
121
|
column :created_at, DateTime, null: false
|
122
122
|
column :updated_at, DateTime, null: false
|
data/lib/inferno/db/schema.rb
CHANGED
@@ -95,13 +95,13 @@ Sequel.migration do
|
|
95
95
|
String :response_body, :text=>true
|
96
96
|
foreign_key :result_id, :results, :type=>String, :size=>255
|
97
97
|
foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255
|
98
|
-
String :"[:test_session_id, :name]"
|
99
98
|
DateTime :created_at, :null=>false
|
100
99
|
DateTime :updated_at, :null=>false
|
101
100
|
|
102
101
|
index [:id]
|
103
102
|
index [:result_id]
|
104
103
|
index [:test_session_id]
|
104
|
+
index [:test_session_id, :name]
|
105
105
|
end
|
106
106
|
|
107
107
|
create_table(:result_outputs, :ignore_index_errors=>true) do
|
@@ -3,22 +3,43 @@ require_relative '../exceptions'
|
|
3
3
|
module Inferno
|
4
4
|
module DSL
|
5
5
|
module Assertions
|
6
|
+
# Make an assertion
|
7
|
+
#
|
8
|
+
# @param test a value whose truthiness will determine whether the
|
9
|
+
# assertion passes or fails
|
10
|
+
# @param message [String] failure message
|
6
11
|
def assert(test, message = '')
|
7
12
|
raise Exceptions::AssertionException, message unless test
|
8
13
|
end
|
9
14
|
|
15
|
+
# @private
|
10
16
|
def bad_response_status_message(expected, received)
|
11
17
|
"Bad response status: expected #{Array.wrap(expected).join(', ')}, but received #{received}"
|
12
18
|
end
|
13
19
|
|
20
|
+
# Check an response's status
|
21
|
+
#
|
22
|
+
# @param status [Integer, Array<Integer>] a single integer or an array of
|
23
|
+
# integer status codes
|
24
|
+
# @param response [Hash]
|
14
25
|
def assert_response_status(status, response: self.response)
|
15
26
|
assert Array.wrap(status).include?(response[:status]), bad_response_status_message(status, response[:status])
|
16
27
|
end
|
17
28
|
|
29
|
+
# @private
|
18
30
|
def bad_resource_type_message(expected, received)
|
19
31
|
"Bad resource type received: expected #{expected}, but received #{received}"
|
20
32
|
end
|
21
33
|
|
34
|
+
# Check a FHIR resource's type
|
35
|
+
#
|
36
|
+
# @param resource_type [String, Symbol, Class]
|
37
|
+
# @param resource [FHIR::Model]
|
38
|
+
# @example
|
39
|
+
# # The resource type can be a symbol, String, or FHIR::Model class
|
40
|
+
# assert_resource_type(:capability_statement)
|
41
|
+
# assert_resource_type('CapabilityStatement')
|
42
|
+
# assert_resource_type(FHIR::CapabilityStatement)
|
22
43
|
def assert_resource_type(resource_type, resource: self.resource)
|
23
44
|
resource_type_name = normalize_resource_type(resource_type)
|
24
45
|
|
@@ -26,15 +47,48 @@ module Inferno
|
|
26
47
|
bad_resource_type_message(resource_type_name, resource&.resourceType)
|
27
48
|
end
|
28
49
|
|
50
|
+
# @private
|
29
51
|
def invalid_resource_message(profile_url)
|
30
52
|
"Resource does not conform to the profile: #{profile_url}"
|
31
53
|
end
|
32
54
|
|
55
|
+
# Validate a FHIR resource
|
56
|
+
#
|
57
|
+
# @param resource [FHIR::Model]
|
58
|
+
# @param profile_url [String] url of the profile to validate against,
|
59
|
+
# defaults to validating against the base FHIR resource
|
33
60
|
def assert_valid_resource(resource: self.resource, profile_url: nil)
|
34
61
|
assert resource_is_valid?(resource: resource, profile_url: profile_url),
|
35
62
|
invalid_resource_message(profile_url)
|
36
63
|
end
|
37
64
|
|
65
|
+
# Validate each entry of a Bundle
|
66
|
+
#
|
67
|
+
# @param bundle [FHIR::Bundle]
|
68
|
+
# @param resource_types
|
69
|
+
# [String,Symbol,FHIR::Model,Array<String,Symbol,FHIR::Model>,Hash] If a
|
70
|
+
# string, symbol, or FHIR::Model is provided, only that resource type
|
71
|
+
# will be validated. If an array of strings is provided, only those
|
72
|
+
# resource types will be validated. If a hash is provided with resource
|
73
|
+
# types as keys and profile urls (or nil) as values, only those resource
|
74
|
+
# types will be validated against the provided profile url or the base
|
75
|
+
# resource if nil.
|
76
|
+
# @example
|
77
|
+
# # Only validate Patient bundle entries
|
78
|
+
# assert_valid_bundle_entries(resource_types: 'Patient')
|
79
|
+
#
|
80
|
+
# # Only valiadte Patient and Condition bundle entries
|
81
|
+
# assert_valid_bundle_entries(resource_types: ['Patient', 'Condition'])
|
82
|
+
#
|
83
|
+
# # Only validate Patient and Condition bundle entries. Validate Patient
|
84
|
+
# # resources against the given profile, and Codition resources against the
|
85
|
+
# # base FHIR Condition resource.
|
86
|
+
# assert_valid_bundle_entries(
|
87
|
+
# resource_types: {
|
88
|
+
# 'Patient': 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient',
|
89
|
+
# 'Condition': nil
|
90
|
+
# }
|
91
|
+
# )
|
38
92
|
def assert_valid_bundle_entries(bundle: resource, resource_types: {})
|
39
93
|
assert_resource_type('Bundle', resource: bundle)
|
40
94
|
|
@@ -56,6 +110,7 @@ module Inferno
|
|
56
110
|
assert invalid_resources.empty?, invalid_bundle_entries_message(invalid_resources)
|
57
111
|
end
|
58
112
|
|
113
|
+
# @private
|
59
114
|
def invalid_bundle_entries_message(invalid_resources)
|
60
115
|
identifier_strings =
|
61
116
|
invalid_resources
|
@@ -64,6 +119,7 @@ module Inferno
|
|
64
119
|
"The following bundle entries are invalid: #{identifier_strings}"
|
65
120
|
end
|
66
121
|
|
122
|
+
# @private
|
67
123
|
def normalize_resource_type(resource_type)
|
68
124
|
if resource_type.is_a? Class
|
69
125
|
resource_type.name.demodulize
|
@@ -72,6 +128,7 @@ module Inferno
|
|
72
128
|
end
|
73
129
|
end
|
74
130
|
|
131
|
+
# @private
|
75
132
|
def normalize_types_to_check(resource_types)
|
76
133
|
case resource_types
|
77
134
|
when Hash
|
@@ -83,14 +140,22 @@ module Inferno
|
|
83
140
|
end
|
84
141
|
end
|
85
142
|
|
143
|
+
# Check for valid JSON
|
144
|
+
#
|
145
|
+
# @param maybe_json_string [String]
|
146
|
+
# @param message [String] extra failure message
|
86
147
|
def assert_valid_json(maybe_json_string, message = '')
|
87
148
|
assert JSON.parse(maybe_json_string)
|
88
149
|
rescue JSON::ParserError
|
89
150
|
assert false, "Invalid JSON. #{message}"
|
90
151
|
end
|
91
152
|
|
153
|
+
# Check for a valid http/https uri
|
154
|
+
#
|
155
|
+
# @param uri [String]
|
156
|
+
# @param message [String] custom failure message
|
92
157
|
def assert_valid_http_uri(uri, message = '')
|
93
|
-
error_message = message || "\"#{uri}\" is not a valid URI"
|
158
|
+
error_message = message.presence || "\"#{uri}\" is not a valid URI"
|
94
159
|
assert uri =~ /\A#{URI::DEFAULT_PARSER.make_regexp(['http', 'https'])}\z/, error_message
|
95
160
|
end
|
96
161
|
|
@@ -35,7 +35,7 @@ module Inferno
|
|
35
35
|
# @see Inferno::FHIRClientBuilder Documentation for the client
|
36
36
|
# configuration DSL
|
37
37
|
module FHIRClient
|
38
|
-
# @
|
38
|
+
# @private
|
39
39
|
def self.included(klass)
|
40
40
|
klass.extend ClassMethods
|
41
41
|
klass.extend Forwardable
|
@@ -54,7 +54,7 @@ module Inferno
|
|
54
54
|
FHIRClientBuilder.new.build(self, self.class.fhir_client_definitions[client])
|
55
55
|
end
|
56
56
|
|
57
|
-
# @
|
57
|
+
# @private
|
58
58
|
def fhir_clients
|
59
59
|
@fhir_clients ||= {}
|
60
60
|
end
|
@@ -69,15 +69,15 @@ module Inferno
|
|
69
69
|
# @param client [Symbol]
|
70
70
|
# @param name [Symbol] Name for this request to allow it to be used by
|
71
71
|
# other tests
|
72
|
-
# @
|
73
|
-
# must be entered as the last piece of input to this method
|
72
|
+
# @param headers [Hash] custom headers for this operation
|
74
73
|
# @return [Inferno::Entities::Request]
|
75
|
-
def fhir_operation(path, body: nil, client: :default, name: nil,
|
74
|
+
def fhir_operation(path, body: nil, client: :default, name: nil, headers: {})
|
76
75
|
store_request('outgoing', name) do
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
operation_headers = fhir_client(client).fhir_headers
|
77
|
+
operation_headers.merge!('Content-Type' => 'application/fhir+json') if body.present?
|
78
|
+
operation_headers.merge!(headers) if headers.present?
|
79
|
+
|
80
|
+
fhir_client(client).send(:post, path, body, operation_headers)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -86,9 +86,8 @@ module Inferno
|
|
86
86
|
# @param client [Symbol]
|
87
87
|
# @param name [Symbol] Name for this request to allow it to be used by
|
88
88
|
# other tests
|
89
|
-
# @param _options [Hash] TODO
|
90
89
|
# @return [Inferno::Entities::Request]
|
91
|
-
def fhir_get_capability_statement(client: :default, name: nil
|
90
|
+
def fhir_get_capability_statement(client: :default, name: nil)
|
92
91
|
store_request('outgoing', name) do
|
93
92
|
fhir_client(client).conformance_statement
|
94
93
|
fhir_client(client).reply
|
@@ -102,9 +101,8 @@ module Inferno
|
|
102
101
|
# @param client [Symbol]
|
103
102
|
# @param name [Symbol] Name for this request to allow it to be used by
|
104
103
|
# other tests
|
105
|
-
# @param _options [Hash] TODO
|
106
104
|
# @return [Inferno::Entities::Request]
|
107
|
-
def fhir_read(resource_type, id, client: :default, name: nil
|
105
|
+
def fhir_read(resource_type, id, client: :default, name: nil)
|
108
106
|
store_request('outgoing', name) do
|
109
107
|
fhir_client(client).read(fhir_class_from_resource_type(resource_type), id)
|
110
108
|
end
|
@@ -117,24 +115,30 @@ module Inferno
|
|
117
115
|
# @param params [Hash] the search params
|
118
116
|
# @param name [Symbol] Name for this request to allow it to be used by
|
119
117
|
# other tests
|
120
|
-
# @param
|
118
|
+
# @param search_method [Symbol] Use `:post` to search via POST
|
121
119
|
# @return [Inferno::Entities::Request]
|
122
|
-
def fhir_search(resource_type, client: :default, params: {}, name: nil,
|
120
|
+
def fhir_search(resource_type, client: :default, params: {}, name: nil, search_method: :get)
|
121
|
+
search =
|
122
|
+
if search_method == :post
|
123
|
+
{ body: params }
|
124
|
+
else
|
125
|
+
{ parameters: params }
|
126
|
+
end
|
123
127
|
store_request('outgoing', name) do
|
124
128
|
fhir_client(client)
|
125
|
-
.search(fhir_class_from_resource_type(resource_type),
|
129
|
+
.search(fhir_class_from_resource_type(resource_type), { search: search })
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
129
133
|
# @todo Make this a FHIR class method? Something like
|
130
134
|
# FHIR.class_for(resource_type)
|
131
|
-
# @
|
135
|
+
# @private
|
132
136
|
def fhir_class_from_resource_type(resource_type)
|
133
137
|
FHIR.const_get(resource_type.to_s.camelize)
|
134
138
|
end
|
135
139
|
|
136
140
|
module ClassMethods
|
137
|
-
# @
|
141
|
+
# @private
|
138
142
|
def fhir_client_definitions
|
139
143
|
@fhir_client_definitions ||= {}
|
140
144
|
end
|
@@ -6,7 +6,7 @@ module Inferno
|
|
6
6
|
class FHIRClientBuilder
|
7
7
|
attr_accessor :runnable
|
8
8
|
|
9
|
-
# @
|
9
|
+
# @private
|
10
10
|
def build(runnable, block)
|
11
11
|
self.runnable = runnable
|
12
12
|
instance_exec(self, &block)
|
@@ -56,14 +56,14 @@ module Inferno
|
|
56
56
|
@headers ||= headers
|
57
57
|
end
|
58
58
|
|
59
|
-
# @
|
59
|
+
# @private
|
60
60
|
def method_missing(name, *args, &block)
|
61
61
|
return runnable.call(name, *args, &block) if runnable.respond_to? name
|
62
62
|
|
63
63
|
super
|
64
64
|
end
|
65
65
|
|
66
|
-
# @
|
66
|
+
# @private
|
67
67
|
def respond_to_missing?(name)
|
68
68
|
runnable.respond_to?(name) || super
|
69
69
|
end
|
@@ -1,38 +1,113 @@
|
|
1
1
|
module Inferno
|
2
2
|
module DSL
|
3
|
+
# This module contains the methods needed to configure a validator to
|
4
|
+
# perform validation of FHIR resources. The actual validation is performed
|
5
|
+
# by an external FHIR validation service. Tests will typically rely on
|
6
|
+
# `assert_valid_resource` for validation rather than directly calling
|
7
|
+
# methods on a validator.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# validator do
|
12
|
+
# url 'http://example.com/validator'
|
13
|
+
# exclude_message { |message| message.type == 'info' }
|
14
|
+
# perform_additional_validation do |resource, profile_url|
|
15
|
+
# if something_is_wrong
|
16
|
+
# { type: 'error', message: 'something is wrong' }
|
17
|
+
# else
|
18
|
+
# { type: 'info', message: 'everything is ok' }
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
3
22
|
module FHIRValidation
|
4
23
|
def self.included(klass)
|
5
24
|
klass.extend ClassMethods
|
6
25
|
end
|
7
26
|
|
27
|
+
# Perform validation, and add validation messages to the runnable
|
28
|
+
#
|
29
|
+
# @param resource [FHIR::Model]
|
30
|
+
# @param profile_url [String]
|
31
|
+
# @param validator [Symbol] the name of the validator to use
|
32
|
+
# @return [Boolean] whether the resource is valid
|
8
33
|
def resource_is_valid?(resource: self.resource, profile_url: nil, validator: :default)
|
9
34
|
find_validator(validator).resource_is_valid?(resource, profile_url, self)
|
10
35
|
end
|
11
36
|
|
37
|
+
# Find a particular validator. Looks through a runnable's parents up to
|
38
|
+
# the suite to find a validator with a particular name
|
12
39
|
def find_validator(validator_name)
|
13
40
|
self.class.find_validator(validator_name)
|
14
41
|
end
|
15
42
|
|
16
43
|
class Validator
|
44
|
+
# @private
|
17
45
|
def initialize(&block)
|
18
46
|
instance_eval(&block)
|
19
47
|
end
|
20
48
|
|
49
|
+
# @private
|
21
50
|
def default_validator_url
|
22
51
|
ENV.fetch('VALIDATOR_URL')
|
23
52
|
end
|
24
53
|
|
54
|
+
# Set the url of the validator service
|
55
|
+
#
|
56
|
+
# @param url [String]
|
25
57
|
def url(validator_url = nil)
|
26
58
|
@url = validator_url if validator_url
|
27
59
|
|
28
60
|
@url
|
29
61
|
end
|
30
62
|
|
63
|
+
# @private
|
64
|
+
def additional_validations
|
65
|
+
@additional_validations ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
# Perform validation steps in addition to FHIR validation.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# perform_additional_validation do |resource, profile_url|
|
72
|
+
# if something_is_wrong
|
73
|
+
# { type: 'error', message: 'something is wrong' }
|
74
|
+
# else
|
75
|
+
# { type: 'info', message: 'everything is ok' }
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
# @yieldparam resource [FHIR::Model] the resource being validated
|
79
|
+
# @yieldparam profile_url [String] the profile the resource is being
|
80
|
+
# validated against
|
81
|
+
# @yieldreturn [Array<Hash<Symbol, String>>,Hash<Symbol, String>] The
|
82
|
+
# block should return a Hash or an Array of Hashes if any validation
|
83
|
+
# messages should be added. The Hash must contain two keys: `:type`
|
84
|
+
# and `:message`. `:type` can have a value of `'info'`, `'warning'`,
|
85
|
+
# or `'error'`. A type of `'error'` means the resource is invalid.
|
86
|
+
# `:message` contains the message string itself.
|
87
|
+
def perform_additional_validation(&block)
|
88
|
+
additional_validations << block
|
89
|
+
end
|
90
|
+
|
91
|
+
# @private
|
92
|
+
def additional_validation_messages(resource, profile_url)
|
93
|
+
additional_validations
|
94
|
+
.flat_map { |step| step.call(resource, profile_url) }
|
95
|
+
.select { |message| message.is_a? Hash }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Filter out unwanted validation messages
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# validator do
|
102
|
+
# exclude_message { |message| message.type == 'info' }
|
103
|
+
# end
|
104
|
+
# @yieldparam message [Inferno::Entities::Message]
|
31
105
|
def exclude_message(&block)
|
32
106
|
@exclude_message = block if block_given?
|
33
107
|
@exclude_message
|
34
108
|
end
|
35
109
|
|
110
|
+
# @see Inferno::DSL::FHIRValidation#resource_is_valid?
|
36
111
|
def resource_is_valid?(resource, profile_url, runnable)
|
37
112
|
profile_url ||= FHIR::Definitions.resource_definition(resource.resourceType).url
|
38
113
|
|
@@ -40,6 +115,8 @@ module Inferno
|
|
40
115
|
|
41
116
|
message_hashes = outcome.issue&.map { |issue| message_hash_from_issue(issue) } || []
|
42
117
|
|
118
|
+
message_hashes.concat(additional_validation_messages(resource, profile_url))
|
119
|
+
|
43
120
|
filter_messages(message_hashes)
|
44
121
|
|
45
122
|
message_hashes
|
@@ -47,10 +124,12 @@ module Inferno
|
|
47
124
|
.none? { |message_hash| message_hash[:type] == 'error' }
|
48
125
|
end
|
49
126
|
|
127
|
+
# @private
|
50
128
|
def filter_messages(message_hashes)
|
51
129
|
message_hashes.reject! { |message| exclude_message.call(Entities::Message.new(message)) } if exclude_message
|
52
130
|
end
|
53
131
|
|
132
|
+
# @private
|
54
133
|
def message_hash_from_issue(issue)
|
55
134
|
{
|
56
135
|
type: issue_severity(issue),
|
@@ -58,6 +137,7 @@ module Inferno
|
|
58
137
|
}
|
59
138
|
end
|
60
139
|
|
140
|
+
# @private
|
61
141
|
def issue_severity(issue)
|
62
142
|
case issue.severity
|
63
143
|
when 'warning'
|
@@ -69,6 +149,7 @@ module Inferno
|
|
69
149
|
end
|
70
150
|
end
|
71
151
|
|
152
|
+
# @private
|
72
153
|
def issue_message(issue)
|
73
154
|
location = if issue.respond_to?(:expression)
|
74
155
|
issue.expression&.join(', ')
|
@@ -79,6 +160,11 @@ module Inferno
|
|
79
160
|
"#{location}: #{issue&.details&.text}"
|
80
161
|
end
|
81
162
|
|
163
|
+
# Post a resource to the validation service for validating.
|
164
|
+
#
|
165
|
+
# @param resource [FHIR::Model]
|
166
|
+
# @param profile_url [String]
|
167
|
+
# @return [String] the body of the validation response
|
82
168
|
def validate(resource, profile_url)
|
83
169
|
RestClient.post(
|
84
170
|
"#{url}/validate",
|
@@ -89,15 +175,33 @@ module Inferno
|
|
89
175
|
end
|
90
176
|
|
91
177
|
module ClassMethods
|
92
|
-
# @
|
178
|
+
# @private
|
93
179
|
def fhir_validators
|
94
180
|
@fhir_validators ||= {}
|
95
181
|
end
|
96
182
|
|
183
|
+
# Define a validator
|
184
|
+
# @example
|
185
|
+
# validator do
|
186
|
+
# url 'http://example.com/validator'
|
187
|
+
# exclude_message { |message| message.type == 'info' }
|
188
|
+
# perform_additional_validation do |resource, profile_url|
|
189
|
+
# if something_is_wrong
|
190
|
+
# { type: 'error', message: 'something is wrong' }
|
191
|
+
# else
|
192
|
+
# { type: 'info', message: 'everything is ok' }
|
193
|
+
# end
|
194
|
+
# end
|
195
|
+
# end
|
196
|
+
#
|
197
|
+
# @param name [Symbol] the name of the validator, only needed if you are
|
198
|
+
# using multiple validators
|
97
199
|
def validator(name = :default, &block)
|
98
200
|
fhir_validators[name] = Inferno::DSL::FHIRValidation::Validator.new(&block)
|
99
201
|
end
|
100
202
|
|
203
|
+
# Find a particular validator. Looks through a runnable's parents up to
|
204
|
+
# the suite to find a validator with a particular name
|
101
205
|
def find_validator(validator_name)
|
102
206
|
validator = fhir_validators[validator_name] || parent&.find_validator(validator_name)
|
103
207
|
|
@@ -16,7 +16,7 @@ module Inferno
|
|
16
16
|
# # performs a GET to https://example.com
|
17
17
|
# get
|
18
18
|
# # performs a GET to https://example.com/abc
|
19
|
-
#
|
19
|
+
# get('abc')
|
20
20
|
#
|
21
21
|
# request # the most recent request
|
22
22
|
# response # the most recent response
|
@@ -27,7 +27,7 @@ module Inferno
|
|
27
27
|
# @see Inferno::FHIRClientBuilder Documentation for the client
|
28
28
|
# configuration DSL
|
29
29
|
module HTTPClient
|
30
|
-
# @
|
30
|
+
# @private
|
31
31
|
def self.included(klass)
|
32
32
|
klass.extend ClassMethods
|
33
33
|
klass.include RequestStorage
|
@@ -47,7 +47,7 @@ module Inferno
|
|
47
47
|
http_clients[client] = HTTPClientBuilder.new.build(self, definition)
|
48
48
|
end
|
49
49
|
|
50
|
-
# @
|
50
|
+
# @private
|
51
51
|
def http_clients
|
52
52
|
@http_clients ||= {}
|
53
53
|
end
|
@@ -104,7 +104,7 @@ module Inferno
|
|
104
104
|
end
|
105
105
|
|
106
106
|
module ClassMethods
|
107
|
-
# @
|
107
|
+
# @private
|
108
108
|
def http_client_definitions
|
109
109
|
@http_client_definitions ||= {}
|
110
110
|
end
|