inferno_core 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/inferno.rb +4 -0
- data/lib/inferno/apps/web/controllers/test_runs/create.rb +17 -10
- data/lib/inferno/apps/web/controllers/test_runs/show.rb +10 -0
- data/lib/inferno/apps/web/controllers/test_sessions/create.rb +1 -0
- data/lib/inferno/apps/web/controllers/test_sessions/last_test_run.rb +22 -0
- data/lib/inferno/apps/web/controllers/test_sessions/results/index.rb +6 -1
- data/lib/inferno/apps/web/controllers/test_sessions/session_data/index.rb +21 -0
- data/lib/inferno/apps/web/router.rb +15 -0
- data/lib/inferno/apps/web/serializers/request.rb +1 -0
- data/lib/inferno/apps/web/serializers/result.rb +8 -0
- data/lib/inferno/apps/web/serializers/session_data.rb +10 -0
- data/lib/inferno/apps/web/serializers/test.rb +1 -3
- data/lib/inferno/apps/web/serializers/test_group.rb +2 -3
- data/lib/inferno/apps/web/serializers/test_run.rb +1 -0
- data/lib/inferno/apps/web/serializers/test_session.rb +1 -1
- data/lib/inferno/apps/web/serializers/test_suite.rb +1 -0
- data/lib/inferno/config/application.rb +4 -2
- data/lib/inferno/config/boot.rb +2 -0
- data/lib/inferno/config/boot/db.rb +10 -1
- data/lib/inferno/config/boot/sidekiq.rb +11 -0
- data/lib/inferno/db/migrations/001_create_initial_structure.rb +0 -21
- data/lib/inferno/db/migrations/002_add_wait_support.rb +7 -0
- data/lib/inferno/db/migrations/003_update_session_data.rb +18 -0
- data/lib/inferno/db/migrations/004_add_request_results_table.rb +9 -0
- data/lib/inferno/db/migrations/005_add_updated_at_index_to_results.rb +5 -0
- data/lib/inferno/db/schema.rb +154 -0
- data/lib/inferno/dsl.rb +1 -3
- data/lib/inferno/dsl/fhir_client_builder.rb +16 -0
- data/lib/inferno/dsl/request_storage.rb +12 -0
- data/lib/inferno/dsl/results.rb +49 -0
- data/lib/inferno/dsl/resume_test_route.rb +89 -0
- data/lib/inferno/dsl/runnable.rb +96 -7
- data/lib/inferno/entities.rb +1 -1
- data/lib/inferno/entities/header.rb +7 -7
- data/lib/inferno/entities/message.rb +8 -6
- data/lib/inferno/entities/request.rb +40 -14
- data/lib/inferno/entities/result.rb +34 -18
- data/lib/inferno/entities/session_data.rb +33 -0
- data/lib/inferno/entities/test.rb +20 -7
- data/lib/inferno/entities/test_run.rb +13 -6
- data/lib/inferno/entities/test_session.rb +8 -8
- data/lib/inferno/exceptions.rb +12 -0
- data/lib/inferno/jobs.rb +16 -0
- data/lib/inferno/jobs/execute_test_run.rb +14 -0
- data/lib/inferno/jobs/resume_test_run.rb +14 -0
- data/lib/inferno/public/bundle.js +1 -1
- data/lib/inferno/repositories/repository.rb +13 -0
- data/lib/inferno/repositories/requests.rb +5 -4
- data/lib/inferno/repositories/results.rb +151 -3
- data/lib/inferno/repositories/session_data.rb +47 -0
- data/lib/inferno/repositories/test_runs.rb +66 -0
- data/lib/inferno/test_runner.rb +121 -29
- data/lib/inferno/utils/middleware/request_logger.rb +16 -3
- data/lib/inferno/version.rb +1 -1
- data/spec/factories/result.rb +8 -0
- data/spec/factories/test_run.rb +2 -0
- metadata +32 -5
- data/lib/inferno/dsl/fhir_manipulation.rb +0 -25
- data/lib/inferno/entities/test_input.rb +0 -20
data/lib/inferno/dsl.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require_relative 'dsl/assertions'
|
2
2
|
require_relative 'dsl/fhir_client'
|
3
|
-
require_relative 'dsl/fhir_manipulation'
|
4
3
|
require_relative 'dsl/fhir_validation'
|
5
4
|
require_relative 'dsl/http_client'
|
6
5
|
require_relative 'dsl/results'
|
@@ -14,8 +13,7 @@ module Inferno
|
|
14
13
|
FHIRClient,
|
15
14
|
HTTPClient,
|
16
15
|
Results,
|
17
|
-
FHIRValidation
|
18
|
-
FHIRManipulation
|
16
|
+
FHIRValidation
|
19
17
|
].freeze
|
20
18
|
|
21
19
|
EXTENDABLE_DSL_MODULES = [
|
@@ -14,6 +14,7 @@ module Inferno
|
|
14
14
|
FHIR::Client.new(url).tap do |client|
|
15
15
|
client.additional_headers = headers if headers
|
16
16
|
client.default_json
|
17
|
+
client.set_bearer_token bearer_token if bearer_token
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -32,6 +33,21 @@ module Inferno
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
36
|
+
# Define the bearer token for a client. A string or symbol can be provided.
|
37
|
+
# A string is interpreted as a token. A symbol is interpreted as the name of
|
38
|
+
# an input to the Runnable.
|
39
|
+
#
|
40
|
+
# @param bearer_token [String, Symbol]
|
41
|
+
# @return [void]
|
42
|
+
def bearer_token(bearer_token = nil)
|
43
|
+
@bearer_token ||=
|
44
|
+
if bearer_token.is_a? Symbol
|
45
|
+
runnable.send(bearer_token)
|
46
|
+
else
|
47
|
+
bearer_token
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
35
51
|
# Define custom headers for a client
|
36
52
|
#
|
37
53
|
# @param headers [Hash]
|
@@ -89,6 +89,18 @@ module Inferno
|
|
89
89
|
named_requests_made.concat(names)
|
90
90
|
end
|
91
91
|
|
92
|
+
# Specify the name for a request received by a test
|
93
|
+
#
|
94
|
+
# @param *names [Symbol] one or more Symbols
|
95
|
+
def receives_request(name)
|
96
|
+
@incoming_request_name = name
|
97
|
+
end
|
98
|
+
|
99
|
+
# @api private
|
100
|
+
def incoming_request_name
|
101
|
+
@incoming_request_name
|
102
|
+
end
|
103
|
+
|
92
104
|
# Specify the named requests used by a test
|
93
105
|
#
|
94
106
|
# @param *names [Symbol] one or more Symbols
|
data/lib/inferno/dsl/results.rb
CHANGED
@@ -49,6 +49,55 @@ module Inferno
|
|
49
49
|
def omit_if(test, message = '')
|
50
50
|
raise Exceptions::OmitException, message if test
|
51
51
|
end
|
52
|
+
|
53
|
+
# Halt execution of the current test and wait for execution to resume.
|
54
|
+
#
|
55
|
+
# @see Inferno::DSL::Runnable#resume_test_route
|
56
|
+
# @example
|
57
|
+
# resume_test_route :get, '/launch' do
|
58
|
+
# request.query_parameters['iss']
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# test do
|
62
|
+
# input :issuer
|
63
|
+
# receives_request :launch
|
64
|
+
#
|
65
|
+
# run do
|
66
|
+
# wait(
|
67
|
+
# identifier: issuer,
|
68
|
+
# message: "Wating to receive a request with an issuer of #{issuer}"
|
69
|
+
# )
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
# @param identifier [String] An identifier which can uniquely identify
|
73
|
+
# this test run based on an incoming request. This is necessary so that
|
74
|
+
# the correct test run can be resumed.
|
75
|
+
# @param message [String]
|
76
|
+
# @param timeout [Integer] Number of seconds to wait for an incoming
|
77
|
+
# request
|
78
|
+
def wait(identifier:, message: '', timeout: 300)
|
79
|
+
identifier(identifier)
|
80
|
+
wait_timeout(timeout)
|
81
|
+
|
82
|
+
raise Exceptions::WaitException, message
|
83
|
+
end
|
84
|
+
|
85
|
+
def identifier(identifier = nil)
|
86
|
+
@identifier ||= identifier
|
87
|
+
end
|
88
|
+
|
89
|
+
def wait_timeout(timeout = nil)
|
90
|
+
@wait_timeout ||= timeout
|
91
|
+
end
|
92
|
+
|
93
|
+
# Halt execution of the current test. This provided for testing purposes
|
94
|
+
# and should not be used in real tests.
|
95
|
+
#
|
96
|
+
# @param message [String]
|
97
|
+
# @api private
|
98
|
+
def cancel(message = '')
|
99
|
+
raise Exceptions::CancelException, message
|
100
|
+
end
|
52
101
|
end
|
53
102
|
end
|
54
103
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'hanami-controller'
|
2
|
+
|
3
|
+
module Inferno
|
4
|
+
module DSL
|
5
|
+
# A base class for creating routes to resume test execution upon receiving
|
6
|
+
# an incoming request.
|
7
|
+
# @api private
|
8
|
+
# @see Inferno::DSL::Runnable#resume_test_route
|
9
|
+
class ResumeTestRoute
|
10
|
+
include Hanami::Action
|
11
|
+
include Import[
|
12
|
+
requests_repo: 'repositories.requests',
|
13
|
+
results_repo: 'repositories.results',
|
14
|
+
test_runs_repo: 'repositories.test_runs',
|
15
|
+
tests_repo: 'repositories.tests'
|
16
|
+
]
|
17
|
+
|
18
|
+
def self.call(params)
|
19
|
+
new.call(params)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The incoming request
|
23
|
+
#
|
24
|
+
# @return [Inferno::Entities::Request]
|
25
|
+
def request
|
26
|
+
@request ||= Inferno::Entities::Request.from_rack_env(@params.env)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def test_run
|
31
|
+
@test_run ||=
|
32
|
+
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def waiting_result
|
37
|
+
@waiting_result ||= results_repo.find_waiting_result(test_run_id: test_run.id)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def update_result
|
42
|
+
results_repo.pass_waiting_result(waiting_result.id)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api private
|
46
|
+
def persist_request
|
47
|
+
requests_repo.create(
|
48
|
+
request.to_hash.merge(
|
49
|
+
test_session_id: test_run.test_session_id,
|
50
|
+
result_id: waiting_result.id,
|
51
|
+
name: test.incoming_request_name
|
52
|
+
)
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def redirect_route
|
58
|
+
"/test_sessions/#{test_run.test_session_id}##{waiting_group_id}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
def test
|
63
|
+
@test ||= tests_repo.find(waiting_result.test_id)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
def waiting_group_id
|
68
|
+
test.parent.id
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def call(_params)
|
73
|
+
if test_run.nil?
|
74
|
+
status(500, "Unable to find test run with identifier '#{test_run_identifier}'.")
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
test_runs_repo.mark_as_no_longer_waiting(test_run.id)
|
79
|
+
|
80
|
+
update_result
|
81
|
+
persist_request
|
82
|
+
|
83
|
+
Jobs.perform(Jobs::ResumeTestRun, test_run.id)
|
84
|
+
|
85
|
+
redirect_to redirect_route
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/inferno/dsl/runnable.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'resume_test_route'
|
2
|
+
|
1
3
|
module Inferno
|
2
4
|
module DSL
|
3
5
|
# This module contains the DSL for defining child entities in the test
|
@@ -37,7 +39,7 @@ module Inferno
|
|
37
39
|
# @api private
|
38
40
|
def copy_instance_variables(subclass)
|
39
41
|
instance_variables.each do |variable|
|
40
|
-
next if [:@id, :@groups, :@tests, :@parent, :@children].include?(variable)
|
42
|
+
next if [:@id, :@groups, :@tests, :@parent, :@children, :@test_count].include?(variable)
|
41
43
|
|
42
44
|
subclass.instance_variable_set(variable, instance_variable_get(variable).dup)
|
43
45
|
end
|
@@ -125,9 +127,9 @@ module Inferno
|
|
125
127
|
# @api private
|
126
128
|
def configure_child_class(klass, hash_args) # rubocop:disable Metrics/CyclomaticComplexity
|
127
129
|
inputs.each do |input_definition|
|
128
|
-
next if klass.inputs.
|
130
|
+
next if klass.inputs.any? { |input| input[:name] == input_definition[:name] }
|
129
131
|
|
130
|
-
klass.input input_definition
|
132
|
+
klass.input input_definition[:name], input_definition
|
131
133
|
end
|
132
134
|
|
133
135
|
outputs.each do |output_definition|
|
@@ -196,12 +198,28 @@ module Inferno
|
|
196
198
|
|
197
199
|
# Define inputs
|
198
200
|
#
|
199
|
-
# @param
|
201
|
+
# @param name [Symbol] name of the input
|
202
|
+
# @param other_names [Symbol] array of symbols if specifying multiple inputs
|
203
|
+
# @param input_definition [Hash] options for input such as type, description, or title
|
204
|
+
# @option input_definition [String] :title Human readable title for input
|
205
|
+
# @option input_definition [String] :description Description for the input
|
206
|
+
# @option input_definition [String] :type text | textarea
|
207
|
+
# @option input_definition [String] :default The default value for the input
|
200
208
|
# @return [void]
|
201
209
|
# @example
|
202
|
-
# input :
|
203
|
-
|
204
|
-
|
210
|
+
# input :patientid, title: 'Patient ID', description: 'The ID of the patient being searched for',
|
211
|
+
# default: 'default_patient_id'
|
212
|
+
# @example
|
213
|
+
# input :textarea, title: 'Textarea Input Example', type: 'textarea'
|
214
|
+
def input(name, *other_names, **input_definition)
|
215
|
+
if other_names.present?
|
216
|
+
[name, *other_names].each do |input_name|
|
217
|
+
inputs.push({ name: input_name, title: nil, description: nil, type: 'text' })
|
218
|
+
end
|
219
|
+
else
|
220
|
+
input_definition[:type] = 'text' unless input_definition.key? :type
|
221
|
+
inputs.push({ name: name }.merge(input_definition))
|
222
|
+
end
|
205
223
|
end
|
206
224
|
|
207
225
|
# Define outputs
|
@@ -229,6 +247,7 @@ module Inferno
|
|
229
247
|
@outputs ||= []
|
230
248
|
end
|
231
249
|
|
250
|
+
# @api private
|
232
251
|
def child_types
|
233
252
|
return [] if ancestors.include? Inferno::Entities::Test
|
234
253
|
return [:groups] if ancestors.include? Inferno::Entities::TestSuite
|
@@ -236,6 +255,7 @@ module Inferno
|
|
236
255
|
[:groups, :tests]
|
237
256
|
end
|
238
257
|
|
258
|
+
# @api private
|
239
259
|
def children
|
240
260
|
@children ||= []
|
241
261
|
end
|
@@ -245,6 +265,75 @@ module Inferno
|
|
245
265
|
|
246
266
|
@validator_url = url
|
247
267
|
end
|
268
|
+
|
269
|
+
# @api private
|
270
|
+
def suite
|
271
|
+
return self if ancestors.include? Inferno::Entities::TestSuite
|
272
|
+
|
273
|
+
parent.suite
|
274
|
+
end
|
275
|
+
|
276
|
+
# Create a route which will resume a test run when a request is received
|
277
|
+
#
|
278
|
+
# @see Inferno::DSL::Results#wait
|
279
|
+
# @example
|
280
|
+
# resume_test_route :get, '/launch' do
|
281
|
+
# request.query_parameters['iss']
|
282
|
+
# end
|
283
|
+
#
|
284
|
+
# test do
|
285
|
+
# input :issuer
|
286
|
+
# receives_request :launch
|
287
|
+
#
|
288
|
+
# run do
|
289
|
+
# wait(
|
290
|
+
# identifier: issuer,
|
291
|
+
# message: "Wating to receive a request with an issuer of #{issuer}"
|
292
|
+
# )
|
293
|
+
# end
|
294
|
+
# end
|
295
|
+
#
|
296
|
+
# @param method [Symbol] the HTTP request type (:get, :post, etc.) for the
|
297
|
+
# incoming request
|
298
|
+
# @param path [String] the path for this request. The route will be served
|
299
|
+
# with a prefix of `/custom/TEST_SUITE_ID` to prevent path conflicts.
|
300
|
+
# [Any of the path options available in Hanami
|
301
|
+
# Router](https://github.com/hanami/router/tree/f41001d4c3ee9e2d2c7bb142f74b43f8e1d3a265#a-beautiful-dsl)
|
302
|
+
# can be used here.
|
303
|
+
# @yield This method takes a block which must return the identifier
|
304
|
+
# defined when a test was set to wait for the test run that hit this
|
305
|
+
# route. The block has access to the `request` method which returns a
|
306
|
+
# {Inferno::DSL::Request} object with the information for the incoming
|
307
|
+
# request.
|
308
|
+
def resume_test_route(method, path, &block)
|
309
|
+
route_class = Class.new(ResumeTestRoute) do
|
310
|
+
define_method(:test_run_identifier, &block)
|
311
|
+
define_method(:request_name, -> { options[:name] })
|
312
|
+
end
|
313
|
+
|
314
|
+
route(method, path, route_class)
|
315
|
+
end
|
316
|
+
|
317
|
+
# Create a route to handle a request
|
318
|
+
#
|
319
|
+
# @param method [Symbol] the HTTP request type (:get, :post, etc.) for the
|
320
|
+
# incoming request. `:all` will accept all HTTP request types.
|
321
|
+
# @param path [String] the path for this request. The route will be served
|
322
|
+
# with a prefix of `/custom/TEST_SUITE_ID` to prevent path conflicts.
|
323
|
+
# [Any of the path options available in Hanami
|
324
|
+
# Router](https://github.com/hanami/router/tree/f41001d4c3ee9e2d2c7bb142f74b43f8e1d3a265#a-beautiful-dsl)
|
325
|
+
# can be used here.
|
326
|
+
# @param handler [#call] the route handler. This can be any Rack
|
327
|
+
# compatible object (e.g. a `Proc` object, a [Sinatra
|
328
|
+
# app](http://sinatrarb.com/)) as described in the [Hanami Router
|
329
|
+
# documentation.](https://github.com/hanami/router/tree/f41001d4c3ee9e2d2c7bb142f74b43f8e1d3a265#mount-rack-applications)
|
330
|
+
def route(method, path, handler)
|
331
|
+
Inferno.routes << { method: method, path: path, handler: handler, suite: suite }
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_count
|
335
|
+
@test_count ||= children&.reduce(0) { |sum, child| sum + child.test_count } || 0
|
336
|
+
end
|
248
337
|
end
|
249
338
|
end
|
250
339
|
end
|
data/lib/inferno/entities.rb
CHANGED
@@ -4,9 +4,9 @@ require_relative 'entities/header'
|
|
4
4
|
require_relative 'entities/message'
|
5
5
|
require_relative 'entities/request'
|
6
6
|
require_relative 'entities/result'
|
7
|
+
require_relative 'entities/session_data'
|
7
8
|
require_relative 'entities/test'
|
8
9
|
require_relative 'entities/test_group'
|
9
|
-
require_relative 'entities/test_input'
|
10
10
|
require_relative 'entities/test_run'
|
11
11
|
require_relative 'entities/test_session'
|
12
12
|
require_relative 'entities/test_suite'
|
@@ -2,13 +2,13 @@ module Inferno
|
|
2
2
|
module Entities
|
3
3
|
# A `Header` represents an HTTP request/response header
|
4
4
|
#
|
5
|
-
# @
|
6
|
-
# @
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
# @
|
10
|
-
# @
|
11
|
-
# @
|
5
|
+
# @attr_accessor [String] id of the header
|
6
|
+
# @attr_accessor [String] request_id index of the HTTP request
|
7
|
+
# @attr_accessor [String] name header name
|
8
|
+
# @attr_accessor [String] value header value
|
9
|
+
# @attr_accessor [String] type request/response
|
10
|
+
# @attr_accessor [Time] created_at
|
11
|
+
# @attr_accessor [Time] updated_at
|
12
12
|
class Header < Entity
|
13
13
|
ATTRIBUTES = [:id, :request_id, :name, :type, :value, :created_at, :updated_at].freeze
|
14
14
|
|
@@ -2,12 +2,14 @@ module Inferno
|
|
2
2
|
module Entities
|
3
3
|
# A `Message` represents a message generated during a test.
|
4
4
|
#
|
5
|
-
# @
|
6
|
-
# @
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
# @
|
10
|
-
# @
|
5
|
+
# @attr_accessor [String] id of the message
|
6
|
+
# @attr_accessor [String] index of the message. Used for ordering.
|
7
|
+
# @attr_accessor [String] result_id
|
8
|
+
# @attr_accessor [Inferno::Entities::Result] result
|
9
|
+
# @attr_accessor [String] type
|
10
|
+
# @attr_accessor [String] message
|
11
|
+
# @attr_accessor [Time] created_at
|
12
|
+
# @attr_accessor [Time] updated_at
|
11
13
|
class Message < Entity
|
12
14
|
ATTRIBUTES = [:id, :index, :message, :result_id, :result, :type, :created_at, :updated_at].freeze
|
13
15
|
TYPES = ['error', 'warning', 'info'].freeze
|
@@ -2,21 +2,21 @@ module Inferno
|
|
2
2
|
module Entities
|
3
3
|
# A `Request` represents a request and response issued during a test.
|
4
4
|
#
|
5
|
-
# @
|
6
|
-
# @
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
# @
|
10
|
-
# @
|
11
|
-
# @
|
12
|
-
# @
|
13
|
-
# @
|
14
|
-
# @
|
5
|
+
# @attr_accessor [String] id of the request
|
6
|
+
# @attr_accessor [String] index of the request. Used for ordering.
|
7
|
+
# @attr_accessor [String] verb http verb
|
8
|
+
# @attr_accessor [String] url request url
|
9
|
+
# @attr_accessor [String] direction incoming/outgoing
|
10
|
+
# @attr_accessor [String] name name for the request
|
11
|
+
# @attr_accessor [String] status http response status code
|
12
|
+
# @attr_accessor [String] request_body body of the http request
|
13
|
+
# @attr_accessor [String] response_body body of the http response
|
14
|
+
# @attr_accessor [Array<Inferno::Entities::Header>] headers http
|
15
15
|
# request/response headers
|
16
|
-
# @
|
17
|
-
# @
|
18
|
-
# @
|
19
|
-
# @
|
16
|
+
# @attr_accessor [String] result_id id of the result for this request
|
17
|
+
# @attr_accessor [String] test_session_id id of the test session for this request
|
18
|
+
# @attr_accessor [Time] created_at creation timestamp
|
19
|
+
# @attr_accessor [Time] updated_at update timestamp
|
20
20
|
class Request < Entity
|
21
21
|
ATTRIBUTES = [
|
22
22
|
:id, :index, :verb, :url, :direction, :name, :status,
|
@@ -36,6 +36,11 @@ module Inferno
|
|
36
36
|
@headers = params[:headers]&.map { |header| header.is_a?(Hash) ? Header.new(header) : header } || []
|
37
37
|
end
|
38
38
|
|
39
|
+
# @return [Hash<String, String>]
|
40
|
+
def query_parameters
|
41
|
+
Addressable::URI.parse(url).query_values || {}
|
42
|
+
end
|
43
|
+
|
39
44
|
# Find a response header
|
40
45
|
#
|
41
46
|
# @param name [String] the header name
|
@@ -117,6 +122,27 @@ module Inferno
|
|
117
122
|
end
|
118
123
|
|
119
124
|
class << self
|
125
|
+
# @api private
|
126
|
+
def from_rack_env(env, name: nil)
|
127
|
+
rack_request = env['router.request'].rack_request
|
128
|
+
url = "#{rack_request.base_url}#{rack_request.path}"
|
129
|
+
url += "?#{rack_request.query_string}" if rack_request.query_string.present?
|
130
|
+
request_headers =
|
131
|
+
env
|
132
|
+
.select { |key, _| key.start_with? 'HTTP_' }
|
133
|
+
.transform_keys { |key| key.delete_prefix('HTTP_').tr('_', '-').downcase }
|
134
|
+
.map { |header_name, value| Header.new(name: header_name, value: value, type: 'request') }
|
135
|
+
|
136
|
+
new(
|
137
|
+
verb: rack_request.request_method.downcase,
|
138
|
+
url: url,
|
139
|
+
direction: 'incoming',
|
140
|
+
name: name,
|
141
|
+
request_body: rack_request.body.string,
|
142
|
+
headers: request_headers
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
120
146
|
# @api private
|
121
147
|
def from_http_response(response, test_session_id:, direction: 'outgoing', name: nil)
|
122
148
|
request_headers =
|