odata4 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.autotest +2 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +75 -0
- data/CHANGELOG.md +120 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +287 -0
- data/Rakefile +7 -0
- data/TODO.md +55 -0
- data/lib/odata4.rb +37 -0
- data/lib/odata4/complex_type.rb +76 -0
- data/lib/odata4/complex_type/property.rb +114 -0
- data/lib/odata4/entity.rb +319 -0
- data/lib/odata4/entity_set.rb +162 -0
- data/lib/odata4/enum_type.rb +95 -0
- data/lib/odata4/enum_type/property.rb +62 -0
- data/lib/odata4/navigation_property.rb +29 -0
- data/lib/odata4/navigation_property/proxy.rb +76 -0
- data/lib/odata4/properties.rb +25 -0
- data/lib/odata4/properties/binary.rb +50 -0
- data/lib/odata4/properties/boolean.rb +37 -0
- data/lib/odata4/properties/date.rb +27 -0
- data/lib/odata4/properties/date_time.rb +83 -0
- data/lib/odata4/properties/date_time_offset.rb +17 -0
- data/lib/odata4/properties/decimal.rb +50 -0
- data/lib/odata4/properties/float.rb +67 -0
- data/lib/odata4/properties/geography.rb +13 -0
- data/lib/odata4/properties/geography/base.rb +162 -0
- data/lib/odata4/properties/geography/line_string.rb +33 -0
- data/lib/odata4/properties/geography/point.rb +31 -0
- data/lib/odata4/properties/geography/polygon.rb +38 -0
- data/lib/odata4/properties/guid.rb +17 -0
- data/lib/odata4/properties/integer.rb +107 -0
- data/lib/odata4/properties/number.rb +14 -0
- data/lib/odata4/properties/string.rb +72 -0
- data/lib/odata4/properties/time.rb +40 -0
- data/lib/odata4/properties/time_of_day.rb +27 -0
- data/lib/odata4/property.rb +118 -0
- data/lib/odata4/property_registry.rb +41 -0
- data/lib/odata4/query.rb +231 -0
- data/lib/odata4/query/criteria.rb +92 -0
- data/lib/odata4/query/criteria/comparison_operators.rb +49 -0
- data/lib/odata4/query/criteria/date_functions.rb +61 -0
- data/lib/odata4/query/criteria/geography_functions.rb +21 -0
- data/lib/odata4/query/criteria/lambda_operators.rb +27 -0
- data/lib/odata4/query/criteria/string_functions.rb +40 -0
- data/lib/odata4/query/in_batches.rb +58 -0
- data/lib/odata4/query/result.rb +84 -0
- data/lib/odata4/query/result/atom.rb +41 -0
- data/lib/odata4/query/result/json.rb +42 -0
- data/lib/odata4/railtie.rb +19 -0
- data/lib/odata4/service.rb +344 -0
- data/lib/odata4/service_registry.rb +52 -0
- data/lib/odata4/version.rb +3 -0
- data/odata4.gemspec +34 -0
- data/spec/fixtures/files/entity_to_xml.xml +17 -0
- data/spec/fixtures/files/metadata.xml +150 -0
- data/spec/fixtures/files/product_0.json +10 -0
- data/spec/fixtures/files/product_0.xml +28 -0
- data/spec/fixtures/files/products.json +106 -0
- data/spec/fixtures/files/products.xml +308 -0
- data/spec/fixtures/files/supplier_0.json +26 -0
- data/spec/fixtures/files/supplier_0.xml +32 -0
- data/spec/fixtures/vcr_cassettes/complex_type_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs.yml +1348 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml +183 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml +256 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/new_entry.yml +185 -0
- data/spec/fixtures/vcr_cassettes/entity_specs.yml +285 -0
- data/spec/fixtures/vcr_cassettes/navigation_property_proxy_specs.yml +346 -0
- data/spec/fixtures/vcr_cassettes/query/result_specs.yml +189 -0
- data/spec/fixtures/vcr_cassettes/query_specs.yml +663 -0
- data/spec/fixtures/vcr_cassettes/service_registry_specs.yml +129 -0
- data/spec/fixtures/vcr_cassettes/service_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/usage_example_specs.yml +749 -0
- data/spec/odata4/complex_type_spec.rb +116 -0
- data/spec/odata4/entity/shared_examples.rb +82 -0
- data/spec/odata4/entity_set_spec.rb +168 -0
- data/spec/odata4/entity_spec.rb +151 -0
- data/spec/odata4/enum_type_spec.rb +134 -0
- data/spec/odata4/navigation_property/proxy_spec.rb +44 -0
- data/spec/odata4/navigation_property_spec.rb +55 -0
- data/spec/odata4/properties/binary_spec.rb +50 -0
- data/spec/odata4/properties/boolean_spec.rb +72 -0
- data/spec/odata4/properties/date_spec.rb +23 -0
- data/spec/odata4/properties/date_time_offset_spec.rb +30 -0
- data/spec/odata4/properties/date_time_spec.rb +23 -0
- data/spec/odata4/properties/decimal_spec.rb +24 -0
- data/spec/odata4/properties/float_spec.rb +45 -0
- data/spec/odata4/properties/geography/line_string_spec.rb +33 -0
- data/spec/odata4/properties/geography/point_spec.rb +29 -0
- data/spec/odata4/properties/geography/polygon_spec.rb +55 -0
- data/spec/odata4/properties/geography/shared_examples.rb +72 -0
- data/spec/odata4/properties/guid_spec.rb +17 -0
- data/spec/odata4/properties/integer_spec.rb +58 -0
- data/spec/odata4/properties/string_spec.rb +46 -0
- data/spec/odata4/properties/time_of_day_spec.rb +23 -0
- data/spec/odata4/properties/time_spec.rb +15 -0
- data/spec/odata4/property_registry_spec.rb +16 -0
- data/spec/odata4/property_spec.rb +32 -0
- data/spec/odata4/query/criteria_spec.rb +229 -0
- data/spec/odata4/query/result_spec.rb +53 -0
- data/spec/odata4/query_spec.rb +196 -0
- data/spec/odata4/service_registry_spec.rb +18 -0
- data/spec/odata4/service_spec.rb +80 -0
- data/spec/odata4/usage_example_spec.rb +176 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/coverage.rb +2 -0
- data/spec/support/vcr.rb +9 -0
- metadata +380 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples 'an operator criterium' do |operator, value, to_s|
|
4
|
+
it { expect(criteria).to eq(subject) }
|
5
|
+
it { expect(criteria.operator).to eq(operator) }
|
6
|
+
it { expect(criteria.value).to eq(value) }
|
7
|
+
it { expect(criteria.to_s).to eq(to_s) }
|
8
|
+
end
|
9
|
+
|
10
|
+
shared_examples 'a function criterium' do |function, argument, to_s|
|
11
|
+
it { expect(criteria).to eq(subject) }
|
12
|
+
it { expect(criteria.function).to eq(function) }
|
13
|
+
it { expect(criteria.argument).to eq(argument) }
|
14
|
+
it { expect(criteria.to_s).to eq(to_s) }
|
15
|
+
end
|
16
|
+
|
17
|
+
shared_examples 'an operator-function criterium' do |function, operator, value, to_s|
|
18
|
+
it { expect(criteria).to eq(subject) }
|
19
|
+
it { expect(criteria.function).to eq(function) }
|
20
|
+
it { expect(criteria.operator).to eq(operator) }
|
21
|
+
it { expect(criteria.value).to eq(value) }
|
22
|
+
it { expect(criteria.to_s).to eq(to_s) }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe OData4::Query::Criteria do
|
26
|
+
let(:string_property) { OData4::Properties::String.new(:Name, nil) }
|
27
|
+
let(:integer_property) { OData4::Properties::Integer.new(:Age, nil) }
|
28
|
+
let(:datetime_property) { OData4::Properties::DateTime.new(:BirthDate, nil) }
|
29
|
+
let(:geo_property) { OData4::Properties::Geography::Point.new(:Position, nil) }
|
30
|
+
# TODO: use actual `NavigationProperty` class here
|
31
|
+
let(:navigation_property) { OData4::Property.new(:Items, nil) }
|
32
|
+
|
33
|
+
let(:subject) { OData4::Query::Criteria.new(property: string_property) }
|
34
|
+
|
35
|
+
it { expect(subject).to respond_to(:property) }
|
36
|
+
it { expect(subject.property).to eq(string_property)}
|
37
|
+
|
38
|
+
it { expect(subject).to respond_to(:operator) }
|
39
|
+
it { expect(subject).to respond_to(:value) }
|
40
|
+
it { expect(subject).to respond_to(:to_s) }
|
41
|
+
|
42
|
+
describe 'comparison operators' do
|
43
|
+
describe '#eq' do
|
44
|
+
let(:criteria) { subject.eq('Bread') }
|
45
|
+
|
46
|
+
it { expect(subject).to respond_to(:eq) }
|
47
|
+
it_behaves_like 'an operator criterium', :eq, 'Bread', "Name eq 'Bread'"
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#ne' do
|
51
|
+
let(:criteria) { subject.ne('Bread') }
|
52
|
+
|
53
|
+
it { expect(subject).to respond_to(:ne) }
|
54
|
+
it_behaves_like 'an operator criterium', :ne, 'Bread', "Name ne 'Bread'"
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#gt' do
|
58
|
+
let(:subject) { OData4::Query::Criteria.new(property: integer_property) }
|
59
|
+
let(:criteria) { subject.gt(5) }
|
60
|
+
|
61
|
+
it { expect(subject).to respond_to(:gt) }
|
62
|
+
it_behaves_like 'an operator criterium', :gt, 5, "Age gt 5"
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#ge' do
|
66
|
+
let(:subject) { OData4::Query::Criteria.new(property: integer_property) }
|
67
|
+
let(:criteria) { subject.ge(5) }
|
68
|
+
|
69
|
+
it { expect(subject).to respond_to(:ge) }
|
70
|
+
it_behaves_like 'an operator criterium', :ge, 5, 'Age ge 5'
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#lt' do
|
74
|
+
let(:subject) { OData4::Query::Criteria.new(property: integer_property) }
|
75
|
+
let(:criteria) { subject.lt(5) }
|
76
|
+
|
77
|
+
it { expect(subject).to respond_to(:lt) }
|
78
|
+
it_behaves_like 'an operator criterium', :lt, 5, 'Age lt 5'
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#le' do
|
82
|
+
let(:subject) { OData4::Query::Criteria.new(property: integer_property) }
|
83
|
+
let(:criteria) { subject.le(5) }
|
84
|
+
|
85
|
+
it { expect(subject).to respond_to(:le) }
|
86
|
+
it_behaves_like 'an operator criterium', :le, 5, 'Age le 5'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'string functions' do
|
91
|
+
describe '#contains' do
|
92
|
+
let(:criteria) { subject.contains('freds') }
|
93
|
+
|
94
|
+
it { expect(subject).to respond_to(:contains) }
|
95
|
+
it_behaves_like 'a function criterium', :contains, 'freds', "contains(Name,'freds')"
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#startswith' do
|
99
|
+
let(:criteria) { subject.startswith('Alfreds') }
|
100
|
+
|
101
|
+
it { expect(subject).to respond_to(:startswith) }
|
102
|
+
it_behaves_like 'a function criterium', :startswith, 'Alfreds', "startswith(Name,'Alfreds')"
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#endswith' do
|
106
|
+
let(:criteria) { subject.endswith('Futterkiste') }
|
107
|
+
|
108
|
+
it { expect(subject).to respond_to(:endswith) }
|
109
|
+
it_behaves_like 'a function criterium', :endswith, 'Futterkiste', "endswith(Name,'Futterkiste')"
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#tolower' do
|
113
|
+
let(:criteria) { subject.tolower.eq('alfreds futterkiste') }
|
114
|
+
|
115
|
+
it { expect(subject).to respond_to(:tolower) }
|
116
|
+
it_behaves_like 'an operator-function criterium', :tolower, :eq, 'alfreds futterkiste', "tolower(Name) eq 'alfreds futterkiste'"
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#toupper' do
|
120
|
+
let(:criteria) { subject.toupper.eq('ALFREDS FUTTERKISTE') }
|
121
|
+
|
122
|
+
it { expect(subject).to respond_to(:toupper) }
|
123
|
+
it_behaves_like 'an operator-function criterium', :toupper, :eq, 'ALFREDS FUTTERKISTE', "toupper(Name) eq 'ALFREDS FUTTERKISTE'"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'date functions' do
|
128
|
+
let(:subject) { OData4::Query::Criteria.new(property: datetime_property) }
|
129
|
+
|
130
|
+
describe '#year' do
|
131
|
+
let(:criteria) { subject.year.eq(1981) }
|
132
|
+
|
133
|
+
it { expect(subject).to respond_to(:year) }
|
134
|
+
it_behaves_like 'an operator-function criterium', :year, :eq, 1981, 'year(BirthDate) eq 1981'
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#month' do
|
138
|
+
let(:criteria) { subject.month.eq(8) }
|
139
|
+
|
140
|
+
it { expect(subject).to respond_to(:month) }
|
141
|
+
it_behaves_like 'an operator-function criterium', :month, :eq, 8, 'month(BirthDate) eq 8'
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#day' do
|
145
|
+
let(:criteria) { subject.day.eq(27) }
|
146
|
+
|
147
|
+
it { expect(subject).to respond_to(:day) }
|
148
|
+
it_behaves_like 'an operator-function criterium', :day, :eq, 27, 'day(BirthDate) eq 27'
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#hour' do
|
152
|
+
let(:criteria) { subject.hour.eq(9) }
|
153
|
+
|
154
|
+
it { expect(subject).to respond_to(:hour) }
|
155
|
+
it_behaves_like 'an operator-function criterium', :hour, :eq, 9, 'hour(BirthDate) eq 9'
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#minute' do
|
159
|
+
let(:criteria) { subject.minute.eq(35) }
|
160
|
+
|
161
|
+
it { expect(subject).to respond_to(:minute) }
|
162
|
+
it_behaves_like 'an operator-function criterium', :minute, :eq, 35, 'minute(BirthDate) eq 35'
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#second' do
|
166
|
+
let(:criteria) { subject.second.eq(11) }
|
167
|
+
|
168
|
+
it { expect(subject).to respond_to(:second) }
|
169
|
+
it_behaves_like 'an operator-function criterium', :second, :eq, 11, 'second(BirthDate) eq 11'
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#fractionalseconds' do
|
173
|
+
let(:criteria) { subject.fractionalseconds.eq(0) }
|
174
|
+
|
175
|
+
it { expect(subject).to respond_to(:fractionalseconds) }
|
176
|
+
it_behaves_like 'an operator-function criterium', :fractionalseconds, :eq, 0, 'fractionalseconds(BirthDate) eq 0'
|
177
|
+
end
|
178
|
+
|
179
|
+
describe '#date' do
|
180
|
+
let(:criteria) { subject.date.ne('date(EndTime)') }
|
181
|
+
|
182
|
+
it { expect(subject).to respond_to(:date) }
|
183
|
+
it_behaves_like 'an operator-function criterium', :date, :ne, 'date(EndTime)', 'date(BirthDate) ne date(EndTime)'
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#time' do
|
187
|
+
let(:criteria) { subject.time.le('StartOfDay') }
|
188
|
+
|
189
|
+
it { expect(subject).to respond_to(:time) }
|
190
|
+
it_behaves_like 'an operator-function criterium', :time, :le, 'StartOfDay', 'time(BirthDate) le StartOfDay'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'geospatial functions' do
|
195
|
+
let(:subject) { OData4::Query::Criteria.new(property: geo_property) }
|
196
|
+
|
197
|
+
describe '#distance' do
|
198
|
+
let(:criteria) { subject.distance('TargetPosition').le(42) }
|
199
|
+
|
200
|
+
it { expect(subject).to respond_to(:distance) }
|
201
|
+
it_behaves_like 'an operator-function criterium', :'geo.distance', :le, 42, 'geo.distance(Position,TargetPosition) le 42'
|
202
|
+
end
|
203
|
+
|
204
|
+
describe '#intersects' do
|
205
|
+
let(:criteria) { subject.intersects('TargetArea') }
|
206
|
+
|
207
|
+
it { expect(subject).to respond_to(:intersects) }
|
208
|
+
it_behaves_like 'a function criterium', :'geo.intersects', 'TargetArea', 'geo.intersects(Position,TargetArea)'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe 'lambda operators' do
|
213
|
+
let(:subject) { OData4::Query::Criteria.new(property: navigation_property) }
|
214
|
+
|
215
|
+
describe '#any' do
|
216
|
+
let(:criteria) { subject.any('Quantity').gt(100) }
|
217
|
+
|
218
|
+
it { expect(subject).to respond_to(:any) }
|
219
|
+
it_behaves_like 'an operator-function criterium', :any, :gt, 100, 'Items/any(d:d/Quantity gt 100)'
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#all' do
|
223
|
+
let(:criteria) { subject.all('Quantity').gt(100) }
|
224
|
+
|
225
|
+
it { expect(subject).to respond_to(:all) }
|
226
|
+
it_behaves_like 'an operator-function criterium', :all, :gt, 100, 'Items/all(d:d/Quantity gt 100)'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples 'valid result' do
|
4
|
+
it { expect(result.count).to eq(11) }
|
5
|
+
|
6
|
+
describe '#empty?' do
|
7
|
+
it { expect(result).to respond_to(:empty?) }
|
8
|
+
it { expect(result.empty?).to eq(false) }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#each' do
|
12
|
+
it { expect(result).to respond_to(:each) }
|
13
|
+
it 'returns just OData4::Entities of the right type' do
|
14
|
+
result.each do |entity|
|
15
|
+
expect(entity).to be_a(OData4::Entity)
|
16
|
+
expect(entity.type).to eq('Product')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe OData4::Query::Result, vcr: {cassette_name: 'query/result_specs'} do
|
23
|
+
before(:example) do
|
24
|
+
OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', name: 'ODataDemo')
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:entity_set) { OData4::ServiceRegistry['ODataDemo']['Products'] }
|
28
|
+
# let(:subject) { entity_set.query.execute }
|
29
|
+
|
30
|
+
let(:response) do
|
31
|
+
response = double('response')
|
32
|
+
allow(response).to receive_messages(
|
33
|
+
headers: { 'Content-Type' => content_type },
|
34
|
+
body: response_body
|
35
|
+
)
|
36
|
+
response
|
37
|
+
end
|
38
|
+
let(:result) { OData4::Query::Result.new(entity_set.query, response) }
|
39
|
+
|
40
|
+
context 'with Atom Result' do
|
41
|
+
let(:content_type) { 'application/atom+xml' }
|
42
|
+
let(:response_body) { File.read('spec/fixtures/files/products.xml') }
|
43
|
+
|
44
|
+
it_behaves_like 'valid result'
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with JSON Result' do
|
48
|
+
let(:content_type) { 'application/json' }
|
49
|
+
let(:response_body) { File.read('spec/fixtures/files/products.json') }
|
50
|
+
|
51
|
+
it_behaves_like 'valid result'
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OData4::Query, vcr: {cassette_name: 'query_specs'} do
|
4
|
+
before(:example) do
|
5
|
+
OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', name: 'ODataDemo')
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:subject) { OData4::Query.new(entity_set) }
|
9
|
+
let(:entity_set) { OData4::EntitySet.new(options) }
|
10
|
+
let(:options) { {
|
11
|
+
container: 'DemoService', namespace: 'ODataDemo', name: 'Products',
|
12
|
+
service_name: 'ODataDemo', type: 'Product'
|
13
|
+
} }
|
14
|
+
|
15
|
+
it { expect(subject).to respond_to(:to_s) }
|
16
|
+
it { expect(subject.to_s).to eq('Products')}
|
17
|
+
|
18
|
+
it { expect(subject).to respond_to(:[]) }
|
19
|
+
describe '#[]' do
|
20
|
+
it { expect(subject[:Name]).to be_a(OData4::Query::Criteria) }
|
21
|
+
it { expect(subject[:Name].property).to be_a(OData4::Property) }
|
22
|
+
end
|
23
|
+
|
24
|
+
it { expect(subject).to respond_to(:find) }
|
25
|
+
describe '#find' do
|
26
|
+
let(:product) { subject.find(0) }
|
27
|
+
|
28
|
+
it 'finds an entity by its ID' do
|
29
|
+
expect(product).to be_a(OData4::Entity)
|
30
|
+
expect(product['ID']).to eq(0)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'allows expanding navigational properties' do
|
34
|
+
product_with_categories = subject.expand('Categories').find(0)
|
35
|
+
expect(product_with_categories['Categories']).to eq([
|
36
|
+
{ "ID" => 0, "Name" => "Food" }
|
37
|
+
])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it { expect(subject).to respond_to(:where) }
|
42
|
+
describe '#where' do
|
43
|
+
let(:criteria) { subject[:Name].eq('Bread') }
|
44
|
+
let(:query_string) { "Products?$filter=Name eq 'Bread'" }
|
45
|
+
|
46
|
+
it { expect(subject.where(criteria)).to eq(subject) }
|
47
|
+
it { expect(subject.where(criteria).to_s).to eq(query_string) }
|
48
|
+
end
|
49
|
+
|
50
|
+
it { expect(subject).to respond_to(:search) }
|
51
|
+
describe '#search' do
|
52
|
+
let(:term) { '"mountain bike"' }
|
53
|
+
let(:query_string) { 'Products?$search="mountain bike"' }
|
54
|
+
|
55
|
+
it { expect(subject.search(term)).to eq(subject) }
|
56
|
+
it { expect(subject.search(term).to_s).to eq(query_string) }
|
57
|
+
|
58
|
+
describe 'with multiple terms' do
|
59
|
+
let(:query_string) { 'Products?$search="mountain bike" AND NOT clothing' }
|
60
|
+
|
61
|
+
it { expect(subject.search(term).search('NOT clothing').to_s).to eq(query_string) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#it { expect(subject).to respond_to(:and) }
|
66
|
+
describe '#and' do
|
67
|
+
it { pending; fail }
|
68
|
+
end
|
69
|
+
|
70
|
+
#it { expect(subject).to respond_to(:or) }
|
71
|
+
describe '#or' do
|
72
|
+
it { pending; fail }
|
73
|
+
end
|
74
|
+
|
75
|
+
it { expect(subject).to respond_to(:skip) }
|
76
|
+
describe '#skip' do
|
77
|
+
it { expect(subject.skip(5)).to eq(subject) }
|
78
|
+
it 'properly formats query with skip specified' do
|
79
|
+
subject.skip(5)
|
80
|
+
expect(subject.to_s).to eq('Products?$skip=5')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it { expect(subject).to respond_to(:limit) }
|
85
|
+
describe '#limit' do
|
86
|
+
|
87
|
+
it { expect(subject.limit(5)).to eq(subject) }
|
88
|
+
it 'properly formats query with limit specified' do
|
89
|
+
subject.limit(5)
|
90
|
+
expect(subject.to_s).to eq('Products?$top=5')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it { expect(subject).to respond_to(:include_count) }
|
95
|
+
describe '#include_count' do
|
96
|
+
it { expect(subject.include_count).to eq(subject) }
|
97
|
+
it 'properly formats query with include_count specified' do
|
98
|
+
subject.include_count
|
99
|
+
expect(subject.to_s).to eq('Products?$count=true')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it { expect(subject).to respond_to(:select) }
|
104
|
+
describe '#select' do
|
105
|
+
it { expect(subject.select(:Name, :Price)).to eq(subject) }
|
106
|
+
it 'properly formats query with select operation specified' do
|
107
|
+
subject.select(:Name, :Price)
|
108
|
+
expect(subject.to_s).to eq('Products?$select=Name,Price')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it { expect(subject).to respond_to(:expand) }
|
113
|
+
describe '#expand' do
|
114
|
+
it { expect(subject.expand(:Supplier)).to eq(subject) }
|
115
|
+
it 'properly formats query with expand operation specified' do
|
116
|
+
subject.expand(:Supplier)
|
117
|
+
expect(subject.to_s).to eq('Products?$expand=Supplier')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it { expect(subject).to respond_to(:order_by) }
|
122
|
+
describe '#order_by' do
|
123
|
+
it { expect(subject.order_by(:Name, :Price)).to eq(subject) }
|
124
|
+
it 'properly formats query with orderby operation specified' do
|
125
|
+
subject.order_by(:Name, :Price)
|
126
|
+
expect(subject.to_s).to eq('Products?$orderby=Name,Price')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#execute' do
|
131
|
+
it { expect(subject).to respond_to(:execute) }
|
132
|
+
it { expect(subject.execute).to be_a(OData4::Query::Result) }
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#count' do
|
136
|
+
it { expect(subject).to respond_to(:count) }
|
137
|
+
it { expect(subject.count).to be_a(Integer) }
|
138
|
+
it { expect(subject.count).to eq(11) }
|
139
|
+
|
140
|
+
context 'with filters' do
|
141
|
+
let(:criteria) { subject[:Name].eq('Bread') }
|
142
|
+
|
143
|
+
it { expect(subject.where(criteria).count).to eq(1) }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#empty?' do
|
148
|
+
it { expect(subject).to respond_to(:empty?) }
|
149
|
+
it { expect(subject.empty?).to eq(false) }
|
150
|
+
|
151
|
+
context 'with filters' do
|
152
|
+
let(:non_empty_criteria) { subject[:Name].eq('Bread') }
|
153
|
+
let(:empty_criteria) { subject[:Name].eq('NonExistent') }
|
154
|
+
|
155
|
+
it { expect(subject.where(non_empty_criteria).empty?).to eq(false) }
|
156
|
+
it { expect(subject.where(empty_criteria).empty?).to eq(true) }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#in_batches' do
|
161
|
+
it { expect(subject).to respond_to(:in_batches) }
|
162
|
+
it 'returns OData4::Entities in batches of specified size' do
|
163
|
+
batch_count = entity_count = 0
|
164
|
+
|
165
|
+
subject.in_batches(of: 5) do |batch|
|
166
|
+
expect(batch).to be_a(OData4::Query::Result)
|
167
|
+
expect(batch.count).to eq(5) unless batch_count == 2
|
168
|
+
|
169
|
+
batch.each do |entity|
|
170
|
+
expect(entity).to be_a(OData4::Entity)
|
171
|
+
expect(entity.type).to eq('Product')
|
172
|
+
entity_count += 1
|
173
|
+
end
|
174
|
+
|
175
|
+
batch_count += 1
|
176
|
+
end
|
177
|
+
|
178
|
+
expect(batch_count).to eq(3)
|
179
|
+
expect(entity_count).to eq(11)
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '#each' do
|
183
|
+
it 'returns OData4::Entities' do
|
184
|
+
entity_count = 0
|
185
|
+
|
186
|
+
subject.in_batches(of: 5).each do |entity|
|
187
|
+
expect(entity).to be_a(OData4::Entity)
|
188
|
+
expect(entity.type).to eq('Product')
|
189
|
+
entity_count += 1
|
190
|
+
end
|
191
|
+
|
192
|
+
expect(entity_count).to eq(11)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|