forest_liana 7.0.0.beta.2 → 7.0.0.beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +20 -18
- data/app/controllers/forest_liana/application_controller.rb +0 -9
- data/app/controllers/forest_liana/associations_controller.rb +2 -2
- data/app/controllers/forest_liana/resources_controller.rb +16 -6
- data/app/controllers/forest_liana/scopes_controller.rb +20 -0
- data/app/controllers/forest_liana/smart_actions_controller.rb +39 -6
- data/app/controllers/forest_liana/stats_controller.rb +5 -5
- data/app/services/forest_liana/apimap_sorter.rb +1 -0
- data/app/services/forest_liana/filters_parser.rb +8 -4
- data/app/services/forest_liana/has_many_dissociator.rb +2 -2
- data/app/services/forest_liana/has_many_getter.rb +2 -2
- data/app/services/forest_liana/leaderboard_stat_getter.rb +20 -14
- data/app/services/forest_liana/line_stat_getter.rb +5 -3
- data/app/services/forest_liana/permissions_checker.rb +42 -37
- data/app/services/forest_liana/permissions_formatter.rb +1 -1
- data/app/services/forest_liana/permissions_getter.rb +3 -6
- data/app/services/forest_liana/pie_stat_getter.rb +6 -3
- data/app/services/forest_liana/resource_getter.rb +6 -3
- data/app/services/forest_liana/resource_updater.rb +5 -2
- data/app/services/forest_liana/resources_getter.rb +6 -5
- data/app/services/forest_liana/scope_manager.rb +102 -0
- data/app/services/forest_liana/search_query_builder.rb +6 -3
- data/app/services/forest_liana/stat_getter.rb +2 -1
- data/app/services/forest_liana/token.rb +1 -0
- data/app/services/forest_liana/utils/beta_schema_utils.rb +1 -1
- data/app/services/forest_liana/value_stat_getter.rb +4 -2
- data/config/routes.rb +3 -1
- data/lib/forest_liana/bootstrapper.rb +4 -2
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/app/controllers/forest/islands_controller.rb +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/lib/forest_liana/collections/island.rb +7 -0
- data/spec/lib/forest_liana/bootstrapper_spec.rb +12 -0
- data/spec/requests/actions_controller_spec.rb +144 -23
- data/spec/requests/authentications_spec.rb +2 -1
- data/spec/requests/resources_spec.rb +2 -0
- data/spec/services/forest_liana/apimap_sorter_spec.rb +6 -4
- data/spec/services/forest_liana/filters_parser_spec.rb +1 -1
- data/spec/services/forest_liana/has_many_getter_spec.rb +116 -0
- data/spec/services/forest_liana/line_stat_getter_spec.rb +14 -6
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +45 -71
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +39 -63
- data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +3 -3
- data/spec/services/forest_liana/permissions_formatter_spec.rb +11 -11
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +114 -0
- data/spec/services/forest_liana/resource_updater_spec.rb +116 -0
- data/spec/services/forest_liana/resources_getter_spec.rb +68 -1
- data/spec/services/forest_liana/scope_manager_spec.rb +232 -0
- data/spec/services/forest_liana/value_stat_getter_spec.rb +96 -0
- metadata +125 -118
- data/app/services/forest_liana/scope_validator.rb +0 -98
- data/test/services/forest_liana/has_many_getter_test.rb +0 -75
- data/test/services/forest_liana/pie_stat_getter_test.rb +0 -29
- data/test/services/forest_liana/resource_updater_test.rb +0 -86
- data/test/services/forest_liana/scope_validator_test.rb +0 -185
- data/test/services/forest_liana/value_stat_getter_test.rb +0 -71
@@ -20,7 +20,8 @@ module ForestLiana
|
|
20
20
|
})
|
21
21
|
]
|
22
22
|
}
|
23
|
-
let(:
|
23
|
+
let(:default_rendering_id) { 1 }
|
24
|
+
let(:segments_permissions) { { default_rendering_id => { 'segments' => nil } } }
|
24
25
|
let(:default_api_permissions) {
|
25
26
|
{
|
26
27
|
"data" => {
|
@@ -41,7 +42,7 @@ module ForestLiana
|
|
41
42
|
}
|
42
43
|
},
|
43
44
|
},
|
44
|
-
'renderings' =>
|
45
|
+
'renderings' => segments_permissions
|
45
46
|
},
|
46
47
|
"meta" => {
|
47
48
|
"rolesACLActivated" => true
|
@@ -61,7 +62,6 @@ module ForestLiana
|
|
61
62
|
},
|
62
63
|
}
|
63
64
|
}
|
64
|
-
let(:default_rendering_id) { 1 }
|
65
65
|
|
66
66
|
before do
|
67
67
|
allow(ForestLiana).to receive(:apimap).and_return(schema)
|
@@ -14,7 +14,7 @@ module ForestLiana
|
|
14
14
|
}
|
15
15
|
}
|
16
16
|
let(:old_format_action_permissions) { { 'allowed' => true, 'users' => nil } }
|
17
|
-
let(:
|
17
|
+
let(:old_format_segments_permissions) { nil }
|
18
18
|
let(:old_format_permissions) {
|
19
19
|
{
|
20
20
|
'collection_1' => {
|
@@ -22,7 +22,7 @@ module ForestLiana
|
|
22
22
|
'actions' => {
|
23
23
|
'action_1' => old_format_action_permissions
|
24
24
|
},
|
25
|
-
'
|
25
|
+
'segments' => old_format_segments_permissions
|
26
26
|
}
|
27
27
|
}
|
28
28
|
}
|
@@ -197,22 +197,22 @@ module ForestLiana
|
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
200
|
-
describe '
|
201
|
-
subject { converted_permission['renderings'][rendering_id]['collection_1']['
|
202
|
-
let(:expected_new_format_permissions) {
|
200
|
+
describe 'segments permissions' do
|
201
|
+
subject { converted_permission['renderings'][rendering_id]['collection_1']['segments'] }
|
202
|
+
let(:expected_new_format_permissions) { old_format_segments_permissions }
|
203
203
|
|
204
|
-
context 'when
|
205
|
-
let(:
|
204
|
+
context 'when segments permissions are set' do
|
205
|
+
let(:old_format_segments_permissions) { ['segmentQuery1', 'segmentQuery2'] }
|
206
206
|
|
207
|
-
it 'expected
|
207
|
+
it 'expected segments permissions should be set' do
|
208
208
|
expect(subject).to eq expected_new_format_permissions
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
|
-
context 'when
|
213
|
-
let(:
|
212
|
+
context 'when segments permissions are nil' do
|
213
|
+
let(:old_format_segments_permissions) { nil }
|
214
214
|
|
215
|
-
it 'expected
|
215
|
+
it 'expected segments permissions should be nil' do
|
216
216
|
expect(subject).to eq expected_new_format_permissions
|
217
217
|
end
|
218
218
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
describe PieStatGetter do
|
3
|
+
let(:rendering_id) { 13 }
|
4
|
+
let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
|
5
|
+
let(:records) { [
|
6
|
+
{ name: 'Young Tree n1', age: 3 },
|
7
|
+
{ name: 'Young Tree n2', age: 3 },
|
8
|
+
{ name: 'Young Tree n3', age: 3 },
|
9
|
+
{ name: 'Young Tree n4', age: 3 },
|
10
|
+
{ name: 'Young Tree n5', age: 3 },
|
11
|
+
{ name: 'Old Tree n1', age: 15 },
|
12
|
+
{ name: 'Old Tree n2', age: 15 },
|
13
|
+
{ name: 'Old Tree n3', age: 15 },
|
14
|
+
{ name: 'Old Tree n4', age: 15 }
|
15
|
+
] }
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
|
19
|
+
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
|
20
|
+
|
21
|
+
records.each { |record|
|
22
|
+
Tree.create!(name: record[:name], age: record[:age])
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:model) { Tree }
|
27
|
+
let(:collection) { 'trees' }
|
28
|
+
let(:params) {
|
29
|
+
{
|
30
|
+
type: 'Pie',
|
31
|
+
collection: collection,
|
32
|
+
timezone: 'Europe/Paris',
|
33
|
+
aggregate: 'Count',
|
34
|
+
group_by_field: group_by_field
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
subject { PieStatGetter.new(model, params, user) }
|
39
|
+
|
40
|
+
describe 'with empty scopes' do
|
41
|
+
let(:scopes) { { } }
|
42
|
+
|
43
|
+
describe 'with an aggregate on the name field' do
|
44
|
+
let(:group_by_field) { 'name' }
|
45
|
+
|
46
|
+
it 'should be as many categories as records count' do
|
47
|
+
subject.perform
|
48
|
+
expect(subject.record.value).to eq [
|
49
|
+
{:key => "Old Tree n1", :value => 1},
|
50
|
+
{:key => "Old Tree n2", :value => 1},
|
51
|
+
{:key => "Old Tree n3", :value => 1},
|
52
|
+
{:key => "Old Tree n4", :value => 1},
|
53
|
+
{:key => "Young Tree n1", :value => 1},
|
54
|
+
{:key => "Young Tree n2", :value => 1},
|
55
|
+
{:key => "Young Tree n3", :value => 1},
|
56
|
+
{:key => "Young Tree n4", :value => 1},
|
57
|
+
{:key => "Young Tree n5", :value => 1}
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'with an aggregate on the age field' do
|
63
|
+
let(:group_by_field) { 'age' }
|
64
|
+
|
65
|
+
it 'should be as many categories as different ages among records' do
|
66
|
+
subject.perform
|
67
|
+
expect(subject.record.value).to eq [{ :key => 3, :value => 5}, { :key => 15, :value => 4 }]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'with scopes' do
|
73
|
+
let(:scopes) {
|
74
|
+
{
|
75
|
+
'Tree' => {
|
76
|
+
'scope'=> {
|
77
|
+
'filter'=> {
|
78
|
+
'aggregator' => 'and',
|
79
|
+
'conditions' => [
|
80
|
+
{ 'field' => 'age', 'operator' => 'less_than', 'value' => 10 }
|
81
|
+
]
|
82
|
+
},
|
83
|
+
'dynamicScopesValues' => { }
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
describe 'with an aggregate on the name field' do
|
90
|
+
let(:group_by_field) { 'name' }
|
91
|
+
|
92
|
+
it 'should be as many categories as records inside the scope' do
|
93
|
+
subject.perform
|
94
|
+
expect(subject.record.value).to eq [
|
95
|
+
{:key => "Young Tree n1", :value => 1},
|
96
|
+
{:key => "Young Tree n2", :value => 1},
|
97
|
+
{:key => "Young Tree n3", :value => 1},
|
98
|
+
{:key => "Young Tree n4", :value => 1},
|
99
|
+
{:key => "Young Tree n5", :value => 1}
|
100
|
+
]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'with an aggregate on the age field' do
|
105
|
+
let(:group_by_field) { 'age' }
|
106
|
+
|
107
|
+
it 'should be only one category' do
|
108
|
+
subject.perform
|
109
|
+
expect(subject.record.value).to eq [{ :key => 3, :value => 5}]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
describe ResourceUpdater do
|
3
|
+
describe 'when updating a record' do
|
4
|
+
let(:params) {
|
5
|
+
ActionController::Parameters.new(
|
6
|
+
id: 1,
|
7
|
+
data: {
|
8
|
+
id: 1,
|
9
|
+
type: 'User',
|
10
|
+
attributes: attributes
|
11
|
+
}
|
12
|
+
)
|
13
|
+
}
|
14
|
+
let(:rendering_id) { 13 }
|
15
|
+
let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
|
16
|
+
let(:scopes) { { } }
|
17
|
+
|
18
|
+
subject {
|
19
|
+
described_class.new(User, params, user)
|
20
|
+
}
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
User.create(name: 'Merry')
|
24
|
+
ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
|
25
|
+
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:each) do
|
29
|
+
User.destroy_all
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'with empty scopes' do
|
33
|
+
describe 'with a missing name in attributes' do
|
34
|
+
let(:attributes) { { } }
|
35
|
+
|
36
|
+
it 'should not update the record name' do
|
37
|
+
subject.perform
|
38
|
+
|
39
|
+
expect(subject.record.valid?).to be true
|
40
|
+
expect(subject.record.name).to eq 'Merry'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'with a null name in attributes' do
|
45
|
+
let(:attributes) { { name: nil } }
|
46
|
+
|
47
|
+
it 'should set the record name to null' do
|
48
|
+
subject.perform
|
49
|
+
|
50
|
+
expect(subject.record.valid?).to be true
|
51
|
+
expect(subject.record.name).to eq nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'with a new value as name in attributes' do
|
56
|
+
let(:attributes) { { name: 'Pippin' } }
|
57
|
+
|
58
|
+
it 'should set the record name to null' do
|
59
|
+
subject.perform
|
60
|
+
|
61
|
+
expect(subject.record.valid?).to be true
|
62
|
+
expect(subject.record.name).to eq 'Pippin'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'with scope excluding target record' do
|
68
|
+
let(:attributes) { { name: 'Gandalf' } }
|
69
|
+
let(:scopes) { {
|
70
|
+
'User' => {
|
71
|
+
'scope'=> {
|
72
|
+
'filter'=> {
|
73
|
+
'aggregator' => 'and',
|
74
|
+
'conditions' => [
|
75
|
+
{ 'field' => 'id', 'operator' => 'greater_than', 'value' => 2 }
|
76
|
+
]
|
77
|
+
},
|
78
|
+
'dynamicScopesValues' => { }
|
79
|
+
}
|
80
|
+
}
|
81
|
+
} }
|
82
|
+
|
83
|
+
it 'should not update the record name' do
|
84
|
+
subject.perform
|
85
|
+
|
86
|
+
expect(subject.record).to be nil
|
87
|
+
expect(subject.errors[0][:detail]).to eq 'Couldn\'t find User with \'id\'=1 [WHERE (("users"."id" > (2)))]'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'with scope including target record' do
|
92
|
+
let(:attributes) { { name: 'Gandalf' } }
|
93
|
+
let(:scopes) { {
|
94
|
+
'User' => {
|
95
|
+
'scope'=> {
|
96
|
+
'filter'=> {
|
97
|
+
'aggregator' => 'and',
|
98
|
+
'conditions' => [
|
99
|
+
{ 'field' => 'id', 'operator' => 'less_than', 'value' => 2 }
|
100
|
+
]
|
101
|
+
},
|
102
|
+
'dynamicScopesValues' => { }
|
103
|
+
}
|
104
|
+
}
|
105
|
+
} }
|
106
|
+
|
107
|
+
it 'should not update the record name' do
|
108
|
+
subject.perform
|
109
|
+
|
110
|
+
expect(subject.record.valid?).to be true
|
111
|
+
expect(subject.record.name).to eq 'Gandalf'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -6,13 +6,21 @@ module ForestLiana
|
|
6
6
|
let(:sort) { 'id' }
|
7
7
|
let(:fields) { }
|
8
8
|
let(:filters) { }
|
9
|
+
let(:scopes) { { } }
|
10
|
+
let(:rendering_id) { 13 }
|
11
|
+
let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
|
9
12
|
|
10
13
|
let(:getter) { described_class.new(resource, {
|
11
14
|
page: { size: pageSize, number: pageNumber },
|
12
15
|
sort: sort,
|
13
16
|
fields: fields,
|
14
17
|
filters: filters,
|
15
|
-
})}
|
18
|
+
}, user) }
|
19
|
+
|
20
|
+
def init_scopes
|
21
|
+
ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
|
22
|
+
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
|
23
|
+
end
|
16
24
|
|
17
25
|
before(:each) do
|
18
26
|
users = ['Michel', 'Robert', 'Vince', 'Sandro', 'Olesya', 'Romain', 'Valentin', 'Jason', 'Arnaud', 'Jeff', 'Steve', 'Marc', 'Xavier', 'Paul', 'Mickael', 'Mike', 'Maxime', 'Gertrude', 'Monique', 'Mia', 'Rachid', 'Edouard', 'Sacha', 'Caro', 'Amand', 'Nathan', 'Noémie', 'Robin', 'Gaelle', 'Isabelle']
|
@@ -43,6 +51,7 @@ module ForestLiana
|
|
43
51
|
].map { |location| Location.create(coordinates: location[:coordinates], island: location[:island]) }
|
44
52
|
|
45
53
|
reference = Reference.create()
|
54
|
+
init_scopes
|
46
55
|
end
|
47
56
|
|
48
57
|
after(:each) do
|
@@ -355,5 +364,63 @@ module ForestLiana
|
|
355
364
|
)
|
356
365
|
end
|
357
366
|
end
|
367
|
+
|
368
|
+
describe 'when scopes are defined' do
|
369
|
+
let(:resource) { Island }
|
370
|
+
let(:pageSize) { 15 }
|
371
|
+
let(:fields) { }
|
372
|
+
let(:filters) { }
|
373
|
+
let(:scopes) {
|
374
|
+
{
|
375
|
+
'Island' => {
|
376
|
+
'scope'=> {
|
377
|
+
'filter'=> {
|
378
|
+
'aggregator' => 'and',
|
379
|
+
'conditions' => [
|
380
|
+
{ 'field' => 'name', 'operator' => 'contains', 'value' => 'u' }
|
381
|
+
]
|
382
|
+
},
|
383
|
+
'dynamicScopesValues' => { }
|
384
|
+
}
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
389
|
+
describe 'when there are NO filters already defined' do
|
390
|
+
it 'should get only the records matching the scope' do
|
391
|
+
getter.perform
|
392
|
+
records = getter.records
|
393
|
+
count = getter.count
|
394
|
+
|
395
|
+
expect(records.count).to eq 3
|
396
|
+
expect(count).to eq 3
|
397
|
+
expect(records.first.name).to eq 'Skull'
|
398
|
+
expect(records.second.name).to eq 'Muerta'
|
399
|
+
expect(records.third.name).to eq 'Treasure'
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
describe 'when there are filters already defined' do
|
404
|
+
let(:filters) { {
|
405
|
+
aggregator: 'and',
|
406
|
+
conditions: [{
|
407
|
+
field: 'name',
|
408
|
+
operator: 'contains',
|
409
|
+
value: 'a',
|
410
|
+
}]
|
411
|
+
}.to_json }
|
412
|
+
|
413
|
+
it 'should get only the records matching the scope' do
|
414
|
+
getter.perform
|
415
|
+
records = getter.records
|
416
|
+
count = getter.count
|
417
|
+
|
418
|
+
expect(records.count).to eq 2
|
419
|
+
expect(count).to eq 2
|
420
|
+
expect(records.first.name).to eq 'Muerta'
|
421
|
+
expect(records.second.name).to eq 'Treasure'
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
358
425
|
end
|
359
426
|
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
describe ScopeManager do
|
3
|
+
let(:rendering_id) { 13 }
|
4
|
+
let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
|
5
|
+
let(:collection_name) { 'Users' }
|
6
|
+
let(:first_collection_scope) {
|
7
|
+
{
|
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
|
+
}
|
30
|
+
}
|
31
|
+
}
|
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) }
|
36
|
+
|
37
|
+
before do
|
38
|
+
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
|
+
end
|
43
|
+
|
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
|
58
|
+
|
59
|
+
describe 'when the backend return an errored response' do
|
60
|
+
let(:first_scopes_api_call_response) { Net::HTTPNotFound.new({}, 404, nil) }
|
61
|
+
|
62
|
+
it 'should raise an error' do
|
63
|
+
expect {
|
64
|
+
described_class.get_scope_for_user(user, collection_name)
|
65
|
+
}.to raise_error 'Unable to fetch scopes'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
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) }
|
93
|
+
|
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 })
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
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) }
|
108
|
+
|
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 })
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
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
|
+
]
|
129
|
+
},
|
130
|
+
'dynamicScopesValues' => {
|
131
|
+
'users' => { '1' => { '$currentUser.firstName' => 'Valentin' } }
|
132
|
+
}
|
133
|
+
}
|
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
|
+
}
|
144
|
+
}
|
145
|
+
|
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 })
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
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) }
|
156
|
+
|
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 })
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
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) }
|
167
|
+
|
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 })
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
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\"}]}" }
|
178
|
+
|
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 })
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
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\"}]}" }
|
190
|
+
|
191
|
+
describe 'when the target collection has NO scopes defined' do
|
192
|
+
let(:first_collection_scope) { { } }
|
193
|
+
|
194
|
+
describe 'when providing NO existing filters' do
|
195
|
+
let(:existing_filter) { nil }
|
196
|
+
let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
|
197
|
+
|
198
|
+
it 'should return nil' do
|
199
|
+
expect(filters).to eq nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe 'when providing existing filters' do
|
204
|
+
let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
|
205
|
+
|
206
|
+
it 'should return only the exisitng filters' do
|
207
|
+
expect(filters).to eq existing_filter
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe 'when the target collection has scopes defined' do
|
213
|
+
describe 'when providing NO existing filters' do
|
214
|
+
let(:existing_filter) { nil }
|
215
|
+
let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
|
216
|
+
|
217
|
+
it 'should return only the scope filters' do
|
218
|
+
expect(filters).to eq first_collection_scope_filter_as_string
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe 'when providing existing filters' do
|
223
|
+
let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
|
224
|
+
|
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}]}"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|