awallis-ri_cal 0.8.8
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.
- data/History.txt +402 -0
- data/Manifest.txt +161 -0
- data/README.txt +410 -0
- data/Rakefile +69 -0
- data/VERSION +1 -0
- data/bin/ri_cal +8 -0
- data/component_attributes/alarm.yml +10 -0
- data/component_attributes/calendar.yml +4 -0
- data/component_attributes/component_property_defs.yml +180 -0
- data/component_attributes/event.yml +45 -0
- data/component_attributes/freebusy.yml +16 -0
- data/component_attributes/journal.yml +35 -0
- data/component_attributes/timezone.yml +3 -0
- data/component_attributes/timezone_period.yml +11 -0
- data/component_attributes/todo.yml +46 -0
- data/copyrights.txt +1 -0
- data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
- data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
- data/docs/incrementers.txt +7 -0
- data/docs/rfc2445.pdf +0 -0
- data/lib/ri_cal.rb +187 -0
- data/lib/ri_cal/component.rb +256 -0
- data/lib/ri_cal/component/alarm.rb +19 -0
- data/lib/ri_cal/component/calendar.rb +257 -0
- data/lib/ri_cal/component/event.rb +58 -0
- data/lib/ri_cal/component/freebusy.rb +16 -0
- data/lib/ri_cal/component/journal.rb +27 -0
- data/lib/ri_cal/component/non_standard.rb +33 -0
- data/lib/ri_cal/component/t_z_info_timezone.rb +153 -0
- data/lib/ri_cal/component/timezone.rb +197 -0
- data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
- data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
- data/lib/ri_cal/component/timezone/timezone_period.rb +76 -0
- data/lib/ri_cal/component/todo.rb +42 -0
- data/lib/ri_cal/core_extensions.rb +11 -0
- data/lib/ri_cal/core_extensions/array.rb +7 -0
- data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
- data/lib/ri_cal/core_extensions/date.rb +13 -0
- data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
- data/lib/ri_cal/core_extensions/date_time.rb +15 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
- data/lib/ri_cal/core_extensions/object.rb +8 -0
- data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
- data/lib/ri_cal/core_extensions/string.rb +8 -0
- data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
- data/lib/ri_cal/core_extensions/time.rb +14 -0
- data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +42 -0
- data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
- data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +55 -0
- data/lib/ri_cal/fast_date_time.rb +234 -0
- data/lib/ri_cal/floating_timezone.rb +32 -0
- data/lib/ri_cal/invalid_property_value.rb +8 -0
- data/lib/ri_cal/invalid_timezone_identifier.rb +20 -0
- data/lib/ri_cal/occurrence_enumerator.rb +265 -0
- data/lib/ri_cal/occurrence_period.rb +17 -0
- data/lib/ri_cal/parser.rb +145 -0
- data/lib/ri_cal/properties.rb +12 -0
- data/lib/ri_cal/properties/alarm.rb +390 -0
- data/lib/ri_cal/properties/calendar.rb +164 -0
- data/lib/ri_cal/properties/event.rb +1523 -0
- data/lib/ri_cal/properties/freebusy.rb +593 -0
- data/lib/ri_cal/properties/journal.rb +1237 -0
- data/lib/ri_cal/properties/timezone.rb +150 -0
- data/lib/ri_cal/properties/timezone_period.rb +416 -0
- data/lib/ri_cal/properties/todo.rb +1559 -0
- data/lib/ri_cal/property_value.rb +159 -0
- data/lib/ri_cal/property_value/array.rb +27 -0
- data/lib/ri_cal/property_value/cal_address.rb +11 -0
- data/lib/ri_cal/property_value/date.rb +184 -0
- data/lib/ri_cal/property_value/date_time.rb +359 -0
- data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
- data/lib/ri_cal/property_value/date_time/time_machine.rb +159 -0
- data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
- data/lib/ri_cal/property_value/duration.rb +110 -0
- data/lib/ri_cal/property_value/geo.rb +11 -0
- data/lib/ri_cal/property_value/integer.rb +12 -0
- data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
- data/lib/ri_cal/property_value/period.rb +86 -0
- data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
- data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
- data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_day_incrementer.rb +86 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +64 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
- data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
- data/lib/ri_cal/property_value/text.rb +44 -0
- data/lib/ri_cal/property_value/uri.rb +11 -0
- data/lib/ri_cal/property_value/utc_offset.rb +33 -0
- data/lib/ri_cal/property_value/zulu_date_time.rb +34 -0
- data/lib/ri_cal/required_timezones.rb +55 -0
- data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
- data/performance/empty_propval/subject.rb +43 -0
- data/performance/paris_eastern/subject.rb +90 -0
- data/performance/penultimate_weekday/subject.rb +15 -0
- data/performance/psm_big_enum/ical.ics +3171 -0
- data/performance/psm_big_enum/subject.rb +16 -0
- data/performance/utah_cycling/subject.rb +55 -0
- data/ri_cal.gemspec +244 -0
- data/script/benchmark_subject +23 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/profile_subject +29 -0
- data/script/txt2html +71 -0
- data/spec/ri_cal/bugreports_spec.rb +276 -0
- data/spec/ri_cal/component/alarm_spec.rb +12 -0
- data/spec/ri_cal/component/calendar_spec.rb +88 -0
- data/spec/ri_cal/component/event_spec.rb +735 -0
- data/spec/ri_cal/component/freebusy_spec.rb +12 -0
- data/spec/ri_cal/component/journal_spec.rb +37 -0
- data/spec/ri_cal/component/t_z_info_timezone_spec.rb +60 -0
- data/spec/ri_cal/component/timezone_spec.rb +236 -0
- data/spec/ri_cal/component/todo_spec.rb +112 -0
- data/spec/ri_cal/component_spec.rb +224 -0
- data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
- data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
- data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
- data/spec/ri_cal/fast_date_time_spec.rb +77 -0
- data/spec/ri_cal/inf_loop_spec.rb +78 -0
- data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
- data/spec/ri_cal/parser_spec.rb +337 -0
- data/spec/ri_cal/property_value/date_spec.rb +53 -0
- data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
- data/spec/ri_cal/property_value/duration_spec.rb +126 -0
- data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
- data/spec/ri_cal/property_value/period_spec.rb +63 -0
- data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
- data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
- data/spec/ri_cal/property_value/text_spec.rb +25 -0
- data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
- data/spec/ri_cal/property_value_spec.rb +125 -0
- data/spec/ri_cal/required_timezones_spec.rb +67 -0
- data/spec/ri_cal_spec.rb +53 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +50 -0
- data/tasks/gem_loader/load_active_support.rb +3 -0
- data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
- data/tasks/ri_cal.rake +412 -0
- data/tasks/spec.rake +102 -0
- metadata +255 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
2
|
+
|
|
3
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
|
4
|
+
|
|
5
|
+
describe "http://rick_denatale.lighthouseapp.com/projects/30941/tickets/17" do
|
|
6
|
+
it "should parse this" do
|
|
7
|
+
RiCal.parse_string(<<-ENDCAL)
|
|
8
|
+
BEGIN:VCALENDAR
|
|
9
|
+
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
|
10
|
+
VERSION:2.0
|
|
11
|
+
CALSCALE:GREGORIAN
|
|
12
|
+
METHOD:PUBLISH
|
|
13
|
+
X-WR-CALNAME:Australian Tech Events
|
|
14
|
+
X-WR-TIMEZONE:Australia/Sydney
|
|
15
|
+
X-WR-CALDESC:TO ADD EVENTS INVITE THIS ADDRESS\;\npf44opfb12hherild7h2pl11b
|
|
16
|
+
4@group.calendar.google.com\n\nThis is a public calendar to know what's com
|
|
17
|
+
ing up all around the country in the technology industry.\n\nIncludes digit
|
|
18
|
+
al\, internet\, web\, enterprise\, software\, hardware\, and it's various f
|
|
19
|
+
lavours. \n\nFeel free to add real events. Keep it real.
|
|
20
|
+
BEGIN:VTIMEZONE
|
|
21
|
+
TZID:Australia/Perth
|
|
22
|
+
X-LIC-LOCATION:Australia/Perth
|
|
23
|
+
BEGIN:STANDARD
|
|
24
|
+
TZOFFSETFROM:+0800
|
|
25
|
+
TZOFFSETTO:+0800
|
|
26
|
+
TZNAME:WST
|
|
27
|
+
DTSTART:19700101T000000
|
|
28
|
+
END:STANDARD
|
|
29
|
+
END:VTIMEZONE
|
|
30
|
+
BEGIN:VTIMEZONE
|
|
31
|
+
TZID:Australia/Sydney
|
|
32
|
+
X-LIC-LOCATION:Australia/Sydney
|
|
33
|
+
BEGIN:STANDARD
|
|
34
|
+
TZOFFSETFROM:+1100
|
|
35
|
+
TZOFFSETTO:+1000
|
|
36
|
+
TZNAME:EST
|
|
37
|
+
DTSTART:19700405T030000
|
|
38
|
+
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
|
|
39
|
+
END:STANDARD
|
|
40
|
+
BEGIN:DAYLIGHT
|
|
41
|
+
TZOFFSETFROM:+1000
|
|
42
|
+
TZOFFSETTO:+1100
|
|
43
|
+
TZNAME:EST
|
|
44
|
+
DTSTART:19701004T020000
|
|
45
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
|
|
46
|
+
END:DAYLIGHT
|
|
47
|
+
END:VTIMEZONE
|
|
48
|
+
BEGIN:VTIMEZONE
|
|
49
|
+
TZID:Australia/Brisbane
|
|
50
|
+
X-LIC-LOCATION:Australia/Brisbane
|
|
51
|
+
BEGIN:STANDARD
|
|
52
|
+
TZOFFSETFROM:+1000
|
|
53
|
+
TZOFFSETTO:+1000
|
|
54
|
+
TZNAME:EST
|
|
55
|
+
DTSTART:19700101T000000
|
|
56
|
+
END:STANDARD
|
|
57
|
+
END:VTIMEZONE
|
|
58
|
+
BEGIN:VEVENT
|
|
59
|
+
DTSTART:20091110T080000Z
|
|
60
|
+
DTEND:20091110T100000Z
|
|
61
|
+
DTSTAMP:20090720T133540Z
|
|
62
|
+
UID:9357CC6B-C4BF-4797-AC5F-83E47C3FDA9E
|
|
63
|
+
URL:thehive.org.au
|
|
64
|
+
CLASS:PUBLIC
|
|
65
|
+
CREATED:20090713T123838Z
|
|
66
|
+
DESCRIPTION:check the website for details
|
|
67
|
+
LAST-MODIFIED:20090713T123838Z
|
|
68
|
+
LOCATION:Melbourne
|
|
69
|
+
SEQUENCE:1
|
|
70
|
+
STATUS:CONFIRMED
|
|
71
|
+
SUMMARY:The Hive MELBOURNE
|
|
72
|
+
TRANSP:OPAQUE
|
|
73
|
+
BEGIN:VALARM
|
|
74
|
+
ACTION:AUDIO
|
|
75
|
+
TRIGGER:-PT5M
|
|
76
|
+
X-WR-ALARMUID:F92A055A-2CD9-4FB2-A22A-BD4834ACEE96
|
|
77
|
+
ATTACH;VALUE=URI:Basso
|
|
78
|
+
END:VALARM
|
|
79
|
+
END:VEVENT
|
|
80
|
+
END:VCALENDAR
|
|
81
|
+
ENDCAL
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "http://rick_denatale.lighthouseapp.com/projects/30941/tickets/18" do
|
|
86
|
+
it "should handle a subcomponent" do
|
|
87
|
+
event = RiCal.Event do |evt|
|
|
88
|
+
evt.alarm do |alarm|
|
|
89
|
+
alarm.trigger = "-PT5M"
|
|
90
|
+
alarm.action = 'AUDIO'
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
lambda {event.export}.should_not raise_error
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe "http://rick_denatale.lighthouseapp.com/projects/30941/tickets/19" do
|
|
99
|
+
before(:each) do
|
|
100
|
+
cals = RiCal.parse_string(<<-ENDCAL)
|
|
101
|
+
BEGIN:VCALENDAR
|
|
102
|
+
METHOD:REQUEST
|
|
103
|
+
PRODID:Microsoft CDO for Microsoft Exchange
|
|
104
|
+
VERSION:2.0
|
|
105
|
+
BEGIN:VTIMEZONE
|
|
106
|
+
TZID:(GMT-05.00) Eastern Time (US & Canada)
|
|
107
|
+
X-MICROSOFT-CDO-TZID:10
|
|
108
|
+
BEGIN:STANDARD
|
|
109
|
+
DTSTART:20010101T020000
|
|
110
|
+
TZOFFSETFROM:-0400
|
|
111
|
+
TZOFFSETTO:-0500
|
|
112
|
+
RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU
|
|
113
|
+
END:STANDARD
|
|
114
|
+
BEGIN:DAYLIGHT
|
|
115
|
+
DTSTART:20010101T020000
|
|
116
|
+
TZOFFSETFROM:-0500
|
|
117
|
+
TZOFFSETTO:-0400
|
|
118
|
+
RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU
|
|
119
|
+
END:DAYLIGHT
|
|
120
|
+
END:VTIMEZONE
|
|
121
|
+
BEGIN:VEVENT
|
|
122
|
+
DTSTAMP:20090724T143205Z
|
|
123
|
+
DTSTART;TZID="(GMT-05.00) Eastern Time (US & Canada)":20090804T120000
|
|
124
|
+
SUMMARY:FW: ALL HANDS MEETING
|
|
125
|
+
DTEND;TZID="(GMT-05.00) Eastern Time (US & Canada)":20090804T133000
|
|
126
|
+
DESCRIPTION:Some event
|
|
127
|
+
END:VEVENT
|
|
128
|
+
END:VCALENDAR
|
|
129
|
+
ENDCAL
|
|
130
|
+
|
|
131
|
+
@event = cals.first.events.first
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "not raise an error accessing DTSTART" do
|
|
135
|
+
lambda {@event.dtstart}.should_not raise_error
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "freebusy problem" do
|
|
140
|
+
before(:each) do
|
|
141
|
+
cal = RiCal.parse_string(<<ENDCAL)
|
|
142
|
+
BEGIN:VCALENDAR
|
|
143
|
+
METHOD:PUBLISH
|
|
144
|
+
VERSION:2.0
|
|
145
|
+
PRODID:Zimbra-Calendar-Provider
|
|
146
|
+
BEGIN:VFREEBUSY
|
|
147
|
+
ORGANIZER:mailto:bj-wagoner@wiu.edu
|
|
148
|
+
DTSTAMP:20090805T200417Z
|
|
149
|
+
DTSTART:20090705T200417Z
|
|
150
|
+
DTEND:20091006T200417Z
|
|
151
|
+
URL:https://zimbra9.wiu.edu/service/home/bjw101/calendar.ifb?null
|
|
152
|
+
FREEBUSY;FBTYPE=BUSY:20090705T200417Z/20090707T050000Z
|
|
153
|
+
FREEBUSY;FBTYPE=BUSY-TENTATIVE:20090711T050000Z/20090712T050000Z
|
|
154
|
+
END:VFREEBUSY
|
|
155
|
+
END:VCALENDAR
|
|
156
|
+
ENDCAL
|
|
157
|
+
@free_busy = cal.first.freebusys.first
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should have two periods" do
|
|
161
|
+
@free_busy.freebusy.map {|fb| fb.to_s}.should == [
|
|
162
|
+
";FBTYPE=BUSY:20090705T200417Z/20090707T050000Z",
|
|
163
|
+
";FBTYPE=BUSY-TENTATIVE:20090711T050000Z/20090712T050000Z"
|
|
164
|
+
]
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
describe "a calendar including vvenue" do
|
|
169
|
+
before(:each) do
|
|
170
|
+
@cal_string = <<ENDCAL
|
|
171
|
+
BEGIN:VCALENDAR
|
|
172
|
+
VERSION:2.0
|
|
173
|
+
X-WR-CALNAME:Upcoming Event: Film in the Park
|
|
174
|
+
PRODID:-//Upcoming.org/Upcoming ICS//EN
|
|
175
|
+
CALSCALE:GREGORIAN
|
|
176
|
+
METHOD:PUBLISH
|
|
177
|
+
BEGIN:VEVENT
|
|
178
|
+
DTSTART:20090807T201500
|
|
179
|
+
DTEND:20090807T220000
|
|
180
|
+
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090822T000000
|
|
181
|
+
GEO:-104.997;39.546
|
|
182
|
+
TRANSP:TRANSPARENT
|
|
183
|
+
SUMMARY:Film in the Park
|
|
184
|
+
DESCRIPTION: [Full details at http://upcoming.yahoo.com/event/3082410/ ] Plan to join the HRCA family summer tradition! Bring a blanket and enjoy great FREE family movies! Mark the dates now!
|
|
185
|
+
URL;VALUE=URI:http://upcoming.yahoo.com/event/3082410/
|
|
186
|
+
UID:http://upcoming.yahoo.com/event/3082410/
|
|
187
|
+
DTSTAMP:20090716T103006
|
|
188
|
+
LAST-UPDATED:20090716T103006
|
|
189
|
+
CATEGORIES:Family
|
|
190
|
+
ORGANIZER;CN=mepling95:X-ADDR:http://upcoming.yahoo.com/user/637615/
|
|
191
|
+
LOCATION;VENUE-UID="http://upcoming.yahoo.com/venue/130821/":Civic Green Park @ 9370 Ridgeline Boulevard\, Highlands Ranch\, Colorado 80126 US
|
|
192
|
+
END:VEVENT
|
|
193
|
+
BEGIN:VVENUE
|
|
194
|
+
X-VVENUE-INFO:http://evdb.com/docs/ical-venue/drft-norris-ical-venue.html
|
|
195
|
+
NAME:Civic Green Park
|
|
196
|
+
ADDRESS:9370 Ridgeline Boulevard
|
|
197
|
+
CITY:Highlands Ranch
|
|
198
|
+
REGION;X-ABBREV=co:Colorado
|
|
199
|
+
COUNTRY;X-ABBREV=us:United States
|
|
200
|
+
POSTALCODE:80126
|
|
201
|
+
GEO:39.546;-104.997
|
|
202
|
+
URL;X-LABEL=Venue Info:http://www.hrmafestival.org
|
|
203
|
+
END:VVENUE
|
|
204
|
+
END:VCALENDAR
|
|
205
|
+
ENDCAL
|
|
206
|
+
|
|
207
|
+
@venue_str = <<ENDVENUE
|
|
208
|
+
BEGIN:VVENUE
|
|
209
|
+
X-VVENUE-INFO:http://evdb.com/docs/ical-venue/drft-norris-ical-venue.html
|
|
210
|
+
NAME:Civic Green Park
|
|
211
|
+
ADDRESS:9370 Ridgeline Boulevard
|
|
212
|
+
CITY:Highlands Ranch
|
|
213
|
+
REGION;X-ABBREV=co:Colorado
|
|
214
|
+
COUNTRY;X-ABBREV=us:United States
|
|
215
|
+
POSTALCODE:80126
|
|
216
|
+
GEO:39.546;-104.997
|
|
217
|
+
URL;X-LABEL=Venue Info:http://www.hrmafestival.org
|
|
218
|
+
END:VVENUE
|
|
219
|
+
ENDVENUE
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "should parse without error" do
|
|
223
|
+
lambda {RiCal.parse_string(@cal_string)}.should_not raise_error
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should export correctly" do
|
|
227
|
+
export = RiCal.parse_string(@cal_string).first.export
|
|
228
|
+
export.should include(@venue_str)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "ticket #23" do
|
|
233
|
+
describe "RecurrenceRule" do
|
|
234
|
+
it "should convert the rrule string to a hash" do
|
|
235
|
+
rrule = RiCal::PropertyValue::RecurrenceRule.convert(nil, 'INTERVAL=2;FREQ=WEEKLY;BYDAY=TH,TU')
|
|
236
|
+
rrule.to_options_hash.should == {:freq => 'WEEKLY', :byday => %w{TH TU}, :interval => 2}
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
context "ticket #26" do
|
|
242
|
+
context "Date property" do
|
|
243
|
+
it "should handle for_parent" do
|
|
244
|
+
lambda {
|
|
245
|
+
RiCal::PropertyValue::Date.convert(:foo, Date.parse("20090927")).for_parent(:bar)}.should_not raise_error
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context "ticket 29:supress-x-rical-tzsource-when-not-relevant" do
|
|
251
|
+
it "should parse its own output" do
|
|
252
|
+
cal_string = %Q(BEGIN:VCALENDAR
|
|
253
|
+
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
|
254
|
+
BEGIN:VEVENT
|
|
255
|
+
DTSTART:20100610T100000
|
|
256
|
+
DTEND:20100610T110000
|
|
257
|
+
END:VEVENT
|
|
258
|
+
END:VCALENDAR)
|
|
259
|
+
lambda {RiCal.parse_string(RiCal.parse_string(cal_string).first.to_s)}.should_not raise_error
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context "X-properties" do
|
|
264
|
+
it "should round-trip the X-WR-CALNAME property" do
|
|
265
|
+
cal_string = %Q(BEGIN:VCALENDAR
|
|
266
|
+
PRODID:-//Markthisdate.com\,0.7
|
|
267
|
+
VERSION:2.0
|
|
268
|
+
CALSCALE:GREGORIAN
|
|
269
|
+
METHOD:PUBLISH
|
|
270
|
+
X-WR-CALNAME: AFC Ajax Eredivisie wedstrijden 2010 - 2011
|
|
271
|
+
END:VCALENDAR)
|
|
272
|
+
cal = RiCal.parse_string(cal_string).first
|
|
273
|
+
cal.x_wr_calname.first.should == " AFC Ajax Eredivisie wedstrijden 2010 - 2011"
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
2
|
+
|
|
3
|
+
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
|
4
|
+
|
|
5
|
+
describe RiCal::Component::Alarm do
|
|
6
|
+
|
|
7
|
+
describe ".entity_name" do
|
|
8
|
+
it "should be VALARM" do
|
|
9
|
+
RiCal::Component::Alarm.entity_name.should == "VALARM"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
3
|
+
|
|
4
|
+
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
|
5
|
+
|
|
6
|
+
describe RiCal::Component::Calendar do
|
|
7
|
+
|
|
8
|
+
context ".entity_name" do
|
|
9
|
+
it "should be VCALENDAR" do
|
|
10
|
+
RiCal::Component::Calendar.entity_name.should == "VCALENDAR"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "a new instance" do
|
|
15
|
+
before(:each) do
|
|
16
|
+
@it = RiCal.Calendar
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should have a tz_source of 'TZ_INFO" do
|
|
20
|
+
@it.tz_source.should == "TZINFO"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
|
|
24
|
+
@it.export.should match(%r{\nPRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN\n})
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "an imported instance with a tzinfo source" do
|
|
29
|
+
before(:each) do
|
|
30
|
+
@it = RiCal.parse_string("BEGIN:VCALENDAR\nPRODID;X-RICAL-TZSOURCE=TZINFO:-\/\/com.denhaven2\/NONSGML ri_cal gem\/\/EN\nCALSCALE:GREGORIAN\nVERSION:2.0\nEND:VCALENDAR\n").first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should have a tz_source of 'TZ_INFO" do
|
|
34
|
+
@it.tz_source.should == "TZINFO"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
|
|
38
|
+
@it.export.should match(%r{\nPRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN\n})
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "an imported instance without a tzinfo source" do
|
|
43
|
+
before(:each) do
|
|
44
|
+
@it = RiCal.parse_string("BEGIN:VCALENDAR\nPRODID:-//Apple Inc.//iCal 3.0//EN\nEND:VCALENDAR\n").first
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should have a tz_source of nil" do
|
|
48
|
+
@it.tz_source.should be_nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should export not export a product id with an X-RICAL-TZSOURCE parameter of TZINFO" do
|
|
52
|
+
@it.export.should_not match(%r{X-RICAL-TZSOURCE=TZINFO:})
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe RiCal::Component::Calendar::FoldingStream do
|
|
57
|
+
before(:each) do
|
|
58
|
+
@it = RiCal::Component::Calendar::FoldingStream.new(nil)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#utf_safe_split" do
|
|
62
|
+
it "should properly split an ascii string" do
|
|
63
|
+
@it.utf8_safe_split("abcdef", 3).should == ["abc", "def"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should return a nil remainder if the string has less than n characters" do
|
|
67
|
+
@it.utf8_safe_split("a",2).should == ["a", nil]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should return a nil remainder if the string has exactly n characters" do
|
|
71
|
+
@it.utf8_safe_split("ab",2).should == ["ab", nil]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should not split a 2-byte utf character" do
|
|
75
|
+
@it.utf8_safe_split("Café", 3).should == ["Caf", "é"]
|
|
76
|
+
@it.utf8_safe_split("Café", 4).should == ["Caf", "é"]
|
|
77
|
+
@it.utf8_safe_split("Café", 5).should == ["Café", nil]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should not split a 3-byte utf character" do
|
|
81
|
+
@it.utf8_safe_split("Prix €200", 5).should == ["Prix ", "€200"]
|
|
82
|
+
@it.utf8_safe_split("Prix €200", 6).should == ["Prix ", "€200"]
|
|
83
|
+
@it.utf8_safe_split("Prix €200", 7).should == ["Prix ", "€200"]
|
|
84
|
+
@it.utf8_safe_split("Prix €200", 8).should == ["Prix €", "200"]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
3
|
+
|
|
4
|
+
require File.join(File.dirname(__FILE__), %w[.. .. spec_helper])
|
|
5
|
+
|
|
6
|
+
describe RiCal::Component::Event do
|
|
7
|
+
|
|
8
|
+
context "with change management properties" do
|
|
9
|
+
it "should use zulu time for all change management datetime properties" do
|
|
10
|
+
new_york_offset = Rational(-1, 6)
|
|
11
|
+
cal = RiCal.Calendar
|
|
12
|
+
event = RiCal::Component::Event.new(cal)
|
|
13
|
+
event.dtstamp = result_time_in_zone(2010, 4, 1, 9, 23, 45, "America/New_York", new_york_offset)
|
|
14
|
+
event.created = result_time_in_zone(2010, 4, 1, 9, 23, 45, "America/New_York", new_york_offset)
|
|
15
|
+
event.last_modified = result_time_in_zone(2010, 4, 1, 12, 23, 45, "America/New_York", new_york_offset)
|
|
16
|
+
event.to_s.should == "BEGIN:VEVENT
|
|
17
|
+
CREATED;VALUE=DATE-TIME:20100401T132345Z
|
|
18
|
+
DTSTAMP;VALUE=DATE-TIME:20100401T132345Z
|
|
19
|
+
LAST-MODIFIED;VALUE=DATE-TIME:20100401T162345Z
|
|
20
|
+
END:VEVENT
|
|
21
|
+
"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context ".finish_time" do
|
|
26
|
+
it "should be the end of the start day for an event with a date dtstart and no dtend or duration" do
|
|
27
|
+
@it = RiCal.Event do |evt|
|
|
28
|
+
evt.dtstart = "20090704"
|
|
29
|
+
end
|
|
30
|
+
@it.finish_time.should == DateTime.parse("20090704T235959")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should be the end of the end day for an event with a date dtstart and a dtend" do
|
|
34
|
+
@it = RiCal.Event do |evt|
|
|
35
|
+
evt.dtstart = "20090704"
|
|
36
|
+
evt.dtend = "20090706"
|
|
37
|
+
end
|
|
38
|
+
@it.finish_time.should == DateTime.parse("20090706T235959")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should be the start time for an event with a datetime dtstart and no dtend or duration" do
|
|
42
|
+
@it = RiCal.Event do |evt|
|
|
43
|
+
evt.dtstart = "20090704T013000Z"
|
|
44
|
+
end
|
|
45
|
+
@it.finish_time.should == DateTime.parse("20090704T013000Z")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should be the end time for an event with a datetime dtend" do
|
|
49
|
+
@it = RiCal.Event do |evt|
|
|
50
|
+
evt.dtstart = "20090704"
|
|
51
|
+
evt.dtend = "20090706T120000"
|
|
52
|
+
end
|
|
53
|
+
@it.finish_time.should == DateTime.parse("20090706T120000")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should be the end time for an event with a datetime dtstart and a duration" do
|
|
57
|
+
@it = RiCal.Event do |evt|
|
|
58
|
+
evt.dtstart = "20090704T120000Z"
|
|
59
|
+
evt.duration = "PT1H30M"
|
|
60
|
+
end
|
|
61
|
+
@it.finish_time.should == DateTime.parse("20090704T133000Z")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should uset the timezone of dtstart when event has a duration" do
|
|
65
|
+
@it = RiCal.Event do |evt|
|
|
66
|
+
evt.dtstart = "TZID=Australia/Sydney:20090712T200000"
|
|
67
|
+
evt.duration = "PT1H"
|
|
68
|
+
end
|
|
69
|
+
@it.finish_time.should == DateTime.parse("2009-07-12T21:00:00+10:00")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context ".before_range?" do
|
|
74
|
+
context "with a Date dtstart and no dtend" do
|
|
75
|
+
before(:each) do
|
|
76
|
+
@it = RiCal.Event do |evt|
|
|
77
|
+
evt.dtstart = "20090704"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should be false if the range start is a date before the start date" do
|
|
82
|
+
@it.before_range?([Date.parse("20090703"), :anything]).should_not be
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should be false if the range start is the start date" do
|
|
86
|
+
@it.before_range?([Date.parse("20090704"), :anything]).should_not be
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should be true if the range start is a date after the start date" do
|
|
90
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should be
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context "with a Date dtstart and date dtend" do
|
|
95
|
+
before(:each) do
|
|
96
|
+
@it = RiCal.Event do |evt|
|
|
97
|
+
evt.dtstart = "20090704"
|
|
98
|
+
evt.dtend = "20090706"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should be false if the range start is a date before the end date" do
|
|
103
|
+
@it.before_range?([Date.parse("20090705"), :anything]).should_not be
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should be false if the range start is the end date" do
|
|
107
|
+
@it.before_range?([Date.parse("20090706"), :anything]).should_not be
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should be true if the range start is a date after the end date" do
|
|
111
|
+
@it.before_range?([Date.parse("20090707"), :anything]).should be
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "bug report from Noboyuki Tomizawa" do
|
|
117
|
+
before(:each) do
|
|
118
|
+
|
|
119
|
+
@it = RiCal.Calendar do |cal|
|
|
120
|
+
cal.event do |event|
|
|
121
|
+
event.description = "test"
|
|
122
|
+
event.dtstart = "TZID=Asia/Tokyo:20090530T123000"
|
|
123
|
+
event.dtend = "TZID=Asia/Tokyo:20090530T123001"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should not fail" do
|
|
129
|
+
lambda {@it.export}.should_not raise_error
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "rdate property methods" do
|
|
134
|
+
before(:each) do
|
|
135
|
+
@event = RiCal.Event do
|
|
136
|
+
rdate "20090101"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "#rdate=" do
|
|
141
|
+
|
|
142
|
+
it "should accept a single Date and replace the existing rdate" do
|
|
143
|
+
@event.rdate = Date.parse("20090102")
|
|
144
|
+
@event.rdate.should == [[Date.parse("20090102")]]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "should accept a single rfc2445 date format string and replace the existing rdate" do
|
|
148
|
+
@event.rdate = "20090102"
|
|
149
|
+
@event.rdate.should == [[Date.parse("20090102")]]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "should accept a single DateTime and replace the existing rdate" do
|
|
153
|
+
@event.rdate = DateTime.parse("20090102T012345")
|
|
154
|
+
@event.rdate.should == [[DateTime.parse("20090102T012345")]]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "should accept a single Time and replace the existing rdate" do
|
|
158
|
+
::RiCal::PropertyValue::DateTime.default_tzid = 'UTC'
|
|
159
|
+
@event.rdate = Time.local(2009, 1, 2, 1, 23, 45)
|
|
160
|
+
@event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "UTC")]]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "should accept a single rfc2445 date-time format string and replace the existing rdate" do
|
|
164
|
+
@event.rdate = "20090102T012345"
|
|
165
|
+
@event.rdate.should == [[DateTime.parse("20090102T012345")]]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should accept a tzid prefixed rfc2445 date-time format string and replace the existing rdate" do
|
|
169
|
+
@event.rdate = "TZID=America/New_York:20090102T012345"
|
|
170
|
+
@event.rdate.should == [[result_time_in_zone(2009, 1, 2, 1, 23, 45, "America/New_York")]]
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
context "comment property methods" do
|
|
178
|
+
before(:each) do
|
|
179
|
+
@event = RiCal.Event
|
|
180
|
+
@event.comment = "Comment"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context "#comment=" do
|
|
184
|
+
it "should result in a single comment for the event" do
|
|
185
|
+
@event.comment.should == ["Comment"]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should replace existing comments" do
|
|
189
|
+
@event.comment = "Replacement"
|
|
190
|
+
@event.comment.should == ["Replacement"]
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
context "#comments=" do
|
|
195
|
+
it "should result in a multiple comments for the event replacing existing comments" do
|
|
196
|
+
@event.comments = "New1", "New2"
|
|
197
|
+
@event.comment.should == ["New1", "New2"]
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context "#add_comment" do
|
|
202
|
+
it "should add a single comment" do
|
|
203
|
+
@event.add_comment "New1"
|
|
204
|
+
@event.comment.should == ["Comment", "New1"]
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
context "#add_comments" do
|
|
209
|
+
it "should add multiple comments" do
|
|
210
|
+
@event.add_comments "New1", "New2"
|
|
211
|
+
@event.comment.should == ["Comment", "New1", "New2"]
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "#remove_comment" do
|
|
216
|
+
it "should remove a single comment" do
|
|
217
|
+
@event.add_comment "New1"
|
|
218
|
+
@event.remove_comment "Comment"
|
|
219
|
+
@event.comment.should == ["New1"]
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context "#remove_comments" do
|
|
224
|
+
it "should remove multiple comments" do
|
|
225
|
+
@event.add_comments "New1", "New2", "New3"
|
|
226
|
+
@event.remove_comments "New2", "Comment"
|
|
227
|
+
@event.comment.should == ["New1", "New3"]
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context ".dtstart=" do
|
|
233
|
+
before(:each) do
|
|
234
|
+
@event = RiCal.Event
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
context "with a datetime only string" do
|
|
238
|
+
before(:each) do
|
|
239
|
+
@event.dtstart = "20090514T202400"
|
|
240
|
+
@it = @event.dtstart
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "should interpret it as the correct date-time" do
|
|
244
|
+
@it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it "should interpret it as a floating date" do
|
|
248
|
+
@it.tzid.should == :floating
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
context "with a TZID and datetime string" do
|
|
253
|
+
before(:each) do
|
|
254
|
+
@event.dtstart = "TZID=America/New_York:20090514T202400"
|
|
255
|
+
@it = @event.dtstart
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should interpret it as the correct date-time" do
|
|
259
|
+
@it.should == result_time_in_zone(2009, 5, 14, 20, 24, 00, "America/New_York")
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "should set the tzid to America/New_York" do
|
|
263
|
+
@it.tzid.should == "America/New_York"
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "with a zulu datetime only string" do
|
|
268
|
+
before(:each) do
|
|
269
|
+
@event.dtstart = "20090514T202400Z"
|
|
270
|
+
@it = @event.dtstart
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "should interpret it as the correct date-time" do
|
|
274
|
+
@it.should == DateTime.civil(2009, 5, 14, 20, 24, 00, Rational(0,24))
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "should set the tzid to UTC" do
|
|
278
|
+
@it.tzid.should == "UTC"
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context "with a date string" do
|
|
283
|
+
before(:each) do
|
|
284
|
+
@event.dtstart = "20090514"
|
|
285
|
+
@it = @event.dtstart
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "should interpret it as the correct date-time" do
|
|
289
|
+
@it.should == Date.parse("14 May 2009")
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
context ".entity_name" do
|
|
295
|
+
it "should be VEVENT" do
|
|
296
|
+
RiCal::Component::Event.entity_name.should == "VEVENT"
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
context "with an rrule" do
|
|
301
|
+
before(:each) do
|
|
302
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nRRULE:FREQ=DAILY\nEND:VEVENT").first
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it "should have an array of rrules" do
|
|
306
|
+
@it.rrule.should be_kind_of(Array)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
context ".start_time" do
|
|
311
|
+
|
|
312
|
+
it "should be nil if there is no dtstart property" do
|
|
313
|
+
RiCal.Event.start_time.should be_nil
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it "should be the same as dtstart for a date time" do
|
|
317
|
+
event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
|
318
|
+
event.start_time.should == DateTime.civil(2009,05,25,15,19,0,0)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "should be the start of the day of dtstart for a date" do
|
|
322
|
+
event = RiCal.Event {|e| e.dtstart = "20090525"}
|
|
323
|
+
event.start_time.should == DateTime.civil(2009,05,25,0,0,0,0)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
context ".finish_time" do
|
|
328
|
+
before(:each) do
|
|
329
|
+
@event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
context "with a given dtend" do
|
|
333
|
+
it "should be the same as dtend for a date time" do
|
|
334
|
+
@event.dtend = "20090525T161900"
|
|
335
|
+
@event.finish_time.should == DateTime.civil(2009,05,25,16,19,0,0)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "with no dtend" do
|
|
342
|
+
context "and a duration" do
|
|
343
|
+
it "should be the dtstart plus the duration" do
|
|
344
|
+
@event.duration = "+PT1H"
|
|
345
|
+
@event.finish_time.should == DateTime.civil(2009,5,25,16,19,0,0)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "and no duration" do
|
|
350
|
+
context "when the dtstart is not set" do
|
|
351
|
+
before(:each) do
|
|
352
|
+
@event.dtstart_property = nil
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "should be nil" do
|
|
356
|
+
@event.finish_time.should be_nil
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
context "when the dstart is a datetime" do
|
|
360
|
+
# For cases where a "VEVENT" calendar component
|
|
361
|
+
# specifies a "DTSTART" property with a DATE-TIME data type but no
|
|
362
|
+
# "DTEND" property, the event ends on the same calendar date and time
|
|
363
|
+
# of day specified by the "DTSTART" property. RFC 2445 p 53
|
|
364
|
+
it "should be the same as start_time" do
|
|
365
|
+
@event.finish_time.should == @event.start_time
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
context "when the dtstart is a date" do
|
|
369
|
+
# For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE data type
|
|
370
|
+
# but no "DTEND" property, the events non-inclusive end is the end of the calendar date specified by
|
|
371
|
+
# the "DTSTART" property. RFC 2445 p 53
|
|
372
|
+
|
|
373
|
+
it "should be the end of the same day as start_time" do
|
|
374
|
+
@event.dtstart = "20090525"
|
|
375
|
+
@event.finish_time.should == DateTime.civil(2009,5,25,23,59,59,0)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
context ".zulu_occurrence_range_start_time" do
|
|
384
|
+
|
|
385
|
+
it "should be nil if there is no dtstart property" do
|
|
386
|
+
RiCal.Event.zulu_occurrence_range_start_time.should be_nil
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
it "should be the utc equivalent of dtstart for a date time" do
|
|
390
|
+
event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
|
|
391
|
+
event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,19,19,0,0)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
it "should be the utc time of the start of the day of dtstart in the earliest timezone for a date" do
|
|
395
|
+
event = RiCal.Event {|e| e.dtstart = "20090525"}
|
|
396
|
+
result = event.zulu_occurrence_range_start_time
|
|
397
|
+
result.should == DateTime.civil(2009,05,24,12,0,0,0)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it "should be the utc time of the dtstart in the earliest timezone if dtstart is a floating datetime" do
|
|
401
|
+
event = RiCal.Event {|e| e.dtstart = "20090525T151900"}
|
|
402
|
+
event.zulu_occurrence_range_start_time.should == DateTime.civil(2009,05,25,3,19,0,0)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
context ".zulu_occurrence_range_finish_time" do
|
|
407
|
+
before(:each) do
|
|
408
|
+
@event = RiCal.Event {|e| e.dtstart = "TZID=America/New_York:20090525T151900"}
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
context "with a given dtend" do
|
|
412
|
+
it "should be the utc equivalent of dtend if dtend is a date time" do
|
|
413
|
+
@event.dtend = "TZID=America/New_York:20090525T161900"
|
|
414
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,05,25, 20,19,0,0)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
context "with no dtend" do
|
|
419
|
+
context "and a duration" do
|
|
420
|
+
it "should be the dtstart plus the duration" do
|
|
421
|
+
@event.duration = "+PT1H"
|
|
422
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,25,20 ,19,0,0)
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
context "and no duration" do
|
|
427
|
+
context "when the dtstart is not set" do
|
|
428
|
+
before(:each) do
|
|
429
|
+
@event.dtstart_property = nil
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it "should be nil" do
|
|
433
|
+
@event.zulu_occurrence_range_finish_time.should be_nil
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
context "when the dstart is a datetime" do
|
|
438
|
+
|
|
439
|
+
it "should be the same as start_time" do
|
|
440
|
+
@event.zulu_occurrence_range_finish_time.should == @event.zulu_occurrence_range_start_time
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
context "when the dtstart is a date" do
|
|
445
|
+
it "should be the utc of end of the same day as start_time in the westermost time zone" do
|
|
446
|
+
@event.dtstart = "20090525"
|
|
447
|
+
@event.zulu_occurrence_range_finish_time.should == DateTime.civil(2009,5,26,11,59,59,0)
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
context "description property" do
|
|
455
|
+
before(:each) do
|
|
456
|
+
@ical_desc = "posted by Joyce per Zan\\nASheville\\, Rayan's Restauratn\\, Biltm\n ore Square"
|
|
457
|
+
@ruby_desc = "posted by Joyce per Zan\nASheville, Rayan's Restauratn, Biltmore Square"
|
|
458
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDESCRIPTION:#{@ical_desc}\nEND:VEVENT").first
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it "should product the converted ruby value" do
|
|
462
|
+
@it.description.should == @ruby_desc
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
it "should produce escaped text for ical" do
|
|
466
|
+
@it.description = "This is a\nnew description, yes; it is"
|
|
467
|
+
@it.description_property.value.should == 'This is a\nnew description\, yes\; it is'
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context "with both dtend and duration specified" do
|
|
473
|
+
before(:each) do
|
|
474
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nDURATION:H1\nEND:VEVENT").first
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
it "should be invalid" do
|
|
478
|
+
@it.should_not be_valid
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
context "with a duration property" do
|
|
483
|
+
before(:each) do
|
|
484
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDURATION:H1\nEND:VEVENT").first
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it "should have a duration property" do
|
|
488
|
+
@it.duration_property.should be
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it "should have a duration of 1 Hour" do
|
|
492
|
+
@it.duration_property.value.should == "H1"
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "should reset the duration property if the dtend property is set" do
|
|
496
|
+
@it.dtend_property = "19970101T123456".to_ri_cal_date_time_value
|
|
497
|
+
@it.duration_property.should be_nil
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
it "should reset the duration property if the dtend ruby value is set" do
|
|
501
|
+
@it.dtend = "19970101"
|
|
502
|
+
@it.duration_property.should == nil
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
context "with a dtend property" do
|
|
507
|
+
before(:each) do
|
|
508
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\nEND:VEVENT").first
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it "should have a duration property" do
|
|
512
|
+
@it.dtend_property.should be
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
it "should reset the dtend property if the duration property is set" do
|
|
516
|
+
@it.duration_property = "PT1H".to_ri_cal_duration_value
|
|
517
|
+
@it.dtend_property.should be_nil
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
it "should reset the dtend property if the duration ruby value is set" do
|
|
521
|
+
@it.duration = "PT1H".to_ri_cal_duration_value
|
|
522
|
+
@it.dtend_property.should be_nil
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
context "with a nested alarm component" do
|
|
527
|
+
before(:each) do
|
|
528
|
+
@it = RiCal::Component::Event.parse_string("BEGIN:VEVENT\nDTEND:19970903T190000Z\n\nBEGIN:VALARM\nEND:VALARM\nEND:VEVENT").first
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
it "should have one alarm" do
|
|
532
|
+
@it.alarms.length.should == 1
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
it "which should be an Alarm component" do
|
|
536
|
+
@it.alarms.first.should be_kind_of(RiCal::Component::Alarm)
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
context ".export" do
|
|
541
|
+
require 'rubygems'
|
|
542
|
+
require 'tzinfo'
|
|
543
|
+
|
|
544
|
+
def date_time_with_tzinfo_zone(date_time, timezone="America/New_York")
|
|
545
|
+
date_time.dup.set_tzid(timezone)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
# Undo the effects of RFC2445 line folding
|
|
549
|
+
def unfold(string)
|
|
550
|
+
string.gsub("\n ", "")
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
before(:each) do
|
|
554
|
+
cal = RiCal.Calendar
|
|
555
|
+
@it = RiCal::Component::Event.new(cal)
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
it "should cause a VTIMEZONE to be included for a dtstart with a local timezone" do
|
|
559
|
+
@it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
|
|
560
|
+
unfold(@it.export).should match(/BEGIN:VTIMEZONE\nTZID;X-RICAL-TZSOURCE=TZINFO:America\/New_York\n/)
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it "should properly format dtstart with a UTC date-time" do
|
|
564
|
+
@it.dtstart = DateTime.parse("April 22, 2009 1:23:45").set_tzid("UTC")
|
|
565
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345Z$/)
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "should properly format dtstart with a floating date-time" do
|
|
569
|
+
@it.dtstart = DateTime.parse("April 22, 2009 1:23:45").with_floating_timezone
|
|
570
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE-TIME:20090422T012345$/)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
it "should properly format dtstart with a local time zone" do
|
|
574
|
+
@it.dtstart = date_time_with_tzinfo_zone(DateTime.parse("April 22, 2009 17:55"), "America/New_York")
|
|
575
|
+
unfold(@it.export).should match(/^DTSTART;TZID=America\/New_York;VALUE=DATE-TIME:20090422T175500$/)
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
it "should properly format dtstart with a date" do
|
|
579
|
+
@it.dtstart = Date.parse("April 22, 2009")
|
|
580
|
+
unfold(@it.export).should match(/^DTSTART;VALUE=DATE:20090422$/)
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
it "should properly fold on export when the description contains a carriage return" do
|
|
584
|
+
@it.description = "Weather report looks nice, 80 degrees and partly cloudy, so following Michael's suggestion, let's meet at the food court at Crossroads:\n\rhttp://www.shopcrossroadsplaza.c...\n"
|
|
585
|
+
export_string = @it.export
|
|
586
|
+
export_string.should match(%r(^DESCRIPTION:Weather report looks nice\\, 80 degrees and partly cloudy\\, so$))
|
|
587
|
+
export_string.should match(%r(^ following Michael's suggestion\\, let's meet at the food court at Crossr$))
|
|
588
|
+
export_string.should match(%r(^ oads:\\nhttp://www\.shopcrossroadsplaza.c\.\.\.\\n$))
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it "should properly fold on export when the description contains multi-byte UTF-8 Characters" do
|
|
592
|
+
@it.description = "Juin 2009 <<Alliance Francaise Reunion>> lieu Café périferôl"
|
|
593
|
+
export_string = @it.export
|
|
594
|
+
export_string.should match(%r(^DESCRIPTION:Juin 2009 <<Alliance Francaise Reunion>> lieu Café périfer$))
|
|
595
|
+
export_string.should match(%r(^ ôl$))
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
if RiCal::TimeWithZone
|
|
600
|
+
context "with ActiveSupport loaded" do
|
|
601
|
+
|
|
602
|
+
context "an event with an timezoned exdate" do
|
|
603
|
+
before(:each) do
|
|
604
|
+
@old_timezone = Time.zone
|
|
605
|
+
Time.zone = "America/New_York"
|
|
606
|
+
@exception_date_time = Time.zone.local(2009, 5, 19, 11, 13)
|
|
607
|
+
cal = RiCal.Calendar do |cal|
|
|
608
|
+
cal.event do |event|
|
|
609
|
+
event.add_exdate @exception_date_time
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
@event = cal.events.first
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
after(:each) do
|
|
616
|
+
Time.zone = @old_timezone
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it "should pickup the timezone in the exdate property" do
|
|
620
|
+
@event.exdate.first.first.tzid.should == "America/New_York"
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
it "should have the timezone in the ical representation of the exdate property" do
|
|
624
|
+
@event.exdate_property.first.to_s.should match(%r{;TZID=America/New_York[:;]})
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
context "An event in a non-tzinfo source calendar" do
|
|
629
|
+
before(:each) do
|
|
630
|
+
cals = RiCal.parse_string <<ENDCAL
|
|
631
|
+
BEGIN:VCALENDAR
|
|
632
|
+
X-WR-TIMEZONE:America/New_York
|
|
633
|
+
PRODID:-//Apple Inc.//iCal 3.0//EN
|
|
634
|
+
CALSCALE:GREGORIAN
|
|
635
|
+
BEGIN:VTIMEZONE
|
|
636
|
+
TZID:US/Eastern
|
|
637
|
+
BEGIN:DAYLIGHT
|
|
638
|
+
TZOFFSETFROM:-0500
|
|
639
|
+
TZOFFSETTO:-0400
|
|
640
|
+
DTSTART:20070311T020000
|
|
641
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
642
|
+
TZNAME:EDT
|
|
643
|
+
END:DAYLIGHT
|
|
644
|
+
BEGIN:STANDARD
|
|
645
|
+
TZOFFSETFROM:-0400
|
|
646
|
+
TZOFFSETTO:-0500
|
|
647
|
+
DTSTART:20071104T020000
|
|
648
|
+
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
649
|
+
TZNAME:EST
|
|
650
|
+
END:STANDARD
|
|
651
|
+
END:VTIMEZONE
|
|
652
|
+
BEGIN:VEVENT
|
|
653
|
+
SEQUENCE:5
|
|
654
|
+
TRANSP:OPAQUE
|
|
655
|
+
UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
|
|
656
|
+
DTSTART;TZID=US/Eastern:20090224T090000
|
|
657
|
+
DTSTAMP:20090225T000908Z
|
|
658
|
+
SUMMARY:Test Event
|
|
659
|
+
CREATED:20090225T000839Z
|
|
660
|
+
DTEND;TZID=US/Eastern:20090224T100000
|
|
661
|
+
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
|
|
662
|
+
END:VEVENT
|
|
663
|
+
END:VCALENDAR
|
|
664
|
+
ENDCAL
|
|
665
|
+
@event = cals.first.events.first
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it "should produce a DateTime for dtstart" do
|
|
669
|
+
@event.dtstart.should be_instance_of(DateTime)
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
context "An event starting in Paris and ending in New York" do
|
|
674
|
+
|
|
675
|
+
before(:each) do
|
|
676
|
+
@start = Time.now.utc.in_time_zone("Europe/Paris")
|
|
677
|
+
@finish = Time.now.utc.in_time_zone("America/New_York")
|
|
678
|
+
cal = RiCal.Calendar do |ical|
|
|
679
|
+
ical.event do |ievent|
|
|
680
|
+
ievent.dtstart @start
|
|
681
|
+
ievent.dtend @finish
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
@event = cal.events.first
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
it "should have the right time zone for dtstart" do
|
|
688
|
+
@event.dtstart.tzid.should == "Europe/Paris"
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
it "should produce a TimeWithZone for dtstart" do
|
|
692
|
+
@event.dtstart.should be_instance_of(RiCal::TimeWithZone)
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
# ActiveRecord::TimeWithZone doesn't implement == as expected
|
|
696
|
+
it "should produce a dtstart which looks like the provided value" do
|
|
697
|
+
@event.dtstart.to_s.should == @start.to_s
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
it "should have the right time zone for dtend" do
|
|
701
|
+
@event.dtend.tzid.should == "America/New_York"
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
it "should produce a TimeWithZone for dtend" do
|
|
705
|
+
@event.dtend.should be_instance_of(RiCal::TimeWithZone)
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
# ActiveRecord::TimeWithZone doesn't implement == as expected
|
|
709
|
+
it "should produce a dtend which looks like the provided value" do
|
|
710
|
+
@event.dtend.to_s.should == @finish.to_s
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
context "An event with a floating start" do
|
|
717
|
+
|
|
718
|
+
before(:each) do
|
|
719
|
+
cal = RiCal.Calendar do |ical|
|
|
720
|
+
ical.event do |ievent|
|
|
721
|
+
ievent.dtstart "20090530T120000"
|
|
722
|
+
end
|
|
723
|
+
end
|
|
724
|
+
@event = cal.events.first
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
it "should produce a DateTime for dtstart" do
|
|
728
|
+
@event.dtstart.should be_instance_of(DateTime)
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
it "should have a floating dtstart" do
|
|
732
|
+
@event.dtstart.should have_floating_timezone
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
end
|