vpim 0.619 → 0.658
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +60 -0
- data/README +37 -30
- data/bin/reminder +1 -1
- data/lib/atom.rb +728 -0
- data/lib/atom/pub.rb +206 -0
- data/lib/atom/version.rb +9 -0
- data/lib/atom/xml/parser.rb +305 -0
- data/lib/plist.rb +22 -0
- data/lib/plist/generator.rb +224 -0
- data/lib/plist/parser.rb +225 -0
- data/lib/vpim/date.rb +1 -1
- data/lib/vpim/enumerator.rb +6 -1
- data/lib/vpim/field.rb +1 -0
- data/lib/vpim/icalendar.rb +74 -29
- data/lib/vpim/property/base.rb +31 -1
- data/lib/vpim/property/common.rb +13 -13
- data/lib/vpim/property/recurrence.rb +30 -14
- data/lib/vpim/repo.rb +120 -55
- data/lib/vpim/rfc2425.rb +5 -4
- data/lib/vpim/rrule.rb +70 -7
- data/lib/vpim/vcard.rb +26 -2
- data/lib/vpim/version.rb +2 -2
- data/lib/vpim/vevent.rb +33 -51
- data/lib/vpim/view.rb +90 -0
- data/lib/vpim/vjournal.rb +12 -0
- data/lib/vpim/vpim.rb +1 -1
- data/lib/vpim/vtodo.rb +11 -2
- data/samples/reminder.rb +1 -1
- data/test/test_all.rb +10 -7
- data/test/test_date.rb +2 -2
- data/test/test_ical.rb +199 -4
- data/test/test_repo.rb +158 -0
- data/test/test_rrule.rb +51 -0
- data/test/test_vcard.rb +129 -0
- data/test/test_view.rb +79 -0
- metadata +16 -12
data/samples/reminder.rb
CHANGED
@@ -118,7 +118,7 @@ end
|
|
118
118
|
puts
|
119
119
|
|
120
120
|
def start_of_first_occurrence(t0, t1, e)
|
121
|
-
e.occurrences
|
121
|
+
e.occurrences(t1) do |t|
|
122
122
|
# An event might start before t0, but end after it..., in which case
|
123
123
|
# we are still interested.
|
124
124
|
if (t + (e.duration || 0)) >= t0
|
data/test/test_all.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'pp'
|
4
|
+
|
3
5
|
$-w = true
|
4
|
-
|
6
|
+
|
7
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
8
|
+
|
9
|
+
|
10
|
+
pp [__LINE__, $:, $"]
|
5
11
|
|
6
12
|
require 'test/unit'
|
7
13
|
|
8
|
-
|
9
|
-
require
|
10
|
-
|
11
|
-
require 'test_ical.rb'
|
12
|
-
require 'test_rrule.rb'
|
13
|
-
require 'test_vcard.rb'
|
14
|
+
Dir[File.dirname(__FILE__) + "/test_*.rb"].each do |test|
|
15
|
+
require test unless test =~ /test_all/
|
16
|
+
end
|
14
17
|
|
data/test/test_date.rb
CHANGED
@@ -8,8 +8,8 @@ class TestVpimDate < Test::Unit::TestCase
|
|
8
8
|
|
9
9
|
def test_to_time
|
10
10
|
# Need to test with DateTime, but I don't have that with ruby 1.6.
|
11
|
-
assert_equal(Time.at(0), Date.new(1970, 1, 1).
|
12
|
-
assert_equal(Time.at(24 * 60 * 60), Date.new(1970, 1, 2).
|
11
|
+
assert_equal(Time.at(0), Date.new(1970, 1, 1).vpim_to_time)
|
12
|
+
assert_equal(Time.at(24 * 60 * 60), Date.new(1970, 1, 2).vpim_to_time)
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_date_weekstart
|
data/test/test_ical.rb
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
require 'vpim/icalendar'
|
4
4
|
require 'test/unit'
|
5
5
|
|
6
|
+
|
7
|
+
# Sorry for the donkey patching...
|
8
|
+
module Enumerable
|
9
|
+
def first
|
10
|
+
find{true}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
include Vpim
|
7
15
|
|
8
16
|
Req_1 =<<___
|
@@ -86,6 +94,10 @@ ___
|
|
86
94
|
|
87
95
|
class TestIcal < Test::Unit::TestCase
|
88
96
|
|
97
|
+
def assert_time(expected, actual, msg = nil)
|
98
|
+
assert_in_delta(expected, actual, 1, msg)
|
99
|
+
end
|
100
|
+
|
89
101
|
# Reported by Kyle Maxwell
|
90
102
|
def test_serialize_todo
|
91
103
|
icstodo =<<___
|
@@ -171,10 +183,12 @@ ___
|
|
171
183
|
|
172
184
|
# FIXME - test bad durations, like 'PT1D'
|
173
185
|
|
174
|
-
def
|
175
|
-
|
176
|
-
|
177
|
-
|
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)
|
178
192
|
|
179
193
|
event = Icalendar::Vevent.create(Date.new(2000, 1, 21),
|
180
194
|
'DURATION' => 'PT1H')
|
@@ -185,6 +199,33 @@ ___
|
|
185
199
|
assert_equal(24*60*60, event.duration)
|
186
200
|
end
|
187
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
|
+
|
188
229
|
def test_decode_duration_four_weeks
|
189
230
|
assert_equal 4*7*86400, Icalendar.decode_duration('P4W')
|
190
231
|
end
|
@@ -216,5 +257,159 @@ ___
|
|
216
257
|
def test_decode_duration_with_composite_duration
|
217
258
|
assert_equal((15*86400+5*3600+20), Icalendar.decode_duration('P15DT5H0M20S'))
|
218
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
|
+
|
219
414
|
end
|
220
415
|
|
data/test/test_repo.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'vpim/repo'
|
4
|
+
require 'vpim/agent/calendars'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
module Enumerable
|
10
|
+
def count
|
11
|
+
self.inject(0){|i,_| i + 1}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestRepo < Test::Unit::TestCase
|
16
|
+
Apple3 = Vpim::Repo::Apple3
|
17
|
+
Directory = Vpim::Repo::Directory
|
18
|
+
Agent = Vpim::Agent
|
19
|
+
Path = Agent::Path
|
20
|
+
NotFound = Agent::NotFound
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@testdir = Dir.getwd + "/test" #File.dirname($0) doesn't work with rcov :-(
|
24
|
+
@caldir = @testdir + "/calendars"
|
25
|
+
@eventsz = Dir[@caldir + "/**/*.ics"].size
|
26
|
+
assert(@testdir)
|
27
|
+
assert(test(?d, @caldir), "no caldir "+@caldir)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _test_each(repo, eventsz)
|
31
|
+
repo.each do |cal|
|
32
|
+
assert_equal(eventsz, cal.events.count, cal.name)
|
33
|
+
assert("", File.extname(cal.name))
|
34
|
+
assert_equal(cal.displayed, true)
|
35
|
+
cal.events do |c|
|
36
|
+
assert_instance_of(Vpim::Icalendar::Vevent, c)
|
37
|
+
end
|
38
|
+
cal.events.each do |c|
|
39
|
+
assert_instance_of(Vpim::Icalendar::Vevent, c)
|
40
|
+
end
|
41
|
+
assert_equal(0, cal.todos.count)
|
42
|
+
assert(cal.encode)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_apple3
|
47
|
+
repo = Apple3.new(@caldir)
|
48
|
+
|
49
|
+
assert_equal(1, repo.count)
|
50
|
+
|
51
|
+
_test_each(repo, @eventsz)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_dir
|
55
|
+
assert(test(?d, @caldir))
|
56
|
+
|
57
|
+
repo = Directory.new(@caldir)
|
58
|
+
|
59
|
+
assert_equal(@eventsz, repo.count)
|
60
|
+
|
61
|
+
_test_each(repo, 1)
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_is_text_calendar(text)
|
65
|
+
lines = text.split("\n")
|
66
|
+
lines = lines.first, lines.last
|
67
|
+
assert_equal("BEGIN:VCALENDAR", lines.first.upcase, lines)
|
68
|
+
assert_equal("END:VCALENDAR", lines.last.upcase, lines)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_agent_calendars
|
72
|
+
repo = Apple3.new(@caldir)
|
73
|
+
rest = Agent::Calendars.new(repo)
|
74
|
+
|
75
|
+
out1, form = rest.get(Path.new("http://host/here", "/here"))
|
76
|
+
assert_equal("text/html", form)
|
77
|
+
#puts(out1)
|
78
|
+
|
79
|
+
out1, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth", "/here"))
|
80
|
+
assert_equal("text/html", form)
|
81
|
+
#puts(out1)
|
82
|
+
|
83
|
+
out2, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth/calendar", "/here"))
|
84
|
+
assert_equal("text/calendar", form)
|
85
|
+
assert_is_text_calendar(out2)
|
86
|
+
|
87
|
+
#assert_equal(out1, out2)
|
88
|
+
|
89
|
+
assert_raise(Vpim::Agent::NotFound) do
|
90
|
+
rest.get(Path.new("http://host/here/weather%2fLeavenworth/an_unknown_protocol", "/here"))
|
91
|
+
end
|
92
|
+
assert_raise(Vpim::Agent::NotFound) do
|
93
|
+
rest.get(Path.new("http://host/here/no_such_calendar", "/here"))
|
94
|
+
end
|
95
|
+
|
96
|
+
assert_equal(["","/","/"], Vpim::Agent::Path.split_path("/%2F/%2F"))
|
97
|
+
assert_equal(["/","/"], Vpim::Agent::Path.split_path("%2F/%2F"))
|
98
|
+
assert_equal(["calendars", "weather/Leavenworth"],
|
99
|
+
Vpim::Agent::Path.split_path("calendars/weather%2FLeavenworth"))
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_agent_calendar_atom
|
103
|
+
repo = Apple3.new(@caldir)
|
104
|
+
rest = Agent::Calendars.new(repo)
|
105
|
+
|
106
|
+
out, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth/atom", "/here"))
|
107
|
+
assert_equal("application/atom+xml", form)
|
108
|
+
#pp out
|
109
|
+
#assert_is_atom(out)
|
110
|
+
end
|
111
|
+
|
112
|
+
def _test_path_shift(url, shifts)
|
113
|
+
# last shift should be a nil
|
114
|
+
shifts << nil
|
115
|
+
|
116
|
+
# presence or absence of a trailing / should not affect shifting
|
117
|
+
["", "/"].each do |trailer|
|
118
|
+
path = Path.new(url + trailer)
|
119
|
+
shifts.each do |_|
|
120
|
+
assert_equal(_, path.shift)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_path_shift
|
126
|
+
_test_path_shift("http://host.ex", [])
|
127
|
+
_test_path_shift("http://host.ex/a", ["a"])
|
128
|
+
_test_path_shift("http://host.ex/a/b", ["a", "b"])
|
129
|
+
_test_path_shift("http://host.ex/a/b/c", ["a", "b", "c"])
|
130
|
+
end
|
131
|
+
|
132
|
+
def _test_path_prefix(base, parts, shifts, prefix)
|
133
|
+
path = Path.new(base+parts.join("/"))
|
134
|
+
shifts.times{ path.shift }
|
135
|
+
assert_equal(prefix, path.prefix)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_path_prefix
|
139
|
+
_test_path_prefix("http://host.ex/", [], 0, "/")
|
140
|
+
_test_path_prefix("http://host.ex/", ["a"], 0, "/")
|
141
|
+
_test_path_prefix("http://host.ex/", ["a"], 1, "/")
|
142
|
+
_test_path_prefix("http://host.ex/", ["a"], 2, "/a/")
|
143
|
+
_test_path_prefix("http://host.ex/", ["a"], 3, "/a/")
|
144
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 0, "/")
|
145
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 1, "/")
|
146
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 2, "/a/")
|
147
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 3, "/a/b/")
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_atomize
|
151
|
+
repo = Apple3.new(@caldir)
|
152
|
+
cal = repo.find{true}
|
153
|
+
a = Vpim::Agent::Atomize.new(cal)
|
154
|
+
assert( a.get(Path.new("http://example.com/path")))
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
data/test/test_rrule.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
ENV['TZ'] = 'EST5EDT'
|
4
4
|
|
5
5
|
require 'vpim/rrule'
|
6
|
+
require 'vpim/icalendar'
|
6
7
|
require 'test/unit'
|
7
8
|
|
8
9
|
require 'pp'
|
@@ -14,6 +15,8 @@ end
|
|
14
15
|
=end
|
15
16
|
|
16
17
|
class TestRrule < Test::Unit::TestCase
|
18
|
+
Rrule = Vpim::Rrule
|
19
|
+
|
17
20
|
#=begin
|
18
21
|
# Comment out these if you want printing!
|
19
22
|
def puts(*args)
|
@@ -975,5 +978,53 @@ RRULE:FREQ=MONTHLY;BYMONTH=12;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYMONTHDAY=26,27,2
|
|
975
978
|
END:VEVENT
|
976
979
|
=end
|
977
980
|
|
981
|
+
|
982
|
+
def test_reccurrence_with_utc_dtstart
|
983
|
+
# Its wrong that the times yielded aren't in the timezone of DTSTART, but
|
984
|
+
# until vPim supports timezones, its the best it'll get.
|
985
|
+
txt = <<'__'
|
986
|
+
BEGIN:VCALENDAR
|
987
|
+
BEGIN:VEVENT
|
988
|
+
DTSTAMP:20080416T174954Z
|
989
|
+
ORGANIZER;CN=Anonymous:MAILTO:ano@nymo.us
|
990
|
+
CREATED:20080401T090904Z
|
991
|
+
LAST-MODIFIED:20080401T090904Z
|
992
|
+
SUMMARY:Very important recurring event
|
993
|
+
RRULE:FREQ=WEEKLY;UNTIL=20080415T093000Z;BYDAY=TU;BYHOUR=9
|
994
|
+
DTSTART:20080401T093000Z
|
995
|
+
DTEND:20080401T110000Z
|
996
|
+
TRANSP:OPAQUE
|
997
|
+
END:VEVENT
|
998
|
+
END:VCALENDAR
|
999
|
+
__
|
1000
|
+
cal = Vpim::Icalendar.decode(txt).first
|
1001
|
+
occurs = cal.events.to_a.first.occurrences.to_a
|
1002
|
+
#p occurs
|
1003
|
+
utc = occurs.map{|y| y.utc}
|
1004
|
+
#p utc
|
1005
|
+
expects = [
|
1006
|
+
Time.utc(2008, 4, 1, 9, 30),
|
1007
|
+
Time.utc(2008, 4, 8, 9, 30),
|
1008
|
+
Time.utc(2008, 4,15, 9, 30),
|
1009
|
+
]
|
1010
|
+
assert_equal(expects, utc)
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def test_maker
|
1014
|
+
assert_equal("FREQ=WEEKLY",
|
1015
|
+
Rrule::Maker.new{|m|m.frequency = "WEEKLY"}.encode)
|
1016
|
+
assert_equal("FREQ=WEEKLY;COUNT=2",
|
1017
|
+
Rrule::Maker.new{|m|m.frequency = "WEEKLY"; m.count = 2}.encode)
|
1018
|
+
assert_raises(ArgumentError) do
|
1019
|
+
Rrule::Maker.new{|m|m.count = 2; m.until = Time.now}
|
1020
|
+
end
|
1021
|
+
assert_raises(ArgumentError) do
|
1022
|
+
Rrule::Maker.new{|m|m.until = Time.now; m.count = 4}
|
1023
|
+
end
|
1024
|
+
assert_raises(ArgumentError) do
|
1025
|
+
Rrule::Maker.new.encode
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
|
978
1029
|
end
|
979
1030
|
|