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,258 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VCardTest < Minitest::Test
6
+ def assert_validate(vcf, options, expected_level, expected_message = nil)
7
+ vcal = Tilia::VObject::Reader.read(vcf)
8
+ result = vcal.validate(options)
9
+
10
+ expect_validate_result(result, expected_level, expected_message)
11
+ end
12
+
13
+ def expect_validate_result(input, expected_level, expected_message = nil)
14
+ messages = []
15
+ input.each do |warning|
16
+ messages << warning['message']
17
+ end
18
+
19
+ if expected_level == 0
20
+ assert_equal(0, input.size, "No validation messages were expected. We got: #{messages.join(', ')}")
21
+ else
22
+ assert_equal(1, input.size, "We expected exactly 1 validation message, We got: #{messages.join(', ')}")
23
+
24
+ assert_equal(expected_message, input[0]['message'])
25
+ assert_equal(expected_level, input[0]['level'])
26
+ end
27
+ end
28
+
29
+ def validate_data
30
+ tests = []
31
+
32
+ # Correct
33
+ tests << [
34
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n",
35
+ [],
36
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n"
37
+ ]
38
+
39
+ # No VERSION
40
+ tests << [
41
+ "BEGIN:VCARD\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n",
42
+ [
43
+ 'VERSION MUST appear exactly once in a VCARD component'
44
+ ],
45
+ "BEGIN:VCARD\r\nVERSION:3.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n"
46
+ ]
47
+
48
+ # Unknown version
49
+ tests << [
50
+ "BEGIN:VCARD\r\nVERSION:2.2\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n",
51
+ [
52
+ 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.'
53
+ ],
54
+ "BEGIN:VCARD\r\nVERSION:2.1\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n"
55
+ ]
56
+
57
+ # No FN
58
+ tests << [
59
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nEND:VCARD\r\n",
60
+ [
61
+ 'The FN property must appear in the VCARD component exactly 1 time'
62
+ ],
63
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nEND:VCARD\r\n"
64
+ ]
65
+ # No FN, N fallback
66
+ tests << [
67
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;John;;;;;\r\nEND:VCARD\r\n",
68
+ [
69
+ 'The FN property must appear in the VCARD component exactly 1 time'
70
+ ],
71
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;John;;;;;\r\nFN:John Doe\r\nEND:VCARD\r\n"
72
+ ]
73
+ # No FN, N fallback, no first name
74
+ tests << [
75
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;;;;;;\r\nEND:VCARD\r\n",
76
+ [
77
+ 'The FN property must appear in the VCARD component exactly 1 time'
78
+ ],
79
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;;;;;;\r\nFN:Doe\r\nEND:VCARD\r\n"
80
+ ]
81
+
82
+ # No FN, ORG fallback
83
+ tests << [
84
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nORG:Acme Co.\r\nEND:VCARD\r\n",
85
+ [
86
+ 'The FN property must appear in the VCARD component exactly 1 time'
87
+ ],
88
+ "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nORG:Acme Co.\r\nFN:Acme Co.\r\nEND:VCARD\r\n"
89
+ ]
90
+ tests
91
+ end
92
+
93
+ def test_validate
94
+ validate_data.each do |data|
95
+ (input, expected_warnings, expected_repaired_output) = data
96
+ vcard = Tilia::VObject::Reader.read(input)
97
+
98
+ warnings = vcard.validate
99
+
100
+ warn_msg = []
101
+ warnings.each do |warning|
102
+ warn_msg << warning['message']
103
+ end
104
+
105
+ assert_equal(expected_warnings, warn_msg)
106
+
107
+ vcard.validate(Tilia::VObject::Component::REPAIR)
108
+
109
+ assert_equal(expected_repaired_output, vcard.serialize)
110
+ end
111
+ end
112
+
113
+ def test_get_document_type
114
+ vcard = Tilia::VObject::Component::VCard.new({}, false)
115
+ vcard['VERSION'] = '2.1'
116
+ assert_equal(Tilia::VObject::Component::VCard::VCARD21, vcard.document_type)
117
+
118
+ vcard = Tilia::VObject::Component::VCard.new({}, false)
119
+ vcard['VERSION'] = '3.0'
120
+ assert_equal(Tilia::VObject::Component::VCard::VCARD30, vcard.document_type)
121
+
122
+ vcard = Tilia::VObject::Component::VCard.new({}, false)
123
+ vcard['VERSION'] = '4.0'
124
+ assert_equal(Tilia::VObject::Component::VCard::VCARD40, vcard.document_type)
125
+
126
+ vcard = Tilia::VObject::Component::VCard.new({}, false)
127
+ assert_equal(Tilia::VObject::Component::VCard::UNKNOWN, vcard.document_type)
128
+ end
129
+
130
+ def test_preferred_no_pref
131
+ vcard = <<VCF
132
+ BEGIN:VCARD
133
+ VERSION:3.0
134
+ EMAIL:1@example.org
135
+ EMAIL:2@example.org
136
+ END:VCARD
137
+ VCF
138
+
139
+ vcard = Tilia::VObject::Reader.read(vcard)
140
+ assert_equal('1@example.org', vcard.preferred('EMAIL').value)
141
+ end
142
+
143
+ def test_preferred_with_pref
144
+ vcard = <<VCF
145
+ BEGIN:VCARD
146
+ VERSION:3.0
147
+ EMAIL:1@example.org
148
+ EMAIL;TYPE=PREF:2@example.org
149
+ END:VCARD
150
+ VCF
151
+
152
+ vcard = Tilia::VObject::Reader.read(vcard)
153
+ assert_equal('2@example.org', vcard.preferred('EMAIL').value)
154
+ end
155
+
156
+ def test_preferred_with40_pref
157
+ vcard = <<VCF
158
+ BEGIN:VCARD
159
+ VERSION:4.0
160
+ EMAIL:1@example.org
161
+ EMAIL;PREF=3:2@example.org
162
+ EMAIL;PREF=2:3@example.org
163
+ END:VCARD
164
+ VCF
165
+
166
+ vcard = Tilia::VObject::Reader.read(vcard)
167
+ assert_equal('3@example.org', vcard.preferred('EMAIL').value)
168
+ end
169
+
170
+ def test_preferred_not_found
171
+ vcard = <<VCF
172
+ BEGIN:VCARD
173
+ VERSION:4.0
174
+ END:VCARD
175
+ VCF
176
+
177
+ vcard = Tilia::VObject::Reader.read(vcard)
178
+ assert_nil(vcard.preferred('EMAIL'))
179
+ end
180
+
181
+ def test_no_uid_card_dav
182
+ vcard = <<VCF
183
+ BEGIN:VCARD
184
+ VERSION:4.0
185
+ FN:John Doe
186
+ END:VCARD
187
+ VCF
188
+ assert_validate(
189
+ vcard,
190
+ Tilia::VObject::Component::VCard::PROFILE_CARDDAV,
191
+ 3,
192
+ 'vCards on CardDAV servers MUST have a UID property.'
193
+ )
194
+ end
195
+
196
+ def test_no_uid_no_card_dav
197
+ vcard = <<VCF
198
+ BEGIN:VCARD
199
+ VERSION:4.0
200
+ FN:John Doe
201
+ END:VCARD
202
+ VCF
203
+ assert_validate(
204
+ vcard,
205
+ 0,
206
+ 2,
207
+ 'Adding a UID to a vCard property is recommended.'
208
+ )
209
+ end
210
+
211
+ def test_no_uid_no_card_dav_repair
212
+ vcard = <<VCF
213
+ BEGIN:VCARD
214
+ VERSION:4.0
215
+ FN:John Doe
216
+ END:VCARD
217
+ VCF
218
+ assert_validate(
219
+ vcard,
220
+ Tilia::VObject::Component::VCard::REPAIR,
221
+ 1,
222
+ 'Adding a UID to a vCard property is recommended.'
223
+ )
224
+ end
225
+
226
+ def test_v_card21_card_dav
227
+ vcard = <<VCF
228
+ BEGIN:VCARD
229
+ VERSION:2.1
230
+ FN:John Doe
231
+ UID:foo
232
+ END:VCARD
233
+ VCF
234
+ assert_validate(
235
+ vcard,
236
+ Tilia::VObject::Component::VCard::PROFILE_CARDDAV,
237
+ 3,
238
+ 'CardDAV servers are not allowed to accept vCard 2.1.'
239
+ )
240
+ end
241
+
242
+ def test_v_card21_no_card_dav
243
+ vcard = <<VCF
244
+ BEGIN:VCARD
245
+ VERSION:2.1
246
+ FN:John Doe
247
+ UID:foo
248
+ END:VCARD
249
+ VCF
250
+ assert_validate(
251
+ vcard,
252
+ 0,
253
+ 0
254
+ )
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VEventTest < Minitest::Test
6
+ def time_range_test_data
7
+ tests = []
8
+ berlin = ActiveSupport::TimeZone.new('Europe/Berlin')
9
+
10
+ calendar = Tilia::VObject::Component::VCalendar.new
11
+
12
+ vevent = calendar.create_component('VEVENT')
13
+ vevent['DTSTART'] = '20111223T120000Z'
14
+ tests << [vevent, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
15
+ tests << [vevent, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
16
+
17
+ vevent2 = vevent.clone
18
+ vevent2['DTEND'] = '20111225T120000Z'
19
+ tests << [vevent2, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
20
+ tests << [vevent2, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
21
+
22
+ vevent3 = vevent.clone
23
+ vevent3['DURATION'] = 'P1D'
24
+ tests << [vevent3, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
25
+ tests << [vevent3, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
26
+
27
+ vevent4 = vevent.clone
28
+ vevent4['DTSTART'] = '20111225'
29
+ vevent4['DTSTART']['VALUE'] = 'DATE'
30
+ tests << [vevent4, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
31
+ tests << [vevent4, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
32
+ # Event with no end date should be treated as lasting the entire day.
33
+ tests << [vevent4, Time.zone.parse('2011-12-25 16:00:00'), Time.zone.parse('2011-12-25 17:00:00'), true]
34
+ # DTEND is non inclusive so all day events should not be returned on the next day.
35
+ tests << [vevent4, Time.zone.parse('2011-12-26 00:00:00'), Time.zone.parse('2011-12-26 17:00:00'), false]
36
+ # The timezone of timerange in question also needs to be considered.
37
+ tests << [vevent4, berlin.parse('2011-12-26 00:00:00'), berlin.parse('2011-12-26 17:00:00'), false]
38
+
39
+ vevent5 = vevent.clone
40
+ vevent5['DURATION'] = 'P1D'
41
+ vevent5['RRULE'] = 'FREQ=YEARLY'
42
+ tests << [vevent5, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
43
+ tests << [vevent5, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
44
+ tests << [vevent5, Time.zone.parse('2013-12-01'), Time.zone.parse('2013-12-31'), true]
45
+
46
+ vevent6 = vevent.clone
47
+ vevent6['DTSTART'] = '20111225'
48
+ vevent6['DTSTART']['VALUE'] = 'DATE'
49
+ vevent6['DTEND'] = '20111225'
50
+ vevent6['DTEND']['VALUE'] = 'DATE'
51
+
52
+ tests << [vevent6, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
53
+ tests << [vevent6, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
54
+
55
+ # Added this test to ensure that recurrence rules with no DTEND also
56
+ # get checked for the entire day.
57
+ vevent7 = vevent.clone
58
+ vevent7['DTSTART'] = '20120101'
59
+ vevent7['DTSTART']['VALUE'] = 'DATE'
60
+ vevent7['RRULE'] = 'FREQ=MONTHLY'
61
+ tests << [vevent7, Time.zone.parse('2012-02-01 15:00:00'), Time.zone.parse('2012-02-02'), true]
62
+ # The timezone of timerange in question should also be considered.
63
+ tests << [vevent7, berlin.parse('2012-02-02 00:00:00'), berlin.parse('2012-02-03 00:00:00'), false]
64
+
65
+ # Added this test to check recurring events that have no instances.
66
+ vevent8 = vevent.clone
67
+ vevent8['DTSTART'] = '20130329T140000'
68
+ vevent8['DTEND'] = '20130329T153000'
69
+ vevent8['RRULE'] = { 'FREQ' => 'WEEKLY', 'BYDAY' => ['FR'], 'UNTIL' => '20130412T115959Z' }
70
+ vevent8.add('EXDATE', '20130405T140000')
71
+ vevent8.add('EXDATE', '20130329T140000')
72
+ tests << [vevent8, Time.zone.parse('2013-03-01'), Time.zone.parse('2013-04-01'), false]
73
+
74
+ tests
75
+ end
76
+
77
+ def test_in_time_range
78
+ time_range_test_data.each do |data|
79
+ (vevent, start, ending, outcome) = data
80
+ assert_equal(outcome, vevent.in_time_range?(start, ending))
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VFreeBusyTest < Minitest::Test
6
+ def test_is_free
7
+ input = <<BLA
8
+ BEGIN:VCALENDAR
9
+ BEGIN:VFREEBUSY
10
+ FREEBUSY;FBTYPE=FREE:20120912T000500Z/PT1H
11
+ FREEBUSY;FBTYPE=BUSY:20120912T010000Z/20120912T020000Z
12
+ FREEBUSY;FBTYPE=BUSY-TENTATIVE:20120912T020000Z/20120912T030000Z
13
+ FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20120912T030000Z/20120912T040000Z
14
+ FREEBUSY;FBTYPE=BUSY:20120912T050000Z/20120912T060000Z,20120912T080000Z/20120912T090000Z
15
+ FREEBUSY;FBTYPE=BUSY:20120912T100000Z/PT1H
16
+ END:VFREEBUSY
17
+ END:VCALENDAR
18
+ BLA
19
+
20
+ obj = Tilia::VObject::Reader.read(input)
21
+ vfb = obj['VFREEBUSY']
22
+
23
+ tz = ActiveSupport::TimeZone.new('UTC')
24
+
25
+ refute(vfb.free?(tz.parse('2012-09-12 01:15:00'), tz.parse('2012-09-12 01:45:00')))
26
+ refute(vfb.free?(tz.parse('2012-09-12 08:05:00'), tz.parse('2012-09-12 08:10:00')))
27
+ refute(vfb.free?(tz.parse('2012-09-12 10:15:00'), tz.parse('2012-09-12 10:45:00')))
28
+
29
+ # Checking whether the end time is treated as non-inclusive
30
+ assert(vfb.free?(tz.parse('2012-09-12 09:00:00'), tz.parse('2012-09-12 09:15:00')))
31
+ assert(vfb.free?(tz.parse('2012-09-12 09:45:00'), tz.parse('2012-09-12 10:00:00')))
32
+ assert(vfb.free?(tz.parse('2012-09-12 11:00:00'), tz.parse('2012-09-12 12:00:00')))
33
+ end
34
+
35
+ def test_validate
36
+ input = <<HI
37
+ BEGIN:VCALENDAR
38
+ VERSION:2.0
39
+ PRODID:YoYo
40
+ BEGIN:VFREEBUSY
41
+ UID:some-random-id
42
+ DTSTAMP:20140402T180200Z
43
+ END:VFREEBUSY
44
+ END:VCALENDAR
45
+ HI
46
+
47
+ obj = Tilia::VObject::Reader.read(input)
48
+
49
+ warnings = obj.validate
50
+ messages = []
51
+ warnings.each do |warning|
52
+ messages << warning['message']
53
+ end
54
+
55
+ assert_equal([], messages)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,85 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VJournalTest < Minitest::Test
6
+ def time_range_test_data
7
+ calendar = Tilia::VObject::Component::VCalendar.new
8
+
9
+ tests = []
10
+
11
+ vjournal = calendar.create_component('VJOURNAL')
12
+ vjournal['DTSTART'] = '20111223T120000Z'
13
+ tests << [vjournal, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
14
+ tests << [vjournal, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
15
+
16
+ vjournal2 = calendar.create_component('VJOURNAL')
17
+ vjournal2['DTSTART'] = '20111223'
18
+ vjournal2['DTSTART']['VALUE'] = 'DATE'
19
+ tests << [vjournal2, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
20
+ tests << [vjournal2, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
21
+
22
+ vjournal3 = calendar.create_component('VJOURNAL')
23
+ tests << [vjournal3, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), false]
24
+ tests << [vjournal3, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
25
+
26
+ tests
27
+ end
28
+
29
+ def test_in_time_range
30
+ time_range_test_data.each do |data|
31
+ (vtodo, start, ending, outcome) = data
32
+ assert_equal(outcome, vtodo.in_time_range?(start, ending))
33
+ end
34
+ end
35
+
36
+ def test_validate
37
+ input = <<HI
38
+ BEGIN:VCALENDAR
39
+ VERSION:2.0
40
+ PRODID:YoYo
41
+ BEGIN:VJOURNAL
42
+ UID:12345678
43
+ DTSTAMP:20140402T174100Z
44
+ END:VJOURNAL
45
+ END:VCALENDAR
46
+ HI
47
+
48
+ obj = Tilia::VObject::Reader.read(input)
49
+
50
+ warnings = obj.validate
51
+ messages = []
52
+ warnings.each do |warning|
53
+ messages << warning['message']
54
+ end
55
+
56
+ assert_equal([], messages)
57
+ end
58
+
59
+ def test_validate_broken
60
+ input = <<HI
61
+ BEGIN:VCALENDAR
62
+ VERSION:2.0
63
+ PRODID:YoYo
64
+ BEGIN:VJOURNAL
65
+ UID:12345678
66
+ DTSTAMP:20140402T174100Z
67
+ URL:http://example.org/
68
+ URL:http://example.com/
69
+ END:VJOURNAL
70
+ END:VCALENDAR
71
+ HI
72
+
73
+ obj = Tilia::VObject::Reader.read(input)
74
+
75
+ warnings = obj.validate
76
+ messages = []
77
+ warnings.each do |warning|
78
+ messages << warning['message']
79
+ end
80
+
81
+ assert_equal(['URL MUST NOT appear more than once in a VJOURNAL component'], messages)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VTimeZoneTest < Minitest::Test
6
+ def test_validate
7
+ input = <<HI
8
+ BEGIN:VCALENDAR
9
+ VERSION:2.0
10
+ PRODID:YoYo
11
+ BEGIN:VTIMEZONE
12
+ TZID:America/Toronto
13
+ END:VTIMEZONE
14
+ END:VCALENDAR
15
+ HI
16
+
17
+ obj = Tilia::VObject::Reader.read(input)
18
+
19
+ warnings = obj.validate
20
+ messages = []
21
+ warnings.each do |warning|
22
+ messages << warning['message']
23
+ end
24
+
25
+ assert_equal([], messages)
26
+ end
27
+
28
+ def test_get_time_zone
29
+ input = <<HI
30
+ BEGIN:VCALENDAR
31
+ VERSION:2.0
32
+ PRODID:YoYo
33
+ BEGIN:VTIMEZONE
34
+ TZID:America/Toronto
35
+ END:VTIMEZONE
36
+ END:VCALENDAR
37
+ HI
38
+
39
+ obj = Tilia::VObject::Reader.read(input)
40
+
41
+ tz = ActiveSupport::TimeZone.new('America/Toronto')
42
+
43
+ assert_equal(tz, obj['VTIMEZONE'].time_zone)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,172 @@
1
+ require 'test_helper'
2
+
3
+ module Tilia
4
+ module VObject
5
+ class VTodoTest < Minitest::Test
6
+ def time_range_test_data
7
+ tests = []
8
+
9
+ calendar = Tilia::VObject::Component::VCalendar.new
10
+
11
+ vtodo = calendar.create_component('VTODO')
12
+ vtodo['DTSTART'] = '20111223T120000Z'
13
+ tests << [vtodo, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
14
+ tests << [vtodo, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
15
+
16
+ vtodo2 = vtodo.clone
17
+ vtodo2['DURATION'] = 'P1D'
18
+ tests << [vtodo2, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
19
+ tests << [vtodo2, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
20
+
21
+ vtodo3 = vtodo.clone
22
+ vtodo3['DUE'] = '20111225'
23
+ tests << [vtodo3, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
24
+ tests << [vtodo3, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
25
+
26
+ vtodo4 = calendar.create_component('VTODO')
27
+ vtodo4['DUE'] = '20111225'
28
+ tests << [vtodo4, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
29
+ tests << [vtodo4, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
30
+
31
+ vtodo5 = calendar.create_component('VTODO')
32
+ vtodo5['COMPLETED'] = '20111225'
33
+ tests << [vtodo5, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
34
+ tests << [vtodo5, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
35
+
36
+ vtodo6 = calendar.create_component('VTODO')
37
+ vtodo6['CREATED'] = '20111225'
38
+ tests << [vtodo6, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
39
+ tests << [vtodo6, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
40
+
41
+ vtodo7 = calendar.create_component('VTODO')
42
+ vtodo7['CREATED'] = '20111225'
43
+ vtodo7['COMPLETED'] = '20111226'
44
+ tests << [vtodo7, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
45
+ tests << [vtodo7, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), false]
46
+
47
+ vtodo7 = calendar.create_component('VTODO')
48
+ tests << [vtodo7, Time.zone.parse('2011-01-01'), Time.zone.parse('2012-01-01'), true]
49
+ tests << [vtodo7, Time.zone.parse('2011-01-01'), Time.zone.parse('2011-11-01'), true]
50
+
51
+ tests
52
+ end
53
+
54
+ def test_in_time_range
55
+ time_range_test_data.each do |data|
56
+ (vtodo, start, ending, outcome) = data
57
+ assert_equal(outcome, vtodo.in_time_range?(start, ending))
58
+ end
59
+ end
60
+
61
+ def test_validate
62
+ input = <<HI
63
+ BEGIN:VCALENDAR
64
+ VERSION:2.0
65
+ PRODID:YoYo
66
+ BEGIN:VTODO
67
+ UID:1234-21355-123156
68
+ DTSTAMP:20140402T183400Z
69
+ END:VTODO
70
+ END:VCALENDAR
71
+ HI
72
+
73
+ obj = Tilia::VObject::Reader.read(input)
74
+
75
+ warnings = obj.validate
76
+ messages = []
77
+ warnings.each do |warning|
78
+ messages << warning['message']
79
+ end
80
+
81
+ assert_equal([], messages)
82
+ end
83
+
84
+ def test_validate_invalid
85
+ input = <<HI
86
+ BEGIN:VCALENDAR
87
+ VERSION:2.0
88
+ PRODID:YoYo
89
+ BEGIN:VTODO
90
+ END:VTODO
91
+ END:VCALENDAR
92
+ HI
93
+
94
+ obj = Tilia::VObject::Reader.read(input)
95
+
96
+ warnings = obj.validate
97
+ messages = []
98
+ warnings.each do |warning|
99
+ messages << warning['message']
100
+ end
101
+
102
+ assert_equal(
103
+ [
104
+ 'UID MUST appear exactly once in a VTODO component',
105
+ 'DTSTAMP MUST appear exactly once in a VTODO component'
106
+ ],
107
+ messages
108
+ )
109
+ end
110
+
111
+ def test_validate_duedtstart_mis_match
112
+ input = <<HI
113
+ BEGIN:VCALENDAR
114
+ VERSION:2.0
115
+ PRODID:YoYo
116
+ BEGIN:VTODO
117
+ UID:FOO
118
+ DTSTART;VALUE=DATE-TIME:20140520T131600Z
119
+ DUE;VALUE=DATE:20140520
120
+ DTSTAMP;VALUE=DATE-TIME:20140520T131600Z
121
+ END:VTODO
122
+ END:VCALENDAR
123
+ HI
124
+
125
+ obj = Tilia::VObject::Reader.read(input)
126
+
127
+ warnings = obj.validate
128
+ messages = []
129
+ warnings.each do |warning|
130
+ messages << warning['message']
131
+ end
132
+
133
+ assert_equal(
134
+ [
135
+ 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART'
136
+ ],
137
+ messages
138
+ )
139
+ end
140
+
141
+ def test_validate_du_ebefore_dtstart
142
+ input = <<HI
143
+ BEGIN:VCALENDAR
144
+ VERSION:2.0
145
+ PRODID:YoYo
146
+ BEGIN:VTODO
147
+ UID:FOO
148
+ DTSTART;VALUE=DATE:20140520
149
+ DUE;VALUE=DATE:20140518
150
+ DTSTAMP;VALUE=DATE-TIME:20140520T131600Z
151
+ END:VTODO
152
+ END:VCALENDAR
153
+ HI
154
+
155
+ obj = Tilia::VObject::Reader.read(input)
156
+
157
+ warnings = obj.validate
158
+ messages = []
159
+ warnings.each do |warning|
160
+ messages << warning['message']
161
+ end
162
+
163
+ assert_equal(
164
+ [
165
+ 'DUE must occur after DTSTART'
166
+ ],
167
+ messages
168
+ )
169
+ end
170
+ end
171
+ end
172
+ end