inferno_core 0.4.29 → 0.4.30

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: 71ffd4d8151e890a5a52cd087d5aeb222efcf27902c2ec01f78d898a08de7d9b
4
- data.tar.gz: afe5c2b4cf3603e54e4b085dc609f061d6e78bd929e1b4ee915294dcb0f87de6
3
+ metadata.gz: 4439e9a6fff9fbd72efd09c4a14342206c509151fc0b6782089bf991b1849442
4
+ data.tar.gz: f386dba398dbf37c48fd3864fa4fe21e89732abccf155c5a2002530f802c7a34
5
5
  SHA512:
6
- metadata.gz: e0caf2d09c500643311b393129a741a9bd8d3ee043d7b6e45c3cad5cd92eb50802642de5c3222bf62188d1ecbe48469c5b54cf2f3005f65548d544b8ac2f6d30
7
- data.tar.gz: bb530410e8303d6fc82132c0f8c3da0fc63987ac6ba48b2be1023d8021ed7350a5158d3941e5bc7090136986248bae9134a64fbf8c6432352bb98ae839abff91
6
+ metadata.gz: 062e5019bcd5b1ca6cf67ac9fe94719e4a9e82fe2e8243f57a928ab28df35e8d517e0b180e48f6e7c1a5555ab691009399fc7f8d509d2d02cbbe0c4cbae8a3a3
7
+ data.tar.gz: 6105c47597428f29714650ea36492892bd399bac93323178144d2ad9b52dcbf27e643d514d18de533ec7c76d63dc9c53128fab9282b50d5cf91ea069ddf2760b
@@ -1,6 +1,7 @@
1
1
  require 'thor'
2
2
  require 'bundler'
3
3
  require_relative '../../utils/named_thor_actions'
4
+ require_relative '../../utils/ig_downloader'
4
5
  require_relative '../../version'
5
6
 
6
7
  module Inferno
@@ -8,17 +9,27 @@ module Inferno
8
9
  class New < Thor::Group
9
10
  include Thor::Actions
10
11
  include Inferno::Utils::NamedThorActions
12
+ include Inferno::Utils::IgDownloader
11
13
 
12
14
  desc <<~HELP
13
15
  Generate a new Inferno test kit for FHIR software testing
14
16
 
15
17
  Examples:
16
18
 
17
- `inferno new test_fhir_app`
18
- => generates an Inferno app
19
+ `inferno new my_test_kit`
20
+ => generates an Inferno test kit
19
21
 
20
- `inferno new test_my_ig -a MyName`
21
- => generates Inferno app and specifies MyName as gemspec author
22
+ `inferno new test-us-core -i hl7.fhir.us.core@6.1.0`
23
+ => generates Inferno test kit with US Core 6.1.0 implementation guide
24
+
25
+ `inferno new TestMatching -i https://build.fhir.org/ig/HL7/fhir-identity-matching-ig/`
26
+ => generates Inferno test kit with an implementation guide from its continuous web build
27
+
28
+ `inferno new test-my-ig -a "My Name" -i file:///absolute/path/to/my/ig/package.tgz`
29
+ => generates Inferno test kit with a local IG and specifies My Name as gem author
30
+
31
+ `inferno new test_my_igs -a "My Name" -a "Another Name" -i file:///my/first/package.tgz -i hl7.fhir.us.core@6.1.0`
32
+ => generates Inferno test kit with multiple IGs and multiple authors
22
33
 
23
34
  https://inferno-framework.github.io/index.html
24
35
  HELP
@@ -45,15 +56,23 @@ module Inferno
45
56
  type: :boolean,
46
57
  aliases: '-b',
47
58
  default: false,
48
- desc: 'Do not run bundle install'
59
+ desc: 'Do not run bundle install or inferno migrate'
60
+ class_option :implementation_guide,
61
+ type: :string,
62
+ aliases: '-i',
63
+ repeatable: true,
64
+ desc: 'Load an Implementation Guide by FHIR Registry name, URL, or absolute path'
49
65
 
50
66
  add_runtime_options!
51
67
 
52
- def create_app
68
+ def create_test_kit
53
69
  directory('.', root_name, { mode: :preserve, recursive: true, verbose: !options['quiet'] })
54
70
 
55
- bundle_install
56
- inferno_migrate
71
+ inside(root_name) do
72
+ bundle_install
73
+ inferno_migrate
74
+ load_igs
75
+ end
57
76
 
58
77
  say_unless_quiet "Created #{root_name} Inferno test kit!", :green
59
78
 
@@ -65,10 +84,6 @@ module Inferno
65
84
 
66
85
  private
67
86
 
68
- def ig_path
69
- File.join('lib', library_name, 'igs')
70
- end
71
-
72
87
  def authors
73
88
  options['author'].presence || [default_author]
74
89
  end
@@ -80,18 +95,27 @@ module Inferno
80
95
  def bundle_install
81
96
  return if options['skip_bundle']
82
97
 
83
- inside(root_name) do
84
- Bundler.with_unbundled_env do
85
- run 'bundle install', verbose: !options['quiet'], capture: options['quiet']
86
- end
98
+ Bundler.with_unbundled_env do
99
+ run 'bundle install', verbose: !options['quiet'], capture: options['quiet']
87
100
  end
88
101
  end
89
102
 
90
103
  def inferno_migrate
91
104
  return if options['skip_bundle']
92
105
 
93
- inside(root_name) do
94
- run 'bundle exec inferno migrate', verbose: !options['quiet'], capture: options['quiet']
106
+ run 'bundle exec inferno migrate', verbose: !options['quiet'], capture: options['quiet']
107
+ end
108
+
109
+ def load_igs
110
+ config = { verbose: !options['quiet'] }
111
+ options['implementation_guide']&.each_with_index do |ig, idx|
112
+ uri = options['implementation_guide'].length == 1 ? load_ig(ig, nil, config) : load_ig(ig, idx, config)
113
+ say_unless_quiet "Downloaded IG from #{uri}"
114
+ rescue OpenURI::HTTPError => e
115
+ say_unless_quiet "Failed to install implementation guide #{ig}", :red
116
+ say_unless_quiet e.message, :red
117
+ rescue StandardError => e
118
+ say_unless_quiet e.message, :red
95
119
  end
96
120
  end
97
121
 
@@ -0,0 +1,14 @@
1
+ Sequel.migration do
2
+ change do
3
+ create_table :validator_sessions do
4
+ column :id, String, primary_key: true, null: false, size: 36
5
+ column :validator_session_id, String, null: false, size: 255
6
+ column :test_suite_id, String, null: false, size: 255
7
+ column :validator_name, String, null: false, size: 255
8
+ column :suite_options, String, text: true
9
+ column :last_accessed, DateTime, null: false
10
+ index [:validator_session_id], unique: true
11
+ index [:test_suite_id, :validator_name, :suite_options], unique: true
12
+ end
13
+ end
14
+ end
@@ -23,6 +23,20 @@ Sequel.migration do
23
23
  primary_key [:id]
24
24
  end
25
25
 
26
+ create_table(:validator_sessions, :ignore_index_errors=>true) do
27
+ String :id, :size=>36, :null=>false
28
+ String :validator_session_id, :size=>255, :null=>false
29
+ String :test_suite_id, :size=>255, :null=>false
30
+ String :validator_name, :size=>255, :null=>false
31
+ String :suite_options, :text=>true
32
+ DateTime :last_accessed, :null=>false
33
+
34
+ primary_key [:id]
35
+
36
+ index [:test_suite_id, :validator_name, :suite_options], :unique=>true
37
+ index [:validator_session_id], :unique=>true
38
+ end
39
+
26
40
  create_table(:session_data, :ignore_index_errors=>true) do
27
41
  String :id, :size=>255, :null=>false
28
42
  foreign_key :test_session_id, :test_sessions, :type=>String, :size=>36, :null=>false, :key=>[:id]
@@ -90,7 +90,7 @@ module Inferno
90
90
 
91
91
  # @private
92
92
  def method_missing(name, *args, &)
93
- return runnable.call(name, *args, &) if runnable.respond_to? name
93
+ return runnable.send(name, *args, &) if runnable.respond_to? name
94
94
 
95
95
  super
96
96
  end
@@ -27,10 +27,12 @@ module Inferno
27
27
 
28
28
  class Validator
29
29
  attr_reader :requirements
30
- attr_accessor :session_id
30
+ attr_accessor :session_id, :name, :test_suite_id
31
31
 
32
32
  # @private
33
- def initialize(requirements = nil, &)
33
+ def initialize(name = nil, test_suite_id = nil, requirements = nil, &)
34
+ @name = name
35
+ @test_suite_id = test_suite_id
34
36
  instance_eval(&)
35
37
  @requirements = requirements
36
38
  end
@@ -40,6 +42,10 @@ module Inferno
40
42
  ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')
41
43
  end
42
44
 
45
+ def validator_session_repo
46
+ @validator_session_repo ||= Inferno::Repositories::ValidatorSessions.new
47
+ end
48
+
43
49
  # Set the url of the validator service
44
50
  #
45
51
  # @param validator_url [String]
@@ -231,6 +237,10 @@ module Inferno
231
237
 
232
238
  # @private
233
239
  def wrap_resource_for_hl7_wrapper(resource, profile_url)
240
+ validator_session_id =
241
+ validator_session_repo.find_validator_session_id(test_suite_id,
242
+ name.to_s, requirements)
243
+ @session_id = validator_session_id if validator_session_id
234
244
  wrapped_resource = {
235
245
  cliContext: {
236
246
  **cli_context.definition,
@@ -269,8 +279,11 @@ module Inferno
269
279
  # @private
270
280
  def operation_outcome_from_hl7_wrapped_response(response)
271
281
  res = JSON.parse(response)
272
-
273
- @session_id = res['sessionId']
282
+ if res['sessionId'] != @session_id
283
+ validator_session_repo.save(test_suite_id:, validator_session_id: res['sessionId'],
284
+ validator_name: name.to_s, suite_options: requirements)
285
+ @session_id = res['sessionId']
286
+ end
274
287
 
275
288
  # assume for now that one resource -> one request
276
289
  issues = res['outcomes'][0]['issues']&.map do |i|
@@ -287,7 +300,7 @@ module Inferno
287
300
  else
288
301
  runnable.add_message('error', "Validator Response: HTTP #{response.status}\n#{response.body}")
289
302
  raise Inferno::Exceptions::ErrorInValidatorException,
290
- 'Validator response was an unexpected format. '\
303
+ 'Validator response was an unexpected format. ' \
291
304
  'Review Messages tab or validator service logs for more information.'
292
305
  end
293
306
  end
@@ -300,7 +313,8 @@ module Inferno
300
313
  CLICONTEXT_DEFAULTS = {
301
314
  sv: '4.0.1',
302
315
  doNative: false,
303
- extensions: ['any']
316
+ extensions: ['any'],
317
+ disableDefaultResourceFetcher: true
304
318
  }.freeze
305
319
 
306
320
  # @private
@@ -353,7 +367,7 @@ module Inferno
353
367
  def fhir_resource_validator(name = :default, required_suite_options: nil, &block)
354
368
  current_validators = fhir_validators[name] || []
355
369
 
356
- new_validator = Inferno::DSL::FHIRResourceValidation::Validator.new(required_suite_options, &block)
370
+ new_validator = Inferno::DSL::FHIRResourceValidation::Validator.new(name, id, required_suite_options, &block)
357
371
 
358
372
  current_validators.reject! { |validator| validator.requirements == required_suite_options }
359
373
  current_validators << new_validator
@@ -45,7 +45,7 @@ module Inferno
45
45
 
46
46
  # @private
47
47
  def method_missing(name, *args, &)
48
- return runnable.call(name, *args, &) if runnable.respond_to? name
48
+ return runnable.send(name, *args, &) if runnable.respond_to? name
49
49
 
50
50
  super
51
51
  end
@@ -0,0 +1,22 @@
1
+ module Inferno
2
+ module Entities
3
+ class ValidatorSession < Entity
4
+ ATTRIBUTES = [
5
+ :id,
6
+ :created_at,
7
+ :updated_at,
8
+ :validator_session_id,
9
+ :test_suite_id,
10
+ :validator_name,
11
+ :suite_options,
12
+ :validator_index
13
+ ].freeze
14
+
15
+ include Inferno::Entities::Attributes
16
+
17
+ def initialize(params)
18
+ super(params, ATTRIBUTES)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -11,6 +11,7 @@ require_relative 'entities/test_group'
11
11
  require_relative 'entities/test_run'
12
12
  require_relative 'entities/test_session'
13
13
  require_relative 'entities/test_suite'
14
+ require_relative 'entities/validator_session'
14
15
 
15
16
  module Inferno
16
17
  # Entities are domain objects whose identity is based on an `id`. Entities
@@ -6,13 +6,13 @@ module Inferno
6
6
  def perform(suite_id, validator_name, validator_index)
7
7
  suite = Inferno::Repositories::TestSuites.new.find suite_id
8
8
  validator = suite.fhir_validators[validator_name.to_sym][validator_index]
9
-
10
9
  response_body = validator.validate(FHIR::Patient.new, 'http://hl7.org/fhir/StructureDefinition/Patient')
11
-
12
10
  if response_body.start_with? '{'
13
11
  res = JSON.parse(response_body)
14
12
  session_id = res['sessionId']
15
- # TODO: (FI-2311) store this session ID so it can be referenced as needed
13
+ session_repo = Inferno::Repositories::ValidatorSessions.new
14
+ session_repo.save(test_suite_id: suite_id, validator_session_id: session_id,
15
+ validator_name:, suite_options: validator.requirements)
16
16
  validator.session_id = session_id
17
17
  else
18
18
  Inferno::Application['logger'].error("InvokeValidatorSession - error from validator: #{response_body}")
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkinferno_web_app=self.webpackChunkinferno_web_app||[]).push([[175],{9175:(t,e,n)=>{n.r(e),n.d(e,{getCLS:()=>d,getFCP:()=>m,getFID:()=>v,getLCP:()=>h,getTTFB:()=>S});var i,a,r=function(t){return{name:t,value:arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,delta:0,entries:[],id:"".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),isFinal:!1}},o=function(t,e){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var n=new PerformanceObserver((function(t){return t.getEntries().map(e)}));return n.observe({type:t,buffered:!0}),n}}catch(t){}},s=!1,u=!1,c=function(t){s=!t.persisted},p=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];u||(addEventListener("pagehide",c),addEventListener("beforeunload",(function(){})),u=!0),addEventListener("visibilitychange",(function(e){var n=e.timeStamp;"hidden"===document.visibilityState&&t({timeStamp:n,isUnloading:s})}),{capture:!0,once:e})},l=function(t,e,n,i){var a;return function(){n&&e.isFinal&&n.disconnect(),e.value>=0&&(i||e.isFinal||"hidden"===document.visibilityState)&&(e.delta=e.value-(a||0),(e.delta||e.isFinal||void 0===a)&&(t(e),a=e.value))}},d=function(t){var e,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=r("CLS",0),a=function(t){t.hadRecentInput||(i.value+=t.value,i.entries.push(t),e())},s=o("layout-shift",a);s&&(e=l(t,i,s,n),p((function(t){var n=t.isUnloading;s.takeRecords().map(a),n&&(i.isFinal=!0),e()})))},f=function(){return void 0===i&&(i="hidden"===document.visibilityState?0:1/0,p((function(t){var e=t.timeStamp;return i=e}),!0)),{get timeStamp(){return i}}},m=function(t){var e,n=r("FCP"),i=f(),a=o("paint",(function(t){"first-contentful-paint"===t.name&&t.startTime<i.timeStamp&&(n.value=t.startTime,n.isFinal=!0,n.entries.push(t),e())}));a&&(e=l(t,n,a))},v=function(t){var e=r("FID"),n=f(),i=function(t){t.startTime<n.timeStamp&&(e.value=t.processingStart-t.startTime,e.entries.push(t),e.isFinal=!0,s())},a=o("first-input",i),s=l(t,e,a);a?p((function(){a.takeRecords().map(i),a.disconnect()}),!0):window.perfMetrics&&window.perfMetrics.onFirstInputDelay&&window.perfMetrics.onFirstInputDelay((function(t,i){i.timeStamp<n.timeStamp&&(e.value=t,e.isFinal=!0,e.entries=[{entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+t}],s())}))},g=function(){return a||(a=new Promise((function(t){return["scroll","keydown","pointerdown"].map((function(e){addEventListener(e,t,{once:!0,passive:!0,capture:!0})}))}))),a},h=function(t){var e,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=r("LCP"),a=f(),s=function(t){var n=t.startTime;n<a.timeStamp?(i.value=n,i.entries.push(t)):i.isFinal=!0,e()},u=o("largest-contentful-paint",s);if(u){e=l(t,i,u,n);var c=function(){i.isFinal||(u.takeRecords().map(s),i.isFinal=!0,e())};g().then(c),p(c,!0)}},S=function(t){var e,n=r("TTFB");e=function(){try{var e=performance.getEntriesByType("navigation")[0]||function(){var t=performance.timing,e={entryType:"navigation",startTime:0};for(var n in t)"navigationStart"!==n&&"toJSON"!==n&&(e[n]=Math.max(t[n]-t.navigationStart,0));return e}();n.value=n.delta=e.responseStart,n.entries=[e],n.isFinal=!0,t(n)}catch(t){}},"complete"===document.readyState?setTimeout(e,0):addEventListener("pageshow",e)}}}]);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main.js": "/public/bundle.js",
3
- "217.bundle.js": "/public/217.bundle.js",
3
+ "175.bundle.js": "/public/175.bundle.js",
4
4
  "inferno_logo.png": "/public/0e0b993fd6ff351f435ff1c2938daf2d.png",
5
5
  "inferno_icon.png": "/public/a5cd39450ab0336db73c5e57228b649d.png"
6
6
  }