forest_liana 9.1.0 → 9.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/forest_liana/ability/permission/smart_action_checker.rb +1 -1
  3. data/app/services/forest_liana/filters_parser.rb +1 -5
  4. data/app/services/forest_liana/leaderboard_stat_getter.rb +1 -1
  5. data/app/services/forest_liana/line_stat_getter.rb +1 -1
  6. data/app/services/forest_liana/pie_stat_getter.rb +1 -1
  7. data/app/services/forest_liana/scope_manager.rb +34 -58
  8. data/app/services/forest_liana/search_query_builder.rb +4 -9
  9. data/app/services/forest_liana/utils/context_variables.rb +41 -0
  10. data/app/services/forest_liana/utils/context_variables_injector.rb +53 -0
  11. data/app/services/forest_liana/value_stat_getter.rb +1 -1
  12. data/lib/forest_liana/version.rb +1 -1
  13. data/spec/requests/actions_controller_spec.rb +32 -4
  14. data/spec/requests/count_spec.rb +1 -1
  15. data/spec/requests/resources_spec.rb +6 -7
  16. data/spec/requests/stats_spec.rb +29 -28
  17. data/spec/services/forest_liana/filters_parser_spec.rb +35 -35
  18. data/spec/services/forest_liana/has_many_getter_spec.rb +13 -11
  19. data/spec/services/forest_liana/line_stat_getter_spec.rb +1 -1
  20. data/spec/services/forest_liana/pie_stat_getter_spec.rb +11 -11
  21. data/spec/services/forest_liana/resource_updater_spec.rb +25 -21
  22. data/spec/services/forest_liana/resources_getter_spec.rb +10 -10
  23. data/spec/services/forest_liana/scope_manager_spec.rb +243 -152
  24. data/spec/services/forest_liana/utils/context_variables_injector_spec.rb +107 -0
  25. data/spec/services/forest_liana/utils/context_variables_spec.rb +43 -0
  26. data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
  27. metadata +12 -6
@@ -1,199 +1,187 @@
1
1
  module ForestLiana
2
2
  describe ScopeManager do
3
3
  let(:rendering_id) { 13 }
4
- let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
5
- let(:collection_name) { 'Users' }
6
- let(:first_collection_scope) {
4
+ let(:user) {
7
5
  {
8
- 'scope'=> {
9
- 'filter'=> {
10
- 'aggregator' => 'and',
11
- 'conditions' => [
12
- { 'field' => 'description', 'operator' => 'contains', 'value' => 'check' }
13
- ]
14
- },
15
- 'dynamicScopesValues' => { }
16
- }
17
- }
18
- }
19
- let(:second_collection_scope) {
20
- {
21
- 'scope'=> {
22
- 'filter'=> {
23
- 'aggregator' => 'and',
24
- 'conditions' => [
25
- { 'field' => 'description', 'operator' => 'contains', 'value' => 'toto' }
26
- ]
27
- },
28
- 'dynamicScopesValues' => { }
29
- }
6
+ 'id' => '1',
7
+ 'email' => 'jd@forestadmin.com',
8
+ 'first_name' => 'John',
9
+ 'last_name' => 'Doe',
10
+ 'team' => 'Operations',
11
+ 'role' => 'role-test',
12
+ 'tags' => [{'key' => 'tag1'}],
13
+ 'rendering_id'=> rendering_id
30
14
  }
31
15
  }
32
- let(:first_json_scopes) { JSON.generate({ collection_name => first_collection_scope }) }
33
- let(:second_json_scopes) { JSON.generate({ collection_name => second_collection_scope }) }
34
- let(:first_scopes_api_call_response) { Net::HTTPOK.new({}, 200, first_json_scopes) }
35
- let(:second_scopes_api_call_response) { Net::HTTPOK.new({}, 200, second_json_scopes) }
16
+ let(:collection_name) { 'User' }
36
17
 
37
18
  before do
38
19
  described_class.invalidate_scope_cache(rendering_id)
39
- allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(first_scopes_api_call_response, second_scopes_api_call_response)
40
- allow(first_scopes_api_call_response).to receive(:body).and_return(first_json_scopes)
41
- allow(second_scopes_api_call_response).to receive(:body).and_return(second_json_scopes)
42
20
  end
43
21
 
44
- describe '#get_scope_for_user' do
45
- describe 'with invalid inputs' do
46
- it 'should raise an error on missing rendering_id' do
47
- expect {
48
- described_class.get_scope_for_user({}, collection_name)
49
- }.to raise_error 'Missing required rendering_id'
50
- end
51
-
52
- it 'should raise an error on missing collection_name' do
53
- expect {
54
- described_class.get_scope_for_user(user, nil)
55
- }.to raise_error 'Missing required collection_name'
56
- end
57
- end
22
+ describe '#get_scope' do
23
+ let(:api_call_response_error) { Net::HTTPNotFound.new({}, 404, nil) }
58
24
 
59
25
  describe 'when the backend return an errored response' do
60
- let(:first_scopes_api_call_response) { Net::HTTPNotFound.new({}, 404, nil) }
26
+ before do
27
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_error)
28
+ end
61
29
 
62
30
  it 'should raise an error' do
63
31
  expect {
64
- described_class.get_scope_for_user(user, collection_name)
32
+ described_class.get_scope(collection_name, user)
65
33
  }.to raise_error 'Unable to fetch scopes'
66
34
  end
67
35
  end
68
36
 
69
- describe 'when retrieving scopes once with no cached value' do
70
- let(:scope) { described_class.get_scope_for_user(user, collection_name) }
71
-
72
- it 'should fetch the relevant scope and return it' do
73
- expect(scope).to eq first_collection_scope['scope']['filter']
74
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once
75
- expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
76
- end
77
- end
78
-
79
- describe 'when retrieving scopes twice before the refresh cache delta' do
80
- let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
81
- let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
82
-
83
- it 'should return the same value twice and have fetch the scopes from the backend only once' do
84
- expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
85
- expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
86
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once.with('/liana/scopes', query: { 'renderingId' => rendering_id })
87
- end
88
- end
89
-
90
- describe 'when retrieving scopes twice after the refresh cache delta' do
91
- let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
92
- let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
37
+ describe 'when retrieving scopes' do
38
+ let(:filled_scope) {
39
+ JSON.generate(
40
+ {
41
+ 'collections' => {
42
+ 'User' => {
43
+ 'scope' => {
44
+ 'aggregator' => 'and',
45
+ 'conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]
46
+ },
47
+ 'segments' => []
48
+ }
49
+ },
50
+ 'stats' => [],
51
+ 'team' => {'id' => '1', 'name' => 'Operations'}
52
+ }
53
+ )
54
+ }
55
+ let(:api_call_response_success) { Net::HTTPOK.new({}, 200, filled_scope) }
93
56
 
94
- it 'should return same value but trigger a fetch twice' do
95
- expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
96
- allow(Time).to receive(:now).and_return(Time.now + 20.minutes)
97
- expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
98
- # sleep to wait for the Thread to trigger the call to the `ForestApiRequester`
99
- sleep(0.001)
100
- expect(ForestLiana::ForestApiRequester).to have_received(:get).twice.with('/liana/scopes', query: { 'renderingId' => rendering_id })
57
+ before do
58
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_success)
59
+ allow(api_call_response_success).to receive(:body).and_return(filled_scope)
101
60
  end
102
- end
103
61
 
104
- describe 'when retrieving scopes three times after the refresh cache delta' do
105
- let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
106
- let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
107
- let(:scope_third_fetch) { described_class.get_scope_for_user(user, collection_name) }
62
+ it 'should fetch the relevant scope and return it' do
63
+ expect(described_class.get_scope(collection_name, user)).to eq(
64
+ {
65
+ 'aggregator' => 'and',
66
+ 'conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]
67
+ }
68
+ )
108
69
 
109
- it 'should return a new value on third call and have fetch the scopes from the backend only twice' do
110
- expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
111
- allow(Time).to receive(:now).and_return(Time.now + 20.minutes)
112
- expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
113
- # sleep to wait for the Thread to update the cache
114
- sleep(0.001)
115
- expect(scope_third_fetch).to eq second_collection_scope['scope']['filter']
116
- expect(ForestLiana::ForestApiRequester).to have_received(:get).twice.with('/liana/scopes', query: { 'renderingId' => rendering_id })
70
+ expect(Rails.cache.read('forest.scopes.' + rendering_id.to_s)).to eq(
71
+ {
72
+ 'scopes' => {'User' => {'aggregator' => 'and', 'conditions'=>[{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]}},
73
+ 'team' => {'id' => '1', 'name' => 'Operations'},
74
+ })
117
75
  end
118
76
  end
119
77
 
120
78
  describe 'when scope contains dynamic values' do
121
- let(:first_collection_scope) {
122
- {
123
- 'scope' => {
124
- 'filter'=> {
125
- 'aggregator' => 'and',
126
- 'conditions' => [
127
- { 'field' => 'description', 'operator' => 'contains', 'value' => '$currentUser.firstName' }
128
- ]
79
+ let(:filled_scope) {
80
+ JSON.generate(
81
+ {
82
+ 'collections' => {
83
+ 'User' => {
84
+ 'scope' => {
85
+ 'aggregator' => 'and',
86
+ 'conditions' => [{'field' => 'email', 'operator' => 'equal', 'value' => '{{currentUser.email}}'}]
87
+ },
88
+ 'segments' => []
89
+ }
129
90
  },
130
- 'dynamicScopesValues' => {
131
- 'users' => { '1' => { '$currentUser.firstName' => 'Valentin' } }
132
- }
91
+ 'stats' => [],
92
+ 'team' => {'id' => '1', 'name' => 'Operations'}
133
93
  }
134
- }
135
- }
136
- let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
137
- let(:expected_filter) {
138
- {
139
- 'aggregator' => 'and',
140
- 'conditions' => [
141
- { 'field' => 'description', 'operator' => 'contains', 'value' => 'Valentin' }
142
- ]
143
- }
94
+ )
144
95
  }
145
96
 
146
- it 'should replace the dynamic values properly' do
147
- expect(scope_filter).to eq expected_filter
148
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once
149
- expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
97
+ let(:api_call_response_success) { Net::HTTPOK.new({}, 200, filled_scope) }
98
+
99
+ before do
100
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_success)
101
+ allow(api_call_response_success).to receive(:body).and_return(filled_scope)
150
102
  end
151
- end
152
103
 
153
- describe 'when target collection has no scopes' do
154
- let(:first_collection_scope) { { } }
155
- let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
104
+ it 'should fetch the relevant scope and return it' do
105
+ expect(described_class.get_scope(collection_name, user)).to eq(
106
+ {
107
+ 'aggregator' => 'and',
108
+ 'conditions' => [{'field' => 'email', 'operator' => 'equal', 'value' => 'jd@forestadmin.com'}]
109
+ }
110
+ )
156
111
 
157
- it 'should return nil' do
158
- expect(scope_filter).to eq nil
159
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once
160
- expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
112
+ expect(Rails.cache.read('forest.scopes.' + rendering_id.to_s)).to eq(
113
+ {
114
+ 'scopes' => {'User' => {'aggregator' => 'and', 'conditions'=>[{'field' => 'email', 'operator' => 'equal', 'value' => '{{currentUser.email}}'}]}},
115
+ 'team' => {'id' => '1', 'name' => 'Operations'},
116
+ }
117
+ )
161
118
  end
162
119
  end
163
120
 
164
121
  describe 'when target collection has no scopes' do
165
- let(:first_collection_scope) { { } }
166
- let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
122
+ let(:empty_scope) {
123
+ JSON.generate(
124
+ {
125
+ 'collections' => {
126
+ 'User' => {
127
+ 'scope' => nil,
128
+ 'segments' => []
129
+ }
130
+ },
131
+ 'stats' => [],
132
+ 'team' => {'id' => '1', 'name' => 'Operations'}
133
+ }
134
+ )
135
+ }
167
136
 
168
- it 'should return nil' do
169
- expect(scope_filter).to eq nil
170
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once
171
- expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
137
+ let(:api_call_response_empty) { Net::HTTPOK.new({}, 200, empty_scope) }
138
+
139
+ before do
140
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_empty)
141
+ allow(api_call_response_empty).to receive(:body).and_return(empty_scope)
172
142
  end
173
- end
174
143
 
175
- describe 'when asking for filters as string' do
176
- let(:scope) { described_class.get_scope_for_user(user, collection_name, as_string: true) }
177
- let(:expected_filters) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"description\",\"operator\":\"contains\",\"value\":\"check\"}]}" }
144
+ it 'should return nil' do
145
+ expect(described_class.get_scope(collection_name, user)).to eq nil
178
146
 
179
- it 'should fetch the relevant scope and return it as a string' do
180
- expect(scope).to eq expected_filters
181
- expect(ForestLiana::ForestApiRequester).to have_received(:get).once
182
- expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
147
+ expect(Rails.cache.read('forest.scopes.' + rendering_id.to_s)).to eq(
148
+ {
149
+ 'scopes' => {},
150
+ 'team' => {'id' => '1', 'name' => 'Operations'},
151
+ }
152
+ )
183
153
  end
184
154
  end
185
155
  end
186
156
 
187
157
  describe '#append_scope_for_user' do
188
- let(:existing_filter) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"shipping_status\",\"operator\":\"equal\",\"value\":\"Shipped\"}]}" }
189
- let(:first_collection_scope_filter_as_string) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"description\",\"operator\":\"contains\",\"value\":\"check\"}]}" }
158
+ let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
190
159
 
191
160
  describe 'when the target collection has NO scopes defined' do
192
- let(:first_collection_scope) { { } }
161
+ let(:api_call_response_empty) { Net::HTTPOK.new({}, 200, empty_scope) }
162
+
163
+ let(:empty_scope) {
164
+ JSON.generate(
165
+ {
166
+ 'collections' => {
167
+ 'User' => {
168
+ 'scope' => nil,
169
+ 'segments' => []
170
+ }
171
+ },
172
+ 'stats' => [],
173
+ 'team' => {'id' => '1', 'name' => 'Operations'}
174
+ }
175
+ )
176
+ }
177
+
178
+ before do
179
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_empty)
180
+ allow(api_call_response_empty).to receive(:body).and_return(empty_scope)
181
+ end
193
182
 
194
183
  describe 'when providing NO existing filters' do
195
184
  let(:existing_filter) { nil }
196
- let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
197
185
 
198
186
  it 'should return nil' do
199
187
  expect(filters).to eq nil
@@ -201,9 +189,9 @@ module ForestLiana
201
189
  end
202
190
 
203
191
  describe 'when providing existing filters' do
204
- let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
192
+ let(:existing_filter) { {'aggregator' => 'and', 'conditions' => [{'field' => 'shipping_status', 'operator' => 'equal', 'value' => 'Shipped'}]} }
205
193
 
206
- it 'should return only the exisitng filters' do
194
+ it 'should return only the existing filters' do
207
195
  expect(filters).to eq existing_filter
208
196
  end
209
197
  end
@@ -212,21 +200,124 @@ module ForestLiana
212
200
  describe 'when the target collection has scopes defined' do
213
201
  describe 'when providing NO existing filters' do
214
202
  let(:existing_filter) { nil }
215
- let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
203
+
204
+ let(:filled_scope) {
205
+ JSON.generate(
206
+ {
207
+ 'collections' => {
208
+ 'User' => {
209
+ 'scope' => {
210
+ 'aggregator' => 'and',
211
+ 'conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]
212
+ },
213
+ 'segments' => []
214
+ }
215
+ },
216
+ 'stats' => [],
217
+ 'team' => {'id' => '1', 'name' => 'Operations'}
218
+ }
219
+ )
220
+ }
221
+
222
+ let(:api_call_response_success) { Net::HTTPOK.new({}, 200, filled_scope) }
223
+
224
+ before do
225
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_success)
226
+ allow(api_call_response_success).to receive(:body).and_return(filled_scope)
227
+ end
216
228
 
217
229
  it 'should return only the scope filters' do
218
- expect(filters).to eq first_collection_scope_filter_as_string
230
+ expect(filters).to eq filters
219
231
  end
220
- end
221
232
 
222
- describe 'when providing existing filters' do
223
- let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
233
+ describe 'when providing existing filters' do
234
+ let(:existing_filter) { {'aggregator' => 'and', 'conditions' => [{'field' => 'shipping_status', 'operator' => 'equal', 'value' => 'Shipped'}]} }
224
235
 
225
- it 'should return the aggregation between the exisitng filters and the scope filters' do
226
- expect(filters).to eq "{\"aggregator\":\"and\",\"conditions\":[#{existing_filter},#{first_collection_scope_filter_as_string}]}"
236
+ it 'should return the aggregation between the existing filters and the scope filters' do
237
+ expect(filters).to eq(
238
+ {
239
+ 'aggregator' => 'and',
240
+ 'conditions' => [
241
+ existing_filter,
242
+ { 'aggregator' => 'and', 'conditions' => [{ 'field' => 'id', 'operator' => 'greater_than', 'value' => '1' }] }
243
+ ]
244
+ }
245
+ )
246
+ end
227
247
  end
228
248
  end
229
249
  end
230
250
  end
251
+
252
+ describe '#apply_scopes_on_records' do
253
+ let(:resource) { User }
254
+
255
+ describe 'when the collection has NO scopes' do
256
+ let(:empty_scope) {
257
+ JSON.generate(
258
+ {
259
+ 'collections' => {
260
+ 'User' => {
261
+ 'scope' => nil,
262
+ 'segments' => []
263
+ }
264
+ },
265
+ 'stats' => [],
266
+ 'team' => {'id' => '1', 'name' => 'Operations'}
267
+ }
268
+ )
269
+ }
270
+ let(:api_call_response_empty) { Net::HTTPOK.new({}, 200, empty_scope) }
271
+
272
+ before do
273
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_empty)
274
+ allow(api_call_response_empty).to receive(:body).and_return(empty_scope)
275
+ end
276
+
277
+ it 'should return the records as is' do
278
+ expect(described_class.apply_scopes_on_records(resource.all, user, collection_name, nil)).to eq resource.all
279
+ end
280
+ end
281
+
282
+ describe 'when the collection has scopes' do
283
+ let(:filled_scope) {
284
+ JSON.generate(
285
+ {
286
+ 'collections' => {
287
+ 'User' => {
288
+ 'scope' => {
289
+ 'aggregator' => 'and',
290
+ 'conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]
291
+ },
292
+ 'segments' => []
293
+ }
294
+ },
295
+ 'stats' => [],
296
+ 'team' => {'id' => '1', 'name' => 'Operations'}
297
+ }
298
+ )
299
+ }
300
+ let(:api_call_response_success) { Net::HTTPOK.new({}, 200, filled_scope) }
301
+
302
+ before do
303
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(api_call_response_success)
304
+ allow(api_call_response_success).to receive(:body).and_return(filled_scope)
305
+ end
306
+
307
+ it 'should apply the scope filters on the records' do
308
+ filters_parser = instance_double(ForestLiana::FiltersParser, apply_filters: resource)
309
+ allow(ForestLiana::FiltersParser).to receive(:new).and_return(filters_parser)
310
+
311
+ described_class.apply_scopes_on_records(resource, user, collection_name, nil)
312
+
313
+ expect(ForestLiana::FiltersParser).to have_received(:new).with(
314
+ {'aggregator' => 'and','conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => '1'}]},
315
+ resource,
316
+ nil
317
+ ).once
318
+ expect(filters_parser).to have_received(:apply_filters).once
319
+ end
320
+ end
321
+ end
231
322
  end
232
323
  end
@@ -0,0 +1,107 @@
1
+ module ForestLiana
2
+ module Utils
3
+ describe ContextVariablesInjector do
4
+ let(:team) { { 'id' => 100, 'name' => 'Ninja' } }
5
+
6
+ let(:user) do
7
+ {
8
+ 'id' => 1,
9
+ 'firstName' => 'John',
10
+ 'lastName' => 'Doe',
11
+ 'fullName' => 'John Doe',
12
+ 'email' => 'john.doe@domain.com',
13
+ 'tags' => [{ 'planet' => 'Death Star' }],
14
+ 'roleId' => 1,
15
+ 'permissionLevel' => 'admin'
16
+ }
17
+ end
18
+
19
+ let(:context_variables) do
20
+ ContextVariables.new(
21
+ team,
22
+ user,
23
+ {
24
+ 'siths.selectedRecord.rank' => 3,
25
+ 'siths.selectedRecord.power' => 'electrocute'
26
+ }
27
+ )
28
+ end
29
+
30
+ context 'when inject_context_in_filter is called' do
31
+ it 'returns it as it is with a number' do
32
+ result = described_class.inject_context_in_value_custom(8) { {} }
33
+
34
+ expect(result).to eq(8)
35
+ end
36
+
37
+ it 'returns it as it is with a array' do
38
+ value = ['test', 'me']
39
+ result = described_class.inject_context_in_value_custom(value) { {} }
40
+
41
+ expect(result).to eq(value)
42
+ end
43
+
44
+ it 'replaces all variables with a string' do
45
+ replace_function = ->(key) { key.split('.').pop.upcase }
46
+ result = described_class.inject_context_in_value_custom(
47
+ 'It should be {{siths.selectedRecord.power}} of rank {{siths.selectedRecord.rank}}. But {{siths.selectedRecord.power}} can be duplicated.'
48
+ ) do |key|
49
+ replace_function.call(key)
50
+ end
51
+
52
+ expect(result).to eq('It should be POWER of rank RANK. But POWER can be duplicated.')
53
+ end
54
+ end
55
+
56
+ context('when inject_context_in_value is called') do
57
+ it 'returns it as it is with a number' do
58
+ result = described_class.inject_context_in_value(8, context_variables)
59
+
60
+ expect(result).to eq(8)
61
+ end
62
+
63
+ it 'returns it as it is with a array' do
64
+ value = ['test', 'me']
65
+ result = described_class.inject_context_in_value(value, context_variables)
66
+
67
+ expect(result).to eq(value)
68
+ end
69
+
70
+ it 'replaces all variables with a string' do
71
+ first_value_part = 'It should be {{siths.selectedRecord.power}} of rank {{siths.selectedRecord.rank}}.'
72
+ second_value_part = 'But {{siths.selectedRecord.power}} can be duplicated.'
73
+ result = described_class.inject_context_in_value(
74
+ "#{first_value_part} #{second_value_part}",
75
+ context_variables
76
+ )
77
+
78
+ expect(result).to eq('It should be electrocute of rank 3. But electrocute can be duplicated.')
79
+ end
80
+
81
+ it 'replaces all currentUser variables' do
82
+ [
83
+ { key: 'email', expected_value: user['email'] },
84
+ { key: 'firstName', expected_value: user['firstName'] },
85
+ { key: 'lastName', expected_value: user['lastName'] },
86
+ { key: 'fullName', expected_value: user['fullName'] },
87
+ { key: 'id', expected_value: user['id'] },
88
+ { key: 'permissionLevel', expected_value: user['permissionLevel'] },
89
+ { key: 'roleId', expected_value: user['roleId'] },
90
+ { key: 'tags.planet', expected_value: user['tags'][0]['planet'] },
91
+ { key: 'team.id', expected_value: team['id'] },
92
+ { key: 'team.name', expected_value: team['name'] }
93
+ ].each do |value|
94
+ key = value[:key]
95
+ expected_value = value[:expected_value]
96
+ expect(
97
+ described_class.inject_context_in_value(
98
+ "{{currentUser.#{key}}}",
99
+ context_variables
100
+ )
101
+ ).to eq(expected_value.to_s)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,43 @@
1
+ module ForestLiana
2
+ module Utils
3
+ describe ContextVariables do
4
+ let(:user) do
5
+ {
6
+ 'id' => '1',
7
+ 'email' => 'jd@forestadmin.com',
8
+ 'first_name' => 'John',
9
+ 'last_name' => 'Doe',
10
+ 'team' => 'Operations',
11
+ 'role' => 'role-test',
12
+ 'tags' => [{'key' => 'tag1', 'value' => 'value1' }, {'key' => 'tag2', 'value' => 'value2'}],
13
+ 'rendering_id'=> '1'
14
+ }
15
+ end
16
+
17
+ let(:team) do
18
+ {
19
+ 'id' => 1,
20
+ 'name' => 'Operations'
21
+ }
22
+ end
23
+
24
+ let(:request_context_variables) do
25
+ {
26
+ 'foo.id' => 100
27
+ }
28
+ end
29
+
30
+ it 'returns the request context variable key when the key is not present into the user data' do
31
+ context_variables = described_class.new(team, user, request_context_variables)
32
+ expect(context_variables.get_value('foo.id')).to eq(100)
33
+ end
34
+
35
+ it 'returns the corresponding value from the key provided of the user data' do
36
+ context_variables = described_class.new(team, user, request_context_variables)
37
+ expect(context_variables.get_value('currentUser.first_name')).to eq('John')
38
+ expect(context_variables.get_value('currentUser.tags.key')).to eq('tag1')
39
+ expect(context_variables.get_value('currentUser.team.id')).to eq(1)
40
+ end
41
+ end
42
+ end
43
+ end