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 +4 -4
- data/lib/inferno/apps/cli/new.rb +42 -18
- data/lib/inferno/db/migrations/010_add_validator_sessions.rb +14 -0
- data/lib/inferno/db/schema.rb +14 -0
- data/lib/inferno/dsl/fhir_client_builder.rb +1 -1
- data/lib/inferno/dsl/fhir_resource_validation.rb +21 -7
- data/lib/inferno/dsl/http_client_builder.rb +1 -1
- data/lib/inferno/entities/validator_session.rb +22 -0
- data/lib/inferno/entities.rb +1 -0
- data/lib/inferno/jobs/invoke_validator_session.rb +3 -3
- data/lib/inferno/public/175.bundle.js +1 -0
- data/lib/inferno/public/assets.json +1 -1
- data/lib/inferno/public/bundle.js +21 -21
- data/lib/inferno/public/bundle.js.LICENSE.txt +17 -5
- data/lib/inferno/repositories/validator_sessions.rb +58 -0
- data/lib/inferno/repositories.rb +1 -0
- data/lib/inferno/utils/ig_downloader.rb +57 -0
- data/lib/inferno/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4439e9a6fff9fbd72efd09c4a14342206c509151fc0b6782089bf991b1849442
|
4
|
+
data.tar.gz: f386dba398dbf37c48fd3864fa4fe21e89732abccf155c5a2002530f802c7a34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 062e5019bcd5b1ca6cf67ac9fe94719e4a9e82fe2e8243f57a928ab28df35e8d517e0b180e48f6e7c1a5555ab691009399fc7f8d509d2d02cbbe0c4cbae8a3a3
|
7
|
+
data.tar.gz: 6105c47597428f29714650ea36492892bd399bac93323178144d2ad9b52dcbf27e643d514d18de533ec7c76d63dc9c53128fab9282b50d5cf91ea069ddf2760b
|
data/lib/inferno/apps/cli/new.rb
CHANGED
@@ -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
|
18
|
-
=> generates an Inferno
|
19
|
+
`inferno new my_test_kit`
|
20
|
+
=> generates an Inferno test kit
|
19
21
|
|
20
|
-
`inferno new
|
21
|
-
=> generates Inferno
|
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
|
68
|
+
def create_test_kit
|
53
69
|
directory('.', root_name, { mode: :preserve, recursive: true, verbose: !options['quiet'] })
|
54
70
|
|
55
|
-
|
56
|
-
|
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
|
-
|
84
|
-
|
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
|
-
|
94
|
-
|
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
|
data/lib/inferno/db/schema.rb
CHANGED
@@ -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]
|
@@ -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
|
-
|
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
|
@@ -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
|
data/lib/inferno/entities.rb
CHANGED
@@ -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
|
-
|
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)}}}]);
|