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,157 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+
6
+ describe RiCal::Component::Event do
7
+
8
+ describe ".entity_name" do
9
+ it "should be VEVENT" do
10
+ RiCal::Component::Event.entity_name.should == "VEVENT"
11
+ end
12
+ end
13
+
14
+ context "with an rrule" do
15
+ before(:each) do
16
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nRRULE:FREQ=DAILY\nEND:VEVENT").first
17
+ end
18
+
19
+ it "should have an array of rrules" do
20
+ @it.rrule.should be_kind_of(Array)
21
+ end
22
+ end
23
+
24
+ context "description property" do
25
+ before(:each) do
26
+ @ical_desc = "posted by Joyce per Zan\\nASheville\\, Rayan's Restauratn\\, Biltm\n ore Square"
27
+ @ruby_desc = "posted by Joyce per Zan\nASheville, Rayan's Restauratn, Biltmore Square"
28
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDESCRIPTION:#{@ical_desc}\nEND:VEVENT").first
29
+ end
30
+
31
+ it "should product the converted ruby value" do
32
+ @it.description.should == @ruby_desc
33
+ end
34
+
35
+ it "should produce escaped text for ical" do
36
+ @it.description = "This is a\nnew description, yes; it is"
37
+ @it.description_property.value.should == 'This is a\nnew description\, yes\; it is'
38
+ end
39
+
40
+ end
41
+
42
+ context "with both dtend and duration specified" do
43
+ before(:each) do
44
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nDURATION:H1\nEND:VEVENT").first
45
+ end
46
+
47
+ it "should be invalid" do
48
+ @it.should_not be_valid
49
+ end
50
+ end
51
+
52
+ context "with a duration property" do
53
+ before(:each) do
54
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDURATION:H1\nEND:VEVENT").first
55
+ end
56
+
57
+ it "should have a duration property" do
58
+ @it.duration_property.should be
59
+ end
60
+
61
+ it "should have a duration of 1 Hour" do
62
+ @it.duration_property.value.should == "H1"
63
+ end
64
+
65
+ it "should reset the duration property if the dtend property is set" do
66
+ @it.dtend_property = "19970101".to_ri_cal_date_time_value
67
+ @it.duration_property.should be_nil
68
+ end
69
+
70
+ it "should reset the duration property if the dtend ruby value is set" do
71
+ @it.dtend = "19970101"
72
+ @it.duration_property.should == nil
73
+ end
74
+ end
75
+
76
+ context "with a dtend property" do
77
+ before(:each) do
78
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nEND:VEVENT").first
79
+ end
80
+
81
+ it "should have a duration property" do
82
+ @it.dtend_property.should be
83
+ end
84
+
85
+ it "should reset the dtend property if the duration property is set" do
86
+ @it.duration_property = "H1".to_ri_cal_duration_value
87
+ @it.dtend_property.should be_nil
88
+ end
89
+
90
+ it "should reset the dtend property if the duration ruby value is set" do
91
+ @it.duration = "H1".to_ri_cal_duration_value
92
+ @it.dtend_property.should be_nil
93
+ end
94
+ end
95
+
96
+ context "with a nested alarm component" do
97
+ before(:each) do
98
+ @it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\n\nBEGIN:VALARM\nEND:VALARM\nEND:VEVENT").first
99
+ end
100
+
101
+ it "should have one alarm" do
102
+ @it.alarms.length.should == 1
103
+ end
104
+
105
+ it "which should be an Alarm component" do
106
+ @it.alarms.first.should be_kind_of(RiCal::Component::Alarm)
107
+ end
108
+ end
109
+
110
+ context ".export" do
111
+ require 'rubygems'
112
+ require 'tzinfo'
113
+
114
+ def date_time_with_tzinfo_zone(date_time, timezone="America/New_York")
115
+ result = date_time.dup
116
+ result.stub!(:acts_like_time?).and_return(true)
117
+ time_zone = TZInfo::Timezone.get(timezone)
118
+ result.stub!(:time_zone).and_return(time_zone)
119
+ result
120
+ end
121
+
122
+ # Undo the effects of RFC2445 line folding
123
+ def unfold(string)
124
+ string.gsub("\n ", "")
125
+ end
126
+
127
+ before(:each) do
128
+ cal = RiCal.Calendar
129
+ @it = RiCal::Component::Event.new(cal)
130
+ end
131
+
132
+ it "should cause a VTIMEZONE to be included for a dtstart with a local timezone" do
133
+ @it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
134
+ unfold(@it.export).should match(/BEGIN:VTIMEZONE\nTZID;X-RICAL-TZSOURCE=TZINFO:America\/New_York\n/)
135
+ end
136
+
137
+ it "should properly format dtstart with a UTC date-time" do
138
+ @it.dtstart = DateTime.parse("April 22, 2009 1:23:45")
139
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345Z$/)
140
+ end
141
+
142
+ it "should properly format dtstart with a floating date-time" do
143
+ @it.dtstart = DateTime.parse("April 22, 2009 1:23:45").with_floating_timezone
144
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345$/)
145
+ end
146
+
147
+ it "should properly format dtstart with a local time zone" do
148
+ @it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
149
+ unfold(@it.export).should match(/^DTSTART;TZID=America\/New_York;VALUE=DATE-TIME:20090422T175500$/)
150
+ end
151
+
152
+ it "should properly format dtstart with a date" do
153
+ @it.dtstart = Date.parse("April 22, 2009")
154
+ unfold(@it.export).should match(/^DTSTART;VALUE=DATE:20090422$/)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,13 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+
6
+ describe RiCal::Component::Freebusy do
7
+
8
+ describe ".entity_name" do
9
+ it "should be VFREEBUSY" do
10
+ RiCal::Component::Freebusy.entity_name.should == "VFREEBUSY"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+
6
+ describe RiCal::Component::Journal do
7
+
8
+ describe ".entity_name" do
9
+ it "should be VJOURNAL" do
10
+ RiCal::Component::Journal.entity_name.should == "VJOURNAL"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+ require 'rubygems'
6
+ require 'tzinfo'
7
+
8
+ describe RiCal::Component::TZInfoTimezone do
9
+
10
+ it "should produce an rfc representation" do
11
+ tz = RiCal::Component::TZInfoTimezone.new(TZInfo::Timezone.get("America/New_York"))
12
+ local_first = DateTime.parse("Apr 10, 2007")
13
+ local_last = DateTime.parse("Apr 6, 2008")
14
+ utc_first = tz.local_to_utc(local_first)
15
+ utc_last = tz.local_to_utc(local_last)
16
+ rez = tz.to_rfc2445_string(utc_first, utc_last)
17
+ rez.should == <<-ENDDATA
18
+ BEGIN:VTIMEZONE
19
+ TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York
20
+ BEGIN:DAYLIGHT
21
+ DTSTART:20070311T030000
22
+ RDATE:20070311T030000,20080309T030000
23
+ TZOFFSETFROM:-0500
24
+ TZOFFSETTO:-0400
25
+ TZNAME:EDT
26
+ END:DAYLIGHT
27
+ BEGIN:STANDARD
28
+ DTSTART:20071104T010000
29
+ RDATE:20071104T010000
30
+ TZOFFSETFROM:-0400
31
+ TZOFFSETTO:-0500
32
+ TZNAME:EST
33
+ END:STANDARD
34
+ END:VTIMEZONE
35
+ ENDDATA
36
+ end
37
+ end
@@ -0,0 +1,155 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+ require 'tzinfo'
6
+
7
+ describe RiCal::Component::Timezone do
8
+
9
+ context ".entity_name" do
10
+ it "should be VTIMEZONE" do
11
+ RiCal::Component::Timezone.entity_name.should == "VTIMEZONE"
12
+ end
13
+ end
14
+
15
+ context "from an iCal.app calendar for America/New_York starting March 11 2007" do
16
+ before(:each) do
17
+ @it = RiCal.parse_string <<TZEND
18
+ BEGIN:VTIMEZONE
19
+ TZID:US/Eastern
20
+ BEGIN:DAYLIGHT
21
+ TZOFFSETFROM:-0500
22
+ TZOFFSETTO:-0400
23
+ DTSTART:20070311T020000
24
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
25
+ TZNAME:EDT
26
+ END:DAYLIGHT
27
+ BEGIN:STANDARD
28
+ TZOFFSETFROM:-0400
29
+ TZOFFSETTO:-0500
30
+ DTSTART:20071104T020000
31
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
32
+ TZNAME:EST
33
+ END:STANDARD
34
+ END:VTIMEZONE
35
+ TZEND
36
+ @it = @it.first
37
+ end
38
+
39
+ it "should be a Timezone" do
40
+ @it.should be_kind_of(RiCal::Component::Timezone)
41
+ end
42
+
43
+ context ".local_to_utc" do
44
+ it "should produce 2/27/2009 18:00 UTC for 2/27/2009 13:00" do
45
+ expected = RiCal::PropertyValue::DateTime.new(nil, :value => "20090227T1800Z" )
46
+ @it.local_to_utc(DateTime.parse("Feb 27, 2009 13:00")).should == expected
47
+ end
48
+ end
49
+
50
+ context ".utc_to_local" do
51
+ it "should produce 2/27/2009 13:00 EST for 2/27/2009 18:00 UTC" do
52
+ expected = RiCal::PropertyValue::DateTime.new(nil, :params => {'TZID' => 'US/Eastern'}, :value => "20090227T1300" )
53
+ @it.utc_to_local(DateTime.parse("Feb 27, 2009 18:00")).should == expected
54
+ end
55
+ end
56
+
57
+ context ".period_for_local" do
58
+ it "should raise TZInfo::PeriodNotFound for an invalid local time, e.g. Mar 8, 2009 2:30" do
59
+ lambda {@it.period_for_local(DateTime.parse("Mar 8, 2009 2:30"))}.should raise_error(TZInfo::PeriodNotFound)
60
+ end
61
+
62
+ context "for an ambiguous local time , e.g. Nov 1, 2009 2:00" do
63
+ context "lacking a dst parameter or block" do
64
+ it "should raise TZInfo::AmbiguousTime" do
65
+ lambda {@it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"))}.should raise_error(TZInfo::AmbiguousTime)
66
+ end
67
+ end
68
+
69
+ context "with a dst parameter" do
70
+ it "should return a dst period if the dst parameter is true" do
71
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), true).should be_dst
72
+ end
73
+
74
+ it "should return a std period if the dst parameter is false" do
75
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00"), false).should_not be_dst
76
+ end
77
+ end
78
+
79
+ context "with a block" do
80
+ it "should return a period if the block returns a TimezonePeriod" do
81
+ mock_period = ::RiCal::Component::Timezone::TimezonePeriod.new(nil)
82
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results|
83
+ mock_period
84
+ }.should == mock_period
85
+ end
86
+
87
+ it "should return a period if the block returns a single element array" do
88
+ mock_period = :foo
89
+ @it.period_for_local(DateTime.parse("Nov 1, 2009 2:00")) { |results|
90
+ [ mock_period]
91
+ }.should == mock_period
92
+ end
93
+
94
+ it "should raise TZInfo::PeriodNotFound if the block returns a multi-element array" do
95
+ lambda {
96
+ @it.period_for_local(DateTime.parse("Mar 8, 2009 2:30")) {|results| [1,2]}
97
+ }.should raise_error(TZInfo::PeriodNotFound)
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+
104
+ context ".periods_for_local" do
105
+ context "for the date on which DST begins springing ahead e.g. Mar 8, 2009" do
106
+ it "should return a 1 element array for 1 second before the transition time" do
107
+ @it.periods_for_local(DateTime.parse("Mar 8, 2009 1:59:59")).length.should == 1
108
+ end
109
+
110
+ it "should return an empty array for the transition time" do
111
+ @it.periods_for_local(DateTime.parse("Mar 8, 2009 2:00:00")).should == []
112
+ end
113
+
114
+ it "should return an empty array for 1 second after the transition time" do
115
+ @it.periods_for_local(DateTime.parse("Mar 8, 2009 2:00:01")).should == []
116
+ end
117
+
118
+ it "should return an empty array for 1 second before the spring ahead time" do
119
+ @it.periods_for_local(DateTime.parse("Mar 8, 2009 2:59:59")).should == []
120
+ end
121
+
122
+ it "should return a 1 element array for the spring ahead time" do
123
+ @it.periods_for_local(DateTime.parse("Mar 8, 2009 3:00:00")).length.should == 1
124
+ end
125
+ end
126
+
127
+ context "for the date on which DST ends falling back e.g. Nov 11, 2009" do
128
+ it "should return a 1 element array for 1 second before the transition time" do
129
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 1:59:59")).length.should == 1
130
+ end
131
+
132
+ it "should return a 2 element array for the transition time" do
133
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 2:00:00")).length.should == 2
134
+ end
135
+
136
+ it "should return a 2 element array for 1 second after the transition time" do
137
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 2:00:01")).length.should == 2
138
+ end
139
+
140
+ it "should return a 2 element array for 59 minutes and 59 seconds after the transition time" do
141
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 2:59:59")).length.should == 2
142
+ end
143
+
144
+ it "should return a 2 element array for 1 hour after the transition time" do
145
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 3:00:00")).length.should == 2
146
+ end
147
+
148
+ it "should return a 2 element array for 1 hour and 1 second after the transition time" do
149
+ @it.periods_for_local(DateTime.parse("Nov 1, 2009 3:00:01")).length.should == 2
150
+ end
151
+ end
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,61 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
5
+
6
+ describe RiCal::Component::Todo do
7
+
8
+ describe "with both due and duration specified" do
9
+ before(:each) do
10
+ @it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDUE:19970903T190000Z\nDURATION:H1\nEND:VTODO").first
11
+ end
12
+
13
+ it "should be invalid" do
14
+ @it.should_not be_valid
15
+ end
16
+ end
17
+
18
+ describe "with a duration property" do
19
+ before(:each) do
20
+ @it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDURATION:H1\nEND:VTODO").first
21
+ end
22
+
23
+ it "should have a duration property" do
24
+ @it.duration_property.should be
25
+ end
26
+
27
+ it "should have a duration of 1 Hour" do
28
+ @it.duration_property.value.should == "H1"
29
+ end
30
+
31
+ it "should reset the duration property if the due property is set" do
32
+ @it.due_property = "19970101".to_ri_cal_date_time_value
33
+ @it.duration_property.should be_nil
34
+ end
35
+
36
+ it "should reset the duration property if the dtend ruby value is set" do
37
+ @it.due = "19970101"
38
+ @it.duration_property.should == nil
39
+ end
40
+ end
41
+
42
+ describe "with a due property" do
43
+ before(:each) do
44
+ @it = RiCal::Component::Todo.parse_string("BEGIN:VTODO\nDUE:19970903T190000Z\nEND:VTODO").first
45
+ end
46
+
47
+ it "should have a due property" do
48
+ @it.due_property.should be
49
+ end
50
+
51
+ it "should reset the due property if the duration property is set" do
52
+ @it.duration_property = "H1".to_ri_cal_duration_value
53
+ @it.due_property.should be_nil
54
+ end
55
+
56
+ it "should reset the duration property if the dtend ruby value is set" do
57
+ @it.duration = "19970101"
58
+ @it.due_property.should == nil
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,212 @@
1
+ #- ©2009 Rick DeNatale
2
+ #- All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
5
+
6
+ describe RiCal::Component do
7
+
8
+ context "building blocks" do
9
+
10
+ context "building an empty calendar" do
11
+ before(:each) do
12
+ @it = RiCal.Calendar.to_s
13
+ end
14
+
15
+ it "should have the default prodid" do
16
+ @it.should match(%r{^PRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN$})
17
+ end
18
+
19
+ it "should have the default calscale" do
20
+ @it.should match(%r{^CALSCALE:GREGORIAN$})
21
+ end
22
+
23
+ it "should have the default icalendar version" do
24
+ @it.should match(%r{^VERSION:2\.0$})
25
+ end
26
+ end
27
+
28
+ context "building a calendar with time zones" do
29
+ it 'should allow specifying the time zone identifier' do
30
+ event = RiCal.Event do
31
+ dtstart [DateTime.parse("Feb 20, 1962 14:47:39"), 'US/Pacific']
32
+ end
33
+ event.dtstart_property.should == dt_prop(DateTime.parse("Feb 20, 1962 14:47:39"), tzid = 'US/Pacific')
34
+ end
35
+
36
+ context "adding an exception date" do
37
+
38
+ it "should test stuff"
39
+ # before(:each) do
40
+ # @event = RiCal.Event do
41
+ # add_exdate [DateTime.parse("Feb 20, 1962 14:47:39"), 'US/Pacific']
42
+ # end
43
+ # @prop = @event.exdate_property.first
44
+ # end
45
+ #
46
+ # it "should produce an OccurrenceList for the property" do
47
+ # @prop.should be_instance_of(RiCal::PropertyValue::OccurrenceList)
48
+ # end
49
+ #
50
+ # it "should have the right exdate value" do
51
+ # @event.exdate.should == ""
52
+ # end
53
+ end
54
+ end
55
+
56
+ context "with a block with 1 parameter" do
57
+ before(:each) do
58
+ @it = RiCal.Event do |event|
59
+ event.description = "MA-6 First US Manned Spaceflight"
60
+ event.dtstart = DateTime.parse("Feb 20, 1962 14:47:39")
61
+ event.dtend = DateTime.parse("Feb 20, 1962 19:43:02")
62
+ event.location = "Cape Canaveral"
63
+ event.add_attendee "john.glenn@nasa.gov"
64
+ event.alarm do
65
+ description "Segment 51"
66
+ end
67
+ event.alarm do |alarm|
68
+ alarm.description = "Second alarm"
69
+ end
70
+ end
71
+ end
72
+
73
+ it "should have the right description" do
74
+ @it.description.should == "MA-6 First US Manned Spaceflight"
75
+ end
76
+ it "should have the right dtstart" do
77
+ @it.dtstart.should == DateTime.parse("Feb 20, 1962 14:47:39")
78
+ end
79
+
80
+ it "should have a zulu time dtstart property" do
81
+ @it.dtstart_property.tzid.should == "UTC"
82
+ end
83
+
84
+ it "should have the right dtend" do
85
+ @it.dtend.should == DateTime.parse("Feb 20, 1962 19:43:02")
86
+ end
87
+
88
+ it "should have a zulu time dtend property" do
89
+ @it.dtend_property.tzid.should == "UTC"
90
+ end
91
+
92
+ it "should have the right location" do
93
+ @it.location.should == "Cape Canaveral"
94
+ end
95
+
96
+ it "should have the right attendee" do
97
+ @it.attendee.should include("john.glenn@nasa.gov")
98
+ end
99
+
100
+ it "should have 2 alarms" do
101
+ @it.alarms.length.should == 2
102
+ end
103
+
104
+ it ".the alarms should have the right description" do
105
+ @it.alarms.first.description.should == "Segment 51"
106
+ @it.alarms.last.description.should == "Second alarm"
107
+ end
108
+ end
109
+
110
+ context "building an event for MA-6" do
111
+ before(:each) do
112
+ @it = RiCal.Event do
113
+ description "MA-6 First US Manned Spaceflight"
114
+ dtstart DateTime.parse("Feb 20, 1962 14:47:39")
115
+ dtend DateTime.parse("Feb 20, 1962 19:43:02")
116
+ location "Cape Canaveral"
117
+ add_attendee "john.glenn@nasa.gov"
118
+ alarm do
119
+ description "Segment 51"
120
+ end
121
+ end
122
+ end
123
+
124
+ it "should have the right description" do
125
+ @it.description.should == "MA-6 First US Manned Spaceflight"
126
+ end
127
+
128
+ it "should have the right dtstart" do
129
+ @it.dtstart.should == DateTime.parse("Feb 20, 1962 14:47:39")
130
+ end
131
+
132
+ it "should have a zulu time dtstart property" do
133
+ @it.dtstart_property.tzid.should == "UTC"
134
+ end
135
+
136
+ it "should have the right dtend" do
137
+ @it.dtend.should == DateTime.parse("Feb 20, 1962 19:43:02")
138
+ end
139
+
140
+ it "should have a zulu time dtend property" do
141
+ @it.dtend_property.tzid.should == "UTC"
142
+ end
143
+
144
+ it "should have the right location" do
145
+ @it.location.should == "Cape Canaveral"
146
+ end
147
+
148
+ it "should have the right attendee" do
149
+ @it.attendee.should include("john.glenn@nasa.gov")
150
+ end
151
+
152
+ it "should have 1 alarm" do
153
+ @it.alarms.length.should == 1
154
+ end
155
+
156
+ it "should have an alarm with the right description" do
157
+ @it.alarms.first.description.should == "Segment 51"
158
+ end
159
+ end
160
+
161
+ context "building a complex calendar" do
162
+
163
+ before(:each) do
164
+ @it = RiCal.Calendar do
165
+ add_x_property 'x_wr_calname', 'My Personal Calendar'
166
+ event do
167
+ summary 'A Recurring Event'
168
+ description "This is some really long note content. It should be appropriately folded in the generated file.\nCarriage returns should work, too."
169
+ dtstart DateTime.parse('Feb 20, 2009 20:30:00')
170
+ dtend DateTime.parse('Feb 20, 2009 21:30:00')
171
+ location 'North Carolina'
172
+ dtstamp Time.now
173
+ rrule :freq => 'daily', :interval => 1
174
+ end
175
+ end
176
+ end
177
+
178
+ it 'should have an x_wr_calname property with the value "My Personal Calendar"' do
179
+ @it.x_wr_calname.should == "My Personal Calendar"
180
+ end
181
+
182
+ context "event with a long description and a dsl built recurence rule" do
183
+ before(:each) do
184
+ @cal = @it
185
+ @it = @cal.events.first
186
+ end
187
+
188
+ context "its description" do
189
+ it "should pass through correctly" do
190
+ @it.description.should == "This is some really long note content. It should be appropriately folded in the generated file.\nCarriage returns should work, too."
191
+ end
192
+ end
193
+
194
+ context "its rrule" do
195
+
196
+ it "should have a 1 rrule" do
197
+ @it.rrule.length.should == 1
198
+ end
199
+
200
+ it "should have the right rrule" do
201
+ @it.rrule.first.should == "FREQ=DAILY"
202
+ end
203
+
204
+ it "should have the right rrule hash" do
205
+ @it.rrule_property.first.to_options_hash.should == {:freq => 'DAILY', :interval => 1}
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ end
212
+ end