inferno_core 0.4.37 → 0.4.39
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/cli/console.rb +3 -0
- data/lib/inferno/apps/cli/main.rb +29 -10
- data/lib/inferno/apps/cli/migration.rb +2 -2
- data/lib/inferno/apps/cli/templates/.env.development +1 -1
- data/lib/inferno/apps/cli/templates/.env.production +1 -1
- data/lib/inferno/apps/cli/templates/.env.test +1 -1
- data/lib/inferno/apps/cli/templates/config/nginx.background.conf.tt +16 -0
- data/lib/inferno/apps/cli/templates/config/nginx.conf.tt +16 -0
- data/lib/inferno/apps/cli/templates/docker-compose.background.yml.tt +11 -0
- data/lib/inferno/apps/cli/templates/docker-compose.yml.tt +4 -0
- data/lib/inferno/apps/cli/templates/lib/%library_name%/igs/README.md +21 -0
- data/lib/inferno/apps/cli/templates/lib/%library_name%.rb.tt +8 -3
- data/lib/inferno/apps/cli/templates/spec/%library_name%/patient_group_spec.rb.tt +25 -6
- data/lib/inferno/config/boot/sidekiq.rb +5 -0
- data/lib/inferno/config/boot/validator.rb +2 -0
- data/lib/inferno/dsl/auth_info.rb +174 -0
- data/lib/inferno/dsl/resume_test_route.rb +59 -20
- data/lib/inferno/dsl/runnable.rb +1 -1
- data/lib/inferno/dsl/suite_endpoint.rb +1 -2
- data/lib/inferno/jobs/invoke_validator_session.rb +1 -0
- data/lib/inferno/public/bundle.js +3 -3
- data/lib/inferno/repositories/session_data.rb +24 -1
- data/lib/inferno/utils/middleware/request_logger.rb +1 -1
- data/lib/inferno/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c569fc01e07576cb3aa512c37a69d730bc7b9848bd24ed95935b23a0d52759c
|
4
|
+
data.tar.gz: 41165f4f56dcf7c7e552ec0c391b868e5020feed0957f12d508489835a91d140
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03cb4fec0a859ba0967d891b62d4741b6a241839bce017ac0a9f212c06cabbec45e3d8c9464d8a75421c697c6e547af19e5bdbe8055ab7ea630344a781dfdf5e
|
7
|
+
data.tar.gz: ad2fc2e5f42777535e912e4bc8217f48d9d90babb074b071b7437fb3b987f4f8470f505f9e1bd29b1b893f7b6ccc36800145ad62fe82664188e0eab965b71cf5
|
@@ -11,6 +11,7 @@ module Inferno
|
|
11
11
|
class Main < Thor
|
12
12
|
desc 'console', 'Start an interactive console session with Inferno'
|
13
13
|
def console
|
14
|
+
Migration.new.run(Logger::INFO)
|
14
15
|
Console.new.run
|
15
16
|
end
|
16
17
|
|
@@ -25,20 +26,25 @@ module Inferno
|
|
25
26
|
type: :boolean,
|
26
27
|
desc: 'Automatically restart Inferno when a file is changed.'
|
27
28
|
def start
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
Migration.new.run(Logger::INFO)
|
30
|
+
|
31
|
+
without_bundler do
|
32
|
+
command = 'foreman start --env=/dev/null'
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
puts "You must install 'rerun' with 'gem install rerun' to restart on file changes."
|
34
|
+
if `gem list -i foreman`.chomp == 'false'
|
35
|
+
puts "You must install foreman with 'gem install foreman' prior to running Inferno."
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
if options[:watch]
|
39
|
+
if `gem list -i rerun`.chomp == 'false'
|
40
|
+
puts "You must install 'rerun' with 'gem install rerun' to restart on file changes."
|
41
|
+
end
|
42
|
+
|
43
|
+
command = "rerun \"#{command}\" --background"
|
44
|
+
end
|
40
45
|
|
41
|
-
|
46
|
+
exec command
|
47
|
+
end
|
42
48
|
end
|
43
49
|
|
44
50
|
desc 'suites', 'List available test suites'
|
@@ -58,6 +64,19 @@ module Inferno
|
|
58
64
|
def version
|
59
65
|
puts "Inferno Core v#{Inferno::VERSION}"
|
60
66
|
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# https://github.com/rubocop/rubocop/issues/12571 - still affects Ruby 3.1 upto Rubocop 1.63
|
71
|
+
# rubocop:disable Naming/BlockForwarding
|
72
|
+
def without_bundler(&block)
|
73
|
+
if defined?(Bundler) && ENV['BUNDLE_GEMFILE']
|
74
|
+
Bundler.with_unbundled_env(&block)
|
75
|
+
else
|
76
|
+
yield
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# rubocop:enable Naming/BlockForwarding
|
61
80
|
end
|
62
81
|
end
|
63
82
|
end
|
@@ -3,9 +3,9 @@ require_relative '../../utils/migration'
|
|
3
3
|
module Inferno
|
4
4
|
module CLI
|
5
5
|
class Migration
|
6
|
-
def run
|
6
|
+
def run(log_level = Logger::DEBUG)
|
7
7
|
Inferno::Application.start(:logging)
|
8
|
-
Inferno::Application['logger'].level =
|
8
|
+
Inferno::Application['logger'].level = log_level
|
9
9
|
|
10
10
|
Utils::Migration.new.run
|
11
11
|
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
1
|
+
FHIR_RESOURCE_VALIDATOR_URL=http://localhost/hl7validatorapi
|
2
2
|
REDIS_URL=redis://localhost:6379/0
|
@@ -1,2 +1,2 @@
|
|
1
1
|
REDIS_URL=redis://redis:6379/0
|
2
|
-
|
2
|
+
FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
1
|
+
FHIR_RESOURCE_VALIDATOR_URL=https://example.com/validatorapi
|
2
2
|
ASYNC_JOBS=false
|
@@ -82,5 +82,21 @@ http {
|
|
82
82
|
|
83
83
|
proxy_pass http://validator_service:4567/;
|
84
84
|
}
|
85
|
+
|
86
|
+
location /hl7validatorapi/ {
|
87
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
88
|
+
proxy_set_header Host $http_host;
|
89
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
90
|
+
proxy_set_header X-Forwarded-Port $server_port;
|
91
|
+
proxy_redirect off;
|
92
|
+
proxy_set_header Connection '';
|
93
|
+
proxy_http_version 1.1;
|
94
|
+
chunked_transfer_encoding off;
|
95
|
+
proxy_buffering off;
|
96
|
+
proxy_cache off;
|
97
|
+
proxy_read_timeout 600s;
|
98
|
+
|
99
|
+
proxy_pass http://hl7_validator_service:3500/;
|
100
|
+
}
|
85
101
|
}
|
86
102
|
}
|
@@ -97,5 +97,21 @@ http {
|
|
97
97
|
|
98
98
|
proxy_pass http://validator_service:4567/;
|
99
99
|
}
|
100
|
+
|
101
|
+
location /hl7validatorapi/ {
|
102
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
103
|
+
proxy_set_header Host $http_host;
|
104
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
105
|
+
proxy_set_header X-Forwarded-Port $server_port;
|
106
|
+
proxy_redirect off;
|
107
|
+
proxy_set_header Connection '';
|
108
|
+
proxy_http_version 1.1;
|
109
|
+
chunked_transfer_encoding off;
|
110
|
+
proxy_buffering off;
|
111
|
+
proxy_cache off;
|
112
|
+
proxy_read_timeout 600s;
|
113
|
+
|
114
|
+
proxy_pass http://hl7_validator_service:3500/;
|
115
|
+
}
|
100
116
|
}
|
101
117
|
}
|
@@ -1,5 +1,16 @@
|
|
1
1
|
version: '3'
|
2
2
|
services:
|
3
|
+
hl7_validator_service:
|
4
|
+
image: infernocommunity/inferno-resource-validator
|
5
|
+
environment:
|
6
|
+
# Defines how long validator sessions last if unused, in minutes:
|
7
|
+
# Negative values mean sessions never expire, 0 means sessions immediately expire
|
8
|
+
SESSION_CACHE_DURATION: -1
|
9
|
+
volumes:
|
10
|
+
- ./<%= ig_path %>:/app/igs
|
11
|
+
# To let the service share your local FHIR package cache,
|
12
|
+
# uncomment the below line
|
13
|
+
# - ~/.fhir:/home/ktor/.fhir
|
3
14
|
validator_service:
|
4
15
|
image: infernocommunity/fhir-validator-service
|
5
16
|
# Update this path to match your directory structure
|
@@ -15,6 +15,10 @@ services:
|
|
15
15
|
command: bundle exec sidekiq -r ./worker.rb
|
16
16
|
depends_on:
|
17
17
|
- redis
|
18
|
+
hl7_validator_service:
|
19
|
+
extends:
|
20
|
+
file: docker-compose.background.yml
|
21
|
+
service: hl7_validator_service
|
18
22
|
validator_service:
|
19
23
|
extends:
|
20
24
|
file: docker-compose.background.yml
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Note on this IGs folder
|
2
|
+
|
3
|
+
There are three reasons why it would be necessary to put an IG package.tgz in this folder. If none of these apply, you do not need to put any files here, or can consider removing any existing files to make it clear they are unused.
|
4
|
+
|
5
|
+
## 1. Generated Test Suites
|
6
|
+
Some test kits use a "generator" to automatically generate the contents of a test suite for an IG. The IG files are required every time the test suites need to be regenerated. Examples of test kits that use this approach are the US Core Test Kit and CARIN IG for Blue Button® Test Kit.
|
7
|
+
|
8
|
+
|
9
|
+
## 2. Non-published IG
|
10
|
+
If your IG, or the specific version of the IG you want to test against, is not published, then the validator service needs to load the IG from file in order to be able to validate resources with it. The IG must be referenced in the `fhir_resource_validator` block in the test suite definition by filename, ie:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
fhir_resource_validator do
|
14
|
+
igs 'igs/filename.tgz'
|
15
|
+
|
16
|
+
...
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
## 3. Inferno Validator UI
|
21
|
+
The Inferno Validator UI is configured to auto-load any IGs present in the igs folder and include them in all validations. In general, the Inferno team is currently leaving IGs in this folder even if not otherwise necessary to make it easy to re-enable the validator UI.
|
@@ -21,9 +21,14 @@ module <%= module_name %>
|
|
21
21
|
oauth_credentials :credentials
|
22
22
|
end
|
23
23
|
|
24
|
-
# All FHIR validation
|
25
|
-
|
26
|
-
|
24
|
+
# All FHIR validation requests will use this FHIR validator
|
25
|
+
fhir_resource_validator do
|
26
|
+
# igs 'identifier#version' # Use this method for published IGs/versions
|
27
|
+
# igs 'igs/filename.tgz' # Use this otherwise
|
28
|
+
|
29
|
+
exclude_message do |message|
|
30
|
+
message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
|
31
|
+
end
|
27
32
|
end
|
28
33
|
|
29
34
|
# Tests and TestGroups can be defined inline
|
@@ -4,7 +4,26 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
4
4
|
let(:session_data_repo) { Inferno::Repositories::SessionData.new }
|
5
5
|
let(:test_session) { repo_create(:test_session, test_suite_id: '<%= test_suite_id %>') }
|
6
6
|
let(:url) { 'http://example.com/fhir' }
|
7
|
-
let(:
|
7
|
+
let(:success_outcome) do
|
8
|
+
{
|
9
|
+
outcomes: [{
|
10
|
+
issues: []
|
11
|
+
}],
|
12
|
+
sessionId: ''
|
13
|
+
}
|
14
|
+
end
|
15
|
+
let(:error_outcome) do
|
16
|
+
{
|
17
|
+
outcomes: [{
|
18
|
+
issues: [{
|
19
|
+
location: 'Patient.identifier[0]',
|
20
|
+
message: 'Identifier.system must be an absolute reference, not a local reference',
|
21
|
+
level: 'ERROR'
|
22
|
+
}]
|
23
|
+
}],
|
24
|
+
sessionId: ''
|
25
|
+
}
|
26
|
+
end
|
8
27
|
|
9
28
|
def run(runnable, inputs = {})
|
10
29
|
test_run_params = { test_session_id: test_session.id }.merge(runnable.reference_hash)
|
@@ -67,9 +86,9 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
67
86
|
let(:test) { group.tests.last }
|
68
87
|
|
69
88
|
it 'passes if the resource is valid' do
|
70
|
-
stub_request(:post, "#{ENV.fetch('
|
89
|
+
stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
|
71
90
|
.with(query: hash_including({}))
|
72
|
-
.to_return(status: 200, body:
|
91
|
+
.to_return(status: 200, body: success_outcome.to_json)
|
73
92
|
|
74
93
|
resource = FHIR::Patient.new
|
75
94
|
repo_create(
|
@@ -79,13 +98,13 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
79
98
|
response_body: resource.to_json
|
80
99
|
)
|
81
100
|
|
82
|
-
result = run(test)
|
101
|
+
result = run(test, url: url)
|
83
102
|
|
84
103
|
expect(result.result).to eq('pass')
|
85
104
|
end
|
86
105
|
|
87
106
|
it 'fails if the resource is not valid' do
|
88
|
-
stub_request(:post, "#{ENV.fetch('
|
107
|
+
stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
|
89
108
|
.with(query: hash_including({}))
|
90
109
|
.to_return(status: 200, body: error_outcome.to_json)
|
91
110
|
|
@@ -97,7 +116,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
97
116
|
response_body: resource.to_json
|
98
117
|
)
|
99
118
|
|
100
|
-
result = run(test)
|
119
|
+
result = run(test, url: url)
|
101
120
|
|
102
121
|
expect(result.result).to eq('fail')
|
103
122
|
end
|
@@ -5,6 +5,11 @@ Inferno::Application.register_provider(:sidekiq) 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') }
|
8
|
+
|
9
|
+
config.capsule('validator_sessions') do |cap|
|
10
|
+
cap.concurrency = ENV.fetch('VALIDATOR_SESSIONS_CONCURRENCY', '1').to_i
|
11
|
+
cap.queues = ['validator_sessions']
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
15
|
end
|
@@ -8,6 +8,8 @@ Inferno::Application.register_provider(:validator) do
|
|
8
8
|
|
9
9
|
next if ENV['APP_ENV'] == 'test'
|
10
10
|
|
11
|
+
next if ENV.fetch('INITIALIZE_VALIDATOR_SESSIONS', 'true').casecmp?('false')
|
12
|
+
|
11
13
|
Inferno::Repositories::TestSuites.new.all.each do |suite|
|
12
14
|
suite.fhir_validators.each do |name, validators|
|
13
15
|
validators.each_with_index do |validator, index|
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require_relative '../entities/attributes'
|
2
|
+
|
3
|
+
module Inferno
|
4
|
+
module DSL
|
5
|
+
# AuthInfo provide a user with a single input which contains the information
|
6
|
+
# needed for a fhir client to perform authorization and refresh an access
|
7
|
+
# token when necessary.
|
8
|
+
#
|
9
|
+
# AuthInfo supports the following `auth_type`:
|
10
|
+
# - `public` - client id only
|
11
|
+
# - `symmetric` - Symmetric confidential (i.e., with a static client id and
|
12
|
+
# secret)
|
13
|
+
# - `asymmetric` - Symmetric confidential (i.e., a client id with a signed
|
14
|
+
# JWT rather than a client secret)
|
15
|
+
# - `backend_services`
|
16
|
+
#
|
17
|
+
# When configuring an AuthInfo input, the invdidual fields are exposed as
|
18
|
+
# `components` in the input's options, and can be configured there similar
|
19
|
+
# to normal inputs.
|
20
|
+
#
|
21
|
+
# The AuthInfo input type supports two different modes in the UI. Different
|
22
|
+
# fields will be presented to the user dependengi on which mode is selected.
|
23
|
+
# - `auth` - This presents the inputs needed to perform authorization, and
|
24
|
+
# is appropriate to use as an input to test groups which perform
|
25
|
+
# authorization
|
26
|
+
# - `access` - This presents the inputs needed to access resources assuming
|
27
|
+
# that authorization has already happened, and is appropriate to use as an
|
28
|
+
# input to test groups which access resources using previously granted
|
29
|
+
# authorization
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# class AuthInfoExampleSuite < Inferno::TestSuite
|
33
|
+
# input :url,
|
34
|
+
# title: 'Base FHIR url'
|
35
|
+
#
|
36
|
+
# group do
|
37
|
+
# title 'Perform public authorization'
|
38
|
+
# input :fhir_auth,
|
39
|
+
# type: :auth_info,
|
40
|
+
# options: {
|
41
|
+
# mode: 'auth',
|
42
|
+
# components: [
|
43
|
+
# {
|
44
|
+
# name: :auth_type,
|
45
|
+
# default: 'public',
|
46
|
+
# locked: true
|
47
|
+
# }
|
48
|
+
# ]
|
49
|
+
# }
|
50
|
+
#
|
51
|
+
# # Some tests here to perform authorization
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# group do
|
55
|
+
# title 'FHIR API Tests'
|
56
|
+
# input :fhir_auth,
|
57
|
+
# type: :auth_info,
|
58
|
+
# options: {
|
59
|
+
# mode: 'access'
|
60
|
+
# }
|
61
|
+
#
|
62
|
+
# fhir_client do
|
63
|
+
# url :url
|
64
|
+
# auth_info :fhir_auth # NOT YET IMPLEMENTED
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # Some tests here to access FHIR API
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
class AuthInfo
|
71
|
+
ATTRIBUTES = [
|
72
|
+
:auth_type,
|
73
|
+
:use_discovery,
|
74
|
+
:token_url,
|
75
|
+
:auth_url,
|
76
|
+
:requested_scopes,
|
77
|
+
:client_id,
|
78
|
+
:client_secret,
|
79
|
+
:redirect_url, # TODO: does this belong here?
|
80
|
+
:pkce_support,
|
81
|
+
:pkce_code_challenge_method,
|
82
|
+
:auth_request_method,
|
83
|
+
:encryption_algorithm,
|
84
|
+
:kid,
|
85
|
+
:jwks,
|
86
|
+
:access_token,
|
87
|
+
:refresh_token,
|
88
|
+
:issue_time,
|
89
|
+
:expires_in,
|
90
|
+
:name
|
91
|
+
].freeze
|
92
|
+
|
93
|
+
include Entities::Attributes
|
94
|
+
|
95
|
+
attr_accessor :client
|
96
|
+
|
97
|
+
# @!attribute [rw] auth_type The type of authorization to be performed.
|
98
|
+
# One of `public`, `symmetric`, `asymmetric`, or `backend_services`
|
99
|
+
# @!attribute [rw] token_url The url of the auth server's token endpoint
|
100
|
+
# @!attribute [rw] auth_url The url of the authorization endpoint
|
101
|
+
# @!attribute [rw] requested_scopes The scopes which will be requested
|
102
|
+
# during authorization
|
103
|
+
# @!attribute [rw] client_id
|
104
|
+
# @!attribute [rw] client_secret
|
105
|
+
# @!attribute [rw] redirect_url
|
106
|
+
# @!attribute [rw] pkce_support Whether PKCE will be used during
|
107
|
+
# authorization. Either `enabled` or `disabled`.
|
108
|
+
# @!attribute [rw] pkce_code_challenge_method Either `S256` (default) or
|
109
|
+
# `plain`
|
110
|
+
# @!attribute [rw] auth_request_method The http method which will be used
|
111
|
+
# to perform the request to the authorization endpoint. Either `get`
|
112
|
+
# (default) or `post`
|
113
|
+
# @!attribute [rw] encryption_algorithm The encryption algorithm which
|
114
|
+
# will be used to sign the JWT client credentials. Either `es384`
|
115
|
+
# (default) or `rs384`
|
116
|
+
# @!attribute [rw] kid The key id for the keys to be used to sign the JWT
|
117
|
+
# client credentials. When blank, the first key for the selected
|
118
|
+
# encryption algorithm will be used
|
119
|
+
# @!attribute [rw] jwks A JWKS (including private keys) which will be used
|
120
|
+
# instead of Inferno's default JWKS if provided
|
121
|
+
# @!attribute [rw] access_token
|
122
|
+
# @!attribute [rw] refresh_token
|
123
|
+
# @!attribute [rw] issue_time An iso8601 formatted string representing the
|
124
|
+
# time the access token was issued
|
125
|
+
# @!attribute [rw] expires_in The lifetime of the access token in seconds
|
126
|
+
# @!attribute [rw] name
|
127
|
+
|
128
|
+
# @private
|
129
|
+
def initialize(raw_attributes_hash)
|
130
|
+
attributes_hash = raw_attributes_hash.symbolize_keys
|
131
|
+
|
132
|
+
invalid_keys = attributes_hash.keys - ATTRIBUTES
|
133
|
+
|
134
|
+
raise Exceptions::UnknownAttributeException.new(invalid_keys, self.class) if invalid_keys.present?
|
135
|
+
|
136
|
+
attributes_hash.each do |name, value|
|
137
|
+
value = DateTime.parse(value) if name == :issue_time && value.is_a?(String)
|
138
|
+
|
139
|
+
instance_variable_set(:"@#{name}", value)
|
140
|
+
end
|
141
|
+
|
142
|
+
self.issue_time = DateTime.now if access_token.present? && issue_time.blank?
|
143
|
+
end
|
144
|
+
|
145
|
+
# @private
|
146
|
+
def to_hash
|
147
|
+
self.class::ATTRIBUTES.each_with_object({}) do |attribute, hash|
|
148
|
+
value = send(attribute)
|
149
|
+
next if value.nil?
|
150
|
+
|
151
|
+
value = issue_time.iso8601 if attribute == :issue_time
|
152
|
+
|
153
|
+
hash[attribute] = value
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# @private
|
158
|
+
def to_s
|
159
|
+
JSON.generate(to_hash)
|
160
|
+
end
|
161
|
+
|
162
|
+
# @private
|
163
|
+
def add_to_client(client)
|
164
|
+
# TODO
|
165
|
+
# client.auth = self
|
166
|
+
# self.client = client
|
167
|
+
|
168
|
+
# return unless access_token.present?
|
169
|
+
|
170
|
+
# client.set_bearer_token(access_token)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'hanami/controller'
|
2
2
|
|
3
3
|
module Inferno
|
4
4
|
module DSL
|
@@ -6,47 +6,58 @@ module Inferno
|
|
6
6
|
# an incoming request.
|
7
7
|
# @private
|
8
8
|
# @see Inferno::DSL::Runnable#resume_test_route
|
9
|
-
class ResumeTestRoute <
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
class ResumeTestRoute < Hanami::Action
|
10
|
+
include Import[
|
11
|
+
requests_repo: 'inferno.repositories.requests',
|
12
|
+
results_repo: 'inferno.repositories.results',
|
13
|
+
test_runs_repo: 'inferno.repositories.test_runs',
|
14
|
+
tests_repo: 'inferno.repositories.tests'
|
15
|
+
]
|
16
|
+
|
17
|
+
def self.call(...)
|
18
|
+
new.call(...)
|
15
19
|
end
|
16
20
|
|
17
21
|
# @private
|
18
|
-
def
|
19
|
-
|
22
|
+
def test_run_identifier_block
|
23
|
+
self.class.singleton_class.instance_variable_get(:@test_run_identifier_block)
|
20
24
|
end
|
21
25
|
|
22
26
|
# @private
|
23
27
|
def tags
|
24
|
-
self.class.singleton_class.instance_variable_get(:@tags)
|
28
|
+
self.class.singleton_class.instance_variable_get(:@tags)
|
25
29
|
end
|
26
30
|
|
27
31
|
# @private
|
28
|
-
def
|
29
|
-
|
32
|
+
def result
|
33
|
+
self.class.singleton_class.instance_variable_get(:@result)
|
30
34
|
end
|
31
35
|
|
32
36
|
# @private
|
33
|
-
def
|
34
|
-
|
37
|
+
def find_test_run(test_run_identifier)
|
38
|
+
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
35
39
|
end
|
36
40
|
|
37
41
|
# @private
|
38
|
-
def
|
39
|
-
|
42
|
+
def find_waiting_result(test_run)
|
43
|
+
results_repo.find_waiting_result(test_run_id: test_run.id)
|
40
44
|
end
|
41
45
|
|
42
46
|
# @private
|
43
|
-
def
|
44
|
-
|
47
|
+
def update_result(waiting_result)
|
48
|
+
results_repo.update_result(waiting_result.id, result)
|
45
49
|
end
|
46
50
|
|
47
51
|
# @private
|
48
|
-
def
|
49
|
-
|
52
|
+
def persist_request(request, test_run, waiting_result, test)
|
53
|
+
requests_repo.create(
|
54
|
+
request.to_hash.merge(
|
55
|
+
test_session_id: test_run.test_session_id,
|
56
|
+
result_id: waiting_result.id,
|
57
|
+
name: test.config.request_name(test.incoming_request_name),
|
58
|
+
tags:
|
59
|
+
)
|
60
|
+
)
|
50
61
|
end
|
51
62
|
|
52
63
|
# @private
|
@@ -54,10 +65,38 @@ module Inferno
|
|
54
65
|
"#{Application['base_url']}/test_sessions/#{test_run.test_session_id}##{resume_ui_at_id(test_run, test)}"
|
55
66
|
end
|
56
67
|
|
68
|
+
# @private
|
69
|
+
def find_test(waiting_result)
|
70
|
+
tests_repo.find(waiting_result.test_id)
|
71
|
+
end
|
72
|
+
|
57
73
|
# @private
|
58
74
|
def resume_ui_at_id(test_run, test)
|
59
75
|
test_run.test_suite_id || test_run.test_group_id || test.parent.id
|
60
76
|
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
def handle(req, res)
|
80
|
+
request = Inferno::Entities::Request.from_hanami_request(req)
|
81
|
+
|
82
|
+
test_run_identifier = instance_exec(request, &test_run_identifier_block)
|
83
|
+
|
84
|
+
test_run = find_test_run(test_run_identifier)
|
85
|
+
|
86
|
+
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
87
|
+
|
88
|
+
test_runs_repo.mark_as_no_longer_waiting(test_run.id)
|
89
|
+
|
90
|
+
waiting_result = find_waiting_result(test_run)
|
91
|
+
test = find_test(waiting_result)
|
92
|
+
|
93
|
+
update_result(waiting_result)
|
94
|
+
persist_request(request, test_run, waiting_result, test)
|
95
|
+
|
96
|
+
Jobs.perform(Jobs::ResumeTestRun, test_run.id)
|
97
|
+
|
98
|
+
res.redirect_to redirect_route(test_run, test)
|
99
|
+
end
|
61
100
|
end
|
62
101
|
end
|
63
102
|
end
|
data/lib/inferno/dsl/runnable.rb
CHANGED
@@ -343,7 +343,7 @@ module Inferno
|
|
343
343
|
route_class = Class.new(ResumeTestRoute) do |klass|
|
344
344
|
klass.singleton_class.instance_variable_set(:@test_run_identifier_block, block)
|
345
345
|
klass.singleton_class.instance_variable_set(:@tags, tags)
|
346
|
-
klass.singleton_class.instance_variable_set(:@
|
346
|
+
klass.singleton_class.instance_variable_set(:@result, result)
|
347
347
|
end
|
348
348
|
|
349
349
|
route(method, path, route_class)
|
@@ -244,7 +244,7 @@ module Inferno
|
|
244
244
|
|
245
245
|
# @private
|
246
246
|
def resume_test_run?
|
247
|
-
find_result&.result != '
|
247
|
+
find_result&.result != 'wait'
|
248
248
|
end
|
249
249
|
|
250
250
|
# @private
|
@@ -289,7 +289,6 @@ module Inferno
|
|
289
289
|
uri.query = env['rack.request.query_string'] if env['rack.request.query_string'].present?
|
290
290
|
url = uri&.to_s
|
291
291
|
verb = env['REQUEST_METHOD']
|
292
|
-
logger.info('get body')
|
293
292
|
request_body = env['rack.input']
|
294
293
|
request_body.rewind if env['rack.input'].respond_to? :rewind
|
295
294
|
request_body = request_body.instance_of?(Puma::NullIO) ? nil : request_body.string
|