rubyredrick-ri_cal 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +122 -0
  3. data/README.txt +271 -0
  4. data/Rakefile +31 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +2 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal/component/alarm.rb +22 -0
  21. data/lib/ri_cal/component/calendar.rb +199 -0
  22. data/lib/ri_cal/component/event.rb +30 -0
  23. data/lib/ri_cal/component/freebusy.rb +19 -0
  24. data/lib/ri_cal/component/journal.rb +22 -0
  25. data/lib/ri_cal/component/t_z_info_timezone.rb +124 -0
  26. data/lib/ri_cal/component/timezone/daylight_period.rb +26 -0
  27. data/lib/ri_cal/component/timezone/standard_period.rb +24 -0
  28. data/lib/ri_cal/component/timezone/timezone_period.rb +54 -0
  29. data/lib/ri_cal/component/timezone.rb +193 -0
  30. data/lib/ri_cal/component/todo.rb +26 -0
  31. data/lib/ri_cal/component.rb +224 -0
  32. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  33. data/lib/ri_cal/core_extensions/array.rb +7 -0
  34. data/lib/ri_cal/core_extensions/date/conversions.rb +27 -0
  35. data/lib/ri_cal/core_extensions/date.rb +13 -0
  36. data/lib/ri_cal/core_extensions/date_time/conversions.rb +27 -0
  37. data/lib/ri_cal/core_extensions/date_time.rb +13 -0
  38. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  39. data/lib/ri_cal/core_extensions/object.rb +8 -0
  40. data/lib/ri_cal/core_extensions/string/conversions.rb +32 -0
  41. data/lib/ri_cal/core_extensions/string.rb +8 -0
  42. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  43. data/lib/ri_cal/core_extensions/time/conversions.rb +27 -0
  44. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  45. data/lib/ri_cal/core_extensions/time.rb +11 -0
  46. data/lib/ri_cal/core_extensions.rb +6 -0
  47. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  48. data/lib/ri_cal/occurrence_enumerator.rb +172 -0
  49. data/lib/ri_cal/parser.rb +138 -0
  50. data/lib/ri_cal/properties/alarm.rb +390 -0
  51. data/lib/ri_cal/properties/calendar.rb +164 -0
  52. data/lib/ri_cal/properties/event.rb +1526 -0
  53. data/lib/ri_cal/properties/freebusy.rb +594 -0
  54. data/lib/ri_cal/properties/journal.rb +1240 -0
  55. data/lib/ri_cal/properties/timezone.rb +151 -0
  56. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  57. data/lib/ri_cal/properties/todo.rb +1562 -0
  58. data/lib/ri_cal/property_value/array.rb +19 -0
  59. data/lib/ri_cal/property_value/cal_address.rb +12 -0
  60. data/lib/ri_cal/property_value/date.rb +119 -0
  61. data/lib/ri_cal/property_value/date_time/additive_methods.rb +43 -0
  62. data/lib/ri_cal/property_value/date_time/time_machine.rb +180 -0
  63. data/lib/ri_cal/property_value/date_time/timezone_support.rb +65 -0
  64. data/lib/ri_cal/property_value/date_time.rb +324 -0
  65. data/lib/ri_cal/property_value/duration.rb +106 -0
  66. data/lib/ri_cal/property_value/geo.rb +12 -0
  67. data/lib/ri_cal/property_value/integer.rb +13 -0
  68. data/lib/ri_cal/property_value/occurrence_list.rb +82 -0
  69. data/lib/ri_cal/property_value/period.rb +63 -0
  70. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +98 -0
  71. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +77 -0
  72. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +149 -0
  73. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +54 -0
  74. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +32 -0
  75. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +794 -0
  76. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +132 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +61 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +34 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +50 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +126 -0
  81. data/lib/ri_cal/property_value/recurrence_rule.rb +146 -0
  82. data/lib/ri_cal/property_value/text.rb +41 -0
  83. data/lib/ri_cal/property_value/uri.rb +12 -0
  84. data/lib/ri_cal/property_value/utc_offset.rb +34 -0
  85. data/lib/ri_cal/property_value.rb +110 -0
  86. data/lib/ri_cal/required_timezones.rb +56 -0
  87. data/lib/ri_cal/time_with_floating_timezone.rb +59 -0
  88. data/lib/ri_cal.rb +134 -0
  89. data/ri_cal.gemspec +47 -0
  90. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  91. data/script/console +10 -0
  92. data/script/destroy +14 -0
  93. data/script/generate +14 -0
  94. data/script/txt2html +71 -0
  95. data/spec/ri_cal/component/alarm_spec.rb +13 -0
  96. data/spec/ri_cal/component/calendar_spec.rb +55 -0
  97. data/spec/ri_cal/component/event_spec.rb +157 -0
  98. data/spec/ri_cal/component/freebusy_spec.rb +13 -0
  99. data/spec/ri_cal/component/journal_spec.rb +13 -0
  100. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +37 -0
  101. data/spec/ri_cal/component/timezone_spec.rb +155 -0
  102. data/spec/ri_cal/component/todo_spec.rb +61 -0
  103. data/spec/ri_cal/component_spec.rb +212 -0
  104. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +189 -0
  105. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +46 -0
  106. data/spec/ri_cal/occurrence_enumerator_spec.rb +218 -0
  107. data/spec/ri_cal/parser_spec.rb +304 -0
  108. data/spec/ri_cal/property_value/date_spec.rb +22 -0
  109. data/spec/ri_cal/property_value/date_time_spec.rb +448 -0
  110. data/spec/ri_cal/property_value/duration_spec.rb +80 -0
  111. data/spec/ri_cal/property_value/period_spec.rb +50 -0
  112. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +22 -0
  113. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1815 -0
  114. data/spec/ri_cal/property_value/text_spec.rb +14 -0
  115. data/spec/ri_cal/property_value/utc_offset_spec.rb +49 -0
  116. data/spec/ri_cal/property_value_spec.rb +111 -0
  117. data/spec/ri_cal/required_timezones_spec.rb +68 -0
  118. data/spec/ri_cal_spec.rb +54 -0
  119. data/spec/spec.opts +4 -0
  120. data/spec/spec_helper.rb +24 -0
  121. data/tasks/ri_cal.rake +403 -0
  122. data/tasks/spec.rake +35 -0
  123. metadata +201 -0
@@ -0,0 +1,189 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
5
+
6
+ describe RiCal::CoreExtensions::Time::Calculations do
7
+
8
+ describe ".iso_week_num" do
9
+
10
+ it "should calculate week 1 for January 1, 2001 for a wkst of 1 (Monday)" do
11
+ Date.new(2001, 1,1).iso_week_num(1).should == 1
12
+ end
13
+
14
+ it "should calculate week 1 for January 7, 2001 for a wkst of 1 (Monday)" do
15
+ Date.new(2001, 1,7).iso_week_num(1).should == 1
16
+ end
17
+
18
+ it "should calculate week 2 for January 8, 2001 for a wkst of 1 (Monday)" do
19
+ Date.new(2001, 1,8).iso_week_num(1).should == 2
20
+ end
21
+
22
+ it "should calculate week 52 for December 31, 2000 for a wkst of 1 (Monday)" do
23
+ Date.new(2000, 12,31).iso_week_num(1).should == 52
24
+ end
25
+
26
+ it "should calculate week 52 for January 1, 2001 for a wkst of 2 (Tuesday)" do
27
+ Date.new(2001, 1, 1).iso_week_num(2).should == 52
28
+ end
29
+
30
+ it "should calculate week 1 for Dec 31, 2003 for a wkst of 1 (Monday)" do
31
+ Date.new(2003, 12, 31).iso_week_num(1).should == 1
32
+ end
33
+ end
34
+
35
+ describe ".iso_year" do
36
+ it "should be 1999 for January 2 2000" do
37
+ Date.new(2000, 1, 2).iso_year(1).should == 1999
38
+ end
39
+
40
+ it "should be 1998 for December 29, 1997" do
41
+ Date.new(1997, 12, 29).iso_year(1).should == 1998
42
+ end
43
+ end
44
+
45
+ describe ".iso_year_start" do
46
+
47
+ it "should calculate January 4 1999 for January 2 2000 for a wkst of 1 (Monday)" do
48
+ Date.new(2000, 1, 2).iso_year_start(1).to_s.should == Date.new(1999, 1, 4).to_s
49
+ end
50
+
51
+ it "should calculate January 3 2000 for January 3 2000 for a wkst of 1 (Monday)" do
52
+ Date.new(2000, 1, 3).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
53
+ end
54
+
55
+ it "should calculate January 3 2000 for January 4 2000 for a wkst of 1 (Monday)" do
56
+ Date.new(2000, 1, 4).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
57
+ end
58
+
59
+ it "should calculate January 3 2000 for December 31 2000 for a wkst of 1 (Monday)" do
60
+ Date.new(2000, 12, 31).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
61
+ end
62
+
63
+ it "should calculate week January 1, 2001 for January 1, 2001 for a wkst of 1 (Monday)" do
64
+ Date.new(2001, 1,1).iso_year_start(1).should == Date.new(2001, 1, 1)
65
+ end
66
+
67
+ it "should calculate week January 1, 2001 for July 4, 2001 for a wkst of 1 (Monday)" do
68
+ Date.new(2001, 7,4).iso_year_start(1).should == Date.new(2001, 1, 1)
69
+ end
70
+
71
+ it "should calculate January 3 2000 for January 3 2000" do
72
+ Date.new(2000, 1, 3).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
73
+ end
74
+
75
+ it "should calculate January 3 2000 for January 4 2000" do
76
+ Date.new(2000, 1, 4).iso_year_start(1).to_s.should == Date.new(2000, 1, 3).to_s
77
+ end
78
+
79
+ # it "should calculate week 1 for January 7, 2001 for a wkst of 1 (Monday)" do
80
+ # Date.new(2001, 1,7).iso_week_num(1).should == 1
81
+ # end
82
+ #
83
+ # it "should calculate week 2 for January 8, 2001 for a wkst of 1 (Monday)" do
84
+ # Date.new(2001, 1,8).iso_week_num(1).should == 2
85
+ # end
86
+ #
87
+ # it "should calculate week 52 for December 31, 2000 for a wkst of 1 (Monday)" do
88
+ # Date.new(2000, 12,31).iso_week_num(1).should == 52
89
+ # end
90
+ #
91
+ # it "should calculate week 52 for January 1, 2001 for a wkst of 2 (Tuesday)" do
92
+ # Date.new(2001, 1, 1).iso_week_num(2).should == 52
93
+ # end
94
+ #
95
+ # it "should calculate week 1 for Dec 31, 2003 for a wkst of 1 (Monday)" do
96
+ # Date.new(2003, 12, 31).iso_week_num(1).should == 1
97
+ # end
98
+ end
99
+
100
+ describe "#iso_week_one" do
101
+
102
+ before(:each) do
103
+ @it = RiCal::CoreExtensions::Time::Calculations
104
+ end
105
+
106
+ describe "with a monday week start" do
107
+ it "should return Jan 3, 2000 for 2000" do
108
+ @it.iso_week_one(2000, 1).should == Date.new(2000, 1, 3)
109
+ end
110
+
111
+ it "should return Jan 1, 2001 for 2001" do
112
+ @it.iso_week_one(2001, 1).should == Date.new(2001, 1,1)
113
+ end
114
+
115
+ it "should return Dec 31, 2001 for 2002" do
116
+ @it.iso_week_one(2002, 1).should == Date.new(2001, 12, 31)
117
+ end
118
+
119
+ it "should return Dec 30, 2002 for 2003" do
120
+ @it.iso_week_one(2003, 1).should == Date.new(2002, 12, 30)
121
+ end
122
+
123
+ it "should return Dec 29, 2003 for 2004" do
124
+ @it.iso_week_one(2004, 1).should == Date.new(2003, 12, 29)
125
+ end
126
+ end
127
+
128
+ it "should return Jan 2, 2001 for 2001 with a Tuesday week start" do
129
+ @it.iso_week_one(2001, 2).should == Date.new(2001, 1, 2)
130
+ end
131
+
132
+ it "should return Jan 3, 2001 for 2001 with a Wednesday week start" do
133
+ @it.iso_week_one(2001, 3).should == Date.new(2001, 1, 3)
134
+ end
135
+
136
+ it "should return Jan 4, 2001 for 2001 with a Thursday week start" do
137
+ @it.iso_week_one(2001, 4).should == Date.new(2001, 1, 4)
138
+ end
139
+
140
+ it "should return Dec 29, 2000 for 2001 with a Friday week start" do
141
+ @it.iso_week_one(2001, 5).should == Date.new(2000, 12, 29)
142
+ end
143
+
144
+ it "should return Dec 30, 2000 for 2001 with a Saturday week start" do
145
+ @it.iso_week_one(2001, 6).should == Date.new(2000, 12, 30)
146
+ end
147
+
148
+ it "should return Dec 31, 2000 for 2001 with a Sunday week start" do
149
+ @it.iso_week_one(2001, 0).should == Date.new(2000, 12, 31)
150
+ end
151
+ end
152
+
153
+ describe ".leap_year?" do
154
+ it "should return true for 2000" do
155
+ Date.parse("1/3/2000").should be_leap_year
156
+ end
157
+
158
+ it "should return false for 2007" do
159
+ Date.parse("1/3/2007").should_not be_leap_year
160
+ end
161
+
162
+ it "should return true for 2008" do
163
+ Date.parse("1/3/2008").should be_leap_year
164
+ end
165
+
166
+ it "should return false for 2100" do
167
+ Date.parse("1/3/2100").should_not be_leap_year
168
+ end
169
+ end
170
+
171
+ describe ".days_in_month" do
172
+
173
+ it "should return 29 for February in a leap year" do
174
+ Date.new(2008, 2, 1).days_in_month.should == 29
175
+ end
176
+
177
+ it "should return 28 for February in a non-leap year" do
178
+ Date.new(2009, 2, 1).days_in_month.should == 28
179
+ end
180
+
181
+ it "should return 31 for January in a leap year" do
182
+ Date.new(2008, 1, 1).days_in_month.should == 31
183
+ end
184
+
185
+ it "should return 31 for January in a non-leap year" do
186
+ Date.new(2009, 1, 1).days_in_month.should == 31
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,46 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
5
+
6
+ describe RiCal::CoreExtensions::Time::WeekDayPredicates do
7
+
8
+ describe ".nth_wday_in_month" do
9
+ it "should return Feb 28, 2005 for the 4th Monday for a date in February 2005" do
10
+ expected = RiCal::PropertyValue::Date.new(nil, :value => "20050228")
11
+ it =Date.parse("Feb 7, 2005").nth_wday_in_month(4, 1)
12
+ it.should == expected
13
+ end
14
+ end
15
+
16
+ describe ".nth_wday_in_month?" do
17
+ it "should return true for Feb 28, 2005 for the 4th Monday" do
18
+ Date.parse("Feb 28, 2005").nth_wday_in_month?(4, 1).should be
19
+ end
20
+ end
21
+
22
+ describe ".start_of_week_with_wkst" do
23
+ describe "for Wednesday Sept 10 1997" do
24
+ before(:each) do
25
+ @date = Date.parse("Sept 10, 1997")
26
+ end
27
+
28
+ it "should return a Date of Sept 7, 1997 00:00 for a wkst of 0 - Sunday" do
29
+ @date.start_of_week_with_wkst(0).should == Date.parse("Sept 7, 1997")
30
+ end
31
+
32
+ it "should return a Date of Sept 8, 1997 00:00 for a wkst of 1 - Monday" do
33
+ @date.start_of_week_with_wkst(1).should == Date.parse("Sept 8, 1997")
34
+ end
35
+
36
+ it "should return a Date of Sept 10, 1997 00:00 for a wkst of 3 - Wednesday" do
37
+ @date.start_of_week_with_wkst(3).should == Date.parse("Sept 10, 1997")
38
+ end
39
+
40
+ it "should return a Date of Sept 4, 1997 00:00 for a wkst of 4 - Thursday" do
41
+ @date.start_of_week_with_wkst(4).should == Date.parse("Sept 4, 1997")
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,218 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper.rb])
5
+
6
+ # Note that this is more of a functional spec
7
+ describe RiCal::OccurrenceEnumerator do
8
+
9
+ Fr13Unbounded_Zulu = <<-TEXT
10
+ BEGIN:VEVENT
11
+ DTSTART:19970902T090000Z
12
+ EXDATE:19970902T090000Z
13
+ RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
14
+ END:VEVENT
15
+ TEXT
16
+
17
+ Fr13Unbounded_Eastern = <<-TEXT
18
+ BEGIN:VEVENT
19
+ DTSTART;TZID=US-Eastern:19970902T090000
20
+ EXDATE;TZID=US-Eastern:19970902T090000
21
+ RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
22
+ END:VEVENT
23
+ TEXT
24
+
25
+ Fr13UnboundedZuluExpectedFive = [
26
+ "19980213T090000Z",
27
+ "19980313T090000Z",
28
+ "19981113T090000Z",
29
+ "19990813T090000Z",
30
+ "20001013T090000Z"
31
+ ].map {|start| src = <<-TEXT
32
+ BEGIN:VEVENT
33
+ DTSTART:#{start}
34
+ RECURRENCE-ID:#{start}
35
+ END:VEVENT
36
+ TEXT
37
+ RiCal.parse_string(src).first
38
+ }
39
+
40
+ describe ".occurrences" do
41
+ describe "with an unbounded component" do
42
+ before(:each) do
43
+ @it = RiCal.parse_string(Fr13Unbounded_Zulu).first
44
+ end
45
+
46
+ it "should raise an ArgumentError with no options to limit result" do
47
+ lambda {@it.occurrences}.should raise_error(ArgumentError)
48
+ end
49
+
50
+ it "should have the right five occurrences when :count => 5 option is used" do
51
+ result = @it.occurrences(:count => 5)
52
+ result.should == Fr13UnboundedZuluExpectedFive
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+
59
+ describe ".each" do
60
+ describe " for Every Friday the 13th, forever" do
61
+ before(:each) do
62
+ event = RiCal.parse_string(Fr13Unbounded_Zulu).first
63
+ @result = []
64
+ event.each do |occurrence|
65
+ break if @result.length >= 5
66
+ @result << occurrence
67
+ end
68
+ end
69
+
70
+ it "should have the right first six occurrences" do
71
+ # TODO - Need to properly deal with timezones
72
+ @result.should == Fr13UnboundedZuluExpectedFive
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+
79
+ describe RiCal::OccurrenceEnumerator::OccurrenceMerger do
80
+ before(:each) do
81
+ @merger = RiCal::OccurrenceEnumerator::OccurrenceMerger
82
+ end
83
+
84
+ describe ".for" do
85
+ it "should return an EmptyEnumerator if the rules parameter is nil" do
86
+ @merger.for(nil, nil).should == RiCal::OccurrenceEnumerator::EmptyRulesEnumerator
87
+ end
88
+
89
+ it "should return an EmptyEnumerator if the rules parameter is empty" do
90
+ @merger.for(nil, []).should == RiCal::OccurrenceEnumerator::EmptyRulesEnumerator
91
+ end
92
+
93
+ describe "with a single rrule" do
94
+ before(:each) do
95
+ @component = mock("component", :dtstart => :dtstart_value)
96
+ @rrule = mock("rrule", :enumerator => :rrule_enumerator)
97
+ end
98
+
99
+ it "should return the enumerator the rrule" do
100
+ @merger.for(@component, [@rrule]).should == :rrule_enumerator
101
+ end
102
+
103
+ it "should pass the component to the enumerator instantiation" do
104
+ @rrule.should_receive(:enumerator).with(@component)
105
+ @merger.for(@component, [@rrule])
106
+ end
107
+ end
108
+
109
+ describe "with multiple rrules" do
110
+ before(:each) do
111
+ @component = mock("component", :dtstart => :dtstart_value)
112
+ @enum1 = mock("rrule_enumerator1", :next_occurrence => :occ1, :bounded? => true)
113
+ @enum2 = mock("rrule_enumerator2", :next_occurrence => :occ2, :bounded? => true)
114
+ @rrule1 = mock("rrule", :enumerator => @enum1)
115
+ @rrule2 = mock("rrule", :enumerator => @enum2)
116
+ end
117
+
118
+ it "should return an instance of RiCal::OccurrenceEnumerator::OccurrenceMerger" do
119
+ @merger.for(@component, [@rrule1, @rrule2]).should be_kind_of(RiCal::OccurrenceEnumerator::OccurrenceMerger)
120
+ end
121
+
122
+ it "should pass the component to the enumerator instantiation" do
123
+ @rrule1.should_receive(:enumerator).with(@component).and_return(@enum1)
124
+ @rrule2.should_receive(:enumerator).with(@component).and_return(@enum2)
125
+ @merger.for(@component, [@rrule1, @rrule2])
126
+ end
127
+
128
+ it "should preload the next occurrences" do
129
+ @enum1.should_receive(:next_occurrence).and_return(:occ1)
130
+ @enum2.should_receive(:next_occurrence).and_return(:occ2)
131
+ @merger.for(@component, [@rrule1, @rrule2])
132
+ end
133
+ end
134
+ end
135
+
136
+ describe "#next_occurence" do
137
+
138
+ describe "with unique nexts" do
139
+ before(:each) do
140
+ @enum1 = mock("rrule_enumerator1", :next_occurrence => 3, :bounded? => true)
141
+ @enum2 = mock("rrule_enumerator2", :next_occurrence => 2, :bounded? => true)
142
+ @rrule1 = mock("rrule", :enumerator => @enum1)
143
+ @rrule2 = mock("rrule", :enumerator => @enum2)
144
+ @it = @merger.new(0, [@rrule1, @rrule2])
145
+ end
146
+
147
+ it "should return the earliest occurrence" do
148
+ @it.next_occurrence.should == 2
149
+ end
150
+
151
+ it "should advance the enumerator which returned the result" do
152
+ @enum2.should_receive(:next_occurrence).and_return(4)
153
+ @it.next_occurrence
154
+ end
155
+
156
+ it "should not advance the other enumerator" do
157
+ @enum1.should_not_receive(:next_occurrence)
158
+ @it.next_occurrence
159
+ end
160
+
161
+ it "should properly update the next array" do
162
+ @enum2.stub!(:next_occurrence).and_return(4)
163
+ @it.next_occurrence
164
+ @it.nexts.should == [3, 4]
165
+ end
166
+ end
167
+
168
+ describe "with duplicated nexts" do
169
+ before(:each) do
170
+ @enum1 = mock("rrule_enumerator1", :next_occurrence => 2, :bounded? => true)
171
+ @enum2 = mock("rrule_enumerator2", :next_occurrence => 2, :bounded? => true)
172
+ @rrule1 = mock("rrule", :enumerator => @enum1)
173
+ @rrule2 = mock("rrule", :enumerator => @enum2)
174
+ @it = @merger.new(0, [@rrule1, @rrule2])
175
+ end
176
+
177
+ it "should return the earliest occurrence" do
178
+ @it.next_occurrence.should == 2
179
+ end
180
+
181
+ it "should advance both enumerators" do
182
+ @enum1.should_receive(:next_occurrence).and_return(5)
183
+ @enum2.should_receive(:next_occurrence).and_return(4)
184
+ @it.next_occurrence
185
+ end
186
+
187
+ it "should properly update the next array" do
188
+ @enum1.stub!(:next_occurrence).and_return(5)
189
+ @enum2.stub!(:next_occurrence).and_return(4)
190
+ @it.next_occurrence
191
+ @it.nexts.should == [5, 4]
192
+ end
193
+
194
+ end
195
+
196
+ describe "with all enumerators at end" do
197
+ before(:each) do
198
+ @enum1 = mock("rrule_enumerator1", :next_occurrence => nil, :bounded? => true)
199
+ @enum2 = mock("rrule_enumerator2", :next_occurrence => nil, :bounded? => true)
200
+ @rrule1 = mock("rrule", :enumerator => @enum1)
201
+ @rrule2 = mock("rrule", :enumerator => @enum2)
202
+ @it = @merger.new(0, [@rrule1, @rrule2])
203
+ end
204
+
205
+ it "should return nil" do
206
+ @it.next_occurrence.should == nil
207
+ end
208
+
209
+ it "should not advance the enumerators which returned the result" do
210
+ @enum1.should_not_receive(:next_occurrence)
211
+ @enum2.should_not_receive(:next_occurrence)
212
+ @it.next_occurrence
213
+ end
214
+ end
215
+ end
216
+ end
217
+
218
+