forest_liana 9.1.10 → 9.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/services/forest_liana/ability/permission/smart_action_checker.rb +1 -1
- data/app/services/forest_liana/filters_parser.rb +1 -5
- data/app/services/forest_liana/leaderboard_stat_getter.rb +1 -1
- data/app/services/forest_liana/line_stat_getter.rb +1 -1
- data/app/services/forest_liana/pie_stat_getter.rb +1 -1
- data/app/services/forest_liana/scope_manager.rb +34 -58
- data/app/services/forest_liana/utils/context_variables.rb +41 -0
- data/app/services/forest_liana/utils/context_variables_injector.rb +53 -0
- data/app/services/forest_liana/value_stat_getter.rb +1 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/requests/actions_controller_spec.rb +32 -4
- data/spec/requests/count_spec.rb +1 -1
- data/spec/requests/resources_spec.rb +6 -7
- data/spec/requests/stats_spec.rb +29 -28
- data/spec/services/forest_liana/filters_parser_spec.rb +35 -35
- data/spec/services/forest_liana/has_many_getter_spec.rb +13 -11
- data/spec/services/forest_liana/line_stat_getter_spec.rb +1 -1
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +11 -11
- data/spec/services/forest_liana/resource_updater_spec.rb +25 -21
- data/spec/services/forest_liana/resources_getter_spec.rb +10 -10
- data/spec/services/forest_liana/scope_manager_spec.rb +243 -152
- data/spec/services/forest_liana/utils/context_variables_injector_spec.rb +107 -0
- data/spec/services/forest_liana/utils/context_variables_spec.rb +43 -0
- data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
- metadata +8 -2
@@ -1,199 +1,187 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
describe ScopeManager do
|
3
3
|
let(:rendering_id) { 13 }
|
4
|
-
let(:user) {
|
5
|
-
let(:collection_name) { 'Users' }
|
6
|
-
let(:first_collection_scope) {
|
4
|
+
let(:user) {
|
7
5
|
{
|
8
|
-
'
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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(:
|
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 '#
|
45
|
-
|
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
|
-
|
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.
|
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
|
70
|
-
let(:
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
95
|
-
|
96
|
-
allow(
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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(:
|
122
|
-
|
123
|
-
|
124
|
-
'
|
125
|
-
'
|
126
|
-
|
127
|
-
|
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
|
-
'
|
131
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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(:
|
166
|
-
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
-
|
176
|
-
|
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
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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(:
|
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(:
|
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(:
|
192
|
+
let(:existing_filter) { {'aggregator' => 'and', 'conditions' => [{'field' => 'shipping_status', 'operator' => 'equal', 'value' => 'Shipped'}]} }
|
205
193
|
|
206
|
-
it 'should return only the
|
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
|
-
|
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
|
230
|
+
expect(filters).to eq filters
|
219
231
|
end
|
220
|
-
end
|
221
232
|
|
222
|
-
|
223
|
-
|
233
|
+
describe 'when providing existing filters' do
|
234
|
+
let(:existing_filter) { {'aggregator' => 'and', 'conditions' => [{'field' => 'shipping_status', 'operator' => 'equal', 'value' => 'Shipped'}]} }
|
224
235
|
|
225
|
-
|
226
|
-
|
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
|