inferno_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/bin/inferno-console +8 -0
  4. data/lib/inferno.rb +15 -0
  5. data/lib/inferno/apps/web/application.rb +12 -0
  6. data/lib/inferno/apps/web/controllers/controller.rb +34 -0
  7. data/lib/inferno/apps/web/controllers/requests/show.rb +16 -0
  8. data/lib/inferno/apps/web/controllers/test_runs/create.rb +39 -0
  9. data/lib/inferno/apps/web/controllers/test_runs/results/index.rb +18 -0
  10. data/lib/inferno/apps/web/controllers/test_runs/show.rb +16 -0
  11. data/lib/inferno/apps/web/controllers/test_sessions/create.rb +26 -0
  12. data/lib/inferno/apps/web/controllers/test_sessions/results/index.rb +17 -0
  13. data/lib/inferno/apps/web/controllers/test_sessions/show.rb +16 -0
  14. data/lib/inferno/apps/web/controllers/test_suites/index.rb +13 -0
  15. data/lib/inferno/apps/web/controllers/test_suites/show.rb +16 -0
  16. data/lib/inferno/apps/web/router.rb +27 -0
  17. data/lib/inferno/apps/web/serializers/header.rb +12 -0
  18. data/lib/inferno/apps/web/serializers/input.rb +16 -0
  19. data/lib/inferno/apps/web/serializers/message.rb +10 -0
  20. data/lib/inferno/apps/web/serializers/request.rb +26 -0
  21. data/lib/inferno/apps/web/serializers/result.rb +21 -0
  22. data/lib/inferno/apps/web/serializers/serializer.rb +16 -0
  23. data/lib/inferno/apps/web/serializers/test.rb +17 -0
  24. data/lib/inferno/apps/web/serializers/test_group.rb +23 -0
  25. data/lib/inferno/apps/web/serializers/test_run.rb +19 -0
  26. data/lib/inferno/apps/web/serializers/test_session.rb +17 -0
  27. data/lib/inferno/apps/web/serializers/test_suite.rb +18 -0
  28. data/lib/inferno/config/application.rb +22 -0
  29. data/lib/inferno/config/boot.rb +5 -0
  30. data/lib/inferno/config/boot/db.rb +23 -0
  31. data/lib/inferno/config/boot/logging.rb +16 -0
  32. data/lib/inferno/config/boot/suites.rb +27 -0
  33. data/lib/inferno/config/boot/web.rb +17 -0
  34. data/lib/inferno/db/migrations/001_create_initial_structure.rb +165 -0
  35. data/lib/inferno/dsl.rb +35 -0
  36. data/lib/inferno/dsl/assertions.rb +93 -0
  37. data/lib/inferno/dsl/fhir_client.rb +152 -0
  38. data/lib/inferno/dsl/fhir_client_builder.rb +56 -0
  39. data/lib/inferno/dsl/fhir_manipulation.rb +25 -0
  40. data/lib/inferno/dsl/fhir_validation.rb +111 -0
  41. data/lib/inferno/dsl/http_client.rb +122 -0
  42. data/lib/inferno/dsl/http_client_builder.rb +54 -0
  43. data/lib/inferno/dsl/request_storage.rb +101 -0
  44. data/lib/inferno/dsl/results.rb +54 -0
  45. data/lib/inferno/dsl/runnable.rb +250 -0
  46. data/lib/inferno/entities.rb +19 -0
  47. data/lib/inferno/entities/attributes.rb +9 -0
  48. data/lib/inferno/entities/entity.rb +15 -0
  49. data/lib/inferno/entities/header.rb +42 -0
  50. data/lib/inferno/entities/message.rb +22 -0
  51. data/lib/inferno/entities/request.rb +166 -0
  52. data/lib/inferno/entities/result.rb +49 -0
  53. data/lib/inferno/entities/test.rb +173 -0
  54. data/lib/inferno/entities/test_group.rb +87 -0
  55. data/lib/inferno/entities/test_input.rb +20 -0
  56. data/lib/inferno/entities/test_run.rb +63 -0
  57. data/lib/inferno/entities/test_session.rb +26 -0
  58. data/lib/inferno/entities/test_suite.rb +73 -0
  59. data/lib/inferno/exceptions.rb +42 -0
  60. data/lib/inferno/public/217.bundle.js +1 -0
  61. data/lib/inferno/public/assets.json +6 -0
  62. data/lib/inferno/public/bundle.js +2 -0
  63. data/lib/inferno/public/bundle.js.LICENSE.txt +65 -0
  64. data/lib/inferno/public/e09b16f5cb645eb05f90c8f38f3409fb.png +0 -0
  65. data/lib/inferno/public/favicon.ico +0 -0
  66. data/lib/inferno/public/logo192.png +0 -0
  67. data/lib/inferno/public/logo512.png +0 -0
  68. data/lib/inferno/repositories.rb +27 -0
  69. data/lib/inferno/repositories/headers.rb +22 -0
  70. data/lib/inferno/repositories/in_memory_repository.rb +41 -0
  71. data/lib/inferno/repositories/messages.rb +35 -0
  72. data/lib/inferno/repositories/repository.rb +106 -0
  73. data/lib/inferno/repositories/requests.rb +89 -0
  74. data/lib/inferno/repositories/results.rb +72 -0
  75. data/lib/inferno/repositories/test_groups.rb +9 -0
  76. data/lib/inferno/repositories/test_runs.rb +46 -0
  77. data/lib/inferno/repositories/test_sessions.rb +56 -0
  78. data/lib/inferno/repositories/test_suites.rb +9 -0
  79. data/lib/inferno/repositories/tests.rb +9 -0
  80. data/lib/inferno/repositories/validate_runnable_reference.rb +42 -0
  81. data/lib/inferno/spec_support.rb +9 -0
  82. data/lib/inferno/test_runner.rb +81 -0
  83. data/lib/inferno/utils/middleware/request_logger.rb +55 -0
  84. data/lib/inferno/version.rb +3 -0
  85. data/spec/support/factory_bot.rb +21 -0
  86. metadata +514 -0
@@ -0,0 +1,13 @@
1
+ module Inferno
2
+ module Web
3
+ module Controllers
4
+ module TestSuites
5
+ class Index < Controller
6
+ def call(_params)
7
+ self.body = serialize(repo.all, view: :summary)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Inferno
2
+ module Web
3
+ module Controllers
4
+ module TestSuites
5
+ class Show < Controller
6
+ def call(params)
7
+ test_suite = repo.find(params[:id])
8
+ halt 404 if test_suite.nil?
9
+
10
+ self.body = serialize(test_suite, view: :full)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require 'erb'
2
+
3
+ module Inferno
4
+ module Web
5
+ client_page = ERB.new(File.read(File.join(Inferno::Application.root, 'lib', 'inferno', 'apps', 'web',
6
+ 'index.html.erb'))).result
7
+
8
+ Router = Hanami::Router.new(namespace: Inferno::Web::Controllers) do
9
+ namespace 'api' do
10
+ resources 'test_runs', only: [:create, :show] do
11
+ resources 'results', only: [:index]
12
+ end
13
+
14
+ resources 'test_sessions', only: [:create, :show] do
15
+ resources 'results', only: [:index]
16
+ end
17
+
18
+ resources 'test_suites', only: [:index, :show]
19
+
20
+ resources 'requests', only: [:show]
21
+ end
22
+
23
+ get '/', to: ->(_env) { [200, {}, [client_page]] }
24
+ get '/test_sessions/:id', to: ->(_env) { [200, {}, [client_page]] }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'serializer'
2
+
3
+ module Inferno
4
+ module Web
5
+ module Serializers
6
+ class Header < Serializer
7
+ field :name
8
+ field :value
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require_relative 'serializer'
2
+
3
+ module Inferno
4
+ module Web
5
+ module Serializers
6
+ class Input < Serializer
7
+ identifier :name
8
+
9
+ field :label, if: :field_present?
10
+ field :description, if: :field_present?
11
+ field :required, if: :field_present?
12
+ field :value, if: :field_present?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class Message < Serializer
5
+ field :type
6
+ field :message
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class Request < Serializer
5
+ view :summary do
6
+ field :id
7
+ field :created_at, name: :timestamp
8
+ field :verb
9
+ field :url
10
+ field :direction
11
+ field :status
12
+ end
13
+
14
+ view :full do
15
+ include_view :summary
16
+
17
+ field :created_at, name: :timestamp
18
+ association :request_headers, blueprint: Header
19
+ association :response_headers, blueprint: Header
20
+ field :request_body
21
+ field :response_body
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class Result < Serializer
5
+ identifier :id
6
+
7
+ field :test_id, if: :field_present?
8
+ field :test_group_id, if: :field_present?
9
+ field :test_suite_id, if: :field_present?
10
+
11
+ field :test_run_id
12
+ field :test_session_id
13
+ field :result
14
+ field :result_message, if: :field_present?
15
+
16
+ association :messages, blueprint: Message, if: :field_present?
17
+ association :requests, blueprint: Request, view: :summary, if: :field_present?
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class Serializer < Blueprinter::Base
5
+ def self.field_present?(field_name, result, options)
6
+ name = options[:name] || field_name
7
+ if result.respond_to?(:[])
8
+ result[name].present?
9
+ else
10
+ result.send(name).present?
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class Test < Serializer
5
+ identifier :id
6
+ field :title
7
+ field :inputs do |test, _options|
8
+ test.inputs.map { |input| { name: input } }
9
+ end
10
+ field :outputs do |test, _options|
11
+ test.outputs.map { |output| { name: output } }
12
+ end
13
+ field :description
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class TestGroup < Serializer
5
+ identifier :id
6
+
7
+ # TODO: fill out test group
8
+ field :title
9
+ field :description
10
+ # field :run_as_group
11
+
12
+ association :groups, name: :test_groups, blueprint: TestGroup
13
+ association :tests, blueprint: Test
14
+ field :inputs do |group, _options|
15
+ group.inputs.map { |input| { name: input } }
16
+ end
17
+ field :outputs do |group, _options|
18
+ group.outputs.map { |input| { name: input } }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class TestRun < Serializer
5
+ identifier :id
6
+ field :test_session_id
7
+
8
+ field :status
9
+
10
+ field :test_group_id, if: :field_present?
11
+ field :test_suite_id, if: :field_present?
12
+ field :test_id, if: :field_present?
13
+
14
+ association :results, blueprint: Result
15
+ association :inputs, blueprint: Input
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'test_suite'
2
+
3
+ module Inferno
4
+ module Web
5
+ module Serializers
6
+ class TestSession < Serializer
7
+ identifier :id
8
+
9
+ field :test_suite_id
10
+
11
+ association :test_suite, blueprint: TestSuite, view: :full
12
+ # association :test_run, blueprint: TestRun
13
+ # association :results, blueprint: Result
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Inferno
2
+ module Web
3
+ module Serializers
4
+ class TestSuite < Serializer
5
+ view :summary do
6
+ identifier :id
7
+ field :title
8
+ field :description
9
+ end
10
+
11
+ view :full do
12
+ include_view :summary
13
+ association :groups, name: :test_groups, blueprint: TestGroup
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'boot'
2
+
3
+ module Inferno
4
+ class Application < Dry::System::Container
5
+ ::Inferno::Import = injector
6
+
7
+ use :env, inferrer: -> { ENV.fetch('APP_ENV', :development).to_sym }
8
+
9
+ configure do |config|
10
+ config.root = File.expand_path('../../..', __dir__)
11
+ config.default_namespace = 'inferno'
12
+ config.system_dir = File.join('lib', 'inferno', 'config')
13
+ config.bootable_dirs = [File.join('lib', 'inferno', 'config', 'boot')]
14
+
15
+ config.auto_register = 'lib'
16
+ end
17
+
18
+ Application.register('js_host', ENV.fetch('JS_HOST', ''))
19
+
20
+ load_paths!('lib')
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ ENV['APP_ENV'] ||= 'development'
2
+
3
+ root_path = Dir.pwd
4
+
5
+ Dotenv.load(File.join(root_path, '.env'), File.join(root_path, ".env.#{ENV['APP_ENV']}"))
@@ -0,0 +1,23 @@
1
+ Inferno::Application.boot(:db) do
2
+ init do
3
+ use :logging
4
+
5
+ require 'yaml'
6
+
7
+ Sequel::Model.plugin :json_serializer
8
+
9
+ config_path = File.expand_path('database.yml', File.join(Dir.pwd, 'config'))
10
+ config = YAML.load_file(config_path)[ENV['APP_ENV']]
11
+ .merge(logger: Inferno::Application['logger'])
12
+ connection = Sequel.connect(config)
13
+
14
+ register('db.config', config)
15
+ register('db.connection', connection)
16
+ end
17
+
18
+ start do
19
+ Sequel.extension :migration
20
+ migration_path = File.join(Inferno::Application.root, 'lib', 'inferno', 'db', 'migrations')
21
+ Sequel::Migrator.run(Inferno::Application['db.connection'], migration_path)
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ Inferno::Application.boot(:logging) do
2
+ init do
3
+ logger =
4
+ if Inferno::Application.env == :test
5
+ log_file_directory = File.join(Dir.pwd, 'tmp')
6
+ FileUtils.mkdir_p(log_file_directory)
7
+ log_file_path = File.join(log_file_directory, 'test.log')
8
+ log_file = File.open(log_file_path, File::WRONLY | File::APPEND | File::CREAT)
9
+ Logger.new(log_file)
10
+ else
11
+ Logger.new($stdout)
12
+ end
13
+
14
+ register('logger', logger)
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ Inferno::Application.boot(:suites) do
2
+ init do
3
+ use :logging
4
+
5
+ files_to_load = Dir.glob(File.join(Dir.pwd, 'lib', '*.rb'))
6
+
7
+ if ENV['LOAD_DEV_SUITES'] == 'true'
8
+ files_to_load.concat Dir.glob(File.join(Inferno::Application.root, 'dev_suites', '**', '*.rb'))
9
+ end
10
+
11
+ if ENV['LOAD_UI_SUITES'] == 'true'
12
+ files_to_load.concat Dir.glob(File.join(Inferno::Application.root, 'ui_suites', '**', '*.rb'))
13
+ end
14
+
15
+ if ENV['APP_ENV'] == 'test'
16
+ files_to_load.concat Dir.glob(File.join(Inferno::Application.root, 'spec', 'fixtures', '**', '*.rb'))
17
+ end
18
+
19
+ files_to_load.map! { |path| File.realpath(path) }
20
+
21
+ files_to_load.each do |path|
22
+ require_relative path
23
+ end
24
+
25
+ ObjectSpace.each_object(TracePoint, &:disable)
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ Inferno::Application.boot(:web) do |_app|
2
+ init do
3
+ require 'blueprinter'
4
+ require 'hanami-router'
5
+ require 'hanami-controller'
6
+ require 'oj'
7
+
8
+ Hanami::Controller.configure do
9
+ default_request_format :json
10
+ default_response_format :json
11
+ end
12
+
13
+ Blueprinter.configure do |config|
14
+ config.generator = Oj
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,165 @@
1
+ Sequel.migration do
2
+ change do
3
+ #
4
+ # NOT NEEDED BECUASE THEY ARE DEFINED WITHIN TEST SUITE.
5
+ # MUST BE REFERENCED USING SOME KIND OF GLOBALLY UNIQUE KEY
6
+ # THAT IS REPRESENTED AS A STRING
7
+ #
8
+
9
+ # create_table :test_suites do
10
+ # end
11
+
12
+ # create_table :test_groups do
13
+ # end
14
+
15
+ # create_table :tests do
16
+ # end
17
+
18
+ # create_table :test_inputs do
19
+ # end
20
+
21
+ # create_table :test_outputs do
22
+ # end
23
+
24
+ # A way for the test to signal that it requires some kind of action by the
25
+ # app that is invoking the test (e.g. SMART Launch, perhaps mid-test manual verification)
26
+ # create_table :test_prompts do
27
+ # end
28
+
29
+ # For a given prompt, the tests specify what fields are associated (e.g redirect uri),
30
+ # Those get filled out and stored within the run
31
+ # create_table :test_prompt_field do
32
+ # end
33
+
34
+ create_table :test_sessions do
35
+ column :id, String, primary_key: true, null: false
36
+ column :test_suite_id, String
37
+
38
+ column :created_at, DateTime, null: false
39
+ column :updated_at, DateTime, null: false
40
+ end
41
+
42
+ create_table :test_runs do
43
+ column :id, String, primary_key: true, null: false
44
+ column :status, String
45
+ foreign_key :test_session_id, :test_sessions, index: true, type: String
46
+ index [:test_session_id, :status] # Searching by unfinished test runs seems like it will be a likely query
47
+
48
+ column :test_suite_id, String, index: true
49
+ column :test_group_id, String, index: true
50
+ column :test_id, String, index: true
51
+
52
+ column :created_at, DateTime, null: false
53
+ column :updated_at, DateTime, null: false
54
+ end
55
+
56
+ create_table :test_run_inputs do
57
+ column :id, String, primary_key: true, null: false
58
+ foreign_key :test_run_id, :test_runs, index: true, type: String
59
+ column :test_input_id, String
60
+ column :value, String
61
+
62
+ column :created_at, DateTime, null: false
63
+ column :updated_at, DateTime, null: false
64
+ end
65
+
66
+ create_table :results do
67
+ column :id, String, primary_key: true, null: false
68
+
69
+ foreign_key :test_run_id, :test_runs, index: true, type: String
70
+ foreign_key :test_session_id, :test_sessions, index: true, type: String
71
+
72
+ column :result, String
73
+ column :result_message, String
74
+
75
+ column :test_suite_id, String
76
+ column :test_group_id, String
77
+ column :test_id, String
78
+
79
+ column :created_at, DateTime, null: false
80
+ column :updated_at, DateTime, null: false
81
+ end
82
+
83
+ create_table :result_inputs do
84
+ column :id, String, primary_key: true, null: false
85
+ foreign_key :result_id, :results, index: true, type: String
86
+ column :test_input_id, String
87
+ column :value, String
88
+
89
+ column :created_at, DateTime, null: false
90
+ column :updated_at, DateTime, null: false
91
+ end
92
+
93
+ create_table :result_outputs do
94
+ column :id, String, primary_key: true, null: false
95
+ foreign_key :result_id, :results, index: true, type: String
96
+ column :test_output_id, String
97
+ column :value, String
98
+
99
+ column :created_at, DateTime, null: false
100
+ column :updated_at, DateTime, null: false
101
+ end
102
+
103
+ create_table :result_prompt_values do
104
+ column :id, String, primary_key: true, null: false
105
+
106
+ foreign_key :result_id, :results, index: true, type: String
107
+
108
+ column :test_prompt_id, String, null: false
109
+ column :value, String, null: false
110
+
111
+ column :created_at, DateTime, null: false
112
+ column :updated_at, DateTime, null: false
113
+ end
114
+
115
+ create_table :messages do
116
+ primary_key :index
117
+ column :id, String, index: true, null: false
118
+ foreign_key :result_id, :results, index: true, type: String
119
+ column :type, String
120
+ column :message, String
121
+
122
+ column :created_at, DateTime, null: false
123
+ column :updated_at, DateTime, null: false
124
+ end
125
+
126
+ create_table :requests do
127
+ primary_key :index
128
+ column :id, String, index: true, null: false
129
+ column :verb, String
130
+ column :url, String
131
+ column :direction, String
132
+ column :status, Integer
133
+ column :name, String
134
+ column :request_body, String, text: true
135
+ column :response_body, String, text: true # It would be nice if we could store this on disk
136
+
137
+ # Requires requests to be a part of tests now.
138
+ foreign_key :result_id, :results, index: true, type: String
139
+ foreign_key :test_session_id, :test_sessions, index: true, type: String
140
+ add_index [:test_session_id, :name], concurrently: true
141
+
142
+ column :created_at, DateTime, null: false
143
+ column :updated_at, DateTime, null: false
144
+ end
145
+
146
+ create_table :headers do
147
+ column :id, String, index: true, null: false
148
+ foreign_key :request_id, :requests, index: true, type: String
149
+ column :type, String # request / response
150
+ column :name, String
151
+ column :value, String
152
+
153
+ column :created_at, DateTime, null: false
154
+ column :updated_at, DateTime, null: false
155
+ end
156
+
157
+ create_table :session_data do
158
+ column :id, String, index: true, null: false
159
+ foreign_key :test_session_id, :test_sessions, index: true, type: String
160
+ column :name, String
161
+ column :value, String
162
+ index [:test_session_id, :name]
163
+ end
164
+ end
165
+ end