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,403 @@
1
+ require 'test_helper'
2
+ require 'stringio'
3
+
4
+ module Tilia
5
+ module VObject
6
+ class ReaderTest < Minitest::Test
7
+ def test_read_component
8
+ data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR"
9
+
10
+ result = Tilia::VObject::Reader.read(data)
11
+
12
+ assert_kind_of(Tilia::VObject::Component, result)
13
+ assert_equal('VCALENDAR', result.name)
14
+ assert_equal(0, result.children.size)
15
+ end
16
+
17
+ def test_read_stream
18
+ data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR"
19
+
20
+ stream = StringIO.new
21
+ stream.write(data)
22
+ stream.rewind
23
+
24
+ result = Tilia::VObject::Reader.read(stream)
25
+
26
+ assert_kind_of(Tilia::VObject::Component, result)
27
+ assert_equal('VCALENDAR', result.name)
28
+ assert_equal(0, result.children.size)
29
+ end
30
+
31
+ def test_read_component_unix_new_line
32
+ data = "BEGIN:VCALENDAR\nEND:VCALENDAR"
33
+
34
+ result = Tilia::VObject::Reader.read(data)
35
+
36
+ assert_kind_of(Tilia::VObject::Component, result)
37
+ assert_equal('VCALENDAR', result.name)
38
+ assert_equal(0, result.children.size)
39
+ end
40
+
41
+ def test_read_component_line_fold
42
+ data = "BEGIN:\r\n\tVCALENDAR\r\nE\r\n ND:VCALENDAR"
43
+
44
+ result = Tilia::VObject::Reader.read(data)
45
+
46
+ assert_kind_of(Tilia::VObject::Component, result)
47
+ assert_equal('VCALENDAR', result.name)
48
+ assert_equal(0, result.children.size)
49
+ end
50
+
51
+ def test_read_corrupt_component
52
+ data = "BEGIN:VCALENDAR\r\nEND:FOO"
53
+
54
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(data) }
55
+ end
56
+
57
+ def test_read_corrupt_sub_component
58
+ data = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:FOO\r\nEND:VCALENDAR"
59
+
60
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(data) }
61
+ end
62
+
63
+ def test_read_property
64
+ data = "BEGIN:VCALENDAR\r\nSUMMARY:propValue\r\nEND:VCALENDAR"
65
+ result = Tilia::VObject::Reader.read(data)
66
+
67
+ result = result['SUMMARY']
68
+ assert_kind_of(Tilia::VObject::Property, result)
69
+ assert_equal('SUMMARY', result.name)
70
+ assert_equal('propValue', result.value)
71
+ end
72
+
73
+ def test_read_property_with_new_line
74
+ data = "BEGIN:VCALENDAR\r\nSUMMARY:Line1\\nLine2\\NLine3\\\\Not the 4th line!\r\nEND:VCALENDAR"
75
+ result = Tilia::VObject::Reader.read(data)
76
+
77
+ result = result['SUMMARY']
78
+ assert_kind_of(Tilia::VObject::Property, result)
79
+ assert_equal('SUMMARY', result.name)
80
+ assert_equal("Line1\nLine2\nLine3\\Not the 4th line!", result.value)
81
+ end
82
+
83
+ def test_read_mapped_property
84
+ data = "BEGIN:VCALENDAR\r\nDTSTART:20110529\r\nEND:VCALENDAR"
85
+ result = Tilia::VObject::Reader.read(data)
86
+
87
+ result = result['DTSTART']
88
+ assert_kind_of(Tilia::VObject::Property::ICalendar::DateTime, result)
89
+ assert_equal('DTSTART', result.name)
90
+ assert_equal('20110529', result.value)
91
+ end
92
+
93
+ def test_read_mapped_property_grouped
94
+ data = "BEGIN:VCALENDAR\r\nfoo.DTSTART:20110529\r\nEND:VCALENDAR"
95
+ result = Tilia::VObject::Reader.read(data)
96
+
97
+ result = result['DTSTART']
98
+ assert_kind_of(Tilia::VObject::Property::ICalendar::DateTime, result)
99
+ assert_equal('DTSTART', result.name)
100
+ assert_equal('20110529', result.value)
101
+ end
102
+
103
+ def test_read_broken_line
104
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;propValue"
105
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(data) }
106
+ end
107
+
108
+ def test_read_property_in_component
109
+ data = [
110
+ 'BEGIN:VCALENDAR',
111
+ 'PROPNAME:propValue',
112
+ 'END:VCALENDAR'
113
+ ]
114
+
115
+ result = Tilia::VObject::Reader.read(data.join("\r\n"))
116
+
117
+ assert_kind_of(Tilia::VObject::Component, result)
118
+ assert_equal('VCALENDAR', result.name)
119
+ assert_equal(1, result.children.size)
120
+ assert_kind_of(Tilia::VObject::Property, result.children[0])
121
+ assert_equal('PROPNAME', result.children[0].name)
122
+ assert_equal('propValue', result.children[0].value)
123
+ end
124
+
125
+ def test_read_nested_component
126
+ data = [
127
+ 'BEGIN:VCALENDAR',
128
+ 'BEGIN:VTIMEZONE',
129
+ 'BEGIN:DAYLIGHT',
130
+ 'END:DAYLIGHT',
131
+ 'END:VTIMEZONE',
132
+ 'END:VCALENDAR'
133
+ ]
134
+
135
+ result = Tilia::VObject::Reader.read(data.join("\r\n"))
136
+
137
+ assert_kind_of(Tilia::VObject::Component, result)
138
+ assert_equal('VCALENDAR', result.name)
139
+ assert_equal(1, result.children.size)
140
+ assert_kind_of(Tilia::VObject::Component, result.children[0])
141
+ assert_equal('VTIMEZONE', result.children[0].name)
142
+ assert_equal(1, result.children[0].children.size)
143
+ assert_kind_of(Tilia::VObject::Component, result.children[0].children[0])
144
+ assert_equal('DAYLIGHT', result.children[0].children[0].name)
145
+ end
146
+
147
+ def test_read_property_parameter
148
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue\r\nEND:VCALENDAR"
149
+ result = Tilia::VObject::Reader.read(data)
150
+
151
+ result = result['PROPNAME']
152
+
153
+ assert_kind_of(Tilia::VObject::Property, result)
154
+ assert_equal('PROPNAME', result.name)
155
+ assert_equal('propValue', result.value)
156
+ assert_equal(1, result.parameters.size)
157
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
158
+ assert_equal('paramvalue', result.parameters['PARAMNAME'].value)
159
+ end
160
+
161
+ def test_read_property_repeating_parameter
162
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;N=1;N=2;N=3,4;N=\"5\",6;N=\"7,8\";N=9,10;N=^'11^':propValue\r\nEND:VCALENDAR"
163
+ result = Tilia::VObject::Reader.read(data)
164
+
165
+ result = result['PROPNAME']
166
+
167
+ assert_kind_of(Tilia::VObject::Property, result)
168
+ assert_equal('PROPNAME', result.name)
169
+ assert_equal('propValue', result.value)
170
+ assert_equal(1, result.parameters.size)
171
+ assert_equal('N', result.parameters['N'].name)
172
+ assert_equal('1,2,3,4,5,6,7,8,9,10,"11"', result.parameters['N'].value)
173
+ assert_equal(['1', '2', '3', '4', '5', '6', '7,8', '9', '10', '"11"'], result.parameters['N'].parts)
174
+ end
175
+
176
+ def test_read_property_repeating_nameless_guessed_parameter
177
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;WORK;VOICE;PREF:propValue\r\nEND:VCALENDAR"
178
+ result = Tilia::VObject::Reader.read(data)
179
+
180
+ result = result['PROPNAME']
181
+
182
+ assert_kind_of(Tilia::VObject::Property, result)
183
+ assert_equal('PROPNAME', result.name)
184
+ assert_equal('propValue', result.value)
185
+ assert_equal(1, result.parameters.size)
186
+ assert_equal('TYPE', result.parameters['TYPE'].name)
187
+ assert_equal('WORK,VOICE,PREF', result.parameters['TYPE'].value)
188
+ assert_equal(['WORK', 'VOICE', 'PREF'], result.parameters['TYPE'].parts)
189
+ end
190
+
191
+ def test_read_property_no_name
192
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PRODIGY:propValue\r\nEND:VCALENDAR"
193
+ result = Tilia::VObject::Reader.read(data)
194
+
195
+ result = result['PROPNAME']
196
+
197
+ assert_kind_of(Tilia::VObject::Property, result)
198
+ assert_equal('PROPNAME', result.name)
199
+ assert_equal('propValue', result.value)
200
+ assert_equal(1, result.parameters.size)
201
+ assert_equal('TYPE', result.parameters['TYPE'].name)
202
+ assert(result.parameters['TYPE'].no_name)
203
+ assert_equal('PRODIGY', result.parameters['TYPE'].to_s)
204
+ end
205
+
206
+ def test_read_property_parameter_extra_colon
207
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue:anotherrandomstring\r\nEND:VCALENDAR"
208
+ result = Tilia::VObject::Reader.read(data)
209
+
210
+ result = result['PROPNAME']
211
+
212
+ assert_kind_of(Tilia::VObject::Property, result)
213
+ assert_equal('PROPNAME', result.name)
214
+ assert_equal('propValue:anotherrandomstring', result.value)
215
+ assert_equal(1, result.parameters.size)
216
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
217
+ assert_equal('paramvalue', result.parameters['PARAMNAME'].value)
218
+ end
219
+
220
+ def test_read_property2_parameters
221
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue;PARAMNAME2=paramvalue2:propValue\r\nEND:VCALENDAR"
222
+ result = Tilia::VObject::Reader.read(data)
223
+
224
+ result = result['PROPNAME']
225
+
226
+ assert_kind_of(Tilia::VObject::Property, result)
227
+ assert_equal('PROPNAME', result.name)
228
+ assert_equal('propValue', result.value)
229
+ assert_equal(2, result.parameters.size)
230
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
231
+ assert_equal('paramvalue', result.parameters['PARAMNAME'].value)
232
+ assert_equal('PARAMNAME2', result.parameters['PARAMNAME2'].name)
233
+ assert_equal('paramvalue2', result.parameters['PARAMNAME2'].value)
234
+ end
235
+
236
+ def test_read_property_parameter_quoted
237
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"paramvalue\":propValue\r\nEND:VCALENDAR"
238
+ result = Tilia::VObject::Reader.read(data)
239
+
240
+ result = result['PROPNAME']
241
+
242
+ assert_kind_of(Tilia::VObject::Property, result)
243
+ assert_equal('PROPNAME', result.name)
244
+ assert_equal('propValue', result.value)
245
+ assert_equal(1, result.parameters.size)
246
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
247
+ assert_equal('paramvalue', result.parameters['PARAMNAME'].value)
248
+ end
249
+
250
+ def test_read_property_parameter_new_lines
251
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue1^nvalue2^^nvalue3:propValue\r\nEND:VCALENDAR"
252
+ result = Tilia::VObject::Reader.read(data)
253
+
254
+ result = result['PROPNAME']
255
+
256
+ assert_kind_of(Tilia::VObject::Property, result)
257
+ assert_equal('PROPNAME', result.name)
258
+ assert_equal('propValue', result.value)
259
+
260
+ assert_equal(1, result.parameters.size)
261
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
262
+ assert_equal("paramvalue1\nvalue2^nvalue3", result.parameters['PARAMNAME'].value)
263
+ end
264
+
265
+ def test_read_property_parameter_quoted_colon
266
+ data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"param:value\":propValue\r\nEND:VCALENDAR"
267
+ result = Tilia::VObject::Reader.read(data)
268
+ result = result['PROPNAME']
269
+
270
+ assert_kind_of(Tilia::VObject::Property, result)
271
+ assert_equal('PROPNAME', result.name)
272
+ assert_equal('propValue', result.value)
273
+ assert_equal(1, result.parameters.size)
274
+ assert_equal('PARAMNAME', result.parameters['PARAMNAME'].name)
275
+ assert_equal('param:value', result.parameters['PARAMNAME'].value)
276
+ end
277
+
278
+ def test_read_forgiving
279
+ data = [
280
+ 'BEGIN:VCALENDAR',
281
+ 'X_PROP:propValue',
282
+ 'END:VCALENDAR'
283
+ ]
284
+
285
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(data.join("\r\n")) }
286
+
287
+ result = Tilia::VObject::Reader.read(data.join("\r\n"), Tilia::VObject::Reader::OPTION_FORGIVING)
288
+
289
+ expected = [
290
+ 'BEGIN:VCALENDAR',
291
+ 'X_PROP:propValue',
292
+ 'END:VCALENDAR',
293
+ ''
294
+ ].join("\r\n")
295
+
296
+ assert_equal(expected, result.serialize)
297
+ end
298
+
299
+ def test_read_with_invalid_line
300
+ data = [
301
+ 'BEGIN:VCALENDAR',
302
+ 'DESCRIPTION:propValue',
303
+ "Yes, we've actually seen a file with non-idented property values on multiple lines",
304
+ 'END:VCALENDAR'
305
+ ]
306
+
307
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(data.join("\r\n")) }
308
+
309
+ result = Tilia::VObject::Reader.read(data.join("\r\n"), Tilia::VObject::Reader::OPTION_IGNORE_INVALID_LINES)
310
+
311
+ expected = [
312
+ 'BEGIN:VCALENDAR',
313
+ 'DESCRIPTION:propValue',
314
+ 'END:VCALENDAR',
315
+ ''
316
+ ].join("\r\n")
317
+
318
+ assert_equal(expected, result.serialize)
319
+ end
320
+
321
+ # Reported as Issue 32.
322
+ def test_read_incomplete_file
323
+ input = <<ICS
324
+ BEGIN:VCALENDAR
325
+ VERSION:1.0
326
+ BEGIN:VEVENT
327
+ X-FUNAMBOL-FOLDER:DEFAULT_FOLDER
328
+ X-FUNAMBOL-ALLDAY:0
329
+ DTSTART:20111017T110000Z
330
+ DTEND:20111017T123000Z
331
+ X-MICROSOFT-CDO-BUSYSTATUS:BUSY
332
+ CATEGORIES:
333
+ LOCATION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Netviewer Meeting
334
+ PRIORITY:1
335
+ STATUS:3
336
+ X-MICROSOFT-CDO-REPLYTIME:20111017T064200Z
337
+ SUMMARY;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Kopieren: test
338
+ CLASS:PUBLIC
339
+ AALARM:
340
+ RRULE:
341
+ X-FUNAMBOL-BILLINGINFO:
342
+ X-FUNAMBOL-COMPANIES:
343
+ X-FUNAMBOL-MILEAGE:
344
+ X-FUNAMBOL-NOAGING:0
345
+ ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Heino' heino@test.com
346
+ ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Markus' test@test.com
347
+ ATTENDEE;STATUS=NEEDS AC
348
+ ICS
349
+
350
+ assert_raises(Tilia::VObject::ParseException) { Tilia::VObject::Reader.read(input) }
351
+ end
352
+
353
+ def test_read_broken_input
354
+ assert_raises(ArgumentError) { Tilia::VObject::Reader.read(false) }
355
+ end
356
+
357
+ def test_read_bom
358
+ data = (0xef).chr + (0xbb).chr + (0xbf).chr + "BEGIN:VCALENDAR\r\nEND:VCALENDAR"
359
+ result = Tilia::VObject::Reader.read(data)
360
+
361
+ assert_kind_of(Tilia::VObject::Component, result)
362
+ assert_equal('VCALENDAR', result.name)
363
+ assert_equal(0, result.children.size)
364
+ end
365
+
366
+ def test_read_xml_component
367
+ data = <<XML
368
+ <?xml version="1.0" encoding="utf-8"?>
369
+ <icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">
370
+ <vcalendar>
371
+ </vcalendar>
372
+ </icalendar>
373
+ XML
374
+
375
+ result = Tilia::VObject::Reader.read_xml(data)
376
+
377
+ assert_kind_of(Tilia::VObject::Component, result)
378
+ assert_equal('VCALENDAR', result.name)
379
+ assert_equal(0, result.children.size)
380
+ end
381
+
382
+ def test_read_xml_stream
383
+ data = <<XML
384
+ <?xml version="1.0" encoding="utf-8"?>
385
+ <icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">
386
+ <vcalendar>
387
+ </vcalendar>
388
+ </icalendar>
389
+ XML
390
+
391
+ stream = StringIO.new
392
+ stream.write(data)
393
+ stream.rewind
394
+
395
+ result = Tilia::VObject::Reader.read_xml(stream)
396
+
397
+ assert_kind_of(Tilia::VObject::Component, result)
398
+ assert_equal('VCALENDAR', result.name)
399
+ assert_equal(0, result.children.size)
400
+ end
401
+ end
402
+ end
403
+ end
@@ -0,0 +1,52 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class ByMonthInDailyTest < Minitest::Test
6
+ # This tests the expansion of dates with DAILY frequency in RRULE with BYMONTH restrictions
7
+ def test_expand
8
+ ics = <<ICS
9
+ BEGIN:VCALENDAR
10
+ VERSION:2.0
11
+ PRODID:-//Apple Inc.//iCal 4.0.4//EN
12
+ CALSCALE:GREGORIAN
13
+ BEGIN:VEVENT
14
+ TRANSP:OPAQUE
15
+ DTEND:20070925T183000Z
16
+ UID:uuid
17
+ DTSTAMP:19700101T000000Z
18
+ LOCATION:
19
+ DESCRIPTION:
20
+ STATUS:CONFIRMED
21
+ SEQUENCE:18
22
+ SUMMARY:Stuff
23
+ DTSTART:20070925T160000Z
24
+ CREATED:20071004T144642Z
25
+ RRULE:FREQ=DAILY;BYMONTH=9,10;BYDAY=SU
26
+ END:VEVENT
27
+ END:VCALENDAR
28
+ ICS
29
+ vcal = Tilia::VObject::Reader.read(ics)
30
+ assert_kind_of(Tilia::VObject::Component::VCalendar, vcal)
31
+
32
+ vcal.expand(Time.zone.parse('2013-09-28'), Time.zone.parse('2014-09-11'))
33
+
34
+ dates = []
35
+ vcal['VEVENT'].each do |event|
36
+ dates << event['DTSTART'].value
37
+ end
38
+
39
+ expected_dates = [
40
+ '20130929T160000Z',
41
+ '20131006T160000Z',
42
+ '20131013T160000Z',
43
+ '20131020T160000Z',
44
+ '20131027T160000Z',
45
+ '20140907T160000Z'
46
+ ]
47
+
48
+ assert_equal(expected_dates, dates, 'Recursed dates are restricted by month')
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,55 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class BySetPosHangTest < Minitest::Test
6
+ # Using this iCalendar object, including BYSETPOS=-2 causes the iterator
7
+ # to hang, as reported in ticket #212.
8
+ #
9
+ # See: https://github.com/fruux/sabre-vobject/issues/212
10
+ def test_expand
11
+ ics = <<ICS
12
+ BEGIN:VCALENDAR
13
+ VERSION:2.0
14
+ PRODID:-//Sabre//Sabre VObject 3.4.2//EN
15
+ CALSCALE:GREGORIAN
16
+ BEGIN:VEVENT
17
+ SUMMARY:Test event 1
18
+ DTSTART;TZID=Europe/Copenhagen:20150101T170000
19
+ RRULE:FREQ=MONTHLY;BYDAY=TH;BYSETPOS=-2
20
+ UID:b4071499-6fe4-418a-83b8-2b8d5ebb38e4
21
+ END:VEVENT
22
+ END:VCALENDAR
23
+ ICS
24
+
25
+ vcal = Tilia::VObject::Reader.read(ics)
26
+ assert_kind_of(Tilia::VObject::Component::VCalendar, vcal)
27
+
28
+ vcal.expand(Time.zone.parse('2015-01-01'), Time.zone.parse('2016-01-01'))
29
+
30
+ dates = []
31
+ vcal['VEVENT'].each do |event|
32
+ dates << event['DTSTART'].value
33
+ end
34
+
35
+ expected_dates = [
36
+ '20150101T160000Z',
37
+ '20150122T160000Z',
38
+ '20150219T160000Z',
39
+ '20150319T160000Z',
40
+ '20150423T150000Z',
41
+ '20150521T150000Z',
42
+ '20150618T150000Z',
43
+ '20150723T150000Z',
44
+ '20150820T150000Z',
45
+ '20150917T150000Z',
46
+ '20151022T150000Z',
47
+ '20151119T160000Z',
48
+ '20151224T160000Z'
49
+ ]
50
+
51
+ assert_equal(expected_dates, dates)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,109 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class ExpandFloatingTimesTest < Minitest::Test
6
+ def test_expand
7
+ input = <<ICS
8
+ BEGIN:VCALENDAR
9
+ VERSION:2.0
10
+ BEGIN:VEVENT
11
+ UID:foo
12
+ DTSTART:20150109T090000
13
+ DTEND:20150109T100000
14
+ RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20191002T070000Z;BYDAY=FR
15
+ END:VEVENT
16
+ END:VCALENDAR
17
+ ICS
18
+
19
+ vcal = Tilia::VObject::Reader.read(input)
20
+ assert_kind_of(Tilia::VObject::Component::VCalendar, vcal)
21
+
22
+ vcal.expand(Time.zone.parse('2015-01-01'), Time.zone.parse('2015-01-31'))
23
+
24
+ result = vcal.serialize
25
+
26
+ output = <<ICS
27
+ BEGIN:VCALENDAR
28
+ VERSION:2.0
29
+ BEGIN:VEVENT
30
+ UID:foo
31
+ DTSTART:20150109T090000Z
32
+ DTEND:20150109T100000Z
33
+ END:VEVENT
34
+ BEGIN:VEVENT
35
+ UID:foo
36
+ DTSTART:20150116T090000Z
37
+ DTEND:20150116T100000Z
38
+ RECURRENCE-ID:20150116T090000Z
39
+ END:VEVENT
40
+ BEGIN:VEVENT
41
+ UID:foo
42
+ DTSTART:20150123T090000Z
43
+ DTEND:20150123T100000Z
44
+ RECURRENCE-ID:20150123T090000Z
45
+ END:VEVENT
46
+ BEGIN:VEVENT
47
+ UID:foo
48
+ DTSTART:20150130T090000Z
49
+ DTEND:20150130T100000Z
50
+ RECURRENCE-ID:20150130T090000Z
51
+ END:VEVENT
52
+ END:VCALENDAR
53
+ ICS
54
+ assert_equal(output, result.delete("\r"))
55
+ end
56
+
57
+ def test_expand_with_reference_timezone
58
+ input = <<ICS
59
+ BEGIN:VCALENDAR
60
+ VERSION:2.0
61
+ BEGIN:VEVENT
62
+ UID:foo
63
+ DTSTART:20150109T090000
64
+ DTEND:20150109T100000
65
+ RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20191002T070000Z;BYDAY=FR
66
+ END:VEVENT
67
+ END:VCALENDAR
68
+ ICS
69
+
70
+ vcal = Tilia::VObject::Reader.read(input)
71
+ assert_kind_of(Tilia::VObject::Component::VCalendar, vcal)
72
+
73
+ vcal.expand(Time.zone.parse('2015-01-01'), Time.zone.parse('2015-01-31'), ActiveSupport::TimeZone.new('Europe/Berlin'))
74
+
75
+ result = vcal.serialize
76
+
77
+ output = <<ICS
78
+ BEGIN:VCALENDAR
79
+ VERSION:2.0
80
+ BEGIN:VEVENT
81
+ UID:foo
82
+ DTSTART:20150109T080000Z
83
+ DTEND:20150109T090000Z
84
+ END:VEVENT
85
+ BEGIN:VEVENT
86
+ UID:foo
87
+ DTSTART:20150116T080000Z
88
+ DTEND:20150116T090000Z
89
+ RECURRENCE-ID:20150116T080000Z
90
+ END:VEVENT
91
+ BEGIN:VEVENT
92
+ UID:foo
93
+ DTSTART:20150123T080000Z
94
+ DTEND:20150123T090000Z
95
+ RECURRENCE-ID:20150123T080000Z
96
+ END:VEVENT
97
+ BEGIN:VEVENT
98
+ UID:foo
99
+ DTSTART:20150130T080000Z
100
+ DTEND:20150130T090000Z
101
+ RECURRENCE-ID:20150130T080000Z
102
+ END:VEVENT
103
+ END:VCALENDAR
104
+ ICS
105
+ assert_equal(output, result.delete("\r"))
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class FifthTuesdayProblemTest < Minitest::Test
6
+ # A pretty slow test. Had to be marked as 'medium' for phpunit to not die
7
+ # after 1 second. Would be good to optimize later.
8
+ #
9
+ # @medium
10
+ def test_get_dt_end
11
+ ics = <<ICS
12
+ BEGIN:VCALENDAR
13
+ VERSION:2.0
14
+ PRODID:-//Apple Inc.//iCal 4.0.4//EN
15
+ CALSCALE:GREGORIAN
16
+ BEGIN:VEVENT
17
+ TRANSP:OPAQUE
18
+ DTEND;TZID=America/New_York:20070925T170000
19
+ UID:uuid
20
+ DTSTAMP:19700101T000000Z
21
+ LOCATION:
22
+ DESCRIPTION:
23
+ STATUS:CONFIRMED
24
+ SEQUENCE:18
25
+ SUMMARY:Stuff
26
+ DTSTART;TZID=America/New_York:20070925T160000
27
+ CREATED:20071004T144642Z
28
+ RRULE:FREQ=MONTHLY;INTERVAL=1;UNTIL=20071030T035959Z;BYDAY=5TU
29
+ END:VEVENT
30
+ END:VCALENDAR
31
+ ICS
32
+
33
+ v_object = Tilia::VObject::Reader.read(ics)
34
+ it = Tilia::VObject::Recur::EventIterator.new(v_object, v_object['VEVENT']['UID'].to_s)
35
+
36
+ it.next while it.valid
37
+
38
+ # If we got here, it means we were successful. The bug that was in the
39
+ # system before would fail on the 5th tuesday of the month, if the 5th
40
+ # tuesday did not exist.
41
+ assert(true)
42
+ end
43
+ end
44
+ end
45
+ end