symphony 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,481 +0,0 @@
1
- # vim: set nosta noet ts=4 sw=4 ft=rspec:
2
-
3
- require_relative '../helpers'
4
- require 'symphony/intervalexpression'
5
- require 'symphony/mixins'
6
-
7
- using Symphony::TimeRefinements
8
-
9
-
10
- #####################################################################
11
- ### C O N T E X T S
12
- #####################################################################
13
-
14
- describe Symphony::IntervalExpression do
15
-
16
- let( :past ) { Time.at(1262376000) }
17
-
18
- it "can't be instantiated directly" do
19
- expect { described_class.new }.to raise_error( NoMethodError )
20
- end
21
-
22
- it "raises an exception if unable to parse the expression" do
23
- expect {
24
- described_class.parse( 'wut!' )
25
- }.to raise_error( Symphony::TimeParseError, /unable to parse/ )
26
- end
27
-
28
- it "normalizes the expression before attempting to parse it" do
29
- allow( Time ).to receive( :now ).and_return( past )
30
- parsed = described_class.parse( '\'";At 2014---01-01 14::00(' )
31
- expect( parsed.to_s ).to eq( 'at 2014-01-01 14:00' )
32
- end
33
-
34
- it "can parse the expression, offset from a different time" do
35
- parsed = described_class.parse( 'every 5 seconds ending in an hour', past )
36
- expect( parsed.starting ).to eq( past )
37
- expect( parsed.ending ).to eq( past + 3600 )
38
- end
39
-
40
- it "is comparable" do
41
- p1 = described_class.parse( 'at 2pm', past )
42
- p2 = described_class.parse( 'at 3pm', past )
43
- p3 = described_class.parse( 'at 2:00pm', past )
44
-
45
- expect( p1 ).to be < p2
46
- expect( p2 ).to be > p1
47
- expect( p1 ).to eq( p3 )
48
- end
49
-
50
- it "won't allow scheduling dates in the past" do
51
- expect {
52
- described_class.parse( 'on 1999-01-01' )
53
- }.to raise_error( Symphony::TimeParseError, /schedule in the past/ )
54
- end
55
-
56
- it "doesn't allow intervals of 0" do
57
- expect {
58
- described_class.parse( 'every 0 seconds' )
59
- }.to raise_error( Symphony::TimeParseError, /unable to parse/ )
60
- end
61
-
62
-
63
- context 'exact times and dates' do
64
-
65
- # stub for Time, tests are from this 'stuck' point:
66
- # 2010-01-01 12:00
67
- #
68
- before( :each ) do
69
- allow( Time ).to receive( :now ).and_return( past )
70
- end
71
-
72
- it 'at 2pm' do |example|
73
- parsed = described_class.parse( example.description )
74
- expect( parsed.valid ).to be
75
- expect( parsed.recurring ).to be_falsey
76
- expect( parsed.interval ).to be( 7200.0 )
77
- end
78
-
79
- it 'at 2:30pm' do |example|
80
- parsed = described_class.parse( example.description )
81
- expect( parsed.valid ).to be_truthy
82
- expect( parsed.interval ).to be( 9000.0 )
83
- end
84
-
85
- it "pushes ambiguous times in today's past into tomorrow (at 11am)" do
86
- parsed = described_class.parse( 'at 11am' )
87
- expect( parsed.valid ).to be_truthy
88
- expect( parsed.interval ).to be( 82800.0 )
89
- end
90
-
91
- it 'on 2010-01-02' do |example|
92
- parsed = described_class.parse( example.description )
93
- expect( parsed.valid ).to be_truthy
94
- expect( parsed.interval ).to be( 43200.0 )
95
- end
96
-
97
- it 'on 2010-01-02 12:00' do |example|
98
- parsed = described_class.parse( example.description )
99
- expect( parsed.valid ).to be_truthy
100
- expect( parsed.interval ).to be( 86400.0 )
101
- end
102
-
103
- it 'on 2010-01-02 12:00:01' do |example|
104
- parsed = described_class.parse( example.description )
105
- expect( parsed.valid ).to be_truthy
106
- expect( parsed.interval ).to be( 86401.0 )
107
- end
108
-
109
- it 'correctly timeboxes the expression' do
110
- parsed = described_class.parse( 'at 2pm' )
111
- expect( parsed.valid ).to be_truthy
112
- expect( parsed.interval ).to be( 7200.0 )
113
- expect( parsed.ending ).to be_nil
114
- expect( parsed.recurring ).to be_falsey
115
- expect( parsed.starting ).to eq( past )
116
- end
117
-
118
- it 'always sets a start time if one is not specified' do
119
- parsed = described_class.parse( 'at 2pm' )
120
- expect( parsed.valid ).to be_truthy
121
- expect( parsed.recurring ).to be_falsey
122
- expect( parsed.starting ).to eq( past )
123
- expect( parsed.interval ).to be( 7200.0 )
124
- end
125
- end
126
-
127
- context 'one-shot intervals' do
128
-
129
- # stub for Time, tests are from this 'stuck' point:
130
- # 2010-01-01 12:00
131
- #
132
- before( :each ) do
133
- allow( Time ).to receive( :now ).and_return( past )
134
- end
135
-
136
- it 'in 30 seconds' do |example|
137
- parsed = described_class.parse( example.description )
138
- expect( parsed.valid ).to be_truthy
139
- expect( parsed.recurring ).to be_falsey
140
- expect( parsed.interval ).to be( 30.0 )
141
- end
142
-
143
- it 'in 30 seconds from now' do |example|
144
- parsed = described_class.parse( example.description )
145
- expect( parsed.valid ).to be_truthy
146
- expect( parsed.interval ).to be( 30.0 )
147
- end
148
-
149
- it 'in an hour from now' do |example|
150
- parsed = described_class.parse( example.description )
151
- expect( parsed.valid ).to be_truthy
152
- expect( parsed.interval ).to be( 3600.0 )
153
- end
154
-
155
- it 'in a minute' do |example|
156
- parsed = described_class.parse( example.description )
157
- expect( parsed.valid ).to be_truthy
158
- expect( parsed.interval ).to be( 60.0 )
159
- end
160
-
161
- it 'correctly timeboxes the expression' do
162
- parsed = described_class.parse( 'in 30 seconds' )
163
- expect( parsed.valid ).to be_truthy
164
- expect( parsed.interval ).to be( 30.0 )
165
- expect( parsed.ending ).to be_nil
166
- expect( parsed.recurring ).to be_falsey
167
- expect( parsed.starting ).to eq( past )
168
- end
169
-
170
- it 'always sets a start time if one is not specified' do
171
- parsed = described_class.parse( 'in 5 seconds' )
172
- expect( parsed.valid ).to be_truthy
173
- expect( parsed.recurring ).to be_falsey
174
- expect( parsed.starting ).to eq( past )
175
- expect( parsed.interval ).to be( 5.0 )
176
- end
177
-
178
- it 'ignores end specifications for non-recurring run times' do
179
- parsed = described_class.parse( 'run at 2010-01-02 end at 2010-03-01' )
180
- expect( parsed.valid ).to be_truthy
181
- expect( parsed.recurring ).to be_falsey
182
- expect( parsed.starting ).to eq( past )
183
- expect( parsed.ending ).to be_falsey
184
- expect( parsed.interval ).to be( 43200.0 )
185
- end
186
- end
187
-
188
- context 'repeating intervals' do
189
-
190
- # stub for Time, tests are from this 'stuck' point:
191
- # 2010-01-01 12:00
192
- #
193
- before( :each ) do
194
- allow( Time ).to receive( :now ).and_return( past )
195
- end
196
-
197
- it 'every 500 milliseconds' do |example|
198
- parsed = described_class.parse( example.description )
199
- expect( parsed.valid ).to be_truthy
200
- expect( parsed.recurring ).to be_truthy
201
- expect( parsed.interval ).to be( 0.5 )
202
- end
203
-
204
- it 'every 30 seconds' do |example|
205
- parsed = described_class.parse( example.description )
206
- expect( parsed.valid ).to be_truthy
207
- expect( parsed.recurring ).to be_truthy
208
- expect( parsed.interval ).to be( 30.0 )
209
- end
210
-
211
- it 'once an hour' do |example|
212
- parsed = described_class.parse( example.description )
213
- expect( parsed.valid ).to be_truthy
214
- expect( parsed.recurring ).to be_truthy
215
- expect( parsed.interval ).to be( 3600.0 )
216
- end
217
-
218
- it 'once a minute' do |example|
219
- parsed = described_class.parse( example.description )
220
- expect( parsed.valid ).to be_truthy
221
- expect( parsed.recurring ).to be_truthy
222
- expect( parsed.interval ).to be( 60.0 )
223
- end
224
-
225
- it 'once per week' do |example|
226
- parsed = described_class.parse( example.description )
227
- expect( parsed.valid ).to be_truthy
228
- expect( parsed.recurring ).to be_truthy
229
- expect( parsed.interval ).to be( 604800.0 )
230
- end
231
-
232
- it 'every day' do |example|
233
- parsed = described_class.parse( example.description )
234
- expect( parsed.valid ).to be_truthy
235
- expect( parsed.recurring ).to be_truthy
236
- expect( parsed.interval ).to be( 86400.0 )
237
- end
238
-
239
- it 'every other day' do |example|
240
- parsed = described_class.parse( example.description )
241
- expect( parsed.valid ).to be_truthy
242
- expect( parsed.recurring ).to be_truthy
243
- expect( parsed.interval ).to be( 172800.0 )
244
- end
245
-
246
- it 'always sets a start time if one is not specified' do
247
- parsed = described_class.parse( 'every 5 seconds' )
248
- expect( parsed.valid ).to be_truthy
249
- expect( parsed.recurring ).to be_truthy
250
- expect( parsed.starting ).to eq( past )
251
- expect( parsed.interval ).to be( 5.0 )
252
- end
253
- end
254
-
255
- context 'repeating intervals with only an expiration date' do
256
-
257
- # stub for Time, tests are from this 'stuck' point:
258
- # 2010-01-01 12:00
259
- #
260
- before( :each ) do
261
- allow( Time ).to receive( :now ).and_return( past )
262
- end
263
-
264
- it 'every day ending in 1 week' do |example|
265
- parsed = described_class.parse( example.description )
266
- expect( parsed.valid ).to be_truthy
267
- expect( parsed.recurring ).to be_truthy
268
- expect( parsed.interval ).to be( 86400.0 )
269
- expect( parsed.ending ).to eq( past + 604800 )
270
- end
271
-
272
- it 'once a day finishing in a week from now' do |example|
273
- parsed = described_class.parse( example.description )
274
- expect( parsed.valid ).to be_truthy
275
- expect( parsed.recurring ).to be_truthy
276
- expect( parsed.interval ).to be( 86400.0 )
277
- expect( parsed.ending ).to eq( past + 604800 )
278
- end
279
-
280
- it 'once a day until 2010-02-01' do |example|
281
- parsed = described_class.parse( example.description )
282
- expect( parsed.valid ).to be_truthy
283
- expect( parsed.recurring ).to be_truthy
284
- expect( parsed.interval ).to be( 86400.0 )
285
- expect( parsed.ending ).to eq( past + 2635200 )
286
- end
287
-
288
- it 'once a day end on 2010-02-01 00:00:10' do |example|
289
- parsed = described_class.parse( example.description )
290
- expect( parsed.valid ).to be_truthy
291
- expect( parsed.recurring ).to be_truthy
292
- expect( parsed.interval ).to be( 86400.0 )
293
- expect( parsed.ending ).to eq( past + 2635210 )
294
- end
295
-
296
- it 'always sets a start time if one is not specified' do
297
- parsed = described_class.parse( 'every 5 seconds ending in 1 week' )
298
- expect( parsed.valid ).to be_truthy
299
- expect( parsed.recurring ).to be_truthy
300
- expect( parsed.starting ).to eq( past )
301
- expect( parsed.interval ).to be( 5.0 )
302
- expect( parsed.ending ).to eq( past + 604800 )
303
- end
304
- end
305
-
306
- context 'repeating intervals with only a start time' do
307
-
308
- # stub for Time, tests are from this 'stuck' point:
309
- # 2010-01-01 12:00
310
- #
311
- before( :each ) do
312
- allow( Time ).to receive( :now ).and_return( past )
313
- end
314
-
315
- it "won't allow explicit start times with non-recurring run times" do
316
- expect {
317
- described_class.parse( 'start at 2010-02-01 run at 2010-02-01' )
318
- }.to raise_error( Symphony::TimeParseError, /use 'at \[datetime\]' instead/ )
319
- end
320
-
321
- it 'starting in 5 minutes, run once a second' do |example|
322
- parsed = described_class.parse( example.description )
323
- expect( parsed.valid ).to be_truthy
324
- expect( parsed.recurring ).to be_truthy
325
- expect( parsed.starting ).to eq( past + 300 )
326
- expect( parsed.interval ).to be( 1.0 )
327
- end
328
-
329
- it 'starting in a day execute every 3 minutes' do |example|
330
- parsed = described_class.parse( example.description )
331
- expect( parsed.valid ).to be_truthy
332
- expect( parsed.recurring ).to be_truthy
333
- expect( parsed.starting ).to eq( past + 86400 )
334
- expect( parsed.interval ).to be( 180.0 )
335
- end
336
-
337
- it 'start at 2010-01-02 execute every 1 minute' do |example|
338
- parsed = described_class.parse( example.description )
339
- expect( parsed.valid ).to be_truthy
340
- expect( parsed.recurring ).to be_truthy
341
- expect( parsed.starting ).to eq( past + 43200 )
342
- expect( parsed.interval ).to be( 60.0 )
343
- end
344
-
345
- it 'always sets a start time if one is not specified' do
346
- parsed = described_class.parse( 'every 5 seconds' )
347
- expect( parsed.valid ).to be_truthy
348
- expect( parsed.recurring ).to be_truthy
349
- expect( parsed.starting ).to eq( past )
350
- expect( parsed.interval ).to be( 5.0 )
351
- end
352
- end
353
-
354
- context 'intervals with start and end times' do
355
-
356
- # stub for Time, tests are from this 'stuck' point:
357
- # 2010-01-01 12:00
358
- #
359
- before( :each ) do
360
- allow( Time ).to receive( :now ).and_return( past )
361
- end
362
-
363
- it 'beginning in 1 hour from now run every 5 seconds ending on 2010-01-02' do |example|
364
- parsed = described_class.parse( example.description )
365
- expect( parsed.valid ).to be_truthy
366
- expect( parsed.recurring ).to be_truthy
367
- expect( parsed.starting ).to eq( past + 3600 )
368
- expect( parsed.interval ).to be( 5.0 )
369
- expect( parsed.ending ).to eq( past + 43200 )
370
- end
371
-
372
- it 'starting in 1 hour, run every 5 seconds and finish at 3pm' do |example|
373
- parsed = described_class.parse( example.description )
374
- expect( parsed.valid ).to be_truthy
375
- expect( parsed.recurring ).to be_truthy
376
- expect( parsed.starting ).to eq( past + 3600 )
377
- expect( parsed.interval ).to be( 5.0 )
378
- expect( parsed.ending ).to eq( past + 3600 * 3 )
379
- end
380
-
381
- it 'begin in an hour run every 5 seconds and then stop at 3pm' do |example|
382
- parsed = described_class.parse( example.description )
383
- expect( parsed.valid ).to be_truthy
384
- expect( parsed.recurring ).to be_truthy
385
- expect( parsed.starting ).to eq( past + 3600 )
386
- expect( parsed.interval ).to be( 5.0 )
387
- expect( parsed.ending ).to eq( past + 3600 * 3 )
388
- end
389
-
390
- it 'start at 2010-01-02 10:00 and then run each minute for the next 6 days' do |example|
391
- parsed = described_class.parse( example.description )
392
- expect( parsed.valid ).to be_truthy
393
- expect( parsed.recurring ).to be_truthy
394
- expect( parsed.starting ).to eq( past + 43200 + 36000 )
395
- expect( parsed.interval ).to be( 60.0 )
396
- expect( parsed.ending ).to eq( Time.parse('2010-01-02 10:00') + 86400 * 6 )
397
- end
398
- end
399
-
400
- context 'intervals with a count' do
401
-
402
- # stub for Time, tests are from this 'stuck' point:
403
- # 2010-01-01 12:00
404
- #
405
- before( :each ) do
406
- allow( Time ).to receive( :now ).and_return( past )
407
- end
408
-
409
- it "won't allow count multipliers without an interval nor an end date" do
410
- expect {
411
- described_class.parse( 'run 10 times' )
412
- }.to raise_error( Symphony::TimeParseError, /end date or interval is required/ )
413
- end
414
-
415
- it '10 times a minute for 2 days' do |example|
416
- parsed = described_class.parse( example.description )
417
- expect( parsed.multiplier ).to be( 10 )
418
- expect( parsed.recurring ).to be_truthy
419
- expect( parsed.starting ).to eq( past )
420
- expect( parsed.interval ).to be( 6.0 )
421
- expect( parsed.ending ).to eq( past + 86400 * 2 )
422
- end
423
-
424
- it 'run 45 times every hour' do |example|
425
- parsed = described_class.parse( example.description )
426
- expect( parsed.multiplier ).to be( 45 )
427
- expect( parsed.recurring ).to be_truthy
428
- expect( parsed.starting ).to eq( past )
429
- expect( parsed.interval ).to be( 80.0 )
430
- expect( parsed.ending ).to be_nil
431
- end
432
-
433
- it 'start at 2010-01-02 run 12 times and end on 2010-01-03' do |example|
434
- parsed = described_class.parse( example.description )
435
- expect( parsed.multiplier ).to be( 12 )
436
- expect( parsed.recurring ).to be_truthy
437
- expect( parsed.starting ).to eq( past + 43200 )
438
- expect( parsed.interval ).to be( 7200.0 )
439
- expect( parsed.ending ).to eq( past + 86400 + 43200 )
440
- end
441
-
442
- it 'starting in an hour from now run 6 times a minute for 2 hours' do |example|
443
- parsed = described_class.parse( example.description )
444
- expect( parsed.multiplier ).to be( 6 )
445
- expect( parsed.recurring ).to be_truthy
446
- expect( parsed.starting ).to eq( past + 3600 )
447
- expect( parsed.interval ).to be( 10.0 )
448
- expect( parsed.ending ).to eq( past + 3600 * 3 )
449
- end
450
-
451
- it 'beginning a day from now, run 30 times per minute and finish in 2 weeks' do |example|
452
- parsed = described_class.parse( example.description )
453
- expect( parsed.multiplier ).to be( 30 )
454
- expect( parsed.recurring ).to be_truthy
455
- expect( parsed.starting ).to eq( past + 86400 )
456
- expect( parsed.interval ).to be( 2.0 )
457
- expect( parsed.ending ).to eq( past + 1209600 + 86400 )
458
- end
459
- end
460
-
461
- context "when checking if it's okay to run" do
462
-
463
- it 'returns true if the interval is within bounds' do
464
- parsed = described_class.parse( 'at 2pm' )
465
- expect( parsed.fire? ).to be_truthy
466
- end
467
-
468
- it 'returns nil if the ending (expiration) date has passed' do
469
- allow( Time ).to receive( :now ).and_return( past )
470
- parsed = described_class.parse( 'every minute' )
471
- parsed.instance_variable_set( :@ending, past - 30 )
472
- expect( parsed.fire? ).to be_nil
473
- end
474
-
475
- it 'returns false if the starting window has yet to occur' do
476
- parsed = described_class.parse( 'starting in 2 hours run each minute' )
477
- expect( parsed.fire? ).to be_falsey
478
- end
479
- end
480
- end
481
-