inferno_core 0.0.8.pre2 → 0.1.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno/apps/web/controllers/test_runs/create.rb +2 -1
  3. data/lib/inferno/apps/web/serializers/result.rb +1 -0
  4. data/lib/inferno/apps/web/serializers/test.rb +4 -0
  5. data/lib/inferno/apps/web/serializers/test_group.rb +4 -0
  6. data/lib/inferno/apps/web/serializers/test_suite.rb +3 -0
  7. data/lib/inferno/db/migrations/001_create_initial_structure.rb +54 -53
  8. data/lib/inferno/db/migrations/002_add_wait_support.rb +2 -2
  9. data/lib/inferno/db/migrations/003_update_session_data.rb +7 -7
  10. data/lib/inferno/db/migrations/004_add_request_results_table.rb +2 -2
  11. data/lib/inferno/db/migrations/005_add_updated_at_index_to_results.rb +1 -1
  12. data/lib/inferno/db/migrations/006_remove_unused_tables.rb +38 -0
  13. data/lib/inferno/db/schema.rb +17 -43
  14. data/lib/inferno/dsl/configurable.rb +12 -5
  15. data/lib/inferno/dsl/fhir_client.rb +58 -6
  16. data/lib/inferno/dsl/fhir_client_builder.rb +16 -0
  17. data/lib/inferno/dsl/http_client.rb +62 -0
  18. data/lib/inferno/dsl/oauth_credentials.rb +119 -0
  19. data/lib/inferno/dsl/runnable.rb +87 -9
  20. data/lib/inferno/entities/has_runnable.rb +26 -0
  21. data/lib/inferno/entities/request.rb +7 -1
  22. data/lib/inferno/entities/result.rb +8 -4
  23. data/lib/inferno/entities/test_group.rb +4 -6
  24. data/lib/inferno/entities/test_run.rb +1 -18
  25. data/lib/inferno/entities/test_suite.rb +3 -4
  26. data/lib/inferno/entities.rb +1 -0
  27. data/lib/inferno/exceptions.rb +19 -0
  28. data/lib/inferno/ext/fhir_client.rb +13 -0
  29. data/lib/inferno/public/bundle.js +15 -15
  30. data/lib/inferno/repositories/session_data.rb +40 -6
  31. data/lib/inferno/result_summarizer.rb +40 -0
  32. data/lib/inferno/spec_support.rb +1 -1
  33. data/lib/inferno/test_runner.rb +13 -9
  34. data/lib/inferno/version.rb +1 -1
  35. data/spec/factories/request.rb +1 -1
  36. data/spec/factories/result.rb +2 -2
  37. data/spec/fixtures/basic_test_group.rb +1 -0
  38. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 323de6e32c25feac594840493d69222a2388bdabef39c36a5d378a1cfeb2b7cc
4
- data.tar.gz: d08c713be3303b146a40a6316765e017d76a4213e3981c6121fd502e7eb4e577
3
+ metadata.gz: 70e3295132f61902fb03d7dcfc6fd3f8593b9cdfb5dd5079a1ae7fe92d6c165c
4
+ data.tar.gz: a3d26fbdbb272907f5f244d90971a5496466419d4204201cc21762bf6939f7ff
5
5
  SHA512:
6
- metadata.gz: 1dfa395166fd30624510ff16f12a216b5580f60265bf8512391fd50d731c9bf7022aec60fa0527aa55e7de48d7fc38c16bb2b4777666c7947c632f6ce4dc2c6a
7
- data.tar.gz: 207262300f159a2eb75bca71f95c8550169dc19488e826d4a2e97556d3c9722ce9bdf97436c9f862cddde5ab62b9d2be4895703c02da5c8eac6cf24cdb4e4475
6
+ metadata.gz: 01cd288246ed891b29f77fd9cfeb57acd35e41fc894c164dba372e1317e3a2d3e8c0a59f3d1f5f62b528c457de0cde9aeb60b6c620387b42889121026570c803
7
+ data.tar.gz: dd3664cc7873ffc8a998a04409632a3a53424b964e189bd5b0918cc8d372a76cdc161e1b0515a54012b43b6f787b79f60b1d1d2b1511ee97187a28c66efcbd6f
@@ -33,7 +33,8 @@ module Inferno
33
33
  session_data_repo.save(
34
34
  test_session_id: test_session.id,
35
35
  name: input[:name],
36
- value: input[:value]
36
+ value: input[:value],
37
+ type: input[:type]
37
38
  )
38
39
  end
39
40
 
@@ -16,6 +16,7 @@ module Inferno
16
16
  field :result_message, if: :field_present?
17
17
  field :created_at
18
18
  field :updated_at
19
+ field :optional?, name: :optional
19
20
 
20
21
  field :outputs do |result, _options|
21
22
  result.output_json.present? ? JSON.parse(result.output_json) : []
@@ -4,10 +4,14 @@ module Inferno
4
4
  class Test < Serializer
5
5
  identifier :id
6
6
  field :title
7
+ field :short_title
7
8
  field :input_definitions, name: :inputs, extractor: HashValueExtractor, blueprint: Input
8
9
  field :output_definitions, name: :outputs, extractor: HashValueExtractor
9
10
  field :description
11
+ field :short_description
12
+ field :input_instructions
10
13
  field :user_runnable?, name: :user_runnable
14
+ field :optional?, name: :optional
11
15
  end
12
16
  end
13
17
  end
@@ -5,10 +5,14 @@ module Inferno
5
5
  identifier :id
6
6
 
7
7
  field :title
8
+ field :short_title
8
9
  field :description
10
+ field :short_description
11
+ field :input_instructions
9
12
  field :test_count
10
13
  field :run_as_group?, name: :run_as_group
11
14
  field :user_runnable?, name: :user_runnable
15
+ field :optional?, name: :optional
12
16
 
13
17
  association :groups, name: :test_groups, blueprint: TestGroup
14
18
  association :tests, blueprint: Test
@@ -5,7 +5,10 @@ module Inferno
5
5
  view :summary do
6
6
  identifier :id
7
7
  field :title
8
+ field :short_title
8
9
  field :description
10
+ field :short_description
11
+ field :input_instructions
9
12
  field :test_count
10
13
  end
11
14
 
@@ -11,81 +11,81 @@ Sequel.migration do
11
11
  # end
12
12
 
13
13
  create_table :test_sessions do
14
- column :id, String, primary_key: true, null: false
15
- column :test_suite_id, String
14
+ column :id, String, primary_key: true, null: false, size: 36
15
+ column :test_suite_id, String, size: 255
16
16
 
17
17
  column :created_at, DateTime, null: false
18
18
  column :updated_at, DateTime, null: false
19
19
  end
20
20
 
21
21
  create_table :test_runs do
22
- column :id, String, primary_key: true, null: false
23
- column :status, String
24
- foreign_key :test_session_id, :test_sessions, index: true, type: String
22
+ column :id, String, primary_key: true, null: false, size: 36
23
+ column :status, String, size: 255
24
+ foreign_key :test_session_id, :test_sessions, index: true, type: String, size: 36, key: [:id]
25
25
  index [:test_session_id, :status] # Searching by unfinished test runs seems like it will be a likely query
26
26
 
27
- column :test_suite_id, String, index: true
28
- column :test_group_id, String, index: true
29
- column :test_id, String, index: true
27
+ column :test_suite_id, String, index: true, size: 255
28
+ column :test_group_id, String, index: true, size: 255
29
+ column :test_id, String, index: true, size: 255
30
30
 
31
31
  column :created_at, DateTime, null: false
32
32
  column :updated_at, DateTime, null: false
33
33
  end
34
34
 
35
35
  create_table :test_run_inputs do
36
- column :id, String, primary_key: true, null: false
37
- foreign_key :test_run_id, :test_runs, index: true, type: String
38
- column :test_input_id, String
39
- column :value, String
36
+ column :id, String, primary_key: true, null: false, size: 36
37
+ foreign_key :test_run_id, :test_runs, index: true, type: String, key: [:id]
38
+ column :test_input_id, String, size: 255
39
+ column :value, String, text: true
40
40
 
41
41
  column :created_at, DateTime, null: false
42
42
  column :updated_at, DateTime, null: false
43
43
  end
44
44
 
45
45
  create_table :results do
46
- column :id, String, primary_key: true, null: false
46
+ column :id, String, primary_key: true, null: false, size: 36
47
47
 
48
- foreign_key :test_run_id, :test_runs, index: true, type: String
49
- foreign_key :test_session_id, :test_sessions, index: true, type: String
48
+ foreign_key :test_run_id, :test_runs, index: true, type: String, size: 36, key: [:id]
49
+ foreign_key :test_session_id, :test_sessions, index: true, type: String, size: 36, key: [:id]
50
50
 
51
- column :result, String
52
- column :result_message, String
51
+ column :result, String, size: 255
52
+ column :result_message, String, text: true
53
53
 
54
- column :test_suite_id, String
55
- column :test_group_id, String
56
- column :test_id, String
54
+ column :test_suite_id, String, size: 255
55
+ column :test_group_id, String, size: 255
56
+ column :test_id, String, size: 255
57
57
 
58
58
  column :created_at, DateTime, null: false
59
59
  column :updated_at, DateTime, null: false
60
60
  end
61
61
 
62
62
  create_table :result_inputs do
63
- column :id, String, primary_key: true, null: false
64
- foreign_key :result_id, :results, index: true, type: String
65
- column :test_input_id, String
66
- column :value, String
63
+ column :id, String, primary_key: true, null: false, size: 36
64
+ foreign_key :result_id, :results, index: true, type: String, size: 36, key: [:id]
65
+ column :test_input_id, String, size: 255
66
+ column :value, String, text: true
67
67
 
68
68
  column :created_at, DateTime, null: false
69
69
  column :updated_at, DateTime, null: false
70
70
  end
71
71
 
72
72
  create_table :result_outputs do
73
- column :id, String, primary_key: true, null: false
74
- foreign_key :result_id, :results, index: true, type: String
75
- column :test_output_id, String
76
- column :value, String
73
+ column :id, String, primary_key: true, null: false, size: 36
74
+ foreign_key :result_id, :results, index: true, type: String, size: 36, key: [:id]
75
+ column :test_output_id, String, size: 255
76
+ column :value, String, text: true
77
77
 
78
78
  column :created_at, DateTime, null: false
79
79
  column :updated_at, DateTime, null: false
80
80
  end
81
81
 
82
82
  create_table :result_prompt_values do
83
- column :id, String, primary_key: true, null: false
83
+ column :id, String, primary_key: true, null: false, size: 36
84
84
 
85
- foreign_key :result_id, :results, index: true, type: String
85
+ foreign_key :result_id, :results, index: true, type: String, size: 36, key: [:id]
86
86
 
87
- column :test_prompt_id, String, null: false
88
- column :value, String, null: false
87
+ column :test_prompt_id, String, null: false, size: 255
88
+ column :value, String, null: false, text: true
89
89
 
90
90
  column :created_at, DateTime, null: false
91
91
  column :updated_at, DateTime, null: false
@@ -93,10 +93,10 @@ Sequel.migration do
93
93
 
94
94
  create_table :messages do
95
95
  primary_key :index
96
- column :id, String, index: true, null: false
97
- foreign_key :result_id, :results, index: true, type: String
98
- column :type, String
99
- column :message, String
96
+ column :id, String, index: true, null: false, size: 36
97
+ foreign_key :result_id, :results, index: true, type: String, size: 36, key: [:id]
98
+ column :type, String, size: 255
99
+ column :message, String, text: true
100
100
 
101
101
  column :created_at, DateTime, null: false
102
102
  column :updated_at, DateTime, null: false
@@ -104,40 +104,41 @@ Sequel.migration do
104
104
 
105
105
  create_table :requests do
106
106
  primary_key :index
107
- column :id, String, index: true, null: false
108
- column :verb, String
109
- column :url, String
110
- column :direction, String
107
+ column :id, String, null: false, size: 36
108
+ column :verb, String, size: 255
109
+ column :url, String, text: true
110
+ column :direction, String, size: 255
111
111
  column :status, Integer
112
- column :name, String
112
+ column :name, String, size: 255
113
113
  column :request_body, String, text: true
114
114
  column :response_body, String, text: true # It would be nice if we could store this on disk
115
+ index [:id], unique: true
115
116
 
116
117
  # Requires requests to be a part of tests now.
117
- foreign_key :result_id, :results, index: true, type: String
118
- foreign_key :test_session_id, :test_sessions, index: true, type: String
119
- index [:test_session_id, :name], concurrently: true
118
+ foreign_key :result_id, :results, index: true, type: String, size: 36, key: [:id]
119
+ foreign_key :test_session_id, :test_sessions, index: true, type: String, size: 36, key: [:id]
120
+ index [:test_session_id, :name]
120
121
 
121
122
  column :created_at, DateTime, null: false
122
123
  column :updated_at, DateTime, null: false
123
124
  end
124
125
 
125
126
  create_table :headers do
126
- column :id, String, index: true, null: false
127
- foreign_key :request_id, :requests, index: true, type: String
128
- column :type, String # request / response
129
- column :name, String
130
- column :value, String
127
+ column :id, String, index: true, null: false, size: 36
128
+ foreign_key :request_id, :requests, index: true, type: Integer, key: [:index]
129
+ column :type, String, size: 255 # request / response
130
+ column :name, String, size: 255
131
+ column :value, String, text: true
131
132
 
132
133
  column :created_at, DateTime, null: false
133
134
  column :updated_at, DateTime, null: false
134
135
  end
135
136
 
136
137
  create_table :session_data do
137
- column :id, String, index: true, null: false
138
- foreign_key :test_session_id, :test_sessions, index: true, type: String
139
- column :name, String
140
- column :value, String
138
+ column :id, String, index: true, null: false, size: 255
139
+ foreign_key :test_session_id, :test_sessions, index: true, type: String, size: 36, key: [:id]
140
+ column :name, String, size: 255
141
+ column :value, String, text: true
141
142
  index [:test_session_id, :name]
142
143
  end
143
144
  end
@@ -1,7 +1,7 @@
1
1
  Sequel.migration do
2
2
  change do
3
- add_column :test_runs, :identifier, String, text: true
3
+ add_column :test_runs, :identifier, String, text: true, size: 255
4
4
  add_column :test_runs, :wait_timeout, DateTime
5
- add_index :test_runs, [:status, :identifier, :wait_timeout, :updated_at], concurrently: true
5
+ add_index :test_runs, [:status, :identifier, :wait_timeout, :updated_at]
6
6
  end
7
7
  end
@@ -4,15 +4,15 @@ Sequel.migration do
4
4
  drop_table :result_inputs
5
5
 
6
6
  set_column_type :session_data, :value, String, text: true
7
- drop_index :session_data, [:test_session_id, :name], concurrently: true
8
- add_index :session_data, [:test_session_id, :name], unique: true, concurrently: true
9
- drop_index :session_data, :id, concurrently: true
10
- add_index :session_data, :id, unique: true, concurrently: true
7
+ drop_index :session_data, [:test_session_id, :name]
8
+ add_index :session_data, [:test_session_id, :name], unique: true
9
+ drop_index :session_data, :id
10
+ add_index :session_data, :id, unique: true
11
11
 
12
12
  add_column :results, :input_json, String, text: true
13
13
  add_column :results, :output_json, String, text: true
14
- add_index :results, [:test_session_id, :test_id], concurrently: true
15
- add_index :results, [:test_session_id, :test_group_id], concurrently: true
16
- add_index :results, [:test_session_id, :test_suite_id], concurrently: true
14
+ add_index :results, [:test_session_id, :test_id]
15
+ add_index :results, [:test_session_id, :test_group_id]
16
+ add_index :results, [:test_session_id, :test_suite_id]
17
17
  end
18
18
  end
@@ -2,8 +2,8 @@ Sequel.migration do
2
2
  change do
3
3
  create_table :requests_results do
4
4
  # using results_id instead of result_id to avoid ambiguous column error
5
- foreign_key :results_id, :results, index: true, type: String, null: false
6
- foreign_key :requests_id, :requests, index: true, type: String, null: false
5
+ foreign_key :results_id, :results, index: true, type: String, null: false, size: 36, key: [:id]
6
+ foreign_key :requests_id, :requests, index: true, type: Integer, null: false, size: 36, key: [:index]
7
7
  end
8
8
  end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  Sequel.migration do
2
2
  change do
3
- add_index :results, [:test_run_id, :updated_at], concurrently: true
3
+ add_index :results, [:test_run_id, :updated_at]
4
4
  end
5
5
  end
@@ -0,0 +1,38 @@
1
+ Sequel.migration do
2
+ change do
3
+ drop_table :result_outputs
4
+ drop_table :result_prompt_values
5
+
6
+ alter_table(:test_sessions) { set_column_not_null :test_suite_id }
7
+
8
+ alter_table(:results) do
9
+ set_column_not_null :test_run_id
10
+ set_column_not_null :test_session_id
11
+ end
12
+
13
+ alter_table(:messages) do
14
+ set_column_not_null :result_id
15
+ set_column_not_null :type
16
+ set_column_not_null :message
17
+ end
18
+
19
+ alter_table(:requests) do
20
+ set_column_not_null :verb
21
+ set_column_not_null :url
22
+ set_column_not_null :direction
23
+ set_column_not_null :result_id
24
+ set_column_not_null :test_session_id
25
+ end
26
+
27
+ alter_table(:headers) do
28
+ set_column_not_null :request_id
29
+ set_column_not_null :type
30
+ set_column_not_null :name
31
+ end
32
+
33
+ alter_table(:session_data) do
34
+ set_column_not_null :test_session_id
35
+ set_column_not_null :name
36
+ end
37
+ end
38
+ end
@@ -6,7 +6,7 @@ Sequel.migration do
6
6
 
7
7
  create_table(:test_sessions) do
8
8
  String :id, :size=>255, :null=>false
9
- String :test_suite_id, :size=>255
9
+ String :test_suite_id, :size=>255, :null=>false
10
10
  DateTime :created_at, :null=>false
11
11
  DateTime :updated_at, :null=>false
12
12
 
@@ -15,8 +15,8 @@ Sequel.migration do
15
15
 
16
16
  create_table(:session_data, :ignore_index_errors=>true) do
17
17
  String :id, :size=>255, :null=>false
18
- foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255
19
- String :name, :size=>255
18
+ foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255, :null=>false
19
+ String :name, :size=>255, :null=>false
20
20
  String :value, :text=>true
21
21
 
22
22
  index [:id], :unique=>true
@@ -48,8 +48,8 @@ Sequel.migration do
48
48
 
49
49
  create_table(:results, :ignore_index_errors=>true) do
50
50
  String :id, :size=>255, :null=>false
51
- foreign_key :test_run_id, :test_runs, :type=>String, :size=>255
52
- foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255
51
+ foreign_key :test_run_id, :test_runs, :type=>String, :size=>255, :null=>false
52
+ foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255, :null=>false
53
53
  String :result, :size=>255
54
54
  String :result_message, :size=>255
55
55
  String :test_suite_id, :size=>255
@@ -73,9 +73,9 @@ Sequel.migration do
73
73
  create_table(:messages, :ignore_index_errors=>true) do
74
74
  primary_key :index
75
75
  String :id, :size=>255, :null=>false
76
- foreign_key :result_id, :results, :type=>String, :size=>255
77
- String :type, :size=>255
78
- String :message, :size=>255
76
+ foreign_key :result_id, :results, :type=>String, :size=>255, :null=>false
77
+ String :type, :size=>255, :null=>false
78
+ String :message, :size=>255, :null=>false
79
79
  DateTime :created_at, :null=>false
80
80
  DateTime :updated_at, :null=>false
81
81
 
@@ -86,55 +86,29 @@ Sequel.migration do
86
86
  create_table(:requests, :ignore_index_errors=>true) do
87
87
  primary_key :index
88
88
  String :id, :size=>255, :null=>false
89
- String :verb, :size=>255
90
- String :url, :size=>255
91
- String :direction, :size=>255
89
+ String :verb, :size=>255, :null=>false
90
+ String :url, :size=>255, :null=>false
91
+ String :direction, :size=>255, :null=>false
92
92
  Integer :status
93
93
  String :name, :size=>255
94
94
  String :request_body, :text=>true
95
95
  String :response_body, :text=>true
96
- foreign_key :result_id, :results, :type=>String, :size=>255
97
- foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255
96
+ foreign_key :result_id, :results, :type=>String, :size=>255, :null=>false
97
+ foreign_key :test_session_id, :test_sessions, :type=>String, :size=>255, :null=>false
98
+ String :"[:test_session_id, :name]"
98
99
  DateTime :created_at, :null=>false
99
100
  DateTime :updated_at, :null=>false
100
101
 
101
102
  index [:id]
102
103
  index [:result_id]
103
104
  index [:test_session_id]
104
- index [:test_session_id, :name]
105
- end
106
-
107
- create_table(:result_outputs, :ignore_index_errors=>true) do
108
- String :id, :size=>255, :null=>false
109
- foreign_key :result_id, :results, :type=>String, :size=>255
110
- String :test_output_id, :size=>255
111
- String :value, :size=>255
112
- DateTime :created_at, :null=>false
113
- DateTime :updated_at, :null=>false
114
-
115
- primary_key [:id]
116
-
117
- index [:result_id]
118
- end
119
-
120
- create_table(:result_prompt_values, :ignore_index_errors=>true) do
121
- String :id, :size=>255, :null=>false
122
- foreign_key :result_id, :results, :type=>String, :size=>255
123
- String :test_prompt_id, :size=>255, :null=>false
124
- String :value, :size=>255, :null=>false
125
- DateTime :created_at, :null=>false
126
- DateTime :updated_at, :null=>false
127
-
128
- primary_key [:id]
129
-
130
- index [:result_id]
131
105
  end
132
106
 
133
107
  create_table(:headers, :ignore_index_errors=>true) do
134
108
  String :id, :size=>255, :null=>false
135
- foreign_key :request_id, :requests, :type=>String, :size=>255
136
- String :type, :size=>255
137
- String :name, :size=>255
109
+ foreign_key :request_id, :requests, :type=>String, :size=>255, :null=>false
110
+ String :type, :size=>255, :null=>false
111
+ String :name, :size=>255, :null=>false
138
112
  String :value, :size=>255
139
113
  DateTime :created_at, :null=>false
140
114
  DateTime :updated_at, :null=>false
@@ -65,20 +65,23 @@ module Inferno
65
65
  inputs.dig(identifier, :name) || identifier
66
66
  end
67
67
 
68
+ def input_type(identifier)
69
+ inputs.dig(identifier, :type)
70
+ end
71
+
68
72
  ### Output Configuration ###
69
73
 
70
74
  def outputs
71
75
  configuration[:outputs] ||= {}
72
76
  end
73
77
 
74
- def add_output(identifier)
75
- return if output_config_exists?(identifier)
76
-
77
- outputs[identifier] = default_output_config(identifier)
78
+ def add_output(identifier, new_config = {})
79
+ existing_config = output_config(identifier) || {}
80
+ outputs[identifier] = default_output_config(identifier).merge(existing_config, new_config)
78
81
  end
79
82
 
80
83
  def default_output_config(identifier)
81
- { name: identifier }
84
+ { name: identifier, type: 'text' }
82
85
  end
83
86
 
84
87
  def output_config_exists?(identifier)
@@ -93,6 +96,10 @@ module Inferno
93
96
  outputs.dig(identifier, :name) || identifier
94
97
  end
95
98
 
99
+ def output_type(identifier)
100
+ outputs.dig(identifier, :type)
101
+ end
102
+
96
103
  ### Request Configuration ###
97
104
 
98
105
  def requests
@@ -72,7 +72,7 @@ module Inferno
72
72
  # @param headers [Hash] custom headers for this operation
73
73
  # @return [Inferno::Entities::Request]
74
74
  def fhir_operation(path, body: nil, client: :default, name: nil, headers: {})
75
- store_request('outgoing', name) do
75
+ store_request_and_refresh_token(fhir_client(client), name) do
76
76
  operation_headers = fhir_client(client).fhir_headers
77
77
  operation_headers.merge!('Content-Type' => 'application/fhir+json') if body.present?
78
78
  operation_headers.merge!(headers) if headers.present?
@@ -88,7 +88,7 @@ module Inferno
88
88
  # other tests
89
89
  # @return [Inferno::Entities::Request]
90
90
  def fhir_get_capability_statement(client: :default, name: nil)
91
- store_request('outgoing', name) do
91
+ store_request_and_refresh_token(fhir_client(client), name) do
92
92
  fhir_client(client).conformance_statement
93
93
  fhir_client(client).reply
94
94
  end
@@ -103,7 +103,7 @@ module Inferno
103
103
  # other tests
104
104
  # @return [Inferno::Entities::Request]
105
105
  def fhir_read(resource_type, id, client: :default, name: nil)
106
- store_request('outgoing', name) do
106
+ store_request_and_refresh_token(fhir_client(client), name) do
107
107
  fhir_client(client).read(fhir_class_from_resource_type(resource_type), id)
108
108
  end
109
109
  end
@@ -124,21 +124,73 @@ module Inferno
124
124
  else
125
125
  { parameters: params }
126
126
  end
127
- store_request('outgoing', name) do
127
+
128
+ store_request_and_refresh_token(fhir_client(client), name) do
128
129
  fhir_client(client)
129
130
  .search(fhir_class_from_resource_type(resource_type), { search: search })
130
131
  end
131
132
  end
132
133
 
134
+ # Perform a FHIR delete interaction.
135
+ #
136
+ # @param resource_type [String, Symbol, Class]
137
+ # @param id [String]
138
+ # @param client [Symbol]
139
+ # @param name [Symbol] Name for this request to allow it to be used by
140
+ # other tests
141
+ # @return [Inferno::Entities::Request]
142
+ def fhir_delete(resource_type, id, client: :default, name: nil)
143
+ store_request('outgoing', name) do
144
+ fhir_client(client).destroy(fhir_class_from_resource_type(resource_type), id)
145
+ end
146
+ end
147
+
133
148
  # @todo Make this a FHIR class method? Something like
134
149
  # FHIR.class_for(resource_type)
135
- # @private
150
+ # @api private
136
151
  def fhir_class_from_resource_type(resource_type)
137
152
  FHIR.const_get(resource_type.to_s.camelize)
138
153
  end
139
154
 
155
+ # This method wraps a request to automatically refresh its access token if
156
+ # expired. It's combined with `store_request` so that all of the fhir
157
+ # request methods don't have to be wrapped twice.
158
+ # @api private
159
+ def store_request_and_refresh_token(client, name, &block)
160
+ store_request('outgoing', name) do
161
+ perform_refresh(client) if client.need_to_refresh? && client.able_to_refresh?
162
+ block.call
163
+ end
164
+ end
165
+
166
+ # @api private
167
+ def perform_refresh(client)
168
+ credentials = client.oauth_credentials
169
+
170
+ post(
171
+ credentials.token_url,
172
+ body: credentials.oauth2_refresh_params,
173
+ headers: credentials.oauth2_refresh_headers
174
+ )
175
+
176
+ return if request.status != 200
177
+
178
+ credentials.update_from_response_body(request)
179
+
180
+ if credentials.name.present?
181
+ Inferno::Repositories::SessionData.new.save(
182
+ name: credentials.name,
183
+ value: credentials,
184
+ type: 'oauth_credentials',
185
+ test_session_id: test_session_id
186
+ )
187
+ end
188
+ rescue StandardError => e
189
+ Inferno::Application[:logger].error "Unable to refresh token: #{e.message}"
190
+ end
191
+
140
192
  module ClassMethods
141
- # @private
193
+ # @api private
142
194
  def fhir_client_definitions
143
195
  @fhir_client_definitions ||= {}
144
196
  end
@@ -1,4 +1,5 @@
1
1
  require 'fhir_client'
2
+ require_relative '../ext/fhir_client'
2
3
 
3
4
  module Inferno
4
5
  module DSL
@@ -15,6 +16,7 @@ module Inferno
15
16
  client.additional_headers = headers if headers
16
17
  client.default_json
17
18
  client.set_bearer_token bearer_token if bearer_token
19
+ oauth_credentials&.add_to_client(client)
18
20
  end
19
21
  end
20
22
 
@@ -48,6 +50,20 @@ module Inferno
48
50
  end
49
51
  end
50
52
 
53
+ # Define OAuth credentials for a client. These can allow a client to
54
+ # automatically refresh its access token when it expires.
55
+ #
56
+ # @param oauth_credentials [Inferno::DSL::OAuthCredentials, Symbol]
57
+ # @return [void]
58
+ def oauth_credentials(oauth_credentials = nil)
59
+ @oauth_credentials ||=
60
+ if oauth_credentials.is_a? Symbol
61
+ runnable.send(oauth_credentials)
62
+ else
63
+ oauth_credentials
64
+ end
65
+ end
66
+
51
67
  # Define custom headers for a client
52
68
  #
53
69
  # @param headers [Hash]