inferno_core 0.4.35 → 0.4.37.dev
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/lib/inferno/apps/web/controllers/controller.rb +7 -3
- data/lib/inferno/apps/web/controllers/test_sessions/client_show.rb +1 -2
- data/lib/inferno/config/application.rb +2 -2
- data/lib/inferno/config/boot/db.rb +3 -3
- data/lib/inferno/config/boot/logging.rb +2 -2
- data/lib/inferno/config/boot/presets.rb +3 -3
- data/lib/inferno/config/boot/sidekiq.rb +2 -2
- data/lib/inferno/config/boot/suites.rb +16 -4
- data/lib/inferno/config/boot/validator.rb +3 -3
- data/lib/inferno/config/boot/web.rb +2 -2
- data/lib/inferno/dsl/runnable.rb +18 -11
- data/lib/inferno/dsl/suite_endpoint.rb +330 -0
- data/lib/inferno/dsl.rb +1 -0
- data/lib/inferno/entities/test_kit.rb +171 -0
- data/lib/inferno/ext/rack.rb +88 -0
- data/lib/inferno/public/bundle.js +3 -3
- data/lib/inferno/repositories/test_kits.rb +9 -0
- data/lib/inferno/repositories.rb +1 -0
- data/lib/inferno/utils/middleware/request_logger.rb +8 -0
- data/lib/inferno/version.rb +1 -1
- metadata +19 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccd64a44d96c18439d7d844bd6ec467d9eb0c23d5964b0928539fd70a0e806f0
|
4
|
+
data.tar.gz: b72e0ac46e7aca9d496fe23f6b89537c4a5c2054acc20690e089dc17d3d2528d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33d89c3291db6f4bfaf92b704eb13177b961e49b2b5c9c358661e062bde12f0eb00f5ab55e91945e089a7d2d83a13002926153c53b75b30b1a18926b69791496
|
7
|
+
data.tar.gz: b6878fd8a73f017dccf8f027ac1ddfb7811a122f287a55ea6fe393b7e4d5dd0f2885d4e55d1a540f6bd5ec723619af8c00bdb8d633fd3ce187f9dd0d63790a97
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'hanami/action/mime/request_mime_weight'
|
2
|
+
|
1
3
|
module Inferno
|
2
4
|
module Web
|
3
5
|
module Controllers
|
@@ -11,12 +13,14 @@ module Inferno
|
|
11
13
|
|
12
14
|
subclass.include Import[repo: "inferno.repositories.#{subclass.resource_name}"]
|
13
15
|
|
14
|
-
subclass.config.default_request_format = :json
|
15
|
-
subclass.config.default_response_format = :json
|
16
|
-
|
17
16
|
subclass.define_method(:serialize) do |*args|
|
18
17
|
Inferno::Web::Serializers.const_get(self.class.resource_class).render(*args)
|
19
18
|
end
|
19
|
+
|
20
|
+
# Hanami Controller 2.0.0 removes the ability to set a default
|
21
|
+
# Content-Type response header, so set it manually if it hasn't been
|
22
|
+
# set.
|
23
|
+
subclass.after { |_req, res| res.format = :json if res.format == :all && res.body&.first&.first == '{' }
|
20
24
|
end
|
21
25
|
|
22
26
|
def self.resource_name
|
@@ -3,8 +3,6 @@ module Inferno
|
|
3
3
|
module Controllers
|
4
4
|
module TestSessions
|
5
5
|
class ClientShow < Controller
|
6
|
-
config.default_response_format = :html
|
7
|
-
|
8
6
|
CLIENT_PAGE =
|
9
7
|
ERB.new(
|
10
8
|
File.read(
|
@@ -31,6 +29,7 @@ module Inferno
|
|
31
29
|
|
32
30
|
halt 404 if test_suite.nil?
|
33
31
|
|
32
|
+
res.format = :html
|
34
33
|
res.body = CLIENT_PAGE
|
35
34
|
end
|
36
35
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support/all'
|
2
2
|
require 'dotenv'
|
3
|
-
require 'dry/system
|
3
|
+
require 'dry/system'
|
4
4
|
require 'sequel'
|
5
5
|
require_relative 'boot'
|
6
6
|
|
@@ -25,7 +25,7 @@ module Inferno
|
|
25
25
|
|
26
26
|
configure do |config|
|
27
27
|
config.root = File.expand_path('../../..', __dir__)
|
28
|
-
config.
|
28
|
+
config.provider_dirs = [File.join('lib', 'inferno', 'config', 'boot')]
|
29
29
|
config.component_dirs.add 'lib'
|
30
30
|
end
|
31
31
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require_relative '../../repositories/presets'
|
2
2
|
|
3
|
-
Inferno::Application.
|
4
|
-
|
5
|
-
|
3
|
+
Inferno::Application.register_provider(:presets) do
|
4
|
+
prepare do
|
5
|
+
target_container.start :suites
|
6
6
|
|
7
7
|
files_to_load = Dir.glob(['config/presets/*.json', 'config/presets/*.json.erb'])
|
8
8
|
files_to_load.map! { |path| File.realpath(path) }
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'sidekiq'
|
2
2
|
|
3
|
-
Inferno::Application.
|
4
|
-
|
3
|
+
Inferno::Application.register_provider(:sidekiq) do
|
4
|
+
prepare do
|
5
5
|
if Inferno::Application['async_jobs']
|
6
6
|
Sidekiq.configure_server do |config|
|
7
7
|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379/0') }
|
@@ -1,10 +1,11 @@
|
|
1
|
-
Inferno::Application.
|
2
|
-
|
3
|
-
|
1
|
+
Inferno::Application.register_provider(:suites) do
|
2
|
+
prepare do
|
3
|
+
target_container.start :logging
|
4
4
|
|
5
5
|
require 'inferno/entities/test'
|
6
6
|
require 'inferno/entities/test_group'
|
7
7
|
require 'inferno/entities/test_suite'
|
8
|
+
require 'inferno/entities/test_kit'
|
8
9
|
|
9
10
|
files_to_load = Dir.glob(File.join(Dir.pwd, 'lib', '*.rb'))
|
10
11
|
|
@@ -18,13 +19,24 @@ Inferno::Application.boot(:suites) do
|
|
18
19
|
files_to_load.concat Dir.glob(File.join(Inferno::Application.root, 'spec', 'fixtures', '**', '*.rb'))
|
19
20
|
end
|
20
21
|
|
22
|
+
# Whenever the definition of a Runnable class ends, add it to the
|
23
|
+
# appropriate repository.
|
24
|
+
in_memory_entities_trace = TracePoint.trace(:end) do |trace|
|
25
|
+
if trace.self < Inferno::Entities::Test ||
|
26
|
+
trace.self < Inferno::Entities::TestGroup ||
|
27
|
+
trace.self < Inferno::Entities::TestSuite ||
|
28
|
+
trace.self < Inferno::Entities::TestKit
|
29
|
+
trace.self.add_self_to_repository
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
files_to_load.map! { |path| File.realpath(path) }
|
22
34
|
|
23
35
|
files_to_load.each do |path|
|
24
36
|
require_relative path
|
25
37
|
end
|
26
38
|
|
27
|
-
|
39
|
+
in_memory_entities_trace.disable
|
28
40
|
|
29
41
|
Inferno::Entities::TestSuite.descendants.each do |descendant|
|
30
42
|
# When ID not assigned in custom test suites, Runnable.id will return default ID
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Inferno::Application.
|
2
|
-
|
3
|
-
|
1
|
+
Inferno::Application.register_provider(:validator) do
|
2
|
+
prepare do
|
3
|
+
target_container.start :suites
|
4
4
|
|
5
5
|
# This process should only run once, to start one job per validator,
|
6
6
|
# so skipping it on workers will start it only once from the "web" process
|
data/lib/inferno/dsl/runnable.rb
CHANGED
@@ -26,17 +26,6 @@ module Inferno
|
|
26
26
|
|
27
27
|
extending_class.define_singleton_method(:inherited) do |subclass|
|
28
28
|
copy_instance_variables(subclass)
|
29
|
-
|
30
|
-
# Whenever the definition of a Runnable class ends, keep track of the
|
31
|
-
# file it came from. Once the Suite loader successfully loads a file,
|
32
|
-
# it will add all of the Runnable classes from that file to the
|
33
|
-
# appropriate repositories.
|
34
|
-
TracePoint.trace(:end) do |trace|
|
35
|
-
if trace.self == subclass
|
36
|
-
subclass.add_self_to_repository
|
37
|
-
trace.disable
|
38
|
-
end
|
39
|
-
end
|
40
29
|
end
|
41
30
|
end
|
42
31
|
|
@@ -360,6 +349,24 @@ module Inferno
|
|
360
349
|
route(method, path, route_class)
|
361
350
|
end
|
362
351
|
|
352
|
+
# Create an endpoint to receive incoming requests during a Test Run.
|
353
|
+
#
|
354
|
+
# @see Inferno::DSL::SuiteEndpoint
|
355
|
+
# @example
|
356
|
+
# suite_endpoint :post, '/my_suite_endpoint', MySuiteEndpoint
|
357
|
+
# @param method [Symbol] the HTTP request type (:get, :post, etc.) for the
|
358
|
+
# incoming request
|
359
|
+
# @param path [String] the path for this request. The route will be served
|
360
|
+
# with a prefix of `/custom/TEST_SUITE_ID` to prevent path conflicts.
|
361
|
+
# [Any of the path options available in Hanami
|
362
|
+
# Router](https://github.com/hanami/router/tree/f41001d4c3ee9e2d2c7bb142f74b43f8e1d3a265#a-beautiful-dsl)
|
363
|
+
# can be used here.
|
364
|
+
# @param [Class] a subclass of Inferno::DSL::SuiteEndpoint
|
365
|
+
# @return [void]
|
366
|
+
def suite_endpoint(method, path, endpoint_class)
|
367
|
+
route(method, path, endpoint_class)
|
368
|
+
end
|
369
|
+
|
363
370
|
# Create a route to handle a request
|
364
371
|
#
|
365
372
|
# @param method [Symbol] the HTTP request type (:get, :post, etc.) for the
|
@@ -0,0 +1,330 @@
|
|
1
|
+
require 'hanami/controller'
|
2
|
+
require 'rack/request'
|
3
|
+
require_relative '../ext/rack'
|
4
|
+
|
5
|
+
module Inferno
|
6
|
+
module DSL
|
7
|
+
# A base class for creating endpoints to test client requests. This class is
|
8
|
+
# based on Hanami::Action, and may be used similarly to [a normal Hanami
|
9
|
+
# endpoint](https://github.com/hanami/controller/tree/v2.0.0).
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# class AuthorizedEndpoint < Inferno::DSL::SuiteEndpoint
|
13
|
+
# # Identify the incoming request based on a bearer token
|
14
|
+
# def test_run_identifier
|
15
|
+
# request.header['authorization']&.delete_prefix('Bearer ')
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Return a json FHIR Patient resource
|
19
|
+
# def make_response
|
20
|
+
# response.status = 200
|
21
|
+
# response.body = FHIR::Patient.new(id: 'abcdef').to_json
|
22
|
+
# response.format = :json
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # Update the waiting test to pass when the incoming request is received.
|
26
|
+
# # This will resume the test run.
|
27
|
+
# def update_result
|
28
|
+
# results_repo.update(result.id, result: 'pass')
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # Apply the 'authorized' tag to the incoming request so that it may be
|
32
|
+
# # used by later tests.
|
33
|
+
# def tags
|
34
|
+
# ['authorized']
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# class AuthorizedRequestSuite < Inferno::TestSuite
|
39
|
+
# id :authorized_suite
|
40
|
+
# suite_endpoint :get, '/authorized_endpoint', AuthorizedEndpoint
|
41
|
+
#
|
42
|
+
# group do
|
43
|
+
# title 'Authorized Request Group'
|
44
|
+
#
|
45
|
+
# test do
|
46
|
+
# title 'Wait for authorized request'
|
47
|
+
#
|
48
|
+
# input :bearer_token
|
49
|
+
#
|
50
|
+
# run do
|
51
|
+
# wait(
|
52
|
+
# identifier: bearer_token,
|
53
|
+
# message: "Waiting to receive a request with bearer_token: #{bearer_token}" \
|
54
|
+
# "at `#{Inferno::Application['base_url']}/custom/authorized_suite/authorized_endpoint`"
|
55
|
+
# )
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
class SuiteEndpoint < Hanami::Action
|
61
|
+
attr_reader :req, :res
|
62
|
+
|
63
|
+
# @!group Overrides These methods should be overridden by subclasses to
|
64
|
+
# define the behavior of the endpoint
|
65
|
+
|
66
|
+
# Override this method to determine a test run's identifier based on an
|
67
|
+
# incoming request.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# def test_run_identifier
|
73
|
+
# # Identify the test session of an incoming request based on the bearer
|
74
|
+
# # token
|
75
|
+
# request.headers['authorization']&.delete_prefix('Bearer ')
|
76
|
+
# end
|
77
|
+
def test_run_identifier
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
# Override this method to build the response.
|
82
|
+
#
|
83
|
+
# @return [Void]
|
84
|
+
#
|
85
|
+
# @example
|
86
|
+
# def make_response
|
87
|
+
# response.status = 200
|
88
|
+
# response.body = { abc: 123 }.to_json
|
89
|
+
# response.format = :json
|
90
|
+
# end
|
91
|
+
def make_response
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
# Override this method to define the tags which will be applied to the
|
96
|
+
# request.
|
97
|
+
#
|
98
|
+
# @return [Array<String>]
|
99
|
+
def tags
|
100
|
+
@tags ||= []
|
101
|
+
end
|
102
|
+
|
103
|
+
# Override this method to assign a name to the request
|
104
|
+
#
|
105
|
+
# @return [String]
|
106
|
+
def name
|
107
|
+
result&.runnable&.incoming_request_name
|
108
|
+
end
|
109
|
+
|
110
|
+
# Override this method to update the current waiting result. To resume the
|
111
|
+
# test run, set the result to something other than 'waiting'.
|
112
|
+
#
|
113
|
+
# @return [Void]
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# def update_result
|
117
|
+
# results_repo.update(result.id, result: 'pass')
|
118
|
+
# end
|
119
|
+
def update_result
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
# Override this method to specify whether this request should be
|
124
|
+
# persisted. Defaults to true.
|
125
|
+
#
|
126
|
+
# @return [Boolean]
|
127
|
+
def persist_request?
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
131
|
+
# @!endgroup
|
132
|
+
|
133
|
+
# @private
|
134
|
+
def self.call(...)
|
135
|
+
new.call(...)
|
136
|
+
end
|
137
|
+
|
138
|
+
# @return [Inferno::Repositories::Requests]
|
139
|
+
def requests_repo
|
140
|
+
@requests_repo ||= Inferno::Repositories::Requests.new
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Inferno::Repositories::Results]
|
144
|
+
def results_repo
|
145
|
+
@results_repo ||= Inferno::Repositories::Results.new
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [Inferno::Repositories::TestRuns]
|
149
|
+
def test_runs_repo
|
150
|
+
@test_runs_repo ||= Inferno::Repositories::TestRuns.new
|
151
|
+
end
|
152
|
+
|
153
|
+
# @return [Inferno::Repositories::Tests]
|
154
|
+
def tests_repo
|
155
|
+
@tests_repo ||= Inferno::Repositories::Tests.new
|
156
|
+
end
|
157
|
+
|
158
|
+
# @private
|
159
|
+
def initialize(config: self.class.config) # rubocop:disable Lint/MissingSuper
|
160
|
+
@config = config
|
161
|
+
end
|
162
|
+
|
163
|
+
# The incoming request as a `Hanami::Action::Request`
|
164
|
+
#
|
165
|
+
# @return [Hanami::Action::Request]
|
166
|
+
#
|
167
|
+
# @example
|
168
|
+
# request.params # Get url/query params
|
169
|
+
# request.body.read # Get body
|
170
|
+
# request.headers['accept'] # Get Accept header
|
171
|
+
def request
|
172
|
+
req
|
173
|
+
end
|
174
|
+
|
175
|
+
# The response as a `Hanami::Action::Response`. Modify this to build the
|
176
|
+
# response to the incoming request.
|
177
|
+
#
|
178
|
+
# @return [Hanami::Action::Response]
|
179
|
+
#
|
180
|
+
# @example
|
181
|
+
# response.status = 200 # Set the status
|
182
|
+
# response.body = 'Ok' # Set the body
|
183
|
+
# # Set headers
|
184
|
+
# response.headers.merge!('X-Custom-Header' => 'CUSTOM_HEADER_VALUE')
|
185
|
+
def response
|
186
|
+
res
|
187
|
+
end
|
188
|
+
|
189
|
+
# The test run which is waiting for incoming requests
|
190
|
+
#
|
191
|
+
# @return [Inferno::Entities::TestRun]
|
192
|
+
def test_run
|
193
|
+
@test_run ||=
|
194
|
+
test_runs_repo.find_latest_waiting_by_identifier(find_test_run_identifier).tap do |test_run|
|
195
|
+
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# The result which is waiting for incoming requests for the current test
|
200
|
+
# run
|
201
|
+
#
|
202
|
+
# @return [Inferno::Entities::Result]
|
203
|
+
def result
|
204
|
+
@result ||= find_result
|
205
|
+
end
|
206
|
+
|
207
|
+
# The test which is currently waiting for incoming requests
|
208
|
+
#
|
209
|
+
# @return [Inferno::Entities::Test]
|
210
|
+
def test
|
211
|
+
@test ||= tests_repo.find(result.test_id)
|
212
|
+
end
|
213
|
+
|
214
|
+
# @return [Logger] Inferno's logger
|
215
|
+
def logger
|
216
|
+
@logger ||= Application['logger']
|
217
|
+
end
|
218
|
+
|
219
|
+
# @private
|
220
|
+
def find_test_run_identifier
|
221
|
+
@test_run_identifier ||= test_run_identifier
|
222
|
+
rescue StandardError => e
|
223
|
+
halt 500, "Unable to determine test run identifier:\n#{e.full_message}"
|
224
|
+
end
|
225
|
+
|
226
|
+
# @private
|
227
|
+
def find_result
|
228
|
+
results_repo.find_waiting_result(test_run_id: test_run.id)
|
229
|
+
end
|
230
|
+
|
231
|
+
# @private
|
232
|
+
# The actual persisting happens in
|
233
|
+
# Inferno::Utils::Middleware::RequestRecorder, which allows the response
|
234
|
+
# to include response headers added by other parts of the rack stack
|
235
|
+
# rather than only the response headers explicitly added in the endpoint.
|
236
|
+
def persist_request
|
237
|
+
req.env['inferno.test_session_id'] = test_run.test_session_id
|
238
|
+
req.env['inferno.result_id'] = result.id
|
239
|
+
req.env['inferno.tags'] = tags
|
240
|
+
req.env['inferno.name'] = name if name.present?
|
241
|
+
|
242
|
+
add_persistence_callback
|
243
|
+
end
|
244
|
+
|
245
|
+
# @private
|
246
|
+
def resume_test_run?
|
247
|
+
find_result&.result != 'waiting'
|
248
|
+
end
|
249
|
+
|
250
|
+
# @private
|
251
|
+
# Inferno::Utils::Middleware::RequestRecorder actually resumes the
|
252
|
+
# TestRun. If it were resumed here, it would be resuming prior to the
|
253
|
+
# Request being persisted.
|
254
|
+
def resume
|
255
|
+
req.env['inferno.resume_test_run'] = true
|
256
|
+
req.env['inferno.test_run_id'] = test_run.id
|
257
|
+
end
|
258
|
+
|
259
|
+
# @private
|
260
|
+
def handle(req, res)
|
261
|
+
@req = req
|
262
|
+
@res = res
|
263
|
+
test_run
|
264
|
+
|
265
|
+
persist_request if persist_request?
|
266
|
+
|
267
|
+
update_result
|
268
|
+
|
269
|
+
resume if resume_test_run?
|
270
|
+
|
271
|
+
make_response
|
272
|
+
rescue StandardError => e
|
273
|
+
halt 500, e.full_message
|
274
|
+
end
|
275
|
+
|
276
|
+
# @private
|
277
|
+
def add_persistence_callback # rubocop:disable Metrics/CyclomaticComplexity
|
278
|
+
logger = Application['logger']
|
279
|
+
env = req.env
|
280
|
+
env['rack.after_reply'] ||= []
|
281
|
+
env['rack.after_reply'] << proc do
|
282
|
+
repo = Inferno::Repositories::Requests.new
|
283
|
+
|
284
|
+
uri = URI('http://example.com')
|
285
|
+
uri.scheme = env['rack.url_scheme']
|
286
|
+
uri.host = env['SERVER_NAME']
|
287
|
+
uri.port = env['SERVER_PORT']
|
288
|
+
uri.path = env['REQUEST_PATH'] || ''
|
289
|
+
uri.query = env['rack.request.query_string'] if env['rack.request.query_string'].present?
|
290
|
+
url = uri&.to_s
|
291
|
+
verb = env['REQUEST_METHOD']
|
292
|
+
logger.info('get body')
|
293
|
+
request_body = env['rack.input']
|
294
|
+
request_body.rewind if env['rack.input'].respond_to? :rewind
|
295
|
+
request_body = request_body.instance_of?(Puma::NullIO) ? nil : request_body.string
|
296
|
+
|
297
|
+
request_headers = ::Rack::Request.new(env).headers.to_h.map { |name, value| { name:, value: } }
|
298
|
+
|
299
|
+
status, response_headers, response_body = env['inferno.response']
|
300
|
+
|
301
|
+
response_headers = response_headers.map { |name, value| { name:, value: } }
|
302
|
+
|
303
|
+
repo.create(
|
304
|
+
verb:,
|
305
|
+
url:,
|
306
|
+
direction: 'incoming',
|
307
|
+
name: env['inferno.name'],
|
308
|
+
status:,
|
309
|
+
request_body:,
|
310
|
+
response_body: response_body.join,
|
311
|
+
result_id: env['inferno.result_id'],
|
312
|
+
test_session_id: env['inferno.test_session_id'],
|
313
|
+
request_headers:,
|
314
|
+
response_headers:,
|
315
|
+
tags: env['inferno.tags']
|
316
|
+
)
|
317
|
+
|
318
|
+
if env['inferno.resume_test_run']
|
319
|
+
test_run_id = env['inferno.test_run_id']
|
320
|
+
Inferno::Repositories::TestRuns.new.mark_as_no_longer_waiting(test_run_id)
|
321
|
+
|
322
|
+
Inferno::Jobs.perform(Jobs::ResumeTestRun, test_run_id)
|
323
|
+
end
|
324
|
+
rescue StandardError => e
|
325
|
+
logger.error(e.full_message)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
data/lib/inferno/dsl.rb
CHANGED