PageRenderTime 92ms CodeModel.GetById 20ms app.highlight 68ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/aef/weekling/week_spec.rb

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