inferno_core 0.2.0.rc4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/inferno/apps/web/controllers/test_runs/create.rb +33 -14
- data/lib/inferno/apps/web/index.html.erb +21 -1
- data/lib/inferno/apps/web/serializers/result.rb +4 -0
- data/lib/inferno/apps/web/serializers/test.rb +1 -1
- data/lib/inferno/apps/web/serializers/test_group.rb +1 -1
- data/lib/inferno/apps/web/serializers/test_suite.rb +1 -0
- data/lib/inferno/dsl/configurable.rb +22 -8
- data/lib/inferno/dsl/fhir_validation.rb +3 -1
- data/lib/inferno/dsl/input_output_handling.rb +185 -0
- data/lib/inferno/dsl/runnable.rb +24 -133
- data/lib/inferno/entities/input.rb +121 -0
- data/lib/inferno/entities/test.rb +5 -5
- data/lib/inferno/ext/fhir_models.rb +59 -0
- data/lib/inferno/public/bundle.js +15 -15
- data/lib/inferno/public/bundle.js.LICENSE.txt +2 -0
- data/lib/inferno/test_runner.rb +24 -2
- data/lib/inferno/utils/preset_template_generator.rb +4 -5
- data/lib/inferno/version.rb +2 -1
- data/spec/factories/result.rb +1 -0
- metadata +11 -8
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative 'attributes'
|
2
|
+
require_relative '../exceptions'
|
3
|
+
|
4
|
+
module Inferno
|
5
|
+
module Entities
|
6
|
+
# This class represents an Input for a runnable.
|
7
|
+
class Input
|
8
|
+
ATTRIBUTES = [
|
9
|
+
:name,
|
10
|
+
:title,
|
11
|
+
:description,
|
12
|
+
:type,
|
13
|
+
:default,
|
14
|
+
:optional,
|
15
|
+
:options,
|
16
|
+
:locked
|
17
|
+
].freeze
|
18
|
+
include Entities::Attributes
|
19
|
+
|
20
|
+
# These attributes require special handling when merging input
|
21
|
+
# definitions.
|
22
|
+
UNINHERITABLE_ATTRIBUTES = [
|
23
|
+
# Locking an input only has meaning at the level it is locked.
|
24
|
+
# Consider:
|
25
|
+
# - ParentGroup
|
26
|
+
# - Group 1, input :a
|
27
|
+
# - Group 2, input :a, locked: true
|
28
|
+
# The input 'a' should be only be locked when running Group 2 in
|
29
|
+
# isolation. It should not be locked when running Group 1 or the
|
30
|
+
# ParentGroup.
|
31
|
+
:locked,
|
32
|
+
# Input type is sometimes only a UI concern (e.g. text vs. textarea), so
|
33
|
+
# it is common to not redeclare the type everywhere it's used and needs
|
34
|
+
# special handling to avoid clobbering the type with the default (text)
|
35
|
+
# type.
|
36
|
+
:type
|
37
|
+
].freeze
|
38
|
+
|
39
|
+
# These are the attributes that can be directly copied when merging a
|
40
|
+
# runnable's input with the input of one of its children.
|
41
|
+
INHERITABLE_ATTRIBUTES = (ATTRIBUTES - UNINHERITABLE_ATTRIBUTES).freeze
|
42
|
+
|
43
|
+
# These are the attributes that can be directly copied when merging a
|
44
|
+
# runnable's input with an input configuration.
|
45
|
+
MERGEABLE_ATTRIBUTES = (ATTRIBUTES - [:type]).freeze
|
46
|
+
|
47
|
+
def initialize(**params)
|
48
|
+
bad_params = params.keys - ATTRIBUTES
|
49
|
+
|
50
|
+
raise Exceptions::UnknownAttributeException.new(bad_params, self.class) if bad_params.present?
|
51
|
+
|
52
|
+
params
|
53
|
+
.compact
|
54
|
+
.each { |key, value| send("#{key}=", value) }
|
55
|
+
|
56
|
+
self.name = name.to_s if params[:name].present?
|
57
|
+
end
|
58
|
+
|
59
|
+
# @private
|
60
|
+
# Merge this input with an input belonging to a child. Fields defined on
|
61
|
+
# this input take precedence over those defined on the child input.
|
62
|
+
def merge_with_child(child_input)
|
63
|
+
return self if child_input.nil?
|
64
|
+
|
65
|
+
INHERITABLE_ATTRIBUTES.each do |attribute|
|
66
|
+
merge_attribute(attribute, primary_source: self, secondary_source: child_input)
|
67
|
+
end
|
68
|
+
|
69
|
+
self.type = child_input.type if child_input.present? && child_input.type != 'text'
|
70
|
+
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
# @private
|
75
|
+
# Merge this input with an input from a configuration. Fields defined in
|
76
|
+
# the configuration take precedence over those defined on this input.
|
77
|
+
def merge(other_input)
|
78
|
+
return self if other_input.nil?
|
79
|
+
|
80
|
+
MERGEABLE_ATTRIBUTES.each do |attribute|
|
81
|
+
merge_attribute(attribute, primary_source: other_input, secondary_source: self)
|
82
|
+
end
|
83
|
+
|
84
|
+
self.type = other_input.type if other_input.type.present? && other_input.type != 'text'
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# @private
|
90
|
+
# Merge an individual attribute. If the primary source contains the
|
91
|
+
# attribute, that value will be used. Otherwise the value from the
|
92
|
+
# secondary source will be used.
|
93
|
+
# @param attribute [Symbol]
|
94
|
+
# @param primary_source [Input]
|
95
|
+
# @param secondary_source [Input]
|
96
|
+
def merge_attribute(attribute, primary_source:, secondary_source:)
|
97
|
+
value = primary_source.send(attribute)
|
98
|
+
value = secondary_source.send(attribute) if value.nil?
|
99
|
+
|
100
|
+
return if value.nil?
|
101
|
+
|
102
|
+
send("#{attribute}=", value)
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_hash
|
106
|
+
ATTRIBUTES.each_with_object({}) do |attribute, hash|
|
107
|
+
value = send(attribute)
|
108
|
+
next if value.nil?
|
109
|
+
|
110
|
+
hash[attribute] = value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def ==(other)
|
115
|
+
return false unless other.is_a? Input
|
116
|
+
|
117
|
+
ATTRIBUTES.all? { |attribute| send(attribute) == other.send(attribute) }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -122,16 +122,16 @@ module Inferno
|
|
122
122
|
#
|
123
123
|
# @param name [Symbol] name of the input
|
124
124
|
# @param other_names [Symbol] array of symbols if specifying multiple inputs
|
125
|
-
# @param
|
126
|
-
# @option
|
127
|
-
# @option
|
128
|
-
# @option
|
125
|
+
# @param input_params [Hash] options for input such as type, description, or title
|
126
|
+
# @option input_params [String] :title Human readable title for input
|
127
|
+
# @option input_params [String] :description Description for the input
|
128
|
+
# @option input_params [String] :type 'text' | 'textarea'
|
129
129
|
# @return [void]
|
130
130
|
# @example
|
131
131
|
# input :patientid, title: 'Patient ID', description: 'The ID of the patient being searched for'
|
132
132
|
# @example
|
133
133
|
# input :textarea, title: 'Textarea Input Example', type: 'textarea'
|
134
|
-
def input(name, *other_names, **
|
134
|
+
def input(name, *other_names, **input_params)
|
135
135
|
super
|
136
136
|
|
137
137
|
if other_names.present?
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
# Extension to FHIR::Model. Prepending this into FHIR::Model (done below)
|
4
|
+
# allows us to call super() on initialize when we overriding it,
|
5
|
+
# while also defining new methods and attributes
|
6
|
+
module InfernoFHIRModelExtensions
|
7
|
+
attr_accessor :source_hash, :source_text
|
8
|
+
|
9
|
+
def initialize(hash = {})
|
10
|
+
super(hash)
|
11
|
+
@source_hash = hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def source_contents
|
15
|
+
@source_text || JSON.generate(@source_hash)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module FHIR
|
20
|
+
class Model
|
21
|
+
prepend ::InfernoFHIRModelExtensions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Extension to FHIR::Json. Prepending this into FHIR::Json (done below)
|
26
|
+
# allows us to call super() on from_json
|
27
|
+
module InfernoJson
|
28
|
+
def from_json(json)
|
29
|
+
resource = super(json)
|
30
|
+
resource.source_text = json
|
31
|
+
resource
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Extension to FHIR::Xml. Prepending this into FHIR::Xml (done below)
|
36
|
+
# allows us to call super() on from_xml
|
37
|
+
module InfernoXml
|
38
|
+
def from_xml(xml)
|
39
|
+
resource = super(xml)
|
40
|
+
resource.source_text = xml
|
41
|
+
resource
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module FHIR
|
46
|
+
module Json
|
47
|
+
class << self
|
48
|
+
prepend InfernoJson
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module FHIR
|
54
|
+
module Xml
|
55
|
+
class << self
|
56
|
+
prepend InfernoXml
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|