inferno_core 0.0.1
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 +7 -0
- data/LICENSE +201 -0
- data/bin/inferno-console +8 -0
- data/lib/inferno.rb +15 -0
- data/lib/inferno/apps/web/application.rb +12 -0
- data/lib/inferno/apps/web/controllers/controller.rb +34 -0
- data/lib/inferno/apps/web/controllers/requests/show.rb +16 -0
- data/lib/inferno/apps/web/controllers/test_runs/create.rb +39 -0
- data/lib/inferno/apps/web/controllers/test_runs/results/index.rb +18 -0
- data/lib/inferno/apps/web/controllers/test_runs/show.rb +16 -0
- data/lib/inferno/apps/web/controllers/test_sessions/create.rb +26 -0
- data/lib/inferno/apps/web/controllers/test_sessions/results/index.rb +17 -0
- data/lib/inferno/apps/web/controllers/test_sessions/show.rb +16 -0
- data/lib/inferno/apps/web/controllers/test_suites/index.rb +13 -0
- data/lib/inferno/apps/web/controllers/test_suites/show.rb +16 -0
- data/lib/inferno/apps/web/router.rb +27 -0
- data/lib/inferno/apps/web/serializers/header.rb +12 -0
- data/lib/inferno/apps/web/serializers/input.rb +16 -0
- data/lib/inferno/apps/web/serializers/message.rb +10 -0
- data/lib/inferno/apps/web/serializers/request.rb +26 -0
- data/lib/inferno/apps/web/serializers/result.rb +21 -0
- data/lib/inferno/apps/web/serializers/serializer.rb +16 -0
- data/lib/inferno/apps/web/serializers/test.rb +17 -0
- data/lib/inferno/apps/web/serializers/test_group.rb +23 -0
- data/lib/inferno/apps/web/serializers/test_run.rb +19 -0
- data/lib/inferno/apps/web/serializers/test_session.rb +17 -0
- data/lib/inferno/apps/web/serializers/test_suite.rb +18 -0
- data/lib/inferno/config/application.rb +22 -0
- data/lib/inferno/config/boot.rb +5 -0
- data/lib/inferno/config/boot/db.rb +23 -0
- data/lib/inferno/config/boot/logging.rb +16 -0
- data/lib/inferno/config/boot/suites.rb +27 -0
- data/lib/inferno/config/boot/web.rb +17 -0
- data/lib/inferno/db/migrations/001_create_initial_structure.rb +165 -0
- data/lib/inferno/dsl.rb +35 -0
- data/lib/inferno/dsl/assertions.rb +93 -0
- data/lib/inferno/dsl/fhir_client.rb +152 -0
- data/lib/inferno/dsl/fhir_client_builder.rb +56 -0
- data/lib/inferno/dsl/fhir_manipulation.rb +25 -0
- data/lib/inferno/dsl/fhir_validation.rb +111 -0
- data/lib/inferno/dsl/http_client.rb +122 -0
- data/lib/inferno/dsl/http_client_builder.rb +54 -0
- data/lib/inferno/dsl/request_storage.rb +101 -0
- data/lib/inferno/dsl/results.rb +54 -0
- data/lib/inferno/dsl/runnable.rb +250 -0
- data/lib/inferno/entities.rb +19 -0
- data/lib/inferno/entities/attributes.rb +9 -0
- data/lib/inferno/entities/entity.rb +15 -0
- data/lib/inferno/entities/header.rb +42 -0
- data/lib/inferno/entities/message.rb +22 -0
- data/lib/inferno/entities/request.rb +166 -0
- data/lib/inferno/entities/result.rb +49 -0
- data/lib/inferno/entities/test.rb +173 -0
- data/lib/inferno/entities/test_group.rb +87 -0
- data/lib/inferno/entities/test_input.rb +20 -0
- data/lib/inferno/entities/test_run.rb +63 -0
- data/lib/inferno/entities/test_session.rb +26 -0
- data/lib/inferno/entities/test_suite.rb +73 -0
- data/lib/inferno/exceptions.rb +42 -0
- data/lib/inferno/public/217.bundle.js +1 -0
- data/lib/inferno/public/assets.json +6 -0
- data/lib/inferno/public/bundle.js +2 -0
- data/lib/inferno/public/bundle.js.LICENSE.txt +65 -0
- data/lib/inferno/public/e09b16f5cb645eb05f90c8f38f3409fb.png +0 -0
- data/lib/inferno/public/favicon.ico +0 -0
- data/lib/inferno/public/logo192.png +0 -0
- data/lib/inferno/public/logo512.png +0 -0
- data/lib/inferno/repositories.rb +27 -0
- data/lib/inferno/repositories/headers.rb +22 -0
- data/lib/inferno/repositories/in_memory_repository.rb +41 -0
- data/lib/inferno/repositories/messages.rb +35 -0
- data/lib/inferno/repositories/repository.rb +106 -0
- data/lib/inferno/repositories/requests.rb +89 -0
- data/lib/inferno/repositories/results.rb +72 -0
- data/lib/inferno/repositories/test_groups.rb +9 -0
- data/lib/inferno/repositories/test_runs.rb +46 -0
- data/lib/inferno/repositories/test_sessions.rb +56 -0
- data/lib/inferno/repositories/test_suites.rb +9 -0
- data/lib/inferno/repositories/tests.rb +9 -0
- data/lib/inferno/repositories/validate_runnable_reference.rb +42 -0
- data/lib/inferno/spec_support.rb +9 -0
- data/lib/inferno/test_runner.rb +81 -0
- data/lib/inferno/utils/middleware/request_logger.rb +55 -0
- data/lib/inferno/version.rb +3 -0
- data/spec/support/factory_bot.rb +21 -0
- metadata +514 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require_relative 'request_storage'
|
|
2
|
+
|
|
3
|
+
module Inferno
|
|
4
|
+
module DSL
|
|
5
|
+
# This module contains the HTTP DSL available to test writers.
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# class MyTestGroup < Inferno::TestGroup
|
|
9
|
+
# # create a "default" client for a group
|
|
10
|
+
# http_client do
|
|
11
|
+
# url 'https://example.com/'
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# test :some_test do
|
|
15
|
+
# run do
|
|
16
|
+
# # performs a GET to https://example.com
|
|
17
|
+
# get
|
|
18
|
+
# # performs a GET to https://example.com/abc
|
|
19
|
+
# get('abc')
|
|
20
|
+
#
|
|
21
|
+
# request # the most recent request
|
|
22
|
+
# response # the most recent response
|
|
23
|
+
# requests # all of the requests which have been made in this test
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
# @see Inferno::FHIRClientBuilder Documentation for the client
|
|
28
|
+
# configuration DSL
|
|
29
|
+
module HTTPClient
|
|
30
|
+
# @api private
|
|
31
|
+
def self.included(klass)
|
|
32
|
+
klass.extend ClassMethods
|
|
33
|
+
klass.include RequestStorage
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Return a previously defined HTTP client
|
|
37
|
+
#
|
|
38
|
+
# @param client [Symbol] the name of the client
|
|
39
|
+
# @return [Faraday::Connection]
|
|
40
|
+
# @see Inferno::HTTPClientBuilder
|
|
41
|
+
def http_client(client = :default)
|
|
42
|
+
return http_clients[client] if http_clients[client]
|
|
43
|
+
|
|
44
|
+
definition = self.class.http_client_definitions[client]
|
|
45
|
+
return nil if definition.nil?
|
|
46
|
+
|
|
47
|
+
http_clients[client] = HTTPClientBuilder.new.build(self, definition)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api private
|
|
51
|
+
def http_clients
|
|
52
|
+
@http_clients ||= {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Perform an HTTP GET request
|
|
56
|
+
#
|
|
57
|
+
# @param url [String] if this request is using a defined client, this will
|
|
58
|
+
# be appended to the client's url. Must be an absolute url for requests
|
|
59
|
+
# made without a defined client
|
|
60
|
+
# @param client [Symbol]
|
|
61
|
+
# @param name [Symbol] Name for this request to allow it to be used by
|
|
62
|
+
# other tests
|
|
63
|
+
# @param _options [Hash] TODO
|
|
64
|
+
# @return [Inferno::Entities::Request]
|
|
65
|
+
def get(url = '', client: :default, name: nil, **_options)
|
|
66
|
+
store_request('outgoing', name) do
|
|
67
|
+
client = http_client(client)
|
|
68
|
+
|
|
69
|
+
if client
|
|
70
|
+
client.get(url)
|
|
71
|
+
elsif url.match?(%r{\Ahttps?://})
|
|
72
|
+
Faraday.get(url)
|
|
73
|
+
else
|
|
74
|
+
raise StandardError, 'Must use an absolute url or define an HTTP client with a base url'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Perform an HTTP POST request
|
|
80
|
+
#
|
|
81
|
+
# @param url [String] if this request is using a defined client, this will
|
|
82
|
+
# be appended to the client's url. Must be an absolute url for requests
|
|
83
|
+
# made without a defined client
|
|
84
|
+
# @param body [String]
|
|
85
|
+
# @param client [Symbol]
|
|
86
|
+
# @param name [Symbol] Name for this request to allow it to be used by
|
|
87
|
+
# other tests
|
|
88
|
+
# @param _options [Hash] TODO
|
|
89
|
+
# @return [Inferno::Entities::Request]
|
|
90
|
+
def post(url = '', body: nil, client: :default, name: nil, **_options)
|
|
91
|
+
store_request('outgoing', name) do
|
|
92
|
+
client = http_client(client)
|
|
93
|
+
|
|
94
|
+
if client
|
|
95
|
+
client.post(url, body)
|
|
96
|
+
elsif url.match?(%r{\Ahttps?://})
|
|
97
|
+
Faraday.post(url, body)
|
|
98
|
+
else
|
|
99
|
+
raise StandardError, 'Must use an absolute url or define an HTTP client with a base url'
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
module ClassMethods
|
|
105
|
+
# @api private
|
|
106
|
+
def http_client_definitions
|
|
107
|
+
@http_client_definitions ||= {}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Define a HTTP client to be used by a Runnable.
|
|
111
|
+
#
|
|
112
|
+
# @param name [Symbol] a name used to reference this particular client
|
|
113
|
+
# @param block a block to configure the client
|
|
114
|
+
# @see Inferno::HTTPClientBuilder Documentation for the client
|
|
115
|
+
# configuration DSL
|
|
116
|
+
def http_client(name = :default, &block)
|
|
117
|
+
http_client_definitions[name] = block
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Inferno
|
|
2
|
+
module DSL
|
|
3
|
+
# This module contains the HTTP DSL available to test writers.
|
|
4
|
+
class HTTPClientBuilder
|
|
5
|
+
attr_accessor :runnable
|
|
6
|
+
|
|
7
|
+
# @api private
|
|
8
|
+
def build(runnable, block)
|
|
9
|
+
self.runnable = runnable
|
|
10
|
+
instance_exec(self, &block)
|
|
11
|
+
|
|
12
|
+
params = { url: url }
|
|
13
|
+
params.merge!(headers: headers) if headers
|
|
14
|
+
|
|
15
|
+
Faraday.new(params)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Define the base url for an HTTP client. A string or symbol can be
|
|
19
|
+
# provided. A string is interpreted as a url. A symbol is interpreted as
|
|
20
|
+
# the name of an input to the Runnable.
|
|
21
|
+
#
|
|
22
|
+
# @param url [String, Symbol]
|
|
23
|
+
# @return [void]
|
|
24
|
+
def url(url = nil)
|
|
25
|
+
@url ||=
|
|
26
|
+
if url.is_a? Symbol
|
|
27
|
+
runnable.send(url)
|
|
28
|
+
else
|
|
29
|
+
url
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Define custom headers for a client
|
|
34
|
+
#
|
|
35
|
+
# @param headers [Hash]
|
|
36
|
+
# @return [void]
|
|
37
|
+
def headers(headers = nil)
|
|
38
|
+
@headers ||= headers
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @api private
|
|
42
|
+
def method_missing(name, *args, &block)
|
|
43
|
+
return runnable.call(name, *args, &block) if runnable.respond_to? name
|
|
44
|
+
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api private
|
|
49
|
+
def respond_to_missing?(name)
|
|
50
|
+
runnable.respond_to?(name) || super
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Inferno
|
|
2
|
+
module DSL
|
|
3
|
+
# This module handles storing and retrieving requests/responses made by
|
|
4
|
+
# FHIR/HTTP clients
|
|
5
|
+
module RequestStorage
|
|
6
|
+
def self.included(klass)
|
|
7
|
+
klass.extend ClassMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Returns the FHIR/HTTP requests that have been made in this `Test`
|
|
11
|
+
#
|
|
12
|
+
# @return [Array<Inferno::Entities::Request>]
|
|
13
|
+
def requests
|
|
14
|
+
@requests ||= []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns the most recent FHIR/HTTP request
|
|
18
|
+
#
|
|
19
|
+
# @return [Inferno::Entities::Request]
|
|
20
|
+
def request
|
|
21
|
+
requests.last
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns the response from the most recent FHIR/HTTP request
|
|
25
|
+
#
|
|
26
|
+
# @return [Hash, nil]
|
|
27
|
+
def response
|
|
28
|
+
request&.response
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns the FHIR resource from the response to the most recent FHIR
|
|
32
|
+
# request
|
|
33
|
+
#
|
|
34
|
+
# @return [FHIR::Model, nil]
|
|
35
|
+
def resource
|
|
36
|
+
request&.resource
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# TODO: do a check in the test runner
|
|
40
|
+
def named_request(name)
|
|
41
|
+
requests.find { |request| request.name == name.to_sym }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @api private
|
|
45
|
+
def store_request(direction, name = nil, &block)
|
|
46
|
+
response = block.call
|
|
47
|
+
|
|
48
|
+
request =
|
|
49
|
+
if response.is_a? FHIR::ClientReply
|
|
50
|
+
Entities::Request.from_fhir_client_reply(
|
|
51
|
+
response, direction: direction, name: name, test_session_id: test_session_id
|
|
52
|
+
)
|
|
53
|
+
else
|
|
54
|
+
Entities::Request.from_http_response(
|
|
55
|
+
response, direction: direction, name: name, test_session_id: test_session_id
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
requests << request
|
|
60
|
+
request
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @api private
|
|
64
|
+
def load_named_requests
|
|
65
|
+
requests_repo = Inferno::Repositories::Requests.new
|
|
66
|
+
self.class.named_requests_used.map do |request_name|
|
|
67
|
+
request = requests_repo.find_named_request(test_session_id, request_name)
|
|
68
|
+
raise StandardError, "Unable to find '#{request_name}' request" if request.nil?
|
|
69
|
+
|
|
70
|
+
requests << request
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
module ClassMethods
|
|
75
|
+
# @api private
|
|
76
|
+
def named_requests_made
|
|
77
|
+
@named_requests_made ||= []
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @api private
|
|
81
|
+
def named_requests_used
|
|
82
|
+
@named_requests_used ||= []
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Specify the named requests made by a test
|
|
86
|
+
#
|
|
87
|
+
# @param *names [Symbol] one or more Symbols
|
|
88
|
+
def makes_request(*names)
|
|
89
|
+
named_requests_made.concat(names)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Specify the named requests used by a test
|
|
93
|
+
#
|
|
94
|
+
# @param *names [Symbol] one or more Symbols
|
|
95
|
+
def uses_request(*names)
|
|
96
|
+
named_requests_used.concat(names)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Inferno
|
|
2
|
+
module DSL
|
|
3
|
+
# This module contains methods to set test results.
|
|
4
|
+
module Results
|
|
5
|
+
# Halt execution of the current test and mark it as passed.
|
|
6
|
+
#
|
|
7
|
+
# @param message [String]
|
|
8
|
+
def pass(message = '')
|
|
9
|
+
raise Exceptions::PassException, message
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Halt execution of the current test and mark it as passed if a condition
|
|
13
|
+
# is true.
|
|
14
|
+
#
|
|
15
|
+
# @param test [Boolean]
|
|
16
|
+
# @param message [String]
|
|
17
|
+
def pass_if(test, message = '')
|
|
18
|
+
raise Exceptions::PassException, message if test
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Halt execution of the current test and mark it as skipped.
|
|
22
|
+
#
|
|
23
|
+
# @param message [String]
|
|
24
|
+
def skip(message = '')
|
|
25
|
+
raise Exceptions::SkipException, message
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Halt execution of the current test and mark it as skipped if a condition
|
|
29
|
+
# is true.
|
|
30
|
+
#
|
|
31
|
+
# @param test [Boolean]
|
|
32
|
+
# @param message [String]
|
|
33
|
+
def skip_if(test, message = '')
|
|
34
|
+
raise Exceptions::SkipException, message if test
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Halt execution of the current test and mark it as omitted.
|
|
38
|
+
#
|
|
39
|
+
# @param message [String]
|
|
40
|
+
def omit(message = '')
|
|
41
|
+
raise Exceptions::OmitException, message
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Halt execution of the current test and mark it as omitted if a condition
|
|
45
|
+
# is true.
|
|
46
|
+
#
|
|
47
|
+
# @param test [Boolean]
|
|
48
|
+
# @param message [String]
|
|
49
|
+
def omit_if(test, message = '')
|
|
50
|
+
raise Exceptions::OmitException, message if test
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
module Inferno
|
|
2
|
+
module DSL
|
|
3
|
+
# This module contains the DSL for defining child entities in the test
|
|
4
|
+
# definition framework.
|
|
5
|
+
module Runnable
|
|
6
|
+
attr_accessor :parent
|
|
7
|
+
|
|
8
|
+
# When a class (e.g. TestSuite/TestGroup) uses this module, set it up
|
|
9
|
+
# so that subclassing it works correctly.
|
|
10
|
+
# - add the subclass to the relevant repository when it is created
|
|
11
|
+
# - copy the class instance variables from the superclass
|
|
12
|
+
# - add a hook to the subclass so that its subclasses do the same
|
|
13
|
+
# @api private
|
|
14
|
+
def self.extended(extending_class)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
extending_class.define_singleton_method(:inherited) do |subclass|
|
|
18
|
+
copy_instance_variables(subclass)
|
|
19
|
+
|
|
20
|
+
# Whenever the definition of a Runnable class ends, keep track of the
|
|
21
|
+
# file it came from. Once the Suite loader successfully loads a file,
|
|
22
|
+
# it will add all of the Runnable classes from that file to the
|
|
23
|
+
# appropriate repositories.
|
|
24
|
+
TracePoint.trace(:end) do |trace|
|
|
25
|
+
if trace.self == subclass
|
|
26
|
+
subclass.add_self_to_repository
|
|
27
|
+
trace.disable
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Class instance variables are used to hold the metadata for Runnable
|
|
34
|
+
# classes. When inheriting from a Runnable class, these class instance
|
|
35
|
+
# variables need to be copied. Any child Runnable classes will themselves
|
|
36
|
+
# need to be subclassed so that their parent can be updated.
|
|
37
|
+
# @api private
|
|
38
|
+
def copy_instance_variables(subclass)
|
|
39
|
+
instance_variables.each do |variable|
|
|
40
|
+
next if [:@id, :@groups, :@tests, :@parent, :@children].include?(variable)
|
|
41
|
+
|
|
42
|
+
subclass.instance_variable_set(variable, instance_variable_get(variable).dup)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
child_types.each do |child_type|
|
|
46
|
+
new_children = send(child_type).map do |child|
|
|
47
|
+
Class.new(child).tap do |subclass_child|
|
|
48
|
+
subclass_child.parent = subclass
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
subclass.instance_variable_set(:"@#{child_type}", new_children)
|
|
53
|
+
subclass.children.concat(new_children)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @api private
|
|
58
|
+
def add_self_to_repository
|
|
59
|
+
repository.insert(self)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# An instance of the repository for the class using this module
|
|
63
|
+
def repository
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# This method defines a child entity. Classes using this module should
|
|
68
|
+
# alias the method name they wish to use to define child entities to this
|
|
69
|
+
# method.
|
|
70
|
+
# @api private
|
|
71
|
+
def define_child(*args, &block)
|
|
72
|
+
hash_args = process_args(args)
|
|
73
|
+
|
|
74
|
+
klass = create_child_class(hash_args)
|
|
75
|
+
|
|
76
|
+
klass.parent = self
|
|
77
|
+
|
|
78
|
+
child_metadata[:collection] << klass
|
|
79
|
+
children << klass
|
|
80
|
+
|
|
81
|
+
configure_child_class(klass, hash_args)
|
|
82
|
+
|
|
83
|
+
handle_child_definition_block(klass, &block)
|
|
84
|
+
|
|
85
|
+
klass.add_self_to_repository
|
|
86
|
+
|
|
87
|
+
klass
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @api private
|
|
91
|
+
def process_args(args)
|
|
92
|
+
hash_args =
|
|
93
|
+
if args[0].is_a? Hash
|
|
94
|
+
args[0]
|
|
95
|
+
elsif args[1].is_a? Hash
|
|
96
|
+
args[1]
|
|
97
|
+
else
|
|
98
|
+
{}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
hash_args[:title] = args[0] if args[0].is_a? String
|
|
102
|
+
|
|
103
|
+
hash_args
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @api private
|
|
107
|
+
def child_metadata(metadata = nil)
|
|
108
|
+
@child_metadata = metadata if metadata
|
|
109
|
+
@child_metadata
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @api private
|
|
113
|
+
def create_child_class(hash_args)
|
|
114
|
+
superclass_id = hash_args.delete :from
|
|
115
|
+
|
|
116
|
+
return Class.new(child_metadata[:class]) if superclass_id.blank?
|
|
117
|
+
|
|
118
|
+
superclass = child_metadata[:repo].find(superclass_id)
|
|
119
|
+
|
|
120
|
+
raise Exceptions::ParentNotLoadedException.new(child_metadata[:class], superclass_id) unless superclass
|
|
121
|
+
|
|
122
|
+
Class.new(superclass)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @api private
|
|
126
|
+
def configure_child_class(klass, hash_args) # rubocop:disable Metrics/CyclomaticComplexity
|
|
127
|
+
inputs.each do |input_definition|
|
|
128
|
+
next if klass.inputs.include? input_definition
|
|
129
|
+
|
|
130
|
+
klass.input input_definition
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
outputs.each do |output_definition|
|
|
134
|
+
next if klass.outputs.include? output_definition
|
|
135
|
+
|
|
136
|
+
klass.output output_definition
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
new_fhir_client_definitions = klass.instance_variable_get(:@fhir_client_definitions) || {}
|
|
140
|
+
fhir_client_definitions.each do |name, definition|
|
|
141
|
+
next if new_fhir_client_definitions.include? name
|
|
142
|
+
|
|
143
|
+
new_fhir_client_definitions[name] = definition.dup
|
|
144
|
+
end
|
|
145
|
+
klass.instance_variable_set(:@fhir_client_definitions, new_fhir_client_definitions)
|
|
146
|
+
|
|
147
|
+
new_http_client_definitions = klass.instance_variable_get(:@http_client_definitions) || {}
|
|
148
|
+
http_client_definitions.each do |name, definition|
|
|
149
|
+
next if new_http_client_definitions.include? name
|
|
150
|
+
|
|
151
|
+
new_http_client_definitions[name] = definition.dup
|
|
152
|
+
end
|
|
153
|
+
klass.instance_variable_set(:@http_client_definitions, new_http_client_definitions)
|
|
154
|
+
|
|
155
|
+
hash_args.each do |key, value|
|
|
156
|
+
klass.send(key, *value)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
klass.children.each do |child_class|
|
|
160
|
+
klass.configure_child_class(child_class, {})
|
|
161
|
+
child_class.add_self_to_repository
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @api private
|
|
166
|
+
def handle_child_definition_block(klass, &block)
|
|
167
|
+
klass.class_eval(&block) if block_given?
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def id(new_id = nil)
|
|
171
|
+
return @id if new_id.nil? && @id.present?
|
|
172
|
+
|
|
173
|
+
prefix =
|
|
174
|
+
if parent
|
|
175
|
+
"#{parent.id}-"
|
|
176
|
+
else
|
|
177
|
+
''
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
@base_id = new_id || @base_id || default_id
|
|
181
|
+
|
|
182
|
+
@id = "#{prefix}#{@base_id}"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def title(new_title = nil)
|
|
186
|
+
return @title if new_title.nil?
|
|
187
|
+
|
|
188
|
+
@title = new_title
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def description(new_description = nil)
|
|
192
|
+
return @description if new_description.nil?
|
|
193
|
+
|
|
194
|
+
@description = new_description
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Define inputs
|
|
198
|
+
#
|
|
199
|
+
# @param inputs [Symbol]
|
|
200
|
+
# @return [void]
|
|
201
|
+
# @example
|
|
202
|
+
# input :patient_id, :bearer_token
|
|
203
|
+
def input(*input_definitions)
|
|
204
|
+
inputs.concat(input_definitions)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Define outputs
|
|
208
|
+
#
|
|
209
|
+
# @param output_definitions [Symbol]
|
|
210
|
+
# @return [void]
|
|
211
|
+
# @example
|
|
212
|
+
# output :patient_id, :bearer_token
|
|
213
|
+
def output(*output_definitions)
|
|
214
|
+
outputs.concat(output_definitions)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# @api private
|
|
218
|
+
def default_id
|
|
219
|
+
to_s
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# @api private
|
|
223
|
+
def inputs
|
|
224
|
+
@inputs ||= []
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# @api private
|
|
228
|
+
def outputs
|
|
229
|
+
@outputs ||= []
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def child_types
|
|
233
|
+
return [] if ancestors.include? Inferno::Entities::Test
|
|
234
|
+
return [:groups] if ancestors.include? Inferno::Entities::TestSuite
|
|
235
|
+
|
|
236
|
+
[:groups, :tests]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def children
|
|
240
|
+
@children ||= []
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def validator_url(url = nil)
|
|
244
|
+
return @validator_url ||= parent&.validator_url if url.nil?
|
|
245
|
+
|
|
246
|
+
@validator_url = url
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|