mongoid-scroll 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,19 +7,23 @@ describe Mongoid::Criteria do
7
7
  subject do
8
8
  Feed::Item.desc(:name).asc(:value)
9
9
  end
10
+
10
11
  it ':scroll' do
11
12
  expect(subject).to respond_to(:scroll)
12
13
  end
14
+
13
15
  it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
14
16
  expect do
15
17
  subject.scroll(cursor_type)
16
18
  end.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError, /You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
17
19
  end
18
20
  end
21
+
19
22
  context 'with different sort fields between the cursor and the criteria' do
20
23
  subject do
21
24
  Feed::Item.desc(:name)
22
25
  end
26
+
23
27
  it 'raises Mongoid::Scroll::Errors::MismatchedSortFieldsError' do
24
28
  record = Feed::Item.create!
25
29
  cursor = cursor_type.from_record(record, field: record.fields['a_string'])
@@ -27,16 +31,19 @@ describe Mongoid::Criteria do
27
31
  expect { subject.scroll(cursor) }.to raise_error Mongoid::Scroll::Errors::MismatchedSortFieldsError, error_string
28
32
  end
29
33
  end
34
+
30
35
  context 'with no sort' do
31
36
  subject do
32
37
  Feed::Item.all
33
38
  end
39
+
34
40
  it 'adds a default sort by _id' do
35
41
  expect(subject.scroll(cursor_type).options[:sort]).to eq('_id' => 1)
36
42
  end
37
43
  end
44
+
38
45
  context 'with data' do
39
- before :each do
46
+ before do
40
47
  10.times do |i|
41
48
  Feed::Item.create!(
42
49
  name: i.to_s,
@@ -48,30 +55,33 @@ describe Mongoid::Criteria do
48
55
  )
49
56
  end
50
57
  end
58
+
51
59
  context 'default' do
52
60
  it 'scrolls all' do
53
61
  records = []
54
- Feed::Item.all.scroll(cursor_type) do |record, _next_cursor|
62
+ Feed::Item.all.scroll(cursor_type) do |record, _iterator|
55
63
  records << record
56
64
  end
57
65
  expect(records.size).to eq 10
58
66
  expect(records).to eq Feed::Item.all.to_a
59
67
  end
68
+
60
69
  it 'does not change original criteria' do
61
70
  criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
62
71
  original_criteria = criteria.dup
63
72
  criteria.limit(2).scroll(cursor_type)
64
73
  expect(criteria).to eq original_criteria
65
74
  cursor = nil
66
- criteria.limit(2).scroll(cursor) do |_record, next_cursor|
67
- cursor = next_cursor
75
+ criteria.limit(2).scroll(cursor) do |_record, iterator|
76
+ cursor = iterator.next_cursor
68
77
  end
69
- criteria.scroll(cursor) do |_record, next_cursor|
70
- cursor = next_cursor
78
+ criteria.scroll(cursor) do |_record, iterator|
79
+ cursor = iterator.next_cursor
71
80
  end
72
81
  expect(criteria).to eq original_criteria
73
82
  end
74
83
  end
84
+
75
85
  context 'with a foreign key' do
76
86
  it 'sorts by object id' do
77
87
  records = []
@@ -79,92 +89,144 @@ describe Mongoid::Criteria do
79
89
  expect(records).not_to be_empty
80
90
  end
81
91
  end
92
+
82
93
  { a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
83
94
  context field_type do
84
95
  it 'scrolls all with a block' do
85
96
  records = []
86
- Feed::Item.asc(field_name).scroll(cursor_type) do |record, _next_cursor|
97
+ Feed::Item.asc(field_name).scroll(cursor_type) do |record, _iterator|
87
98
  records << record
88
99
  end
89
100
  expect(records.size).to eq 10
90
101
  expect(records).to eq Feed::Item.all.to_a
91
102
  end
103
+
92
104
  it 'scrolls all with a break' do
93
105
  records = []
94
106
  cursor = nil
95
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
107
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
96
108
  records << record
97
- cursor = next_cursor
109
+ cursor = iterator.next_cursor
98
110
  end
99
111
  expect(records.size).to eq 5
100
- Feed::Item.asc(field_name).scroll(cursor) do |record, next_cursor|
112
+ Feed::Item.asc(field_name).scroll(cursor) do |record, iterator|
101
113
  records << record
102
- cursor = next_cursor
114
+ cursor = iterator.next_cursor
103
115
  end
104
116
  expect(records.size).to eq 10
105
117
  expect(records).to eq Feed::Item.all.to_a
106
118
  end
119
+
107
120
  it 'scrolls from a cursor' do
108
121
  last_record = nil
109
122
  cursor = nil
110
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
123
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
111
124
  last_record = record
112
- cursor = next_cursor
125
+ cursor = iterator.next_cursor
113
126
  end
114
127
  sixth_item = Feed::Item.asc(field_name).to_a[5]
115
128
  from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
116
129
  expect(from_item).to eq sixth_item
117
130
  end
131
+
118
132
  it 'includes the current record when Mongoid::Scroll::Cursor#include_current is true' do
119
133
  last_record = nil
120
134
  cursor = nil
121
- Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, next_cursor|
135
+ Feed::Item.asc(field_name).limit(5).scroll(cursor_type) do |record, iterator|
122
136
  last_record = record
123
- cursor = next_cursor
137
+ cursor = iterator.next_cursor
124
138
  end
125
139
  fifth_item = last_record
126
140
  cursor.include_current = true
127
141
  from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
128
142
  expect(from_item).to eq fifth_item
129
143
  end
144
+
130
145
  it 'scrolls in descending order' do
131
146
  records = []
132
- Feed::Item.desc(field_name).limit(3).scroll(cursor_type) do |record, _next_cursor|
147
+ Feed::Item.desc(field_name).limit(3).scroll(cursor_type) do |record, _iterator|
133
148
  records << record
134
149
  end
135
150
  expect(records.size).to eq 3
136
151
  expect(records).to eq Feed::Item.desc(field_name).limit(3).to_a
137
152
  end
153
+
138
154
  it 'map' do
139
155
  record = Feed::Item.desc(field_name).limit(3).scroll(cursor_type).map { |r| r }.last
140
- expect(record).to_not be nil
156
+ expect(record).not_to be_nil
141
157
  cursor = cursor_type.from_record(record, field_type: field_type, field_name: field_name)
142
- expect(cursor).to_not be nil
158
+ expect(cursor).not_to be_nil
143
159
  expect(cursor.tiebreak_id).to eq record.id
144
160
  expect(cursor.value).to eq record.send(field_name)
145
161
  end
162
+
146
163
  it 'can be reused' do
147
164
  ids = Feed::Item.asc(field_name).limit(2).map(&:id)
148
- Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, cursor|
149
- cursor.include_current = true
150
- expect(Feed::Item.asc(field_name).limit(2).scroll(cursor).pluck(:id)).to eq ids
165
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
166
+ iterator.next_cursor.include_current = true
167
+ expect(Feed::Item.asc(field_name).limit(2).scroll(iterator.next_cursor).pluck(:id)).to eq ids
151
168
  break
152
169
  end
153
170
  end
171
+
154
172
  it 'can be re-created and reused' do
155
173
  ids = Feed::Item.asc(field_name).limit(2).map(&:id)
156
- Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, cursor|
157
- new_cursor = cursor_type.new(cursor.to_s, field_type: field_type, field_name: field_name)
174
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
175
+ new_cursor = cursor_type.new(iterator.next_cursor.to_s, field_type: field_type, field_name: field_name)
158
176
  new_cursor.include_current = true
159
177
  expect(Feed::Item.asc(field_name).limit(2).scroll(new_cursor).pluck(:id)).to eq ids
160
178
  break
161
179
  end
162
180
  end
181
+
182
+ it 'can scroll back with the previous cursor' do
183
+ first_iterator = nil
184
+ second_iterator = nil
185
+ third_iterator = nil
186
+
187
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, iterator|
188
+ first_iterator = iterator
189
+ end
190
+
191
+ Feed::Item.asc(field_name).limit(2).scroll(first_iterator.next_cursor) do |_, iterator|
192
+ second_iterator = iterator
193
+ end
194
+
195
+ Feed::Item.asc(field_name).limit(2).scroll(second_iterator.next_cursor) do |_, iterator|
196
+ third_iterator = iterator
197
+ end
198
+
199
+ records = Feed::Item.asc(field_name)
200
+ expect(Feed::Item.asc(field_name).limit(2).scroll(second_iterator.previous_cursor)).to eq(records.limit(2))
201
+ expect(Feed::Item.asc(field_name).limit(2).scroll(third_iterator.previous_cursor)).to eq(records.skip(2).limit(2))
202
+ end
203
+
204
+ it 'can loop over the same records with the current cursor' do
205
+ current_cursor = nil
206
+ cursor = cursor_type.from_record Feed::Item.skip(4).first, field_name: field_name, field_type: field_type, include_current: true
207
+
208
+ Feed::Item.asc(field_name).limit(2).scroll(cursor) do |_, iterator|
209
+ current_cursor = iterator.current_cursor
210
+ end
211
+
212
+ expect(Feed::Item.asc(field_name).limit(2).scroll(current_cursor).to_a).to eq(Feed::Item.asc(field_name).skip(4).limit(2).to_a)
213
+ end
214
+
215
+ it 'can loop over the first records with the first page cursor' do
216
+ first_cursor = nil
217
+
218
+ Feed::Item.asc(field_name).limit(2).scroll(cursor_type) do |_, it|
219
+ first_cursor = it.first_cursor
220
+ end
221
+
222
+ expect(Feed::Item.asc(field_name).limit(2).scroll(first_cursor).to_a).to eq(Feed::Item.asc(field_name).limit(2).to_a)
223
+ end
163
224
  end
164
225
  end
165
226
  end
227
+
166
228
  context 'with logic in initial criteria' do
167
- before :each do
229
+ before do
168
230
  3.times do |i|
169
231
  Feed::Item.create!(
170
232
  name: "Feed Item #{i}",
@@ -184,63 +246,69 @@ describe Mongoid::Criteria do
184
246
  a_time: Time.new(2014, 2, 2, 1, 2, 3)
185
247
  )
186
248
  end
249
+
187
250
  it 'respects original criteria with OR logic' do
188
251
  criteria = Feed::Item.where(
189
252
  '$or' => [{ :a_time.gt => Time.new(2015, 7, 22, 1, 2, 3) }, { :a_time.lte => Time.new(2015, 7, 22, 1, 2, 3), :a_date.gte => Date.new(2015, 7, 30) }]
190
253
  ).asc(:a_time)
191
254
  records = []
192
255
  cursor = nil
193
- criteria.limit(2).scroll(cursor_type) do |record, next_cursor|
256
+ criteria.limit(2).scroll(cursor_type) do |record, iterator|
194
257
  records << record
195
- cursor = next_cursor
258
+ cursor = iterator.next_cursor
196
259
  end
197
260
  expect(records.size).to eq 2
198
261
  expect(records.map(&:name)).to eq ['Feed Item 0', 'Feed Item 1']
199
262
  records = []
200
- criteria.limit(2).scroll(cursor) do |record, next_cursor|
263
+ criteria.limit(2).scroll(cursor) do |record, iterator|
201
264
  records << record
202
- cursor = next_cursor
265
+ cursor = iterator.next_cursor
203
266
  end
204
267
  expect(records.size).to eq 1
205
268
  expect(records.map(&:name)).to eq ['Feed Item 2']
206
269
  end
207
270
  end
271
+
208
272
  context 'with embeddable objects' do
209
273
  before do
210
274
  @item = Feed::Item.create! a_integer: 1, name: 'item'
211
275
  @embedded_item = Feed::EmbeddedItem.create! name: 'embedded', item: @item
212
276
  end
277
+
213
278
  it 'respects embedded queries' do
214
279
  records = []
215
280
  criteria = @item.embedded_items.limit(2)
216
- criteria.scroll(cursor_type) do |record, _next_cursor|
281
+ criteria.scroll(cursor_type) do |record, _iterator|
217
282
  records << record
218
283
  end
219
284
  expect(records.size).to eq 1
220
285
  expect(records.map(&:name)).to eq ['embedded']
221
286
  end
222
287
  end
288
+
223
289
  context 'with overlapping data', if: MongoDB.mmapv1? do
224
- before :each do
290
+ before do
225
291
  3.times { Feed::Item.create! a_integer: 5 }
226
292
  Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
227
293
  end
294
+
228
295
  it 'natural order is different from order by id' do
229
296
  # natural order isn't necessarily going to be the same as _id order
230
297
  # if a document is updated and grows in size, it may need to be relocated and
231
298
  # thus cause the natural order to change
232
- expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq(Feed::Item.order_by(_id: 1).to_a)
299
+ expect(Feed::Item.order_by('$natural' => 1).to_a).not_to eq(Feed::Item.order_by(_id: 1).to_a)
233
300
  end
301
+
234
302
  [{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
235
303
  it "scrolls by #{sort_order}" do
236
304
  records = []
237
305
  cursor = nil
238
- Feed::Item.order_by(sort_order).limit(2).scroll(cursor_type) do |record, next_cursor|
306
+ Feed::Item.order_by(sort_order).limit(2).scroll(cursor_type) do |record, iterator|
239
307
  records << record
240
- cursor = next_cursor
308
+ cursor = iterator.next_cursor
241
309
  end
242
310
  expect(records.size).to eq 2
243
- Feed::Item.order_by(sort_order).scroll(cursor) do |record, _next_cursor|
311
+ Feed::Item.order_by(sort_order).scroll(cursor) do |record, _iterator|
244
312
  records << record
245
313
  end
246
314
  expect(records.size).to eq 3
@@ -248,10 +316,12 @@ describe Mongoid::Criteria do
248
316
  end
249
317
  end
250
318
  end
319
+
251
320
  context 'with several records having the same value' do
252
- before :each do
321
+ before do
253
322
  3.times { Feed::Item.create! a_integer: 5 }
254
323
  end
324
+
255
325
  it 'returns records from the current one when Mongoid::Scroll::Cursor#include_current is true' do
256
326
  _first_item, second_item, third_item = Feed::Item.asc(:a_integer).to_a
257
327
  cursor = Mongoid::Scroll::Cursor.from_record(second_item, field: Feed::Item.fields['a_integer'])
@@ -260,6 +330,7 @@ describe Mongoid::Criteria do
260
330
  expect(items).to eq([second_item, third_item])
261
331
  end
262
332
  end
333
+
263
334
  context 'with DateTime with a milisecond precision' do
264
335
  let!(:item_1) { Feed::Item.create!(a_datetime: DateTime.new(2013, 1, 21, 1, 42, 3.1, 'UTC')) }
265
336
  let!(:item_2) { Feed::Item.create!(a_datetime: DateTime.new(2013, 1, 21, 1, 42, 3.2, 'UTC')) }
@@ -268,9 +339,9 @@ describe Mongoid::Criteria do
268
339
  it 'doesn\'t lose the precision when rebuilding the cursor' do
269
340
  records = []
270
341
  cursor = nil
271
- Feed::Item.order_by(a_datetime: 1).limit(2).scroll(cursor_type) do |record, next_cursor|
342
+ Feed::Item.order_by(a_datetime: 1).limit(2).scroll(cursor_type) do |record, iterator|
272
343
  records << record
273
- cursor = next_cursor
344
+ cursor = iterator.next_cursor
274
345
  end
275
346
  expect(records).to eq [item_1, item_2]
276
347
  cursor = cursor_type.new(cursor.to_s, field: Feed::Item.fields['a_datetime'])
@@ -5,125 +5,158 @@ describe Mongoid::Scroll::Cursor do
5
5
  subject do
6
6
  Mongoid::Scroll::Cursor.new nil, field_name: 'a_string', field_type: String
7
7
  end
8
- its(:tiebreak_id) { should be_nil }
9
- its(:value) { should be_nil }
10
- its(:criteria) { should eq({}) }
8
+
9
+ its(:tiebreak_id) { is_expected.to be_nil }
10
+ its(:value) { is_expected.to be_nil }
11
+ its(:criteria) { is_expected.to eq({}) }
11
12
  end
13
+
12
14
  context 'an invalid cursor' do
13
15
  it 'raises InvalidCursorError' do
14
16
  expect { Mongoid::Scroll::Cursor.new 'invalid', field_name: 'a_string', field_type: String }.to raise_error Mongoid::Scroll::Errors::InvalidCursorError,
15
17
  /The cursor supplied is invalid: invalid./
16
18
  end
17
19
  end
20
+
18
21
  context 'an id field cursor' do
19
- let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
20
22
  subject do
21
23
  Mongoid::Scroll::Cursor.new "#{feed_item.id}:#{feed_item.id}", field_name: '_id', field_type: BSON::ObjectId, direction: 1
22
24
  end
23
- its(:value) { should eq feed_item.id }
24
- its(:tiebreak_id) { should eq feed_item.id }
25
+
26
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
27
+
28
+ its(:value) { is_expected.to eq feed_item.id }
29
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
30
+
25
31
  its(:criteria) do
26
- should eq('$or' => [
27
- { '_id' => { '$gt' => BSON::ObjectId(feed_item.id.to_s) } }
28
- ])
32
+ is_expected.to eq('$or' => [
33
+ { '_id' => { '$gt' => BSON::ObjectId(feed_item.id.to_s) } }
34
+ ])
29
35
  end
30
36
  end
37
+
31
38
  context 'a string field cursor' do
32
- let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
33
39
  subject do
34
40
  Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String
35
41
  end
36
- its(:value) { should eq feed_item.a_string }
37
- its(:tiebreak_id) { should eq feed_item.id }
42
+
43
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
44
+
45
+ its(:value) { is_expected.to eq feed_item.a_string }
46
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
47
+
38
48
  its(:criteria) do
39
- should eq('$or' => [
40
- { 'a_string' => { '$gt' => feed_item.a_string } },
41
- { 'a_string' => feed_item.a_string, '_id' => { '$gt' => feed_item.id } }
42
- ])
49
+ is_expected.to eq('$or' => [
50
+ { 'a_string' => { '$gt' => feed_item.a_string } },
51
+ { 'a_string' => feed_item.a_string, '_id' => { '$gt' => feed_item.id } }
52
+ ])
43
53
  end
44
54
  end
55
+
45
56
  context 'an integer field cursor' do
46
- let(:feed_item) { Feed::Item.create!(a_integer: 10) }
47
57
  subject do
48
58
  Mongoid::Scroll::Cursor.new "#{feed_item.a_integer}:#{feed_item.id}", field_name: 'a_integer', field_type: Integer
49
59
  end
50
- its(:value) { should eq feed_item.a_integer }
51
- its(:tiebreak_id) { should eq feed_item.id }
60
+
61
+ let(:feed_item) { Feed::Item.create!(a_integer: 10) }
62
+
63
+ its(:value) { is_expected.to eq feed_item.a_integer }
64
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
65
+
52
66
  its(:criteria) do
53
- should eq('$or' => [
54
- { 'a_integer' => { '$gt' => feed_item.a_integer } },
55
- { 'a_integer' => feed_item.a_integer, '_id' => { '$gt' => feed_item.id } }
56
- ])
67
+ is_expected.to eq('$or' => [
68
+ { 'a_integer' => { '$gt' => feed_item.a_integer } },
69
+ { 'a_integer' => feed_item.a_integer, '_id' => { '$gt' => feed_item.id } }
70
+ ])
57
71
  end
58
72
  end
73
+
59
74
  context 'a date/time field cursor' do
60
- let(:feed_item) { Feed::Item.create!(a_datetime: DateTime.new(2013, 12, 21, 1, 42, 3, 'UTC')) }
61
75
  subject do
62
76
  Mongoid::Scroll::Cursor.new "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}", field_name: 'a_datetime', field_type: DateTime
63
77
  end
64
- its(:value) { should eq feed_item.a_datetime }
65
- its(:tiebreak_id) { should eq feed_item.id }
66
- its(:to_s) { should eq "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}" }
78
+
79
+ let(:feed_item) { Feed::Item.create!(a_datetime: DateTime.new(2013, 12, 21, 1, 42, 3, 'UTC')) }
80
+
81
+ its(:value) { is_expected.to eq feed_item.a_datetime }
82
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
83
+ its(:to_s) { is_expected.to eq "#{feed_item.a_datetime.utc.to_f.round(3)}:#{feed_item.id}" }
84
+
67
85
  its(:criteria) do
68
- should eq('$or' => [
69
- { 'a_datetime' => { '$gt' => feed_item.a_datetime } },
70
- { 'a_datetime' => feed_item.a_datetime, '_id' => { '$gt' => feed_item.id } }
71
- ])
86
+ is_expected.to eq('$or' => [
87
+ { 'a_datetime' => { '$gt' => feed_item.a_datetime } },
88
+ { 'a_datetime' => feed_item.a_datetime, '_id' => { '$gt' => feed_item.id } }
89
+ ])
72
90
  end
73
91
  end
92
+
74
93
  context 'a date field cursor' do
75
- let(:feed_item) { Feed::Item.create!(a_date: Date.new(2013, 12, 21)) }
76
94
  subject do
77
95
  Mongoid::Scroll::Cursor.new "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}", field_name: 'a_date', field_type: Date
78
96
  end
79
- its(:value) { should eq feed_item.a_date }
80
- its(:tiebreak_id) { should eq feed_item.id }
81
- its(:to_s) { should eq "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}" }
97
+
98
+ let(:feed_item) { Feed::Item.create!(a_date: Date.new(2013, 12, 21)) }
99
+
100
+ its(:value) { is_expected.to eq feed_item.a_date }
101
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
102
+ its(:to_s) { is_expected.to eq "#{feed_item.a_date.to_datetime.to_i}:#{feed_item.id}" }
103
+
82
104
  its(:criteria) do
83
- should eq('$or' => [
84
- { 'a_date' => { '$gt' => feed_item.a_date.to_datetime } },
85
- { 'a_date' => feed_item.a_date.to_datetime, '_id' => { '$gt' => feed_item.id } }
86
- ])
105
+ is_expected.to eq('$or' => [
106
+ { 'a_date' => { '$gt' => feed_item.a_date.to_datetime } },
107
+ { 'a_date' => feed_item.a_date.to_datetime, '_id' => { '$gt' => feed_item.id } }
108
+ ])
87
109
  end
88
110
  end
111
+
89
112
  context 'a time field cursor' do
90
- let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
91
113
  subject do
92
114
  Mongoid::Scroll::Cursor.new "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}", field_name: 'a_time', field_type: Time
93
115
  end
94
- its(:value) { should eq feed_item.a_time }
95
- its(:tiebreak_id) { should eq feed_item.id }
96
- its(:to_s) { should eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
116
+
117
+ let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
118
+
119
+ its(:value) { is_expected.to eq feed_item.a_time }
120
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
121
+ its(:to_s) { is_expected.to eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
122
+
97
123
  its(:criteria) do
98
- should eq('$or' => [
99
- { 'a_time' => { '$gt' => feed_item.a_time } },
100
- { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
101
- ])
124
+ is_expected.to eq('$or' => [
125
+ { 'a_time' => { '$gt' => feed_item.a_time } },
126
+ { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
127
+ ])
102
128
  end
103
129
  end
130
+
104
131
  context 'a time field cursor with a field option' do
105
- let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
106
132
  subject do
107
133
  Mongoid::Scroll::Cursor.new "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}", field: Feed::Item.fields['a_time']
108
134
  end
109
- its(:value) { should eq feed_item.a_time }
110
- its(:tiebreak_id) { should eq feed_item.id }
111
- its(:to_s) { should eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
135
+
136
+ let(:feed_item) { Feed::Item.create!(a_time: Time.new(2013, 12, 21, 1, 2, 3)) }
137
+
138
+ its(:value) { is_expected.to eq feed_item.a_time }
139
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
140
+ its(:to_s) { is_expected.to eq "#{feed_item.a_time.to_f.round(3)}:#{feed_item.id}" }
141
+
112
142
  its(:criteria) do
113
- should eq('$or' => [
114
- { 'a_time' => { '$gt' => feed_item.a_time } },
115
- { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
116
- ])
143
+ is_expected.to eq('$or' => [
144
+ { 'a_time' => { '$gt' => feed_item.a_time } },
145
+ { 'a_time' => feed_item.a_time, '_id' => { '$gt' => feed_item.id } }
146
+ ])
117
147
  end
118
148
  end
149
+
119
150
  context 'an array field cursor' do
120
151
  let(:feed_item) { Feed::Item.create!(a_array: %w[x y]) }
152
+
121
153
  it 'is not supported' do
122
154
  expect do
123
155
  Mongoid::Scroll::Cursor.from_record feed_item, field_name: 'a_array', field_type: Array
124
156
  end.to raise_error Mongoid::Scroll::Errors::UnsupportedFieldTypeError, /The type of the field 'a_array' is not supported: Array./
125
157
  end
126
158
  end
159
+
127
160
  context 'an invalid field cursor' do
128
161
  it 'raises ArgumentError' do
129
162
  expect do
@@ -131,23 +164,38 @@ describe Mongoid::Scroll::Cursor do
131
164
  end.to raise_error ArgumentError
132
165
  end
133
166
  end
134
- context 'a cursor with include_current set to true' do
167
+
168
+ context 'an invalid type cursor' do
135
169
  let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
170
+
171
+ it 'raises Mongoid::Scroll::Errors::UnsupportedTypeError' do
172
+ expect do
173
+ Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String, include_current: true, type: :invalid
174
+ end.to raise_error Mongoid::Scroll::Errors::UnsupportedTypeError, /The type supplied in the cursor is not supported: invalid./
175
+ end
176
+ end
177
+
178
+ context 'a cursor with include_current set to true' do
136
179
  subject do
137
180
  Mongoid::Scroll::Cursor.new "#{feed_item.a_string}:#{feed_item.id}", field_name: 'a_string', field_type: String, include_current: true
138
181
  end
139
- its(:value) { should eq 'astring' }
140
- its(:tiebreak_id) { should eq feed_item.id }
182
+
183
+ let(:feed_item) { Feed::Item.create!(a_string: 'astring') }
184
+
185
+ its(:value) { is_expected.to eq 'astring' }
186
+ its(:tiebreak_id) { is_expected.to eq feed_item.id }
187
+
141
188
  its(:criteria) do
142
- should eq('$or' => [
143
- { 'a_string' => { '$gt' => 'astring' } },
144
- { '_id' => { '$gte' => BSON::ObjectId(feed_item.id.to_s) }, 'a_string' => 'astring' }
145
- ])
189
+ is_expected.to eq('$or' => [
190
+ { 'a_string' => { '$gt' => 'astring' } },
191
+ { '_id' => { '$gte' => BSON::ObjectId(feed_item.id.to_s) }, 'a_string' => 'astring' }
192
+ ])
146
193
  end
147
194
  end
195
+
148
196
  context 'criteria' do
149
197
  context 'with data' do
150
- before :each do
198
+ before do
151
199
  3.times do |i|
152
200
  Feed::Item.create!(
153
201
  name: "Feed Item #{i}",
@@ -159,6 +207,7 @@ describe Mongoid::Scroll::Cursor do
159
207
  a_time: Time.new(2014, 2, 2, 1, 2, 3)
160
208
  )
161
209
  end
210
+
162
211
  it 'merges cursor criteria when no sort field is given' do
163
212
  criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
164
213
  feed_item = Feed::Item.where(name: 'Feed Item 1').first
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongoid::Scroll::VERSION do
4
- it { should_not be_nil }
4
+ it { is_expected.not_to be_nil }
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
+ require 'coveralls'
5
+ Coveralls.wear! do
6
+ add_filter 'spec'
7
+ end
8
+
4
9
  require 'rubygems'
5
10
  require 'rspec'
6
11
  require 'rspec/its'
7
12
  require 'database_cleaner'
8
13
  require 'mongoid-scroll'
9
14
 
15
+ Time.zone ||= 'EST'
16
+
10
17
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
11
18
  require f
12
19
  end
@@ -18,9 +25,9 @@ end
18
25
  RSpec.configure do |config|
19
26
  config.before :all do
20
27
  Mongoid.logger.level = Logger::INFO
21
- Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
28
+ Mongo::Logger.logger.level = Logger::INFO
22
29
  end
23
- config.before :each do
30
+ config.before do
24
31
  DatabaseCleaner.clean
25
32
  end
26
33
  end