vpim2 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +504 -0
  3. data/COPYING +58 -0
  4. data/README +182 -0
  5. data/lib/atom.rb +728 -0
  6. data/lib/plist.rb +22 -0
  7. data/lib/vpim.rb +13 -0
  8. data/lib/vpim/address.rb +219 -0
  9. data/lib/vpim/attachment.rb +102 -0
  10. data/lib/vpim/date.rb +222 -0
  11. data/lib/vpim/dirinfo.rb +277 -0
  12. data/lib/vpim/duration.rb +119 -0
  13. data/lib/vpim/enumerator.rb +32 -0
  14. data/lib/vpim/field.rb +614 -0
  15. data/lib/vpim/icalendar.rb +381 -0
  16. data/lib/vpim/maker/vcard.rb +16 -0
  17. data/lib/vpim/property/base.rb +193 -0
  18. data/lib/vpim/property/common.rb +315 -0
  19. data/lib/vpim/property/location.rb +38 -0
  20. data/lib/vpim/property/priority.rb +43 -0
  21. data/lib/vpim/property/recurrence.rb +69 -0
  22. data/lib/vpim/property/resources.rb +24 -0
  23. data/lib/vpim/repo.rb +181 -0
  24. data/lib/vpim/rfc2425.rb +367 -0
  25. data/lib/vpim/rrule.rb +591 -0
  26. data/lib/vpim/vcard.rb +1430 -0
  27. data/lib/vpim/version.rb +18 -0
  28. data/lib/vpim/vevent.rb +187 -0
  29. data/lib/vpim/view.rb +90 -0
  30. data/lib/vpim/vjournal.rb +58 -0
  31. data/lib/vpim/vpim.rb +65 -0
  32. data/lib/vpim/vtodo.rb +103 -0
  33. data/samples/README.mutt +93 -0
  34. data/samples/ab-query.rb +57 -0
  35. data/samples/cmd-itip.rb +156 -0
  36. data/samples/ex_cpvcard.rb +55 -0
  37. data/samples/ex_get_vcard_photo.rb +22 -0
  38. data/samples/ex_mkv21vcard.rb +34 -0
  39. data/samples/ex_mkvcard.rb +64 -0
  40. data/samples/ex_mkyourown.rb +29 -0
  41. data/samples/ics-dump.rb +210 -0
  42. data/samples/ics-to-rss.rb +84 -0
  43. data/samples/mutt-aliases-to-vcf.rb +45 -0
  44. data/samples/osx-wrappers.rb +86 -0
  45. data/samples/reminder.rb +203 -0
  46. data/samples/rrule.rb +71 -0
  47. data/samples/tabbed-file-to-vcf.rb +390 -0
  48. data/samples/vcf-dump.rb +86 -0
  49. data/samples/vcf-lines.rb +61 -0
  50. data/samples/vcf-to-ics.rb +22 -0
  51. data/samples/vcf-to-mutt.rb +121 -0
  52. data/test/test_all.rb +17 -0
  53. data/test/test_date.rb +120 -0
  54. data/test/test_dur.rb +41 -0
  55. data/test/test_field.rb +156 -0
  56. data/test/test_ical.rb +415 -0
  57. data/test/test_repo.rb +158 -0
  58. data/test/test_rrule.rb +1030 -0
  59. data/test/test_vcard.rb +973 -0
  60. data/test/test_view.rb +79 -0
  61. metadata +117 -0
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'pp'
5
+ require 'vpim/field'
6
+
7
+ Field=Vpim::DirectoryInfo::Field
8
+
9
+ class TestField < Test::Unit::TestCase
10
+
11
+ def test_encode_decode_text()
12
+ enc_in = "+\\\\+\\n+\\N+\\,+\\;+\\a+\\b+\\c+"
13
+ dec = Vpim.decode_text(enc_in)
14
+ #puts("<#{enc_in}> => <#{dec}>")
15
+ assert_equal("+\\+\n+\n+,+;+a+b+c+", dec)
16
+ enc_out = Vpim.encode_text(dec)
17
+ should_be = "+\\\\+\\n+\\n+\\,+\\;+a+b+c+"
18
+ # Note a, b, and c are allowed to be escaped, but shouldn't be and
19
+ # aren't in output
20
+ #puts("<#{dec}> => <#{enc_out}>")
21
+ assert_equal(should_be, enc_out)
22
+
23
+ end
24
+
25
+ def test_field4
26
+ line = 't;e=a,b: 4 '
27
+ part = Field.decode0(line)
28
+ assert_equal("4", part[ 3 ])
29
+ end
30
+
31
+ def test_field3
32
+ line = 't;e=a,b:4'
33
+ part = Field.decode0(line)
34
+ assert_equal("4", part[ 3 ])
35
+ assert_equal( {'E' => [ 'a','b' ] }, part[ 2 ])
36
+ end
37
+
38
+ def test_field2
39
+ line = 'tel;type=work,voice,msg:+1 313 747-4454'
40
+ part = Field.decode0(line)
41
+ assert_equal("+1 313 747-4454", part[ 3 ])
42
+ assert_equal( {'TYPE' => [ 'work','voice','msg' ] }, part[ 2 ])
43
+ end
44
+
45
+ def test_field1
46
+ line = 'ORGANIZER;CN="xxxx, xxxx [SC100:370:EXCH]":MAILTO:xxxx@americasm01.nt.com'
47
+ parts = Field.decode0(line)
48
+
49
+ assert_equal(nil, parts[0])
50
+ assert_equal('ORGANIZER', parts[1])
51
+ assert_equal({ 'CN' => [ "xxxx, xxxx [SC100:370:EXCH]" ] }, parts[2])
52
+ assert_equal('MAILTO:xxxx@americasm01.nt.com', parts[3])
53
+ end
54
+
55
+ =begin this can not be done :-(
56
+ def test_case_equiv
57
+ line = 'ORGANIZER;CN="xxxx, xxxx [SC100:370:EXCH]":MAILTO:xxxx@americasm01.nt.com'
58
+ field = Field.decode(line)
59
+ assert_equal(true, field.name?('organIZER'))
60
+ assert_equal(true, field === 'organIZER')
61
+
62
+ b = nil
63
+ case field
64
+ when 'organIZER'
65
+ b = true
66
+ end
67
+
68
+ assert_equal(true, b)
69
+ end
70
+ =end
71
+
72
+ def test_field0
73
+ assert_equal('name:', line = Field.encode0(nil, 'name'))
74
+ assert_equal([ nil, 'NAME', {}, ''], Field.decode0(line))
75
+
76
+ assert_equal('name:value', line = Field.encode0(nil, 'name', {}, 'value'))
77
+ assert_equal([ nil, 'NAME', {}, 'value'], Field.decode0(line))
78
+
79
+ assert_equal('name;encoding=B:dmFsdWU=', line = Field.encode0(nil, 'name', { 'encoding'=>:b64 }, 'value'))
80
+ assert_equal([ nil, 'NAME', { 'ENCODING'=>['B']}, ['value'].pack('m').chomp ], Field.decode0(line))
81
+
82
+ assert_equal('group.name:value', line = Field.encode0('group', 'name', {}, 'value'))
83
+ assert_equal([ 'GROUP', 'NAME', {}, 'value'], Field.decode0(line))
84
+ end
85
+
86
+ def tEst_invalid_fields
87
+ [
88
+ 'g.:',
89
+ ':v',
90
+ ].each do |line|
91
+ assert_raises(Vpim::InvalidEncodingError) { Field.decode0(line) }
92
+ end
93
+ end
94
+
95
+ def test_date_encode
96
+ assert_equal("DTSTART:20040101\n", Field.create('DTSTART', Date.new(2004, 1, 1) ).to_s)
97
+ assert_equal("DTSTART:20040101\n", Field.create('DTSTART', [Date.new(2004, 1, 1)]).to_s)
98
+ end
99
+
100
+ def test_field_modify
101
+ f = Field.create('name')
102
+
103
+ assert_equal('', f.value)
104
+ f.value = ''
105
+ assert_equal('', f.value)
106
+ f.value = 'z'
107
+ assert_equal('z', f.value)
108
+
109
+ f.group = 'z.b'
110
+ assert_equal('Z.B', f.group)
111
+ assert_equal("z.b.NAME:z\n", f.encode)
112
+
113
+ assert_raises(TypeError) { f.value = :group }
114
+
115
+ assert_equal('Z.B', f.group)
116
+
117
+ assert_equal("z.b.NAME:z\n", f.encode)
118
+
119
+ assert_raises(TypeError) { f.group = :group }
120
+
121
+ assert_equal("z.b.NAME:z\n", f.encode)
122
+ assert_equal('Z.B', f.group)
123
+
124
+ f['p0'] = "hi julie"
125
+
126
+ assert_equal("Z.B.NAME;P0=hi julie:z\n", f.encode)
127
+ assert_equal(['hi julie'], f.param('p0'))
128
+ assert_equal(['hi julie'], f['p0'])
129
+ assert_equal('NAME', f.name)
130
+ assert_equal('Z.B', f.group)
131
+
132
+ # FAIL assert_raises(ArgumentError) { f.group = 'z.b:' }
133
+
134
+ assert_equal('Z.B', f.group)
135
+
136
+ f.value = 'some text'
137
+
138
+ assert_equal('some text', f.value)
139
+ assert_equal('some text', f.value_raw)
140
+
141
+ f['encoding'] = :b64
142
+
143
+ assert_equal('some text', f.value)
144
+ assert_equal([ 'some text' ].pack('m*').chomp, f.value_raw)
145
+ end
146
+
147
+ def test_field_wrapping
148
+ assert_equal("0:x\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 1).encode(4))
149
+ assert_equal("0:xx\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 2).encode(4))
150
+ assert_equal("0:xx\n x\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 3).encode(4))
151
+ assert_equal("0:xx\n xx\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 4).encode(4))
152
+ assert_equal("0:xx\n xxxx\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 6).encode(4))
153
+ assert_equal("0:xx\n xxxx\n x\n", Vpim::DirectoryInfo::Field.create('0', 'x' * 7).encode(4))
154
+ end
155
+ end
156
+
data/test/test_ical.rb ADDED
@@ -0,0 +1,415 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'vpim/icalendar'
4
+ require 'test/unit'
5
+
6
+
7
+ # Sorry for the donkey patching...
8
+ module Enumerable
9
+ def first
10
+ find{true}
11
+ end
12
+ end
13
+
14
+ include Vpim
15
+
16
+ Req_1 =<<___
17
+ BEGIN:VCALENDAR
18
+ METHOD:REQUEST
19
+ PRODID:-//Lotus Development Corporation//NONSGML Notes 6.0//EN
20
+ VERSION:2.0
21
+ X-LOTUS-CHARSET:UTF-8
22
+ BEGIN:VTIMEZONE
23
+ TZID:Pacific
24
+ BEGIN:STANDARD
25
+ DTSTART:19501029T020000
26
+ TZOFFSETFROM:-0700
27
+ TZOFFSETTO:-0800
28
+ RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10
29
+ END:STANDARD
30
+ BEGIN:DAYLIGHT
31
+ DTSTART:19500402T020000
32
+ TZOFFSETFROM:-0800
33
+ TZOFFSETTO:-0700
34
+ RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=1SU;BYMONTH=4
35
+ END:DAYLIGHT
36
+ END:VTIMEZONE
37
+ BEGIN:VEVENT
38
+ ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN="Gary Pope/Certicom"
39
+ ;RSVP=FALSE:mailto:gpope@certicom.com
40
+ ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION
41
+ ;CN="Mike Harvey/Certicom";RSVP=TRUE:mailto:MHarvey@certicom.com
42
+ ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE
43
+ :mailto:rgallant@emilpost.certicom.com
44
+ ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION
45
+ ;CN="Sam Roberts/Certicom";RSVP=TRUE:mailto:SRoberts@certicom.com
46
+ ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION
47
+ ;CN="Tony Walters/Certicom";RSVP=TRUE:mailto:TWalters@certicom.com
48
+ CLASS:PUBLIC
49
+ DTEND;TZID="Pacific":20040415T130000
50
+ DTSTAMP:20040319T205045Z
51
+ DTSTART;TZID="Pacific":20040415T120000
52
+ ORGANIZER;CN="Gary Pope/Certicom":mailto:gpope@certicom.com
53
+ SEQUENCE:0
54
+ SUMMARY:hjold intyel
55
+ TRANSP:OPAQUE
56
+ UID:3E19204063C93D2388256E5C006BF8D9-Lotus_Notes_Generated
57
+ X-LOTUS-BROADCAST:FALSE
58
+ X-LOTUS-CHILD_UID:3E19204063C93D2388256E5C006BF8D9
59
+ X-LOTUS-NOTESVERSION:2
60
+ X-LOTUS-NOTICETYPE:I
61
+ X-LOTUS-UPDATE-SEQ:1
62
+ X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1
63
+ END:VEVENT
64
+ END:VCALENDAR
65
+ ___
66
+
67
+ Rep_1 =<<___
68
+ BEGIN:VCALENDAR
69
+ CALSCALE:GREGORIAN
70
+ PRODID:-//Apple Computer\, Inc//iCal 1.5//EN
71
+ VERSION:2.0
72
+ METHOD:REPLY
73
+ BEGIN:VEVENT
74
+ ATTENDEE;CN="Sam Roberts/Certicom";PARTSTAT=ACCEPTED;ROLE=REQ-PARTICIPAN
75
+ T;RSVP=TRUE:mailto:SRoberts@certicom.com
76
+ CLASS:PUBLIC
77
+ DTEND;TZID=Pacific:20040415T130000
78
+ DTSTAMP:20040319T205045Z
79
+ DTSTART;TZID=Pacific:20040415T120000
80
+ ORGANIZER;CN="Gary Pope/Certicom":mailto:gpope@certicom.com
81
+ SEQUENCE:0
82
+ SUMMARY:hjold intyel
83
+ TRANSP:OPAQUE
84
+ UID:3E19204063C93D2388256E5C006BF8D9-Lotus_Notes_Generated
85
+ X-LOTUS-BROADCAST:FALSE
86
+ X-LOTUS-CHILDUID:3E19204063C93D2388256E5C006BF8D9
87
+ X-LOTUS-NOTESVERSION:2
88
+ X-LOTUS-NOTICETYPE:I
89
+ X-LOTUS-UPDATE-SEQ:1
90
+ X-LOTUS-UPDATE-WISL:$S:1\;$L:1\;$B:1\;$R:1\;$E:1
91
+ END:VEVENT
92
+ END:VCALENDAR
93
+ ___
94
+
95
+ class TestIcal < Test::Unit::TestCase
96
+
97
+ def assert_time(expected, actual, msg = nil)
98
+ assert_in_delta(expected, actual, 1, msg)
99
+ end
100
+
101
+ # Reported by Kyle Maxwell
102
+ def test_serialize_todo
103
+ icstodo =<<___
104
+ BEGIN:VCALENDAR
105
+ VERSION:2.0
106
+ BEGIN:VTODO
107
+ END:VTODO
108
+ END:VCALENDAR
109
+ ___
110
+
111
+ cal = Icalendar.decode(icstodo)
112
+ assert_equal(icstodo, cal.to_s)
113
+ end
114
+
115
+ # Tracker #18920
116
+ def test_recurring_todos
117
+ icstodo =<<___
118
+ BEGIN:VCALENDAR
119
+ VERSION:2.0
120
+ BEGIN:VTODO
121
+ SUMMARY:todo
122
+ DTSTART:20040415T120000
123
+ RRULE:FREQ=WEEKLY;COUNT=2
124
+ END:VTODO
125
+ END:VCALENDAR
126
+ ___
127
+
128
+ cal = Icalendar.decode(icstodo).first
129
+ todo = cal.todos.first
130
+ assert(todo)
131
+ assert_equal(todo.occurrences.to_a.size, 2)
132
+ end
133
+
134
+ def test_1
135
+ req = Icalendar.decode(Req_1).first
136
+
137
+ req.components { }
138
+ req.components(Icalendar::Vevent) { }
139
+ req.components(Icalendar::Vjournal) { }
140
+ assert_equal(1, req.components.size)
141
+ assert_equal(1, req.components(Icalendar::Vevent).size)
142
+ assert_equal(0, req.components(Icalendar::Vjournal).size)
143
+
144
+ assert_equal(req.protocol, 'REQUEST')
145
+
146
+ event = req.events.first
147
+
148
+ assert(event)
149
+
150
+ assert( event.attendee?('mailto:sroberts@certicom.com'))
151
+ assert(!event.attendee?('mailto:sroberts@uniserve.com'))
152
+
153
+ me = event.attendees('mailto:sroberts@certicom.com').first
154
+
155
+ assert(me)
156
+ assert(me == 'mailto:sroberts@certicom.com')
157
+
158
+ reply = Icalendar.create_reply
159
+
160
+ reply.push(event.accept(me))
161
+
162
+ # puts "Reply=>"
163
+ # puts reply.to_s
164
+ end
165
+
166
+ def test_hal1
167
+ # Hal was encoding raw strings, here's how to do it with the API.
168
+
169
+ cal = Icalendar.create
170
+
171
+ start = Time.now
172
+
173
+ event = Icalendar::Vevent.create(start,
174
+ 'DTEND' => start + 60 * 60,
175
+ 'SUMMARY' => "this is an event",
176
+ 'RRULE' => 'freq=monthly;byday=2fr,4fr;count=5'
177
+ )
178
+
179
+ cal.push event
180
+
181
+ #puts cal.encode
182
+ end
183
+
184
+ # FIXME - test bad durations, like 'PT1D'
185
+
186
+ def test_event_duration
187
+ now = Time.now
188
+ event = Icalendar::Vevent.create(now)
189
+ assert_time(now, event.dtstart)
190
+ assert_nil(event.duration)
191
+ assert_nil(event.dtend)
192
+
193
+ event = Icalendar::Vevent.create(Date.new(2000, 1, 21),
194
+ 'DURATION' => 'PT1H')
195
+ assert_equal(Time.gm(2000, 1, 21, 1), event.dtend)
196
+
197
+ event = Icalendar::Vevent.create(Date.new(2000, 1, 21),
198
+ 'DTEND' => Date.new(2000, 1, 22))
199
+ assert_equal(24*60*60, event.duration)
200
+ end
201
+
202
+ def test_todo_duration
203
+ todo = Icalendar::Vtodo.create()
204
+ assert_nil(todo.dtstart)
205
+ assert_nil(todo.duration)
206
+ assert_nil(todo.due)
207
+
208
+ todo = Icalendar::Vtodo.create('DTSTART' => Date.new(2000, 1, 21),
209
+ 'DURATION' => 'PT1H')
210
+ assert_equal(Time.gm(2000, 1, 21, 1), todo.due)
211
+
212
+ todo = Icalendar::Vtodo.create('DTSTART' => Date.new(2000, 1, 21),
213
+ 'DUE' => Date.new(2000, 1, 22))
214
+ assert_equal(24*60*60, todo.duration)
215
+ end
216
+
217
+ def test_journal_create
218
+ vj = Icalendar::Vjournal.create('DESCRIPTION' => "description")
219
+ assert_equal("description", vj.description)
220
+ end
221
+
222
+ def TODO_test_occurrence_with_date_start
223
+ d = Date.new(2000, 1, 21)
224
+ event = Icalendar::Vevent.create(d)
225
+ d1 = event.occurences.to_a.first
226
+ assert_equal(d.class, d1.class)
227
+ end
228
+
229
+ def test_decode_duration_four_weeks
230
+ assert_equal 4*7*86400, Icalendar.decode_duration('P4W')
231
+ end
232
+
233
+ def test_decode_duration_negative_two_weeks
234
+ assert_equal(-2*7*86400, Icalendar.decode_duration('-P2W'))
235
+ end
236
+
237
+ def test_decode_duration_five_days
238
+ assert_equal 5*86400, Icalendar.decode_duration('P5D')
239
+ end
240
+
241
+ def test_decode_duration_one_hour
242
+ assert_equal 3600, Icalendar.decode_duration('PT1H')
243
+ end
244
+
245
+ def test_decode_duration_five_minutes
246
+ assert_equal 5*60, Icalendar.decode_duration('PT5M')
247
+ end
248
+
249
+ def test_decode_duration_ten_seconds
250
+ assert_equal 10, Icalendar.decode_duration('PT10S')
251
+ end
252
+
253
+ def test_decode_duration_with_leading_plus
254
+ assert_equal 10, Icalendar.decode_duration('+PT10S')
255
+ end
256
+
257
+ def test_decode_duration_with_composite_duration
258
+ assert_equal((15*86400+5*3600+20), Icalendar.decode_duration('P15DT5H0M20S'))
259
+ end
260
+
261
+ def test_create_with_prodid
262
+ prodid = "me//here/non-sgml"
263
+ cal = Icalendar.create2(prodid) do |cal|
264
+ assert_respond_to(cal, :push)
265
+ end
266
+ assert_equal(prodid, cal.producer)
267
+ end
268
+
269
+ def test_occurences
270
+ t0 = Time.now
271
+ vc = Icalendar.create2 do |vc|
272
+ vc.add_event do |ve|
273
+ ve.dtstart t0
274
+ end
275
+ end
276
+ ve = vc.components(Icalendar::Vevent).first
277
+ assert_time(t0, ve.occurences.select{true}.first)
278
+ ve.occurences do |t|
279
+ assert_time(t0, t)
280
+ end
281
+
282
+ vc = Icalendar.decode(<<__).first
283
+ BEGIN:VCALENDAR
284
+ BEGIN:VEVENT
285
+ END:VEVENT
286
+ END:VCALENDAR
287
+ __
288
+ ve = vc.components(Icalendar::Vevent).first
289
+ assert_raises(ArgumentError) { ve.occurences }
290
+ end
291
+
292
+ def test_each
293
+ vc = Icalendar.decode(<<__).first
294
+ BEGIN:VCALENDAR
295
+ BEGIN:VEVENT
296
+ END:VEVENT
297
+ BEGIN:VTODO
298
+ END:VTODO
299
+ BEGIN:VJOURNAL
300
+ END:VJOURNAL
301
+ BEGIN:VTIMEZONE
302
+ END:VTIMEZONE
303
+ BEGIN:X-UNKNOWN
304
+ END:X-UNKNOWN
305
+ END:VCALENDAR
306
+ __
307
+ count = Hash.new(0)
308
+
309
+ vc.each do |c| count[c.class] += 1 end
310
+
311
+ assert_equal(3, count.size)
312
+ count.each do |_,v| assert_equal(1, v) end
313
+
314
+ count = Hash.new(0)
315
+ vc.events do |c| count[c.class] += 1 end
316
+ vc.todos do |c| count[c.class] += 1 end
317
+ vc.journals do |c| count[c.class] += 1 end
318
+ assert_equal(3, count.size)
319
+ count.each do |_,v| assert_equal(1, v) end
320
+
321
+ assert_equal(3, vc.each.to_a.size)
322
+ assert_equal(1, vc.each.select{|c| Vpim::Icalendar::Vevent === c}.size)
323
+ assert_equal(1, vc.each.select{|c| Vpim::Icalendar::Vtodo === c}.size)
324
+ assert_equal(1, vc.each.select{|c| Vpim::Icalendar::Vjournal === c}.size)
325
+
326
+ assert_equal(1, vc.events.to_a.size)
327
+ assert_equal(1, vc.todos.to_a.size)
328
+ assert_equal(1, vc.journals.to_a.size)
329
+
330
+ vc.to_s # Shouldn't raise...
331
+ # TODO - encode isn't round-tripping, unknown components are lost, which is
332
+ # not good.
333
+ end
334
+
335
+ def test_calscale
336
+ req = Icalendar.decode(<<__).first
337
+ BEGIN:VCALENDAR
338
+ END:VCALENDAR
339
+ __
340
+ assert_equal("GREGORIAN", req.calscale)
341
+ req = Icalendar.decode(<<__).first
342
+ BEGIN:VCALENDAR
343
+ CALSCALE:GREGORIAN
344
+ END:VCALENDAR
345
+ __
346
+ assert_equal("GREGORIAN", req.calscale)
347
+ end
348
+
349
+ def test_version
350
+ req = Icalendar.decode(<<__).first
351
+ BEGIN:VCALENDAR
352
+ END:VCALENDAR
353
+ __
354
+ assert_raises(InvalidEncodingError) { req.version }
355
+
356
+ req = Icalendar.decode(<<__).first
357
+ BEGIN:VCALENDAR
358
+ VERSION:2.0
359
+ END:VCALENDAR
360
+ __
361
+ assert_equal(20, req.version)
362
+ end
363
+
364
+ def test_protocol
365
+ req = Icalendar.decode(<<__).first
366
+ BEGIN:VCALENDAR
367
+ METHOD:GET
368
+ END:VCALENDAR
369
+ __
370
+ assert(req.protocol?("get"))
371
+ assert(!req.protocol?("set"))
372
+ end
373
+
374
+ def test_transparency
375
+ transparency = Icalendar.decode(<<__).first.to_a.first.transparency
376
+ BEGIN:VCALENDAR
377
+ BEGIN:VEVENT
378
+ END:VEVENT
379
+ END:VCALENDAR
380
+ __
381
+ assert_equal("OPAQUE", transparency, "check default")
382
+
383
+ transparency = Icalendar.decode(<<__).first.to_a.first.transparency
384
+ BEGIN:VCALENDAR
385
+ BEGIN:VEVENT
386
+ TRANSP:Opaque
387
+ END:VEVENT
388
+ END:VCALENDAR
389
+ __
390
+ assert_equal("OPAQUE", transparency, "check opaque")
391
+
392
+ transparency = Icalendar.decode(<<__).first.to_a.first.transparency
393
+ BEGIN:VCALENDAR
394
+ BEGIN:VEVENT
395
+ TRANSP:TrANSPARENT
396
+ END:VEVENT
397
+ END:VCALENDAR
398
+ __
399
+ assert_equal("TRANSPARENT", transparency, "check transparent")
400
+
401
+ end
402
+
403
+ def test_event_maker_w_rrule
404
+ vc = Icalendar.create2 do |vc|
405
+ vc.add_event do |m|
406
+ m.add_rrule("freq=monthly")
407
+ m.set_rrule do |_| _.frequency = "daily" end
408
+ end
409
+ end
410
+ assert_no_match(/RRULE:FREQ=MONTHLY/, vc.to_s)
411
+ assert_match(/RRULE:FREQ=DAILY/, vc.to_s)
412
+ end
413
+
414
+ end
415
+