weekling 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,596 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@raxys.net>, 2012
4
+
5
+ This file is part of Weekling.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'spec_helper'
21
+ require 'aef/weekling/week'
22
+ require 'ostruct'
23
+
24
+ describe Aef::Weekling::Week do
25
+ [:today, :now].each do |method|
26
+ context ".#{method}" do
27
+ it "should find the current week" do
28
+ week = described_class.method(method).call
29
+ today = Date.today
30
+
31
+ week.year.should eql Aef::Weekling::Year.new(today.year)
32
+ week.index.should eql today.cweek
33
+ end
34
+ end
35
+ end
36
+
37
+ context ".parse" do
38
+ it "should recognize an ancient week" do
39
+ week = described_class.parse('-1503-W50')
40
+
41
+ week.year.should eql Aef::Weekling::Year.new(-1503)
42
+ week.index.should eql 50
43
+ end
44
+
45
+ it "should recognize a normal week" do
46
+ week = described_class.parse('2011-W30')
47
+
48
+ week.year.should eql Aef::Weekling::Year.new(2011)
49
+ week.index.should eql 30
50
+ end
51
+
52
+ it "should recognize a post apocalyptic week" do
53
+ week = described_class.parse('50023-W03')
54
+
55
+ week.year.should eql Aef::Weekling::Year.new(50023)
56
+ week.index.should eql 3
57
+ end
58
+
59
+ it "should report being unable to parse the given String" do
60
+ lambda{
61
+ described_class.parse('no week!')
62
+ }.should raise_error(ArgumentError, 'No week found for parsing')
63
+ end
64
+ end
65
+
66
+ context ".new" do
67
+ it "should complain about a param of invalid type" do
68
+ lambda {
69
+ described_class.new(123)
70
+ }.should raise_error(ArgumentError, 'A single argument must either respond to #year and #index or to #to_date')
71
+ end
72
+
73
+ it "should complain about less than one argument" do
74
+ lambda {
75
+ described_class.new
76
+ }.should raise_error(ArgumentError, 'wrong number of arguments (0 for 1..2)')
77
+ end
78
+
79
+ it "should complain about more than two arguments" do
80
+ lambda {
81
+ described_class.new(123, 456, 789)
82
+ }.should raise_error(ArgumentError, 'wrong number of arguments (3 for 1..2)')
83
+ end
84
+
85
+ it "should be able to initialize an ancient week by year and index" do
86
+ week = described_class.new(-1691, 11)
87
+
88
+ week.year.should eql Aef::Weekling::Year.new(-1691)
89
+ week.index.should eql 11
90
+ end
91
+
92
+ it "should be able to initialize a normal week by year and index" do
93
+ week = described_class.new(2012, 40)
94
+
95
+ week.year.should eql Aef::Weekling::Year.new(2012)
96
+ week.index.should eql 40
97
+ end
98
+
99
+ it "should be able to initialize a post apocalyptic week by year and index" do
100
+ week = described_class.new(23017, 29)
101
+
102
+ week.year.should eql Aef::Weekling::Year.new(23017)
103
+ week.index.should eql 29
104
+ end
105
+
106
+ it "should be able to initialize a week by a given Week object" do
107
+ old_week = described_class.new(2011, 30)
108
+ week = described_class.new(old_week)
109
+
110
+ week.year.should eql old_week.year
111
+ week.index.should eql old_week.index
112
+ end
113
+
114
+ it "should be able to initialize a week by a given Date object" do
115
+ date = Date.today
116
+ week = described_class.new(date)
117
+
118
+ week.year.should eql Aef::Weekling::Year.new(date.year)
119
+ week.index.should eql date.cweek
120
+ end
121
+
122
+ it "should be able to initialize a week by a given DateTime object" do
123
+ date = DateTime.now
124
+ week = described_class.new(date)
125
+
126
+ week.year.should eql Aef::Weekling::Year.new(date.year)
127
+ week.index.should eql date.cweek
128
+ end
129
+
130
+ it "should be able to initialize a week by a given Time object" do
131
+ time = Time.now
132
+ week = described_class.new(time)
133
+
134
+ date = time.to_date
135
+
136
+ week.year.should eql Aef::Weekling::Year.new(date.year)
137
+ week.index.should eql date.cweek
138
+ end
139
+
140
+ it "should accept week 53 for year in which one exists" do
141
+ lambda{
142
+ described_class.new(2015, 53)
143
+ }.should_not raise_error
144
+ end
145
+
146
+ it "should report week 53 doesn't exist in the given year" do
147
+ lambda{
148
+ described_class.new(2011, 53)
149
+ }.should raise_error(ArgumentError, /Index .* is invalid. Year .* has only 52 weeks/)
150
+ end
151
+
152
+ it "should always report if weeks below index 1 are given" do
153
+ lambda{
154
+ described_class.new(2011, 0)
155
+ }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
156
+ end
157
+
158
+ it "should always report if weeks above index 53 are given" do
159
+ lambda{
160
+ described_class.new(2011, 54)
161
+ }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
162
+ end
163
+ end
164
+
165
+ context "#== (type independent equality)" do
166
+ it "should be true if year and index match" do
167
+ week = described_class.new(2012, 1)
168
+ other = described_class.new(2012, 1)
169
+
170
+ week.should == other
171
+ end
172
+
173
+ it "should be true if year and index match, independent of the other object's type" do
174
+ week = described_class.new(2012, 1)
175
+
176
+ other = OpenStruct.new
177
+ other.year = Aef::Weekling::Year.new(2012)
178
+ other.index = 1
179
+
180
+ week.should == other
181
+ end
182
+
183
+ it "should be false if year matches but not index" do
184
+ week = described_class.new(2012, 1)
185
+ other = described_class.new(2012, 13)
186
+
187
+ week.should_not == other
188
+ end
189
+
190
+ it "should be false if year matches but not index, independent of the other object's type" do
191
+ week = described_class.new(2012, 1)
192
+
193
+ other = OpenStruct.new
194
+ other.year = Aef::Weekling::Year.new(2012)
195
+ other.index = 13
196
+
197
+ week.should_not == other
198
+ end
199
+
200
+ it "should be false if index matches but not year" do
201
+ week = described_class.new(2012, 1)
202
+ other = described_class.new(2005, 1)
203
+
204
+ week.should_not == other
205
+ end
206
+
207
+ it "should be false if index matches but not year, independent of the other object's type" do
208
+ week = described_class.new(2012, 1)
209
+
210
+ other = OpenStruct.new
211
+ other.year = Aef::Weekling::Year.new(2005)
212
+ other.index = 1
213
+
214
+ week.should_not == other
215
+ end
216
+
217
+ it "should be false if both index and year do not match" do
218
+ week = described_class.new(2012, 1)
219
+ other = described_class.new(2005, 13)
220
+
221
+ week.should_not == other
222
+ end
223
+
224
+ it "should be false if both index and year do not match, independent of the other object's type" do
225
+ week = described_class.new(2012, 1)
226
+
227
+ other = OpenStruct.new
228
+ other.year = Aef::Weekling::Year.new(2005)
229
+ other.index = 13
230
+
231
+ week.should_not == other
232
+ end
233
+ end
234
+
235
+ context "#eql? (type dependant equality)" do
236
+ it "should be true if year and index and type matches and of same class" do
237
+ week = described_class.new(2012, 1)
238
+ other = described_class.new(2012, 1)
239
+
240
+ week.should eql other
241
+ end
242
+
243
+ it "should be true if year and index and type matches and of inheriting class" do
244
+ week = described_class.new(2012, 1)
245
+
246
+ inheriting_class = Class.new(described_class)
247
+
248
+ other = inheriting_class.new(2012, 1)
249
+
250
+ week.should eql other
251
+ end
252
+
253
+ it "should be false if year and index match but type differs" do
254
+ week = described_class.new(2012, 1)
255
+
256
+ other = OpenStruct.new
257
+ other.year = Aef::Weekling::Year.new(2012)
258
+ other.index = 1
259
+
260
+ week.should_not eql other
261
+ end
262
+
263
+ it "should be false if year matches but not index" do
264
+ week = described_class.new(2012, 1)
265
+ other = described_class.new(2012, 13)
266
+
267
+ week.should_not eql other
268
+ end
269
+
270
+ it "should be false if index matches but not year" do
271
+ week = described_class.new(2012, 1)
272
+ other = described_class.new(2005, 1)
273
+
274
+ week.should_not eql other
275
+ end
276
+
277
+ it "should be false if both index and year do not match" do
278
+ week = described_class.new(2012, 1)
279
+ other = described_class.new(2005, 13)
280
+
281
+ week.should_not eql other
282
+ end
283
+ end
284
+
285
+ context "#hash" do
286
+ it "should return Integers" do
287
+ a_week = described_class.new(2012, 5)
288
+ another_week = described_class.new(2012, 6)
289
+
290
+ a_week.hash.should be_a(Integer)
291
+ another_week.hash.should be_a(Integer)
292
+ end
293
+
294
+ it "should discriminate a week from another one" do
295
+ a_week = described_class.new(2012, 5)
296
+ another_week = described_class.new(2012, 6)
297
+
298
+ a_week.hash.should_not == another_week.hash
299
+ end
300
+ end
301
+
302
+ context "#<=>" do
303
+ it "should correctly determine the order of weeks based on year" do
304
+ lower_week = described_class.new(2011, 14)
305
+ higher_week = described_class.new(2012, 14)
306
+
307
+ lower_week.should < higher_week
308
+ end
309
+
310
+ it "should correctly determine the order of weeks based on year, independent of type" do
311
+ lower_week = described_class.new(2011, 14)
312
+
313
+ higher_week = OpenStruct.new
314
+ higher_week.year = Aef::Weekling::Year.new(2012)
315
+ higher_week.index = 14
316
+
317
+ lower_week.should < higher_week
318
+ end
319
+
320
+ it "should correctly determine the order of weeks based on index" do
321
+ lower_week = described_class.new(2011, 14)
322
+ higher_week = described_class.new(2011, 15)
323
+
324
+ lower_week.should < higher_week
325
+ end
326
+
327
+ it "should correctly determine the order of weeks based on index, independent of type" do
328
+ lower_week = described_class.new(2011, 14)
329
+
330
+ higher_week = OpenStruct.new
331
+ higher_week.year = Aef::Weekling::Year.new(2011)
332
+ higher_week.index = 15
333
+
334
+ lower_week.should < higher_week
335
+ end
336
+
337
+ it "should prioritize the order years when determining the order of weeks" do
338
+ lower_week = described_class.new(2011, 14)
339
+ higher_week = described_class.new(2012, 13)
340
+
341
+ lower_week.should < higher_week
342
+ end
343
+
344
+ it "should prioritize the order years when determining the order of weeks, independent of type" do
345
+ lower_week = described_class.new(2011, 14)
346
+
347
+ higher_week = OpenStruct.new
348
+ higher_week.year = Aef::Weekling::Year.new(2012)
349
+ higher_week.index = 13
350
+
351
+ lower_week.should < higher_week
352
+ end
353
+ end
354
+
355
+ context "#to_s" do
356
+ it "should be able to display an ancient week" do
357
+ week = described_class.new(-1503, 50)
358
+
359
+ week.to_s.should eql '-1503-W50'
360
+ end
361
+
362
+ it "should be able to display a normal week" do
363
+ week = described_class.new(2011, 30)
364
+
365
+ week.to_s.should eql '2011-W30'
366
+ end
367
+
368
+ it "should be able to display a post apocalyptic week" do
369
+ week = described_class.new(50023, 3)
370
+
371
+ week.to_s.should eql '50023-W03'
372
+ end
373
+ end
374
+
375
+ context "#inspect" do
376
+ it "should be able to display an ancient week" do
377
+ week = described_class.new(-1503, 50)
378
+
379
+ week.inspect.should eql '#<Aef::Weekling::Week: -1503-W50>'
380
+ end
381
+
382
+ it "should be able to display a normal week" do
383
+ week = described_class.new(2011, 30)
384
+
385
+ week.inspect.should eql '#<Aef::Weekling::Week: 2011-W30>'
386
+ end
387
+
388
+ it "should be able to display a post apocalyptic week" do
389
+ week = described_class.new(50023, 3)
390
+
391
+ week.inspect.should eql '#<Aef::Weekling::Week: 50023-W03>'
392
+ end
393
+ end
394
+
395
+ context "#to_week" do
396
+ it "should return itself" do
397
+ week = described_class.new(2011, 30)
398
+ week.to_week.should equal(week)
399
+ end
400
+ end
401
+
402
+ [:next, :succ].each do |method|
403
+ context "##{method}" do
404
+ it "should return the next week" do
405
+ described_class.new(2011, 19).method(method).call.should eql described_class.new(2011, 20)
406
+ end
407
+
408
+ it "should return the next week at the end of a year" do
409
+ described_class.new(2011, 52).method(method).call.should eql described_class.new(2012, 1)
410
+ end
411
+
412
+ it "should return the next week one week before the end of a year with 53 weeks" do
413
+ described_class.new(2015, 52).method(method).call.should eql described_class.new(2015, 53)
414
+ end
415
+
416
+ it "should return the next week at the end of a year with 53 weeks" do
417
+ described_class.new(2015, 53).method(method).call.should eql described_class.new(2016, 1)
418
+ end
419
+ end
420
+ end
421
+
422
+ [:previous, :pred].each do |method|
423
+ context "##{method}" do
424
+ it "should return the previous week" do
425
+ described_class.new(2011, 20).method(method).call.should eql described_class.new(2011, 19)
426
+ end
427
+
428
+ it "should return the previous week at the beginning of a year" do
429
+ described_class.new(2012, 1).method(method).call.should eql described_class.new(2011, 52)
430
+ end
431
+
432
+ it "should return the previous week at the beginning of a year after one with 53 weeks" do
433
+ described_class.new(2016, 1).method(method).call.should eql described_class.new(2015, 53)
434
+ end
435
+
436
+ it "should return the previous week at the end of a year with 53 weeks" do
437
+ described_class.new(2015, 53).method(method).call.should eql described_class.new(2015, 52)
438
+ end
439
+ end
440
+ end
441
+
442
+ context "#+" do
443
+ it "should be able to add a positive amount of weeks" do
444
+ (described_class.new(1998, 10) + 15).should eql described_class.new(1998, 25)
445
+ end
446
+
447
+ it "should be able to add a positive amount of weeks so that the result isn't in the year anymore" do
448
+ (described_class.new(1996, 48) + 8).should eql described_class.new(1997, 4)
449
+ end
450
+
451
+ it "should be able to add a positive amount of weeks so that the result isn't in the year with 53 weeks anymore" do
452
+ (described_class.new(2004, 48) + 8).should eql described_class.new(2005, 3)
453
+ end
454
+
455
+ it "should be able to add a negative amount of weeks" do
456
+ (described_class.new(1998, 20) + -15).should eql described_class.new(1998, 5)
457
+ end
458
+
459
+ it "should be able to add a negative amount of weeks so that the result isn't in the year anymore" do
460
+ (described_class.new(1998, 10) + -12).should eql described_class.new(1997, 50)
461
+ end
462
+
463
+ it "should be able to add a negative amount of weeks so that the result is in the previous year which has 53 weeks" do
464
+ (described_class.new(2005, 23) + -25).should eql described_class.new(2004, 51)
465
+ end
466
+ end
467
+
468
+ context "#-" do
469
+ it "should be able to subtract a positive amount of weeks" do
470
+ (described_class.new(1998, 37) - 15).should eql described_class.new(1998, 22)
471
+ end
472
+
473
+ it "should be able to subtract a positive amount of weeks so that the result isn't in the year anymore" do
474
+ (described_class.new(1998, 48) - 53).should eql described_class.new(1997, 47)
475
+ end
476
+
477
+ it "should be able to subtract a positive amount of weeks so that the result is in the previous year which has 53 weeks" do
478
+ (described_class.new(2005, 16) - 32).should eql described_class.new(2004, 37)
479
+ end
480
+
481
+ it "should be able to subtract a negative amount of weeks" do
482
+ (described_class.new(1998, 20) - -15).should eql described_class.new(1998, 35)
483
+ end
484
+
485
+ it "should be able to subtract a negative amount of weeks so that the result isn't in the year anymore" do
486
+ (described_class.new(1996, 40) - -23).should eql described_class.new(1997, 11)
487
+ end
488
+
489
+ it "should be able to subtract a negative amount of weeks so that the result isn't in the year with 53 weeks anymore" do
490
+ (described_class.new(2004, 49) - -31).should eql described_class.new(2005, 27)
491
+ end
492
+ end
493
+
494
+ context "#until_index" do
495
+ it "should return a range ending in the current year if the given index is greater to the weeks index" do
496
+ week = described_class.new(2011, 13)
497
+
498
+ week.until_index(46).should eql (week .. described_class.new(2011, 46))
499
+ end
500
+
501
+ it "should return a range ending in the next year if the given index is equal to the weeks index" do
502
+ week = described_class.new(2011, 13)
503
+
504
+ week.until_index(13).should eql (week .. described_class.new(2012, 13))
505
+ end
506
+
507
+ it "should return a range ending in the next year if the given index is equal to the weeks index" do
508
+ week = described_class.new(2011, 13)
509
+
510
+ week.until_index(3).should eql (week .. described_class.new(2012, 3))
511
+ end
512
+ end
513
+
514
+ context "#even?" do
515
+ it "should be true if the index is even" do
516
+ described_class.new(420, 6).should be_even
517
+ described_class.new(2011, 42).should be_even
518
+ described_class.new(25043, 28).should be_even
519
+ end
520
+
521
+ it "should be false if the index is odd" do
522
+ described_class.new(420, 7).should_not be_even
523
+ described_class.new(2011, 43).should_not be_even
524
+ described_class.new(25043, 29).should_not be_even
525
+ end
526
+ end
527
+
528
+ context "#odd?" do
529
+ it "should be true if the index is odd" do
530
+ described_class.new(420, 7).should be_odd
531
+ described_class.new(2011, 43).should be_odd
532
+ described_class.new(25043, 29).should be_odd
533
+ end
534
+
535
+ it "should be false if the index is even" do
536
+ described_class.new(420, 6).should_not be_odd
537
+ described_class.new(2011, 42).should_not be_odd
538
+ described_class.new(25043, 28).should_not be_odd
539
+ end
540
+ end
541
+
542
+ context "#days" do
543
+ it "should return a range of the weeks days" do
544
+ described_class.new(2011, 15).days.should eql(
545
+ (Aef::Weekling::WeekDay.new(2011, 15, 1)..Aef::Weekling::WeekDay.new(2011, 15, 7)))
546
+ end
547
+ end
548
+
549
+ context "#day" do
550
+ it "should return a day by index" do
551
+ described_class.new(2011, 15).day(1).should eql Aef::Weekling::WeekDay.new(2011, 15, 1)
552
+ end
553
+
554
+ it "should return a day by symbol" do
555
+ described_class.new(2011, 15).day(:friday).should eql Aef::Weekling::WeekDay.new(2011, 15, 5)
556
+ end
557
+ end
558
+
559
+ context "weekday methods" do
560
+ before(:all) do
561
+ @week = described_class.new(2011, 17)
562
+ end
563
+
564
+ it "should deliver monday" do
565
+ @week.monday.should eql Aef::Weekling::WeekDay.new(@week, 1)
566
+ end
567
+
568
+ it "should deliver tuesday" do
569
+ @week.tuesday.should eql Aef::Weekling::WeekDay.new(@week, 2)
570
+ end
571
+
572
+ it "should deliver wednesday" do
573
+ @week.wednesday.should eql Aef::Weekling::WeekDay.new(@week, 3)
574
+ end
575
+
576
+ it "should deliver thursday" do
577
+ @week.thursday.should eql Aef::Weekling::WeekDay.new(@week, 4)
578
+ end
579
+
580
+ it "should deliver friday" do
581
+ @week.friday.should eql Aef::Weekling::WeekDay.new(@week, 5)
582
+ end
583
+
584
+ it "should deliver saturday" do
585
+ @week.saturday.should eql Aef::Weekling::WeekDay.new(@week, 6)
586
+ end
587
+
588
+ it "should deliver sunday" do
589
+ @week.sunday.should eql Aef::Weekling::WeekDay.new(@week, 7)
590
+ end
591
+
592
+ it "should deliver the weekend" do
593
+ @week.weekend.should eql [Aef::Weekling::WeekDay.new(@week, 6), Aef::Weekling::WeekDay.new(@week, 7)]
594
+ end
595
+ end
596
+ end