tilia-vobject 4.0.0.pre.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +32 -0
  4. data/.simplecov +4 -0
  5. data/.travis.yml +3 -0
  6. data/CHANGELOG.sabre.md +626 -0
  7. data/CONTRIBUTING.md +25 -0
  8. data/Gemfile +17 -0
  9. data/Gemfile.lock +68 -0
  10. data/LICENSE +27 -0
  11. data/LICENSE.sabre +27 -0
  12. data/README.md +63 -0
  13. data/Rakefile +17 -0
  14. data/bin/vobject +7 -0
  15. data/lib/tilia/v_object/birthday_calendar_generator.rb +142 -0
  16. data/lib/tilia/v_object/cli.rb +582 -0
  17. data/lib/tilia/v_object/component/available.rb +107 -0
  18. data/lib/tilia/v_object/component/v_alarm.rb +114 -0
  19. data/lib/tilia/v_object/component/v_availability.rb +128 -0
  20. data/lib/tilia/v_object/component/v_calendar.rb +468 -0
  21. data/lib/tilia/v_object/component/v_card.rb +457 -0
  22. data/lib/tilia/v_object/component/v_event.rb +127 -0
  23. data/lib/tilia/v_object/component/v_free_busy.rb +81 -0
  24. data/lib/tilia/v_object/component/v_journal.rb +75 -0
  25. data/lib/tilia/v_object/component/v_time_zone.rb +51 -0
  26. data/lib/tilia/v_object/component/v_todo.rb +147 -0
  27. data/lib/tilia/v_object/component.rb +591 -0
  28. data/lib/tilia/v_object/date_time_parser.rb +486 -0
  29. data/lib/tilia/v_object/document.rb +218 -0
  30. data/lib/tilia/v_object/element_list.rb +18 -0
  31. data/lib/tilia/v_object/eof_exception.rb +8 -0
  32. data/lib/tilia/v_object/free_busy_data.rb +149 -0
  33. data/lib/tilia/v_object/free_busy_generator.rb +465 -0
  34. data/lib/tilia/v_object/i_tip/broker.rb +909 -0
  35. data/lib/tilia/v_object/i_tip/i_tip_exception.rb +9 -0
  36. data/lib/tilia/v_object/i_tip/message.rb +109 -0
  37. data/lib/tilia/v_object/i_tip/same_organizer_for_all_components_exception.rb +13 -0
  38. data/lib/tilia/v_object/i_tip.rb +10 -0
  39. data/lib/tilia/v_object/node.rb +192 -0
  40. data/lib/tilia/v_object/parameter.rb +327 -0
  41. data/lib/tilia/v_object/parse_exception.rb +7 -0
  42. data/lib/tilia/v_object/parser/json.rb +149 -0
  43. data/lib/tilia/v_object/parser/mime_dir.rb +543 -0
  44. data/lib/tilia/v_object/parser/parser.rb +61 -0
  45. data/lib/tilia/v_object/parser/xml/element/key_value.rb +60 -0
  46. data/lib/tilia/v_object/parser/xml/element.rb +11 -0
  47. data/lib/tilia/v_object/parser/xml.rb +322 -0
  48. data/lib/tilia/v_object/parser.rb +10 -0
  49. data/lib/tilia/v_object/property/binary.rb +96 -0
  50. data/lib/tilia/v_object/property/boolean.rb +57 -0
  51. data/lib/tilia/v_object/property/flat_text.rb +52 -0
  52. data/lib/tilia/v_object/property/float_value.rb +107 -0
  53. data/lib/tilia/v_object/property/i_calendar/cal_address.rb +49 -0
  54. data/lib/tilia/v_object/property/i_calendar/date.rb +15 -0
  55. data/lib/tilia/v_object/property/i_calendar/date_time.rb +330 -0
  56. data/lib/tilia/v_object/property/i_calendar/duration.rb +65 -0
  57. data/lib/tilia/v_object/property/i_calendar/period.rb +124 -0
  58. data/lib/tilia/v_object/property/i_calendar/recur.rb +173 -0
  59. data/lib/tilia/v_object/property/i_calendar.rb +14 -0
  60. data/lib/tilia/v_object/property/integer_value.rb +60 -0
  61. data/lib/tilia/v_object/property/text.rb +352 -0
  62. data/lib/tilia/v_object/property/time.rb +85 -0
  63. data/lib/tilia/v_object/property/unknown.rb +30 -0
  64. data/lib/tilia/v_object/property/uri.rb +78 -0
  65. data/lib/tilia/v_object/property/utc_offset.rb +56 -0
  66. data/lib/tilia/v_object/property/v_card/date.rb +31 -0
  67. data/lib/tilia/v_object/property/v_card/date_and_or_time.rb +343 -0
  68. data/lib/tilia/v_object/property/v_card/date_time.rb +22 -0
  69. data/lib/tilia/v_object/property/v_card/language_tag.rb +41 -0
  70. data/lib/tilia/v_object/property/v_card/time_stamp.rb +74 -0
  71. data/lib/tilia/v_object/property/v_card.rb +13 -0
  72. data/lib/tilia/v_object/property.rb +532 -0
  73. data/lib/tilia/v_object/reader.rb +73 -0
  74. data/lib/tilia/v_object/recur/event_iterator.rb +417 -0
  75. data/lib/tilia/v_object/recur/no_instances_exception.rb +11 -0
  76. data/lib/tilia/v_object/recur/r_date_iterator.rb +138 -0
  77. data/lib/tilia/v_object/recur/r_rule_iterator.rb +717 -0
  78. data/lib/tilia/v_object/recur.rb +10 -0
  79. data/lib/tilia/v_object/settings.rb +32 -0
  80. data/lib/tilia/v_object/splitter/i_calendar.rb +95 -0
  81. data/lib/tilia/v_object/splitter/splitter_interface.rb +31 -0
  82. data/lib/tilia/v_object/splitter/v_card.rb +56 -0
  83. data/lib/tilia/v_object/splitter.rb +9 -0
  84. data/lib/tilia/v_object/string_util.rb +58 -0
  85. data/lib/tilia/v_object/time_zone_data/exchange_zones.rb +96 -0
  86. data/lib/tilia/v_object/time_zone_data/lotus_zones.rb +104 -0
  87. data/lib/tilia/v_object/time_zone_data/php_zones.rb +49 -0
  88. data/lib/tilia/v_object/time_zone_data/windows_zones.rb +121 -0
  89. data/lib/tilia/v_object/time_zone_data.rb +10 -0
  90. data/lib/tilia/v_object/time_zone_util.rb +213 -0
  91. data/lib/tilia/v_object/uuid_util.rb +51 -0
  92. data/lib/tilia/v_object/v_card_converter.rb +354 -0
  93. data/lib/tilia/v_object/version.rb +9 -0
  94. data/lib/tilia/v_object/writer.rb +56 -0
  95. data/lib/tilia/v_object.rb +45 -0
  96. data/lib/tilia/vobject.rb +1 -0
  97. data/resources/schema/xcal.rng +1192 -0
  98. data/resources/schema/xcard.rng +388 -0
  99. data/test/test_helper.rb +56 -0
  100. data/test/v_object/attach_issue_test.rb +19 -0
  101. data/test/v_object/birthday_calendar_generator_test.rb +463 -0
  102. data/test/v_object/cli_mock.rb +19 -0
  103. data/test/v_object/cli_test.rb +460 -0
  104. data/test/v_object/component/available_test.rb +59 -0
  105. data/test/v_object/component/v_alarm_test.rb +160 -0
  106. data/test/v_object/component/v_availability_test.rb +388 -0
  107. data/test/v_object/component/v_calendar_test.rb +646 -0
  108. data/test/v_object/component/v_card_test.rb +258 -0
  109. data/test/v_object/component/v_event_test.rb +85 -0
  110. data/test/v_object/component/v_free_busy_test.rb +59 -0
  111. data/test/v_object/component/v_journal_test.rb +85 -0
  112. data/test/v_object/component/v_time_zone_test.rb +47 -0
  113. data/test/v_object/component/v_todo_test.rb +172 -0
  114. data/test/v_object/component_test.rb +419 -0
  115. data/test/v_object/date_time_parser_test.rb +526 -0
  116. data/test/v_object/document_test.rb +71 -0
  117. data/test/v_object/element_list_test.rb +27 -0
  118. data/test/v_object/em_client_test.rb +53 -0
  119. data/test/v_object/empty_parameter_test.rb +65 -0
  120. data/test/v_object/empty_value_issue_test.rb +25 -0
  121. data/test/v_object/fake_component.rb +21 -0
  122. data/test/v_object/free_busy_data_test.rb +285 -0
  123. data/test/v_object/free_busy_generator_test.rb +637 -0
  124. data/test/v_object/google_colon_escaping_test.rb +27 -0
  125. data/test/v_object/i_calendar/attach_parse_test.rb +24 -0
  126. data/test/v_object/i_tip/broker_attendee_reply_test.rb +1042 -0
  127. data/test/v_object/i_tip/broker_delete_event_test.rb +175 -0
  128. data/test/v_object/i_tip/broker_new_event_test.rb +440 -0
  129. data/test/v_object/i_tip/broker_process_message_test.rb +153 -0
  130. data/test/v_object/i_tip/broker_process_reply_test.rb +402 -0
  131. data/test/v_object/i_tip/broker_tester.rb +71 -0
  132. data/test/v_object/i_tip/broker_update_event_test.rb +763 -0
  133. data/test/v_object/i_tip/evolution_test.rb +2644 -0
  134. data/test/v_object/i_tip/message_test.rb +25 -0
  135. data/test/v_object/issue153.vcf +352 -0
  136. data/test/v_object/issue153_test.rb +12 -0
  137. data/test/v_object/issue26_test.rb +25 -0
  138. data/test/v_object/issue36_work_around_test.rb +37 -0
  139. data/test/v_object/issue40_test.rb +26 -0
  140. data/test/v_object/issue64.vcf +351 -0
  141. data/test/v_object/issue64_test.rb +17 -0
  142. data/test/v_object/issue96_test.rb +22 -0
  143. data/test/v_object/issue_undefined_index_test.rb +24 -0
  144. data/test/v_object/j_cal_test.rb +150 -0
  145. data/test/v_object/j_card_test.rb +192 -0
  146. data/test/v_object/line_folding_issue_test.rb +19 -0
  147. data/test/v_object/mock_document.rb +6 -0
  148. data/test/v_object/parameter_test.rb +109 -0
  149. data/test/v_object/parser/json_test.rb +370 -0
  150. data/test/v_object/parser/mime_dir_test.rb +14 -0
  151. data/test/v_object/parser/quoted_printable_test.rb +78 -0
  152. data/test/v_object/parser/xml_test.rb +2563 -0
  153. data/test/v_object/property/binary_test.rb +12 -0
  154. data/test/v_object/property/boolean_test.rb +18 -0
  155. data/test/v_object/property/compound_test.rb +43 -0
  156. data/test/v_object/property/float_test.rb +20 -0
  157. data/test/v_object/property/i_calendar/cal_address_test.rb +26 -0
  158. data/test/v_object/property/i_calendar/date_time_test.rb +303 -0
  159. data/test/v_object/property/i_calendar/duration_test.rb +14 -0
  160. data/test/v_object/property/i_calendar/recur_test.rb +39 -0
  161. data/test/v_object/property/text_test.rb +81 -0
  162. data/test/v_object/property/v_card/date_and_or_time_test.rb +205 -0
  163. data/test/v_object/property/v_card/language_tag_test.rb +35 -0
  164. data/test/v_object/property_test.rb +338 -0
  165. data/test/v_object/reader_test.rb +403 -0
  166. data/test/v_object/recur/event_iterator/by_month_in_daily_test.rb +52 -0
  167. data/test/v_object/recur/event_iterator/by_set_pos_hang_test.rb +55 -0
  168. data/test/v_object/recur/event_iterator/expand_floating_times_test.rb +109 -0
  169. data/test/v_object/recur/event_iterator/fifth_tuesday_problem_test.rb +45 -0
  170. data/test/v_object/recur/event_iterator/incorrect_expand_test.rb +53 -0
  171. data/test/v_object/recur/event_iterator/infinite_loop_problem_test.rb +75 -0
  172. data/test/v_object/recur/event_iterator/issue48_test.rb +43 -0
  173. data/test/v_object/recur/event_iterator/issue50_test.rb +123 -0
  174. data/test/v_object/recur/event_iterator/main_test.rb +1222 -0
  175. data/test/v_object/recur/event_iterator/missing_overridden_test.rb +55 -0
  176. data/test/v_object/recur/event_iterator/no_instances_test.rb +32 -0
  177. data/test/v_object/recur/event_iterator/override_first_event_test.rb +106 -0
  178. data/test/v_object/recur/r_date_iterator_test.rb +44 -0
  179. data/test/v_object/recur/r_rule_iterator_test.rb +608 -0
  180. data/test/v_object/recurrence_iterator/UntilRespectsTimezoneTest.ics +39 -0
  181. data/test/v_object/slash_r_test.rb +15 -0
  182. data/test/v_object/splitter/i_calendar_test.rb +299 -0
  183. data/test/v_object/splitter/v_card_test.rb +173 -0
  184. data/test/v_object/string_util_test.rb +37 -0
  185. data/test/v_object/test_case.rb +42 -0
  186. data/test/v_object/time_zone_util_test.rb +271 -0
  187. data/test/v_object/uuid_util_test.rb +18 -0
  188. data/test/v_object/v_card21_test.rb +43 -0
  189. data/test/v_object/v_card_converter_test.rb +419 -0
  190. data/test/v_object/version_test.rb +15 -0
  191. data/test/v_object/writer_test.rb +33 -0
  192. data/tilia-vobject.gemspec +17 -0
  193. metadata +308 -0
@@ -0,0 +1,1042 @@
1
+ require 'test_helper'
2
+ require 'v_object/i_tip/broker_tester'
3
+
4
+ module Tilia
5
+ module VObject
6
+ class BrokerAttendeeReplyTest < ITip::BrokerTester
7
+ def test_accepted
8
+ old_message = <<ICS
9
+ BEGIN:VCALENDAR
10
+ VERSION:2.0
11
+ BEGIN:VEVENT
12
+ UID:foobar
13
+ SUMMARY:B-day party
14
+ SEQUENCE:1
15
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
16
+ ATTENDEE;CN=One:mailto:one@example.org
17
+ DTSTART:20140716T120000Z
18
+ END:VEVENT
19
+ END:VCALENDAR
20
+ ICS
21
+
22
+ new_message = <<ICS
23
+ BEGIN:VCALENDAR
24
+ VERSION:2.0
25
+ BEGIN:VEVENT
26
+ UID:foobar
27
+ SUMMARY:B-day party
28
+ SEQUENCE:1
29
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
30
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
31
+ DTSTART:20140716T120000Z
32
+ END:VEVENT
33
+ END:VCALENDAR
34
+ ICS
35
+
36
+ version = Tilia::VObject::Version::VERSION
37
+
38
+ expected = [
39
+ {
40
+ 'uid' => 'foobar',
41
+ 'method' => 'REPLY',
42
+ 'component' => 'VEVENT',
43
+ 'sender' => 'mailto:one@example.org',
44
+ 'sender_name' => 'One',
45
+ 'recipient' => 'mailto:strunk@example.org',
46
+ 'recipient_name' => 'Strunk',
47
+ 'message' => <<ICS
48
+ BEGIN:VCALENDAR
49
+ VERSION:2.0
50
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
51
+ CALSCALE:GREGORIAN
52
+ METHOD:REPLY
53
+ BEGIN:VEVENT
54
+ UID:foobar
55
+ SEQUENCE:1
56
+ DTSTART:20140716T120000Z
57
+ SUMMARY:B-day party
58
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
59
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
60
+ END:VEVENT
61
+ END:VCALENDAR
62
+ ICS
63
+
64
+ }
65
+ ]
66
+
67
+ parse(old_message, new_message, expected)
68
+ end
69
+
70
+ def test_recurring_reply
71
+ old_message = <<ICS
72
+ BEGIN:VCALENDAR
73
+ VERSION:2.0
74
+ BEGIN:VEVENT
75
+ UID:foobar
76
+ SEQUENCE:1
77
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
78
+ ATTENDEE;CN=One:mailto:one@example.org
79
+ DTSTART:20140724T120000Z
80
+ SUMMARY:Daily sprint
81
+ RRULE;FREQ=DAILY
82
+ END:VEVENT
83
+ END:VCALENDAR
84
+ ICS
85
+
86
+ new_message = <<ICS
87
+ BEGIN:VCALENDAR
88
+ VERSION:2.0
89
+ BEGIN:VEVENT
90
+ UID:foobar
91
+ SEQUENCE:1
92
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
93
+ ATTENDEE;PARTSTAT=NEEDS-ACTION;CN=One:mailto:one@example.org
94
+ DTSTART:20140724T120000Z
95
+ SUMMARY:Daily sprint
96
+ END:VEVENT
97
+ BEGIN:VEVENT
98
+ UID:foobar
99
+ SEQUENCE:1
100
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
101
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
102
+ DTSTART:20140726T120000Z
103
+ RECURRENCE-ID:20140726T120000Z
104
+ END:VEVENT
105
+ BEGIN:VEVENT
106
+ UID:foobar
107
+ SEQUENCE:1
108
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
109
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
110
+ DTSTART:20140724T120000Z
111
+ RECURRENCE-ID:20140724T120000Z
112
+ END:VEVENT
113
+ BEGIN:VEVENT
114
+ UID:foobar
115
+ SEQUENCE:1
116
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
117
+ ATTENDEE;PARTSTAT=TENTATIVE;CN=One:mailto:one@example.org
118
+ DTSTART:20140728T120000Z
119
+ RECURRENCE-ID:20140728T120000Z
120
+ END:VEVENT
121
+ BEGIN:VEVENT
122
+ UID:foobar
123
+ SEQUENCE:1
124
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
125
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
126
+ DTSTART:20140729T120000Z
127
+ RECURRENCE-ID:20140729T120000Z
128
+ END:VEVENT
129
+ BEGIN:VEVENT
130
+ UID:foobar
131
+ SEQUENCE:1
132
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
133
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
134
+ DTSTART:20140725T120000Z
135
+ RECURRENCE-ID:20140725T120000Z
136
+ END:VEVENT
137
+ END:VCALENDAR
138
+ ICS
139
+
140
+ version = Tilia::VObject::Version::VERSION
141
+
142
+ expected = [
143
+ {
144
+ 'uid' => 'foobar',
145
+ 'method' => 'REPLY',
146
+ 'component' => 'VEVENT',
147
+ 'sender' => 'mailto:one@example.org',
148
+ 'sender_name' => 'One',
149
+ 'recipient' => 'mailto:strunk@example.org',
150
+ 'recipient_name' => 'Strunk',
151
+ 'message' => <<ICS
152
+ BEGIN:VCALENDAR
153
+ VERSION:2.0
154
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
155
+ CALSCALE:GREGORIAN
156
+ METHOD:REPLY
157
+ BEGIN:VEVENT
158
+ UID:foobar
159
+ SEQUENCE:1
160
+ DTSTART:20140726T120000Z
161
+ SUMMARY:Daily sprint
162
+ RECURRENCE-ID:20140726T120000Z
163
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
164
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
165
+ END:VEVENT
166
+ BEGIN:VEVENT
167
+ UID:foobar
168
+ SEQUENCE:1
169
+ DTSTART:20140724T120000Z
170
+ SUMMARY:Daily sprint
171
+ RECURRENCE-ID:20140724T120000Z
172
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
173
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
174
+ END:VEVENT
175
+ BEGIN:VEVENT
176
+ UID:foobar
177
+ SEQUENCE:1
178
+ DTSTART:20140728T120000Z
179
+ SUMMARY:Daily sprint
180
+ RECURRENCE-ID:20140728T120000Z
181
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
182
+ ATTENDEE;PARTSTAT=TENTATIVE;CN=One:mailto:one@example.org
183
+ END:VEVENT
184
+ BEGIN:VEVENT
185
+ UID:foobar
186
+ SEQUENCE:1
187
+ DTSTART:20140729T120000Z
188
+ SUMMARY:Daily sprint
189
+ RECURRENCE-ID:20140729T120000Z
190
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
191
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
192
+ END:VEVENT
193
+ BEGIN:VEVENT
194
+ UID:foobar
195
+ SEQUENCE:1
196
+ DTSTART:20140725T120000Z
197
+ SUMMARY:Daily sprint
198
+ RECURRENCE-ID:20140725T120000Z
199
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
200
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
201
+ END:VEVENT
202
+ END:VCALENDAR
203
+ ICS
204
+
205
+ }
206
+ ]
207
+
208
+ parse(old_message, new_message, expected)
209
+ end
210
+
211
+ def test_recurring_all_day
212
+ old_message = <<ICS
213
+ BEGIN:VCALENDAR
214
+ VERSION:2.0
215
+ BEGIN:VEVENT
216
+ UID:foobar
217
+ SEQUENCE:1
218
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
219
+ ATTENDEE;CN=One:mailto:one@example.org
220
+ DTSTART;VALUE=DATE:20140724
221
+ RRULE;FREQ=DAILY
222
+ END:VEVENT
223
+ END:VCALENDAR
224
+ ICS
225
+
226
+ new_message = <<ICS
227
+ BEGIN:VCALENDAR
228
+ VERSION:2.0
229
+ BEGIN:VEVENT
230
+ UID:foobar
231
+ SEQUENCE:1
232
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
233
+ ATTENDEE;PARTSTAT=NEEDS-ACTION;CN=One:mailto:one@example.org
234
+ DTSTART;VALUE=DATE:20140724
235
+ END:VEVENT
236
+ BEGIN:VEVENT
237
+ UID:foobar
238
+ SEQUENCE:1
239
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
240
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
241
+ DTSTART;VALUE=DATE:20140726
242
+ RECURRENCE-ID;VALUE=DATE:20140726
243
+ END:VEVENT
244
+ BEGIN:VEVENT
245
+ UID:foobar
246
+ SEQUENCE:1
247
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
248
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
249
+ DTSTART;VALUE=DATE:20140724
250
+ RECURRENCE-ID;VALUE=DATE:20140724
251
+ END:VEVENT
252
+ BEGIN:VEVENT
253
+ UID:foobar
254
+ SEQUENCE:1
255
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
256
+ ATTENDEE;PARTSTAT=TENTATIVE;CN=One:mailto:one@example.org
257
+ DTSTART;VALUE=DATE:20140728
258
+ RECURRENCE-ID;VALUE=DATE:20140728
259
+ END:VEVENT
260
+ BEGIN:VEVENT
261
+ UID:foobar
262
+ SEQUENCE:1
263
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
264
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
265
+ DTSTART;VALUE=DATE:20140729
266
+ RECURRENCE-ID;VALUE=DATE:20140729
267
+ END:VEVENT
268
+ BEGIN:VEVENT
269
+ UID:foobar
270
+ SEQUENCE:1
271
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
272
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
273
+ DTSTART;VALUE=DATE:20140725
274
+ RECURRENCE-ID;VALUE=DATE:20140725
275
+ END:VEVENT
276
+ END:VCALENDAR
277
+ ICS
278
+
279
+ version = Tilia::VObject::Version::VERSION
280
+
281
+ expected = [
282
+ {
283
+ 'uid' => 'foobar',
284
+ 'method' => 'REPLY',
285
+ 'component' => 'VEVENT',
286
+ 'sender' => 'mailto:one@example.org',
287
+ 'sender_name' => 'One',
288
+ 'recipient' => 'mailto:strunk@example.org',
289
+ 'recipient_name' => 'Strunk',
290
+ 'message' => <<ICS
291
+ BEGIN:VCALENDAR
292
+ VERSION:2.0
293
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
294
+ CALSCALE:GREGORIAN
295
+ METHOD:REPLY
296
+ BEGIN:VEVENT
297
+ UID:foobar
298
+ SEQUENCE:1
299
+ DTSTART;VALUE=DATE:20140726
300
+ RECURRENCE-ID;VALUE=DATE:20140726
301
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
302
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
303
+ END:VEVENT
304
+ BEGIN:VEVENT
305
+ UID:foobar
306
+ SEQUENCE:1
307
+ DTSTART;VALUE=DATE:20140724
308
+ RECURRENCE-ID;VALUE=DATE:20140724
309
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
310
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
311
+ END:VEVENT
312
+ BEGIN:VEVENT
313
+ UID:foobar
314
+ SEQUENCE:1
315
+ DTSTART;VALUE=DATE:20140728
316
+ RECURRENCE-ID;VALUE=DATE:20140728
317
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
318
+ ATTENDEE;PARTSTAT=TENTATIVE;CN=One:mailto:one@example.org
319
+ END:VEVENT
320
+ BEGIN:VEVENT
321
+ UID:foobar
322
+ SEQUENCE:1
323
+ DTSTART;VALUE=DATE:20140729
324
+ RECURRENCE-ID;VALUE=DATE:20140729
325
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
326
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
327
+ END:VEVENT
328
+ BEGIN:VEVENT
329
+ UID:foobar
330
+ SEQUENCE:1
331
+ DTSTART;VALUE=DATE:20140725
332
+ RECURRENCE-ID;VALUE=DATE:20140725
333
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
334
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
335
+ END:VEVENT
336
+ END:VCALENDAR
337
+ ICS
338
+ }
339
+ ]
340
+
341
+ parse(old_message, new_message, expected)
342
+ end
343
+
344
+ def test_no_change
345
+ old_message = <<ICS
346
+ BEGIN:VCALENDAR
347
+ VERSION:2.0
348
+ BEGIN:VEVENT
349
+ UID:foobar
350
+ SEQUENCE:1
351
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
352
+ ATTENDEE;CN=One:mailto:one@example.org
353
+ DTSTART:20140716T120000Z
354
+ END:VEVENT
355
+ END:VCALENDAR
356
+ ICS
357
+
358
+ new_message = <<ICS
359
+ BEGIN:VCALENDAR
360
+ VERSION:2.0
361
+ BEGIN:VEVENT
362
+ UID:foobar
363
+ SEQUENCE:1
364
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
365
+ ATTENDEE;PARTSTAT=NEEDS-ACTION;CN=One:mailto:one@example.org
366
+ DTSTART:20140716T120000Z
367
+ END:VEVENT
368
+ END:VCALENDAR
369
+ ICS
370
+
371
+ expected = []
372
+ parse(old_message, new_message, expected)
373
+ end
374
+
375
+ def test_no_change_force_send
376
+ old_message = <<ICS
377
+ BEGIN:VCALENDAR
378
+ VERSION:2.0
379
+ BEGIN:VEVENT
380
+ UID:foobar
381
+ SEQUENCE:1
382
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
383
+ ATTENDEE;CN=One:mailto:one@example.org
384
+ DTSTART:20140716T120000Z
385
+ END:VEVENT
386
+ END:VCALENDAR
387
+ ICS
388
+
389
+ new_message = <<ICS
390
+ BEGIN:VCALENDAR
391
+ VERSION:2.0
392
+ BEGIN:VEVENT
393
+ UID:foobar
394
+ SEQUENCE:1
395
+ ORGANIZER;SCHEDULE-FORCE-SEND=REPLY;CN=Strunk:mailto:strunk@example.org
396
+ ATTENDEE;PARTSTAT=NEEDS-ACTION;CN=One:mailto:one@example.org
397
+ DTSTART:20140716T120000Z
398
+ END:VEVENT
399
+ END:VCALENDAR
400
+ ICS
401
+
402
+ version = Tilia::VObject::Version::VERSION
403
+ expected = [
404
+ {
405
+ 'uid' => 'foobar',
406
+ 'method' => 'REPLY',
407
+ 'component' => 'VEVENT',
408
+ 'sender' => 'mailto:one@example.org',
409
+ 'sender_name' => 'One',
410
+ 'recipient' => 'mailto:strunk@example.org',
411
+ 'recipient_name' => 'Strunk',
412
+ 'message' => <<ICS
413
+ BEGIN:VCALENDAR
414
+ VERSION:2.0
415
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
416
+ CALSCALE:GREGORIAN
417
+ METHOD:REPLY
418
+ BEGIN:VEVENT
419
+ UID:foobar
420
+ SEQUENCE:1
421
+ DTSTART:20140716T120000Z
422
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
423
+ ATTENDEE;PARTSTAT=NEEDS-ACTION;CN=One:mailto:one@example.org
424
+ END:VEVENT
425
+ END:VCALENDAR
426
+ ICS
427
+ }
428
+ ]
429
+
430
+ parse(old_message, new_message, expected)
431
+ end
432
+
433
+ def test_no_relevant_attendee
434
+ old_message = <<ICS
435
+ BEGIN:VCALENDAR
436
+ VERSION:2.0
437
+ BEGIN:VEVENT
438
+ UID:foobar
439
+ SEQUENCE:1
440
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
441
+ ATTENDEE;CN=Two:mailto:two@example.org
442
+ DTSTART:20140716T120000Z
443
+ END:VEVENT
444
+ END:VCALENDAR
445
+ ICS
446
+
447
+ new_message = <<ICS
448
+ BEGIN:VCALENDAR
449
+ VERSION:2.0
450
+ BEGIN:VEVENT
451
+ UID:foobar
452
+ SEQUENCE:1
453
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
454
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=Two:mailto:two@example.org
455
+ DTSTART:20140716T120000Z
456
+ END:VEVENT
457
+ END:VCALENDAR
458
+ ICS
459
+ expected = []
460
+ parse(old_message, new_message, expected)
461
+ end
462
+
463
+ # In this test, an event exists in an attendees calendar. The event
464
+ # is recurring, and the attendee deletes 1 instance of the event.
465
+ # This instance shows up in EXDATE
466
+ #
467
+ # This should automatically generate a DECLINED message for that
468
+ # specific instance.
469
+ def test_create_reply_by_exception
470
+ old_message = <<ICS
471
+ BEGIN:VCALENDAR
472
+ VERSION:2.0
473
+ BEGIN:VEVENT
474
+ UID:foobar
475
+ SEQUENCE:1
476
+ DTSTART:20140811T200000Z
477
+ RRULE:FREQ=WEEKLY
478
+ ORGANIZER:mailto:organizer@example.org
479
+ ATTENDEE:mailto:one@example.org
480
+ END:VEVENT
481
+ END:VCALENDAR
482
+ ICS
483
+
484
+ new_message = <<ICS
485
+ BEGIN:VCALENDAR
486
+ VERSION:2.0
487
+ BEGIN:VEVENT
488
+ UID:foobar
489
+ SEQUENCE:1
490
+ DTSTART:20140811T200000Z
491
+ RRULE:FREQ=WEEKLY
492
+ ORGANIZER:mailto:organizer@example.org
493
+ ATTENDEE:mailto:one@example.org
494
+ EXDATE:20140818T200000Z
495
+ END:VEVENT
496
+ END:VCALENDAR
497
+ ICS
498
+
499
+ version = Tilia::VObject::Version::VERSION
500
+ expected = [
501
+ {
502
+ 'uid' => 'foobar',
503
+ 'method' => 'REPLY',
504
+ 'component' => 'VEVENT',
505
+ 'sender' => 'mailto:one@example.org',
506
+ 'sender_name' => nil,
507
+ 'recipient' => 'mailto:organizer@example.org',
508
+ 'recipient_name' => nil,
509
+ 'message' => <<ICS
510
+ BEGIN:VCALENDAR
511
+ VERSION:2.0
512
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
513
+ CALSCALE:GREGORIAN
514
+ METHOD:REPLY
515
+ BEGIN:VEVENT
516
+ UID:foobar
517
+ SEQUENCE:1
518
+ DTSTART:20140818T200000Z
519
+ RECURRENCE-ID:20140818T200000Z
520
+ ORGANIZER:mailto:organizer@example.org
521
+ ATTENDEE;PARTSTAT=DECLINED:mailto:one@example.org
522
+ END:VEVENT
523
+ END:VCALENDAR
524
+ ICS
525
+ }
526
+ ]
527
+ parse(old_message, new_message, expected)
528
+ end
529
+
530
+ # This test is identical to the last, but now we're working with
531
+ # timezones.
532
+ def test_create_reply_by_exception_tz
533
+ old_message = <<ICS
534
+ BEGIN:VCALENDAR
535
+ VERSION:2.0
536
+ BEGIN:VEVENT
537
+ UID:foobar
538
+ SEQUENCE:1
539
+ DTSTART;TZID=America/Toronto:20140811T200000
540
+ RRULE:FREQ=WEEKLY
541
+ ORGANIZER:mailto:organizer@example.org
542
+ ATTENDEE:mailto:one@example.org
543
+ END:VEVENT
544
+ END:VCALENDAR
545
+ ICS
546
+
547
+ new_message = <<ICS
548
+ BEGIN:VCALENDAR
549
+ VERSION:2.0
550
+ BEGIN:VEVENT
551
+ UID:foobar
552
+ SEQUENCE:1
553
+ DTSTART;TZID=America/Toronto:20140811T200000
554
+ RRULE:FREQ=WEEKLY
555
+ ORGANIZER:mailto:organizer@example.org
556
+ ATTENDEE:mailto:one@example.org
557
+ EXDATE;TZID=America/Toronto:20140818T200000
558
+ END:VEVENT
559
+ END:VCALENDAR
560
+ ICS
561
+
562
+ version = Tilia::VObject::Version::VERSION
563
+ expected = [
564
+ {
565
+ 'uid' => 'foobar',
566
+ 'method' => 'REPLY',
567
+ 'component' => 'VEVENT',
568
+ 'sender' => 'mailto:one@example.org',
569
+ 'sender_name' => nil,
570
+ 'recipient' => 'mailto:organizer@example.org',
571
+ 'recipient_name' => nil,
572
+ 'message' => <<ICS
573
+ BEGIN:VCALENDAR
574
+ VERSION:2.0
575
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
576
+ CALSCALE:GREGORIAN
577
+ METHOD:REPLY
578
+ BEGIN:VEVENT
579
+ UID:foobar
580
+ SEQUENCE:1
581
+ DTSTART;TZID=America/Toronto:20140818T200000
582
+ RECURRENCE-ID;TZID=America/Toronto:20140818T200000
583
+ ORGANIZER:mailto:organizer@example.org
584
+ ATTENDEE;PARTSTAT=DECLINED:mailto:one@example.org
585
+ END:VEVENT
586
+ END:VCALENDAR
587
+ ICS
588
+ }
589
+ ]
590
+
591
+ parse(old_message, new_message, expected)
592
+ end
593
+
594
+ def test_create_reply_by_exception_all_day
595
+ old_message = <<ICS
596
+ BEGIN:VCALENDAR
597
+ VERSION:2.0
598
+ BEGIN:VEVENT
599
+ SUMMARY:Weekly meeting
600
+ UID:foobar
601
+ SEQUENCE:1
602
+ DTSTART;VALUE=DATE:20140811
603
+ RRULE:FREQ=WEEKLY
604
+ ORGANIZER:mailto:organizer@example.org
605
+ ATTENDEE:mailto:one@example.org
606
+ END:VEVENT
607
+ END:VCALENDAR
608
+ ICS
609
+
610
+ new_message = <<ICS
611
+ BEGIN:VCALENDAR
612
+ VERSION:2.0
613
+ BEGIN:VEVENT
614
+ SUMMARY:Weekly meeting
615
+ UID:foobar
616
+ SEQUENCE:1
617
+ DTSTART;VALUE=DATE:20140811
618
+ RRULE:FREQ=WEEKLY
619
+ ORGANIZER:mailto:organizer@example.org
620
+ ATTENDEE:mailto:one@example.org
621
+ EXDATE;VALUE=DATE:20140818
622
+ END:VEVENT
623
+ END:VCALENDAR
624
+ ICS
625
+
626
+ version = Tilia::VObject::Version::VERSION
627
+ expected = [
628
+ {
629
+ 'uid' => 'foobar',
630
+ 'method' => 'REPLY',
631
+ 'component' => 'VEVENT',
632
+ 'sender' => 'mailto:one@example.org',
633
+ 'sender_name' => nil,
634
+ 'recipient' => 'mailto:organizer@example.org',
635
+ 'recipient_name' => nil,
636
+ 'message' => <<ICS
637
+ BEGIN:VCALENDAR
638
+ VERSION:2.0
639
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
640
+ CALSCALE:GREGORIAN
641
+ METHOD:REPLY
642
+ BEGIN:VEVENT
643
+ UID:foobar
644
+ SEQUENCE:1
645
+ DTSTART;VALUE=DATE:20140818
646
+ SUMMARY:Weekly meeting
647
+ RECURRENCE-ID;VALUE=DATE:20140818
648
+ ORGANIZER:mailto:organizer@example.org
649
+ ATTENDEE;PARTSTAT=DECLINED:mailto:one@example.org
650
+ END:VEVENT
651
+ END:VCALENDAR
652
+ ICS
653
+ }
654
+ ]
655
+
656
+ parse(old_message, new_message, expected)
657
+ end
658
+
659
+ def test_declined
660
+ old_message = <<ICS
661
+ BEGIN:VCALENDAR
662
+ VERSION:2.0
663
+ BEGIN:VEVENT
664
+ UID:foobar
665
+ SEQUENCE:1
666
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
667
+ ATTENDEE;CN=One:mailto:one@example.org
668
+ DTSTART:20140716T120000Z
669
+ END:VEVENT
670
+ END:VCALENDAR
671
+ ICS
672
+
673
+ new_message = <<ICS
674
+ BEGIN:VCALENDAR
675
+ VERSION:2.0
676
+ BEGIN:VEVENT
677
+ UID:foobar
678
+ SEQUENCE:1
679
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
680
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
681
+ DTSTART:20140716T120000Z
682
+ END:VEVENT
683
+ END:VCALENDAR
684
+ ICS
685
+
686
+ version = Tilia::VObject::Version::VERSION
687
+
688
+ expected = [
689
+ {
690
+ 'uid' => 'foobar',
691
+ 'method' => 'REPLY',
692
+ 'component' => 'VEVENT',
693
+ 'sender' => 'mailto:one@example.org',
694
+ 'sender_name' => 'One',
695
+ 'recipient' => 'mailto:strunk@example.org',
696
+ 'recipient_name' => 'Strunk',
697
+ 'message' => <<ICS
698
+ BEGIN:VCALENDAR
699
+ VERSION:2.0
700
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
701
+ CALSCALE:GREGORIAN
702
+ METHOD:REPLY
703
+ BEGIN:VEVENT
704
+ UID:foobar
705
+ SEQUENCE:1
706
+ DTSTART:20140716T120000Z
707
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
708
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
709
+ END:VEVENT
710
+ END:VCALENDAR
711
+ ICS
712
+ }
713
+ ]
714
+
715
+ parse(old_message, new_message, expected)
716
+ end
717
+
718
+ def test_declined_cancelled_event
719
+ old_message = <<ICS
720
+ BEGIN:VCALENDAR
721
+ VERSION:2.0
722
+ BEGIN:VEVENT
723
+ STATUS:CANCELLED
724
+ UID:foobar
725
+ SEQUENCE:1
726
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
727
+ ATTENDEE;CN=One:mailto:one@example.org
728
+ DTSTART:20140716T120000Z
729
+ END:VEVENT
730
+ END:VCALENDAR
731
+ ICS
732
+
733
+ new_message = <<ICS
734
+ BEGIN:VCALENDAR
735
+ VERSION:2.0
736
+ BEGIN:VEVENT
737
+ STATUS:CANCELLED
738
+ UID:foobar
739
+ SEQUENCE:1
740
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
741
+ ATTENDEE;PARTSTAT=DECLINED;CN=One:mailto:one@example.org
742
+ DTSTART:20140716T120000Z
743
+ END:VEVENT
744
+ END:VCALENDAR
745
+ ICS
746
+
747
+ expected = []
748
+
749
+ parse(old_message, new_message, expected)
750
+ end
751
+
752
+ # In this test, a new exception is created by an attendee as well.
753
+ #
754
+ # Except in this case, there was already an overridden event, and the
755
+ # overridden event was marked as cancelled by the attendee.
756
+ #
757
+ # For any other attendence status, the new status would have been
758
+ # declined, but for this, no message should we sent.
759
+ def test_dont_create_reply_when_event_was_declined
760
+ old_message = <<ICS
761
+ BEGIN:VCALENDAR
762
+ VERSION:2.0
763
+ BEGIN:VEVENT
764
+ UID:foobar
765
+ SEQUENCE:1
766
+ DTSTART:20140811T200000Z
767
+ RRULE:FREQ=WEEKLY
768
+ ORGANIZER:mailto:organizer@example.org
769
+ ATTENDEE:mailto:one@example.org
770
+ END:VEVENT
771
+ BEGIN:VEVENT
772
+ RECURRENCE-ID:20140818T200000Z
773
+ UID:foobar
774
+ SEQUENCE:1
775
+ DTSTART:20140818T200000Z
776
+ RRULE:FREQ=WEEKLY
777
+ ORGANIZER:mailto:organizer@example.org
778
+ ATTENDEE;PARTSTAT=DECLINED:mailto:one@example.org
779
+ END:VEVENT
780
+ END:VCALENDAR
781
+ ICS
782
+
783
+ new_message = <<ICS
784
+ BEGIN:VCALENDAR
785
+ VERSION:2.0
786
+ BEGIN:VEVENT
787
+ UID:foobar
788
+ SEQUENCE:1
789
+ DTSTART:20140811T200000Z
790
+ RRULE:FREQ=WEEKLY
791
+ ORGANIZER:mailto:organizer@example.org
792
+ ATTENDEE:mailto:one@example.org
793
+ EXDATE:20140818T200000Z
794
+ END:VEVENT
795
+ END:VCALENDAR
796
+ ICS
797
+
798
+ expected = []
799
+
800
+ parse(old_message, new_message, expected)
801
+ end
802
+
803
+ def test_schedule_agent_on_organizer
804
+ old_message = <<ICS
805
+ BEGIN:VCALENDAR
806
+ VERSION:2.0
807
+ BEGIN:VEVENT
808
+ UID:foobar
809
+ SEQUENCE:1
810
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
811
+ ATTENDEE;CN=One:mailto:one@example.org
812
+ DTSTART:20140716T120000Z
813
+ END:VEVENT
814
+ END:VCALENDAR
815
+ ICS
816
+
817
+ new_message = <<ICS
818
+ BEGIN:VCALENDAR
819
+ VERSION:2.0
820
+ BEGIN:VEVENT
821
+ UID:foobar
822
+ SEQUENCE:1
823
+ ORGANIZER;SCHEDULE-AGENT=CLIENT;CN=Strunk:mailto:strunk@example.org
824
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
825
+ DTSTART:20140716T120000Z
826
+ END:VEVENT
827
+ END:VCALENDAR
828
+ ICS
829
+
830
+ expected = []
831
+ parse(old_message, new_message, expected)
832
+ end
833
+
834
+ def test_accepted_all_day
835
+ old_message = <<ICS
836
+ BEGIN:VCALENDAR
837
+ VERSION:2.0
838
+ BEGIN:VEVENT
839
+ UID:foobar
840
+ SEQUENCE:1
841
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
842
+ ATTENDEE;CN=One:mailto:one@example.org
843
+ DTSTART;VALUE=DATE:20140716
844
+ END:VEVENT
845
+ END:VCALENDAR
846
+ ICS
847
+
848
+ new_message = <<ICS
849
+ BEGIN:VCALENDAR
850
+ VERSION:2.0
851
+ BEGIN:VEVENT
852
+ UID:foobar
853
+ SEQUENCE:1
854
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
855
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
856
+ DTSTART;VALUE=DATE:20140716
857
+ END:VEVENT
858
+ END:VCALENDAR
859
+ ICS
860
+
861
+ version = Tilia::VObject::Version::VERSION
862
+
863
+ expected = [
864
+ {
865
+ 'uid' => 'foobar',
866
+ 'method' => 'REPLY',
867
+ 'component' => 'VEVENT',
868
+ 'sender' => 'mailto:one@example.org',
869
+ 'sender_name' => 'One',
870
+ 'recipient' => 'mailto:strunk@example.org',
871
+ 'recipient_name' => 'Strunk',
872
+ 'message' => <<ICS
873
+ BEGIN:VCALENDAR
874
+ VERSION:2.0
875
+ PRODID:-//Tilia//Tilia VObject #{version}//EN
876
+ CALSCALE:GREGORIAN
877
+ METHOD:REPLY
878
+ BEGIN:VEVENT
879
+ UID:foobar
880
+ SEQUENCE:1
881
+ DTSTART;VALUE=DATE:20140716
882
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
883
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
884
+ END:VEVENT
885
+ END:VCALENDAR
886
+ ICS
887
+ }
888
+ ]
889
+
890
+ parse(old_message, new_message, expected)
891
+ end
892
+
893
+ # This function tests an attendee updating their status to an event where
894
+ # they don't have the master event of.
895
+ #
896
+ # This is possible in cases an organizer created a recurring event, and
897
+ # invited an attendee for one instance of the event.
898
+ def test_reply_no_master_event
899
+ old_message = <<ICS
900
+ BEGIN:VCALENDAR
901
+ VERSION:2.0
902
+ BEGIN:VEVENT
903
+ UID:foobar
904
+ SEQUENCE:1
905
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
906
+ ATTENDEE;CN=One:mailto:one@example.org
907
+ RECURRENCE-ID:20140724T120000Z
908
+ DTSTART:20140724T120000Z
909
+ SUMMARY:Daily sprint
910
+ END:VEVENT
911
+ END:VCALENDAR
912
+ ICS
913
+
914
+ new_message = <<ICS
915
+ BEGIN:VCALENDAR
916
+ VERSION:2.0
917
+ BEGIN:VEVENT
918
+ UID:foobar
919
+ SEQUENCE:1
920
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
921
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
922
+ RECURRENCE-ID:20140724T120000Z
923
+ DTSTART:20140724T120000Z
924
+ SUMMARY:Daily sprint
925
+ END:VEVENT
926
+ END:VCALENDAR
927
+ ICS
928
+
929
+ expected = [
930
+ {
931
+ 'uid' => 'foobar',
932
+ 'method' => 'REPLY',
933
+ 'component' => 'VEVENT',
934
+ 'sender' => 'mailto:one@example.org',
935
+ 'sender_name' => 'One',
936
+ 'recipient' => 'mailto:strunk@example.org',
937
+ 'recipient_name' => 'Strunk',
938
+ 'message' => <<ICS
939
+ BEGIN:VCALENDAR
940
+ VERSION:2.0
941
+ CALSCALE:GREGORIAN
942
+ METHOD:REPLY
943
+ BEGIN:VEVENT
944
+ UID:foobar
945
+ SEQUENCE:1
946
+ DTSTART:20140724T120000Z
947
+ SUMMARY:Daily sprint
948
+ RECURRENCE-ID:20140724T120000Z
949
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
950
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
951
+ END:VEVENT
952
+ END:VCALENDAR
953
+ ICS
954
+ }
955
+ ]
956
+
957
+ parse(old_message, new_message, expected)
958
+ end
959
+
960
+ # A party crasher is an attendee that accepted an event, but was not in
961
+ # any original invite.
962
+ def test_party_crasher
963
+ old_message = <<ICS
964
+ BEGIN:VCALENDAR
965
+ VERSION:2.0
966
+ BEGIN:VEVENT
967
+ UID:foobar
968
+ SUMMARY:B-day party
969
+ SEQUENCE:1
970
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
971
+ DTSTART:20140716T120000Z
972
+ RRULE:FREQ=DAILY
973
+ END:VEVENT
974
+ BEGIN:VEVENT
975
+ UID:foobar
976
+ RECURRENCE-ID:20140717T120000Z
977
+ SUMMARY:B-day party
978
+ SEQUENCE:1
979
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
980
+ DTSTART:20140717T120000Z
981
+ RRULE:FREQ=DAILY
982
+ END:VEVENT
983
+ END:VCALENDAR
984
+ ICS
985
+
986
+ new_message = <<ICS
987
+ BEGIN:VCALENDAR
988
+ VERSION:2.0
989
+ BEGIN:VEVENT
990
+ UID:foobar
991
+ SUMMARY:B-day party
992
+ SEQUENCE:1
993
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
994
+ DTSTART:20140716T120000Z
995
+ RRULE:FREQ=DAILY
996
+ END:VEVENT
997
+ BEGIN:VEVENT
998
+ UID:foobar
999
+ RECURRENCE-ID:20140717T120000Z
1000
+ SUMMARY:B-day party
1001
+ SEQUENCE:1
1002
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
1003
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
1004
+ DTSTART:20140717T120000Z
1005
+ RRULE:FREQ=DAILY
1006
+ END:VEVENT
1007
+ END:VCALENDAR
1008
+ ICS
1009
+
1010
+ expected = [
1011
+ {
1012
+ 'uid' => 'foobar',
1013
+ 'method' => 'REPLY',
1014
+ 'component' => 'VEVENT',
1015
+ 'sender' => 'mailto:one@example.org',
1016
+ 'sender_name' => 'One',
1017
+ 'recipient' => 'mailto:strunk@example.org',
1018
+ 'recipient_name' => 'Strunk',
1019
+ 'message' => <<ICS
1020
+ BEGIN:VCALENDAR
1021
+ VERSION:2.0
1022
+ CALSCALE:GREGORIAN
1023
+ METHOD:REPLY
1024
+ BEGIN:VEVENT
1025
+ UID:foobar
1026
+ SEQUENCE:1
1027
+ DTSTART:20140717T120000Z
1028
+ SUMMARY:B-day party
1029
+ RECURRENCE-ID:20140717T120000Z
1030
+ ORGANIZER;CN=Strunk:mailto:strunk@example.org
1031
+ ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
1032
+ END:VEVENT
1033
+ END:VCALENDAR
1034
+ ICS
1035
+ }
1036
+ ]
1037
+
1038
+ parse(old_message, new_message, expected)
1039
+ end
1040
+ end
1041
+ end
1042
+ end