inferno_core 0.6.17 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f5e1cae1c23852f0f5cab017eb7b1fc361fce08f53c7ad1cc47859a0a3546ab
4
- data.tar.gz: 34be067581780bca55ae925bfaae31bd56a6f6ed864774b915f0ac9147d426e1
3
+ metadata.gz: d8f8cb64cc07cf0ea3225a930fa47c6e54619da91d739912452cf0b8c8e27568
4
+ data.tar.gz: fcc3c0d0b6f20a0cb34021f26a79f32a8abff955333a105a4b7cc94de0307db7
5
5
  SHA512:
6
- metadata.gz: 8e082414599d3d7c9d84129cfa78a4cafb3fcf3a3df1f4aec586119cfc67c234d183374256545217a827c916ca16bcdbe2bd3955dc1149383871e31247260aed
7
- data.tar.gz: 5ca8d4645f9667cba2e2ef92c9690a947d2e70027537f57bbedb4bb239742c01c95d6c3e853367b4840d58cdb728f3c89aa671e5bfaff75a3e85be284b3fde15
6
+ metadata.gz: 749b0cc95ead3ef3a7c200918f314aae140c789f98d10199f26b65d973c23b269115cfdbe45e19358e0a13cc71f284c7366f7c8b90c29277b52eaed95215afc3
7
+ data.tar.gz: 593752aa7a14ec8c04b921403eae863e72d84e2de4f452ea656d2a56bf102597e5a88c444447cb02ea0bf93918039cf51ac88dce58338686da1d7cf8f861f5d1
@@ -115,7 +115,7 @@ module Inferno
115
115
  test_session.suite_options
116
116
  )
117
117
 
118
- persist_inputs(session_data_repo, create_params(test_session, suite), test_run)
118
+ persist_inputs(session_data_repo, create_params(test_session, suite), runnable)
119
119
 
120
120
  dispatch_job(test_run)
121
121
  end
@@ -1,6 +1,6 @@
1
- require:
1
+ plugins:
2
2
  - rubocop-rspec
3
-
3
+
4
4
  AllCops:
5
5
  NewCops: enable
6
6
  SuggestExtensions: false
@@ -3,7 +3,6 @@ require_relative 'example_suite/patient_group'
3
3
 
4
4
  module <%= module_name %>
5
5
  class ExampleSuite < Inferno::TestSuite
6
-
7
6
  id :<%= test_suite_id %>
8
7
  title '<%= title_name %>'
9
8
  short_title '<%= title_name %>'
@@ -1,3 +1,4 @@
1
+ # @note includes RSpec shared context 'when testing a runnable'
1
2
  RSpec.describe <%= module_name %>::PatientGroup do
2
3
  let(:suite_id) { '<%= test_suite_id %>' }
3
4
  let(:group) { suite.groups[1] }
@@ -7,7 +8,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
7
8
  outcomes: [{
8
9
  issues: []
9
10
  }],
10
- sessionId: ''
11
+ sessionId: test_session.id
11
12
  }
12
13
  end
13
14
  let(:error_outcome) do
@@ -19,7 +20,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
19
20
  level: 'ERROR'
20
21
  }]
21
22
  }],
22
- sessionId: ''
23
+ sessionId: test_session.id
23
24
  }
24
25
  end
25
26
 
@@ -34,7 +35,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
34
35
 
35
36
  result = run(test, url: url, patient_id: patient_id)
36
37
 
37
- expect(result.result).to eq('pass')
38
+ expect(result.result).to eq('pass'), result.result_message
38
39
  end
39
40
 
40
41
  it 'fails if a 200 is not received' do
@@ -44,7 +45,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
44
45
 
45
46
  result = run(test, url: url, patient_id: patient_id)
46
47
 
47
- expect(result.result).to eq('fail')
48
+ expect(result.result).to eq('fail'), result.result_message
48
49
  expect(result.result_message).to match(/200/)
49
50
  end
50
51
 
@@ -55,7 +56,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
55
56
 
56
57
  result = run(test, url: url, patient_id: patient_id)
57
58
 
58
- expect(result.result).to eq('fail')
59
+ expect(result.result).to eq('fail'), result.result_message
59
60
  expect(result.result_message).to match(/Patient/)
60
61
  end
61
62
 
@@ -66,7 +67,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
66
67
 
67
68
  result = run(test, url: url, patient_id: patient_id)
68
69
 
69
- expect(result.result).to eq('fail')
70
+ expect(result.result).to eq('fail'), result.result_message
70
71
  expect(result.result_message).to match(/resource with id/)
71
72
  end
72
73
  end
@@ -75,7 +76,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
75
76
  let(:test) { group.tests.last }
76
77
 
77
78
  it 'passes if the resource is valid' do
78
- stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
79
+ stub_request(:post, validation_url)
79
80
  .with(query: hash_including({}))
80
81
  .to_return(status: 200, body: success_outcome.to_json)
81
82
 
@@ -89,11 +90,11 @@ RSpec.describe <%= module_name %>::PatientGroup do
89
90
 
90
91
  result = run(test, url: url)
91
92
 
92
- expect(result.result).to eq('pass')
93
+ expect(result.result).to eq('pass'), result.result_message
93
94
  end
94
95
 
95
96
  it 'fails if the resource is not valid' do
96
- stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
97
+ stub_request(:post, validation_url)
97
98
  .with(query: hash_including({}))
98
99
  .to_return(status: 200, body: error_outcome.to_json)
99
100
 
@@ -107,7 +108,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
107
108
 
108
109
  result = run(test, url: url)
109
110
 
110
- expect(result.result).to eq('fail')
111
+ expect(result.result).to eq('fail'), result.result_message
111
112
  end
112
113
  end
113
114
  end
@@ -35,7 +35,7 @@ module Inferno
35
35
 
36
36
  res.body = serialize(test_run, suite_options: test_session.suite_options)
37
37
 
38
- persist_inputs(session_data_repo, req.params, test_run)
38
+ persist_inputs(session_data_repo, req.params, test_run.runnable)
39
39
 
40
40
  Jobs.perform(Jobs::ExecuteTestRun, test_run.id)
41
41
  rescue Sequel::ValidationFailed, Sequel::ForeignKeyConstraintViolation,
@@ -1,12 +1,18 @@
1
+ require_relative '../../../utils/verify_runnable'
2
+ require_relative '../../../utils/persist_inputs'
3
+
1
4
  module Inferno
2
5
  module Web
3
6
  module Controllers
4
7
  class TestSessionFormPostController < Hanami::Action
8
+ include ::Inferno::Utils::VerifyRunnable
9
+ include ::Inferno::Utils::PersistInputs
10
+
5
11
  def self.call(...)
6
12
  new.call(...)
7
13
  end
8
14
 
9
- def handle(req, res)
15
+ def handle(req, res) # rubocop:disable Metrics/CyclomaticComplexity
10
16
  test_suite_id = req.params[:test_suite_id]
11
17
 
12
18
  test_suite = Inferno::Repositories::TestSuites.new.find(test_suite_id)
@@ -31,7 +37,32 @@ module Inferno
31
37
  repo.apply_preset(session, preset_id)
32
38
  end
33
39
 
40
+ inputs = req.params[:inputs]
41
+
42
+ if inputs.present?
43
+ begin
44
+ verify_runnable(
45
+ test_suite,
46
+ inputs,
47
+ session.suite_options
48
+ )
49
+ rescue Inferno::Exceptions::RequiredInputsNotFound => e
50
+ Application['logger'].info("#{e.message}. Can be added later at test run creation.")
51
+ end
52
+
53
+ params.merge!(inputs:, test_session_id: session.id)
54
+
55
+ session_data_repo = Inferno::Repositories::SessionData.new
56
+ persist_inputs(session_data_repo, params, test_suite)
57
+
58
+ end
59
+
34
60
  res.redirect_to "#{Inferno::Application['base_url']}/#{test_suite_id}/#{session.id}"
61
+ rescue Inferno::Exceptions::NotUserRunnableException => e
62
+ halt 422, { errors: e.message }.to_json
63
+ rescue StandardError => e
64
+ Application['logger'].error(e.full_message)
65
+ halt 500, { errors: e.message }.to_json
35
66
  end
36
67
  end
37
68
  end
@@ -7,7 +7,7 @@ module Inferno
7
7
  ERB.new(
8
8
  File.read(
9
9
  File.join(
10
- Inferno::Application.root, 'lib', 'inferno', 'apps', 'web', 'index.html.erb'
10
+ Inferno::Application.root, 'lib', 'inferno', 'apps', 'web', 'templates', 'client_index.html.erb'
11
11
  )
12
12
  )
13
13
  ).result.freeze
@@ -1,5 +1,8 @@
1
1
  require 'erb'
2
+ require 'kramdown'
3
+ require 'kramdown-parser-gfm'
2
4
  require_relative '../../feature'
5
+ require_relative '../../repositories/test_kits'
3
6
 
4
7
  Dir.glob(File.join(__dir__, 'controllers', '**', '*.rb')).each { |path| require_relative path }
5
8
 
@@ -7,9 +10,11 @@ module Inferno
7
10
  module Web
8
11
  client_page = ERB.new(
9
12
  File.read(
10
- File.join(Inferno::Application.root, 'lib', 'inferno', 'apps', 'web', 'index.html.erb')
13
+ File.join(Inferno::Application.root, 'lib', 'inferno', 'apps', 'web', 'templates', 'client_index.html.erb')
11
14
  )
12
15
  ).result
16
+
17
+ test_kit_template = ERB.new(File.read(File.join(__dir__, 'templates', 'test_kit.html.erb')))
13
18
  CLIENT_PAGE_RESPONSE = ->(_env) { [200, { 'Content-Type' => 'text/html' }, [client_page]] }
14
19
 
15
20
  base_path = Application['base_path']&.delete_prefix('/')
@@ -69,7 +74,16 @@ module Inferno
69
74
 
70
75
  # Should not need Content-Type header but GitHub Codespaces will not work without them.
71
76
  # This could be investigated and likely removed if addressed properly elsewhere.
72
- get '/', to: CLIENT_PAGE_RESPONSE
77
+ get '/',
78
+ to: lambda { |env|
79
+ local_test_kit = Inferno::Repositories::TestKits.new.local_test_kit
80
+ if local_test_kit.present?
81
+ base = Inferno::Application['base_path'].present? ? "/#{Inferno::Application['base_path']}" : ''
82
+ [301, { 'Location' => "#{base}/#{local_test_kit.url_fragment}" }, []]
83
+ else
84
+ CLIENT_PAGE_RESPONSE.call(env)
85
+ end
86
+ }
73
87
  get '/jwks.json', to: lambda { |_env|
74
88
  [200, { 'Content-Type' => 'application/json' }, [Inferno::JWKS.jwks_json]]
75
89
  }, as: :jwks
@@ -87,7 +101,20 @@ module Inferno
87
101
 
88
102
  Inferno::Repositories::TestSuites.all.map { |suite| "/#{suite.id}" }.each do |suite_path|
89
103
  Application['logger'].info("Registering suite route: #{suite_path}")
90
- get suite_path, to: CLIENT_PAGE_RESPONSE
104
+ get suite_path, to: lambda { |env|
105
+ test_kit = Inferno::Repositories::TestKits.new.test_kit_for_suite(suite_path.delete_prefix('/'))
106
+ if test_kit.present?
107
+ [200, { 'Content-Type' => 'text/html' }, [test_kit_template.result_with_hash(test_kit:)]]
108
+ else
109
+ CLIENT_PAGE_RESPONSE.call(env)
110
+ end
111
+ }
112
+ end
113
+
114
+ Inferno::Repositories::TestKits.all.each do |test_kit|
115
+ Application['logger'].info("Registering test kit route: /#{test_kit.url_fragment}")
116
+ get "/#{test_kit.url_fragment}",
117
+ to: ->(_env) { [200, { 'Content-Type' => 'text/html' }, [test_kit_template.result_with_hash(test_kit:)]] }
91
118
  end
92
119
 
93
120
  get '/test_sessions/:id', to: Inferno::Web::Controllers::TestSessions::ClientShow, as: :client_session_show
@@ -0,0 +1,17 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class RequirementsFilteringExtractor < Blueprinter::Extractor
5
+ def extract(_field_name, runnable, local_options, _options)
6
+ if local_options[:suite_requirement_ids].blank?
7
+ runnable.verifies_requirements
8
+ else
9
+ runnable.verifies_requirements.select do |requirement_id|
10
+ local_options[:suite_requirement_ids].include? requirement_id
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,6 @@
1
1
  require_relative 'hash_value_extractor'
2
2
  require_relative 'input'
3
+ require_relative 'requirements_filtering_extractor'
3
4
 
4
5
  module Inferno
5
6
  module Web
@@ -20,7 +21,7 @@ module Inferno
20
21
  field :input_instructions
21
22
  field :user_runnable?, name: :user_runnable
22
23
  field :optional?, name: :optional
23
- field :verifies_requirements, if: :field_present?
24
+ field :verifies_requirements, if: :field_present?, extractor: RequirementsFilteringExtractor
24
25
  end
25
26
  end
26
27
  end
@@ -1,3 +1,5 @@
1
+ require_relative 'hash_value_extractor'
2
+ require_relative 'requirements_filtering_extractor'
1
3
  require_relative 'test'
2
4
 
3
5
  module Inferno
@@ -21,18 +23,20 @@ module Inferno
21
23
  end
22
24
  field :test_groups do |group, options|
23
25
  suite_options = options[:suite_options]
24
- TestGroup.render_as_hash(group.groups(suite_options), suite_options:)
26
+ suite_requirement_ids = options[:suite_requirement_ids]
27
+ TestGroup.render_as_hash(group.groups(suite_options), suite_options:, suite_requirement_ids:)
25
28
  end
26
29
  field :tests do |group, options|
27
30
  suite_options = options[:suite_options]
28
- Test.render_as_hash(group.tests(suite_options), suite_options:)
31
+ suite_requirement_ids = options[:suite_requirement_ids]
32
+ Test.render_as_hash(group.tests(suite_options), suite_options:, suite_requirement_ids:)
29
33
  end
30
34
  field :inputs do |group, options|
31
35
  suite_options = options[:suite_options]
32
36
  Input.render_as_hash(group.available_inputs(suite_options).values)
33
37
  end
34
38
  field :output_definitions, name: :outputs, extractor: HashValueExtractor
35
- field :verifies_requirements, if: :field_present?
39
+ field :verifies_requirements, if: :field_present?, extractor: RequirementsFilteringExtractor
36
40
  end
37
41
  end
38
42
  end
@@ -10,8 +10,18 @@ module Inferno
10
10
  field :test_suite_id
11
11
  association :suite_options, blueprint: SuiteOption
12
12
 
13
- field :test_suite do |session, _options|
14
- TestSuite.render_as_hash(session.test_suite, view: :full, suite_options: session.suite_options)
13
+ field :test_suite do |test_session, _options|
14
+ suite_requirement_ids =
15
+ Inferno::Repositories::Requirements.new
16
+ .requirements_for_suite(test_session.test_suite_id, test_session.id)
17
+ .map(&:id)
18
+
19
+ TestSuite.render_as_hash(
20
+ test_session.test_suite,
21
+ view: :full,
22
+ suite_options: test_session.suite_options,
23
+ suite_requirement_ids:
24
+ )
15
25
  end
16
26
  end
17
27
  end
@@ -1,4 +1,5 @@
1
1
  require_relative 'preset'
2
+ require_relative 'requirements_filtering_extractor'
2
3
  require_relative 'requirement_set'
3
4
  require_relative 'suite_option'
4
5
  require_relative 'test_group'
@@ -22,6 +23,11 @@ module Inferno
22
23
  suite.test_count(options[:suite_options])
23
24
  end
24
25
 
26
+ field :inputs do |suite, options|
27
+ suite_options = options[:suite_options]
28
+ Input.render_as_hash(suite.available_inputs(suite_options).values)
29
+ end
30
+
25
31
  association :suite_options, blueprint: SuiteOption
26
32
  association :presets, view: :summary, blueprint: Preset
27
33
  end
@@ -31,13 +37,10 @@ module Inferno
31
37
 
32
38
  field :test_groups do |suite, options|
33
39
  suite_options = options[:suite_options]
34
- TestGroup.render_as_hash(suite.groups(suite_options), suite_options:)
40
+ suite_requirement_ids = options[:suite_requirement_ids]
41
+ TestGroup.render_as_hash(suite.groups(suite_options), suite_options:, suite_requirement_ids:)
35
42
  end
36
43
  field :configuration_messages
37
- field :inputs do |suite, options|
38
- suite_options = options[:suite_options]
39
- Input.render_as_hash(suite.available_inputs(suite_options).values)
40
- end
41
44
  field :requirement_sets, if: :field_present? do |suite, options|
42
45
  selected_options = options[:suite_options] || []
43
46
  requirement_sets = suite.requirement_sets.select do |requirement_set|
@@ -46,7 +49,7 @@ module Inferno
46
49
 
47
50
  RequirementSet.render_as_hash(requirement_sets)
48
51
  end
49
- field :verifies_requirements, if: :field_present?
52
+ field :verifies_requirements, if: :field_present?, extractor: RequirementsFilteringExtractor
50
53
  end
51
54
  end
52
55
  end