forest_liana 6.0.5 → 6.2.2
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/stats_controller.rb +47 -2
- data/app/helpers/forest_liana/schema_helper.rb +6 -0
- data/app/services/forest_liana/filters_parser.rb +43 -17
- data/app/services/forest_liana/permissions_checker.rb +52 -3
- data/config/initializers/errors.rb +6 -0
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/app/models/island.rb +1 -0
- data/spec/dummy/app/models/location.rb +3 -0
- data/spec/dummy/app/models/reference.rb +2 -0
- data/spec/dummy/db/migrate/20210326110524_create_references.rb +8 -0
- data/spec/dummy/db/migrate/20210326140855_create_locations.rb +10 -0
- data/spec/dummy/db/schema.rb +14 -1
- data/spec/dummy/lib/forest_liana/collections/location.rb +10 -0
- data/spec/dummy/lib/forest_liana/collections/user.rb +15 -0
- data/spec/requests/stats_spec.rb +114 -0
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +3 -3
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +2 -2
- data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +131 -0
- data/spec/services/forest_liana/resources_getter_spec.rb +359 -0
- data/spec/services/forest_liana/schema_adapter_spec.rb +1 -1
- metadata +135 -119
- data/test/services/forest_liana/resources_getter_test.rb +0 -284
@@ -109,7 +109,7 @@ module ForestLiana
|
|
109
109
|
|
110
110
|
describe 'handling cache' do
|
111
111
|
let(:collection_name) { 'all_rights_collection' }
|
112
|
-
let(:fake_ressource) {
|
112
|
+
let(:fake_ressource) { collection_name }
|
113
113
|
let(:default_rendering_id) { 1 }
|
114
114
|
|
115
115
|
context 'when calling twice the same permissions' do
|
@@ -191,7 +191,7 @@ module ForestLiana
|
|
191
191
|
|
192
192
|
|
193
193
|
context 'scopes cache' do
|
194
|
-
let(:fake_ressource) {
|
194
|
+
let(:fake_ressource) { collection_name }
|
195
195
|
let(:rendering_id) { 1 }
|
196
196
|
let(:collection_name) { 'custom' }
|
197
197
|
let(:scope_permissions) { { rendering_id => { 'custom' => nil } } }
|
@@ -349,7 +349,7 @@ module ForestLiana
|
|
349
349
|
describe '#is_authorized?' do
|
350
350
|
# Resource is only used to retrieve the collection name as it's stubbed it does not
|
351
351
|
# need to be defined
|
352
|
-
let(:fake_ressource) {
|
352
|
+
let(:fake_ressource) { collection_name }
|
353
353
|
let(:default_rendering_id) { nil }
|
354
354
|
let(:api_permissions) { default_api_permissions }
|
355
355
|
let(:collection_name) { 'all_rights_collection' }
|
@@ -132,7 +132,7 @@ module ForestLiana
|
|
132
132
|
|
133
133
|
describe 'handling cache' do
|
134
134
|
let(:collection_name) { 'all_rights_collection_boolean' }
|
135
|
-
let(:fake_ressource) {
|
135
|
+
let(:fake_ressource) { collection_name }
|
136
136
|
let(:default_rendering_id) { 1 }
|
137
137
|
|
138
138
|
context 'collections cache' do
|
@@ -396,7 +396,7 @@ module ForestLiana
|
|
396
396
|
describe '#is_authorized?' do
|
397
397
|
# Resource is only used to retrieve the collection name as it's stub it does not
|
398
398
|
# need to be defined
|
399
|
-
let(:fake_ressource) {
|
399
|
+
let(:fake_ressource) { collection_name }
|
400
400
|
let(:default_rendering_id) { nil }
|
401
401
|
let(:api_permissions) { default_api_permissions }
|
402
402
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
describe PermissionsChecker do
|
3
|
+
before(:each) do
|
4
|
+
described_class.empty_cache
|
5
|
+
end
|
6
|
+
|
7
|
+
let(:user_id) { 1 }
|
8
|
+
let(:schema) {
|
9
|
+
[
|
10
|
+
ForestLiana::Model::Collection.new({
|
11
|
+
name: 'all_rights_collection_boolean',
|
12
|
+
fields: [],
|
13
|
+
actions: [
|
14
|
+
ForestLiana::Model::Action.new({
|
15
|
+
name: 'Test',
|
16
|
+
endpoint: 'forest/actions/Test',
|
17
|
+
http_method: 'POST'
|
18
|
+
})
|
19
|
+
]
|
20
|
+
})
|
21
|
+
]
|
22
|
+
}
|
23
|
+
let(:scope_permissions) { nil }
|
24
|
+
let(:default_api_permissions) {
|
25
|
+
{
|
26
|
+
"data" => {
|
27
|
+
'collections' => {
|
28
|
+
"all_rights_collection_boolean" => {
|
29
|
+
"collection" => {
|
30
|
+
"browseEnabled" => true,
|
31
|
+
"readEnabled" => true,
|
32
|
+
"editEnabled" => true,
|
33
|
+
"addEnabled" => true,
|
34
|
+
"deleteEnabled" => true,
|
35
|
+
"exportEnabled" => true
|
36
|
+
},
|
37
|
+
"actions" => {
|
38
|
+
"Test" => {
|
39
|
+
"triggerEnabled" => true
|
40
|
+
},
|
41
|
+
}
|
42
|
+
},
|
43
|
+
},
|
44
|
+
'renderings' => scope_permissions
|
45
|
+
},
|
46
|
+
"meta" => {
|
47
|
+
"rolesACLActivated" => true
|
48
|
+
},
|
49
|
+
"stats" => {
|
50
|
+
"queries" => [
|
51
|
+
'SELECT COUNT(*) AS value FROM products;',
|
52
|
+
'SELECT COUNT(*) AS value FROM sometings;'
|
53
|
+
],
|
54
|
+
"values" => [
|
55
|
+
{
|
56
|
+
"type" => "Value",
|
57
|
+
"collection" => "Product",
|
58
|
+
"aggregate" => "Count"
|
59
|
+
}
|
60
|
+
],
|
61
|
+
},
|
62
|
+
}
|
63
|
+
}
|
64
|
+
let(:default_rendering_id) { 1 }
|
65
|
+
|
66
|
+
before do
|
67
|
+
allow(ForestLiana).to receive(:apimap).and_return(schema)
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#is_authorized?' do
|
71
|
+
# Resource is only used to retrieve the collection name as it's stub it does not
|
72
|
+
# need to be defined
|
73
|
+
let(:fake_ressource) { nil }
|
74
|
+
let(:default_rendering_id) { nil }
|
75
|
+
let(:api_permissions) { default_api_permissions }
|
76
|
+
|
77
|
+
before do
|
78
|
+
allow(ForestLiana::PermissionsGetter).to receive(:get_permissions_for_rendering).and_return(api_permissions)
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when permissions liveQueries' do
|
82
|
+
context 'contains the query' do
|
83
|
+
request_info = {
|
84
|
+
"type" => "Value",
|
85
|
+
"collection" => "Product",
|
86
|
+
"aggregate" => "Count"
|
87
|
+
};
|
88
|
+
subject { described_class.new(fake_ressource, 'liveQueries', default_rendering_id, user_id: user_id, query_request_info: 'SELECT COUNT(*) AS value FROM sometings;') }
|
89
|
+
|
90
|
+
it 'should be authorized' do
|
91
|
+
expect(subject.is_authorized?).to be true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'does not contains the query' do
|
96
|
+
subject { described_class.new(fake_ressource, 'liveQueries', default_rendering_id, user_id: user_id, query_request_info: 'SELECT * FROM products WHERE category = Gifts OR 1=1-- AND released = 1') }
|
97
|
+
it 'should NOT be authorized' do
|
98
|
+
expect(subject.is_authorized?).to be false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'when permissions statWithParameters' do
|
104
|
+
context 'contains the stat with the same parameters' do
|
105
|
+
request_info = {
|
106
|
+
"type" => "Value",
|
107
|
+
"collection" => "Product",
|
108
|
+
"aggregate" => "Count"
|
109
|
+
};
|
110
|
+
subject { described_class.new(fake_ressource, 'statWithParameters', default_rendering_id, user_id: user_id, query_request_info: request_info) }
|
111
|
+
|
112
|
+
it 'should be authorized' do
|
113
|
+
expect(subject.is_authorized?).to be true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'does not contains the stat with the same parameters' do
|
118
|
+
other_request_info = {
|
119
|
+
"type" => "Leaderboard",
|
120
|
+
"collection" => "Product",
|
121
|
+
"aggregate" => "Sum"
|
122
|
+
};
|
123
|
+
subject { described_class.new(fake_ressource, 'statWithParameters', default_rendering_id, user_id: user_id, query_request_info: other_request_info) }
|
124
|
+
it 'should NOT be authorized' do
|
125
|
+
expect(subject.is_authorized?).to be false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,359 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
describe ResourcesGetter do
|
3
|
+
let(:resource) { User }
|
4
|
+
let(:pageSize) { 10 }
|
5
|
+
let(:pageNumber) { 1 }
|
6
|
+
let(:sort) { 'id' }
|
7
|
+
let(:fields) { }
|
8
|
+
let(:filters) { }
|
9
|
+
|
10
|
+
let(:getter) { described_class.new(resource, {
|
11
|
+
page: { size: pageSize, number: pageNumber },
|
12
|
+
sort: sort,
|
13
|
+
fields: fields,
|
14
|
+
filters: filters,
|
15
|
+
})}
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
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']
|
19
|
+
.map { |name| User.create(name: name) }
|
20
|
+
|
21
|
+
islands = [
|
22
|
+
{ :name => 'Skull', :updated_at => Time.now - 1.years },
|
23
|
+
{ :name => 'Muerta', :updated_at => Time.now - 5.years },
|
24
|
+
{ :name => 'Treasure', :updated_at => Time.now },
|
25
|
+
{ :name => 'Birds', :updated_at => Time.now - 7.years },
|
26
|
+
{ :name => 'Lille', :updated_at => Time.now - 1.years }
|
27
|
+
].map { |island| Island.create(name: island[:name], updated_at: island[:updated_at]) }
|
28
|
+
|
29
|
+
trees = [
|
30
|
+
{ :name => 'Lemon Tree', :created_at => Time.now - 7.years, :island => islands[0], :owner => users[0], :cutter => users[0] },
|
31
|
+
{ :name => 'Ginger Tree', :created_at => Time.now - 7.years, :island => islands[0], :owner => users[1], :cutter => users[0] },
|
32
|
+
{ :name => 'Apple Tree', :created_at => Time.now - 5.years, :island => islands[1], :owner => users[2], :cutter => users[0] },
|
33
|
+
{ :name => 'Pear Tree', :created_at => Time.now + 4.hours, :island => islands[3], :owner => users[3], :cutter => users[1] },
|
34
|
+
{ :name => 'Choco Tree', :created_at => Time.now, :island => islands[3], :owner => users[4], :cutter => users[1] }
|
35
|
+
].map { |tree| Tree.create(name: tree[:name], created_at: tree[:created_at], island: tree[:island], owner: tree[:owner], cutter: tree[:cutter]) }
|
36
|
+
|
37
|
+
locations = [
|
38
|
+
{ :coordinates => '12345', :island => islands[0] },
|
39
|
+
{ :coordinates => '54321', :island => islands[1] },
|
40
|
+
{ :coordinates => '43215', :island => islands[2] },
|
41
|
+
{ :coordinates => '21543', :island => islands[3] },
|
42
|
+
{ :coordinates => '32154', :island => islands[4] }
|
43
|
+
].map { |location| Location.create(coordinates: location[:coordinates], island: location[:island]) }
|
44
|
+
|
45
|
+
reference = Reference.create()
|
46
|
+
end
|
47
|
+
|
48
|
+
after(:each) do
|
49
|
+
User.destroy_all
|
50
|
+
Island.destroy_all
|
51
|
+
Location.destroy_all
|
52
|
+
Tree.destroy_all
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'when there are more records than the page size' do
|
56
|
+
describe 'when asking for the 1st page and 15 records' do
|
57
|
+
let(:pageSize) { 15 }
|
58
|
+
let(:sort) { '-id' }
|
59
|
+
|
60
|
+
it 'should get only the expected records' do
|
61
|
+
getter.perform
|
62
|
+
records = getter.records
|
63
|
+
count = getter.count
|
64
|
+
|
65
|
+
expect(records.count).to eq 15
|
66
|
+
expect(count).to eq 30
|
67
|
+
expect(records.first.id).to eq 30
|
68
|
+
expect(records.last.id).to eq 16
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'when asking for the 2nd page and 10 records' do
|
73
|
+
let(:pageNumber) { 2 }
|
74
|
+
let(:sort) { '-id' }
|
75
|
+
|
76
|
+
it 'should get only the expected records' do
|
77
|
+
getter.perform
|
78
|
+
records = getter.records
|
79
|
+
count = getter.count
|
80
|
+
|
81
|
+
expect(records.count).to eq 10
|
82
|
+
expect(count).to eq 30
|
83
|
+
expect(records.first.id).to eq 20
|
84
|
+
expect(records.last.id).to eq 11
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'when on a model having a reserved SQL word as name' do
|
90
|
+
let(:resource) { Reference }
|
91
|
+
|
92
|
+
it 'should get the ressource properly' do
|
93
|
+
getter.perform
|
94
|
+
records = getter.records
|
95
|
+
count = getter.count
|
96
|
+
|
97
|
+
expect(records.count).to eq 1
|
98
|
+
expect(count).to eq 1
|
99
|
+
expect(records.first.id).to eq 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'when sorting by a specific field' do
|
104
|
+
let(:pageSize) { 5 }
|
105
|
+
let(:sort) { '-name' }
|
106
|
+
|
107
|
+
it 'should get only the expected records' do
|
108
|
+
getter.perform
|
109
|
+
records = getter.records
|
110
|
+
count = getter.count
|
111
|
+
|
112
|
+
expect(records.count).to eq 5
|
113
|
+
expect(count).to eq 30
|
114
|
+
expect(records.map(&:name)).to eq ['Xavier', 'Vince', 'Valentin', 'Steve', 'Sandro']
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'when sorting by a belongs_to association' do
|
119
|
+
let(:resource) { Tree }
|
120
|
+
let(:sort) { 'owner.name' }
|
121
|
+
|
122
|
+
it 'should get only the expected records' do
|
123
|
+
getter.perform
|
124
|
+
records = getter.records
|
125
|
+
count = getter.count
|
126
|
+
|
127
|
+
expect(records.count).to eq 5
|
128
|
+
expect(count).to eq 5
|
129
|
+
expect(records.map(&:id)).to eq [1, 5, 2, 4, 3]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'when sorting by a has_one association' do
|
134
|
+
let(:resource) { Island }
|
135
|
+
let(:sort) { 'location.coordinates' }
|
136
|
+
let(:pageSize) { 5 }
|
137
|
+
|
138
|
+
it 'should get only the expected records' do
|
139
|
+
getter.perform
|
140
|
+
records = getter.records
|
141
|
+
count = getter.count
|
142
|
+
|
143
|
+
expect(records.count).to eq 5
|
144
|
+
expect(count).to eq 5
|
145
|
+
expect(records.map(&:id)).to eq [1, 4, 5, 3, 2]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'when filtering on an ambiguous field' do
|
150
|
+
let(:resource) { Tree }
|
151
|
+
let(:pageSize) { 5 }
|
152
|
+
let(:fields) { { 'Tree' => 'id' } }
|
153
|
+
let(:filters) { {
|
154
|
+
aggregator: 'and',
|
155
|
+
conditions: [{
|
156
|
+
field: 'created_at',
|
157
|
+
operator: 'after',
|
158
|
+
value: "#{Time.now - 6.year}",
|
159
|
+
}, {
|
160
|
+
field: 'cutter:name',
|
161
|
+
operator: 'equal',
|
162
|
+
value: 'Michel'
|
163
|
+
}]
|
164
|
+
}.to_json }
|
165
|
+
|
166
|
+
it 'should get only the expected records' do
|
167
|
+
getter.perform
|
168
|
+
records = getter.records
|
169
|
+
count = getter.count
|
170
|
+
|
171
|
+
expect(records.count).to eq 1
|
172
|
+
expect(count).to eq 1
|
173
|
+
expect(records.first.id).to eq 3
|
174
|
+
expect(records.first.name).to eq 'Apple Tree'
|
175
|
+
expect(records.first.cutter.name).to eq 'Michel'
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe 'when filtering on before x hours ago' do
|
180
|
+
let(:resource) { Tree }
|
181
|
+
let(:fields) { { 'Tree' => 'id' } }
|
182
|
+
let(:filters) { {
|
183
|
+
field: 'created_at',
|
184
|
+
operator: 'before_x_hours_ago',
|
185
|
+
value: 3
|
186
|
+
}.to_json }
|
187
|
+
|
188
|
+
it 'should filter as expected' do
|
189
|
+
getter.perform
|
190
|
+
records = getter.records
|
191
|
+
count = getter.count
|
192
|
+
|
193
|
+
expect(records.count).to eq 3
|
194
|
+
expect(count).to eq 3
|
195
|
+
expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree', 'Apple Tree']
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe 'when filtering on after x hours ago' do
|
200
|
+
let(:resource) { Tree }
|
201
|
+
let(:fields) { { 'Tree' => 'id' } }
|
202
|
+
let(:filters) { {
|
203
|
+
field: 'created_at',
|
204
|
+
operator: 'after_x_hours_ago',
|
205
|
+
value: 3
|
206
|
+
}.to_json }
|
207
|
+
|
208
|
+
it 'should filter as expected' do
|
209
|
+
getter.perform
|
210
|
+
records = getter.records
|
211
|
+
count = getter.count
|
212
|
+
|
213
|
+
expect(records.count).to eq 2
|
214
|
+
expect(count).to eq 2
|
215
|
+
expect(records.map(&:name)).to eq ['Pear Tree', 'Choco Tree']
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe 'when sorting on an ambiguous field name with a filter' do
|
220
|
+
let(:resource) { Tree }
|
221
|
+
let(:sort) { '-name' }
|
222
|
+
let(:fields) { { 'Tree' => 'id' } }
|
223
|
+
let(:filters) { {
|
224
|
+
field: 'cutter:name',
|
225
|
+
operator: 'equal',
|
226
|
+
value: 'Michel'
|
227
|
+
}.to_json }
|
228
|
+
|
229
|
+
it 'should get only the sorted expected records' do
|
230
|
+
getter.perform
|
231
|
+
records = getter.records
|
232
|
+
count = getter.count
|
233
|
+
|
234
|
+
expect(records.count).to eq 3
|
235
|
+
expect(count).to eq 3
|
236
|
+
expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree', 'Apple Tree']
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe 'when filtering on an updated_at field of the main collection' do
|
241
|
+
let(:resource) { Island }
|
242
|
+
let(:filters) { {
|
243
|
+
field: 'updated_at',
|
244
|
+
operator: 'previous_year'
|
245
|
+
}.to_json }
|
246
|
+
|
247
|
+
it 'should get only the expected records' do
|
248
|
+
getter.perform
|
249
|
+
records = getter.records
|
250
|
+
count = getter.count
|
251
|
+
|
252
|
+
expect(records.count).to eq 2
|
253
|
+
expect(count).to eq 2
|
254
|
+
expect(records.map(&:name)).to eq ['Skull', 'Lille']
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe 'when filtering on an updated_at field of an associated collection' do
|
259
|
+
let(:resource) { Tree }
|
260
|
+
let(:fields) { { 'Tree' => 'id' } }
|
261
|
+
let(:filters) { {
|
262
|
+
field: 'island:updated_at',
|
263
|
+
operator: 'previous_year'
|
264
|
+
}.to_json }
|
265
|
+
|
266
|
+
it 'should get only the expected records' do
|
267
|
+
getter.perform
|
268
|
+
records = getter.records
|
269
|
+
count = getter.count
|
270
|
+
|
271
|
+
expect(records.count).to eq 2
|
272
|
+
expect(count).to eq 2
|
273
|
+
expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree']
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe 'when filtering on an exact updated_at field of an associated collection' do
|
278
|
+
let(:resource) { Tree }
|
279
|
+
let(:fields) { { 'Tree' => 'id' } }
|
280
|
+
let(:filters) { {
|
281
|
+
field: 'island:updated_at',
|
282
|
+
operator: 'equal',
|
283
|
+
value: 'Sat Jul 02 2016 11:52:00 GMT-0400 (EDT)',
|
284
|
+
}.to_json }
|
285
|
+
|
286
|
+
it 'should get only the expected records' do
|
287
|
+
getter.perform
|
288
|
+
records = getter.records
|
289
|
+
count = getter.count
|
290
|
+
|
291
|
+
expect(records.count).to eq 0
|
292
|
+
expect(count).to eq 0
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe 'when filtering on a field of an associated collection that does not exist' do
|
297
|
+
let(:resource) { Tree }
|
298
|
+
let(:fields) { { 'Tree' => 'id' } }
|
299
|
+
let(:filters) { {
|
300
|
+
field: 'leaf:id',
|
301
|
+
operator: 'equal',
|
302
|
+
value: 1
|
303
|
+
}.to_json }
|
304
|
+
|
305
|
+
it 'should raise the right error' do
|
306
|
+
expect { getter }.to raise_error(ForestLiana::Errors::HTTP422Error, "Association 'leaf' not found")
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe 'when filtering on a field that does not exists' do
|
311
|
+
let(:resource) { Tree }
|
312
|
+
let(:fields) { { 'Tree' => 'id' } }
|
313
|
+
let(:filters) { {
|
314
|
+
field: 'content',
|
315
|
+
operator: 'contains',
|
316
|
+
value: 'c'
|
317
|
+
}.to_json }
|
318
|
+
|
319
|
+
it 'should raise the right error' do
|
320
|
+
expect { getter }.to raise_error(ForestLiana::Errors::HTTP422Error, "Field 'content' not found")
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe 'when filtering on a smart field' do
|
325
|
+
let(:filters) { {
|
326
|
+
field: 'cap_name',
|
327
|
+
operator: 'equal',
|
328
|
+
value: 'MICHEL',
|
329
|
+
}.to_json }
|
330
|
+
|
331
|
+
it 'should filter as expected' do
|
332
|
+
getter.perform
|
333
|
+
records = getter.records
|
334
|
+
count = getter.count
|
335
|
+
|
336
|
+
expect(records.count).to eq 1
|
337
|
+
expect(count).to eq 1
|
338
|
+
expect(records.first.id).to eq 1
|
339
|
+
expect(records.first.name).to eq 'Michel'
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
describe 'when filtering on a smart field with no filter method' do
|
344
|
+
let(:resource) { Location }
|
345
|
+
let(:filters) { {
|
346
|
+
field: 'alter_coordinates',
|
347
|
+
operator: 'equal',
|
348
|
+
value: '12345XYZ',
|
349
|
+
}.to_json }
|
350
|
+
|
351
|
+
it 'should raise the right error' do
|
352
|
+
expect { getter }.to raise_error(
|
353
|
+
ForestLiana::Errors::NotImplementedMethodError,
|
354
|
+
"method filter on smart field 'alter_coordinates' not found"
|
355
|
+
)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|