cs210-gcal4ruby 0.5.8.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,302 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+
19
+ class Time
20
+
21
+ #Returns a ISO 8601 complete formatted string of the time
22
+ def complete
23
+ self.utc.strftime("%Y%m%dT%H%M%S")
24
+ end
25
+
26
+ def self.parse_complete(value)
27
+ unless value.nil? || value.empty?
28
+ if value.include?("T")
29
+ d, h = value.split("T")
30
+ return Time.parse(d+" "+h.to_s.gsub("Z", ""))
31
+ else
32
+ value = value.to_s
33
+ return Time.parse("#{value[0..3]}-#{value[4..5]}-#{value[6..7]}")
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ module GCal4Ruby
41
+ #The Recurrence class stores information on an Event's recurrence. The class implements
42
+ #the RFC 2445 iCalendar recurrence description.
43
+ class Recurrence
44
+ #The event start date/time
45
+ attr_reader :start_time
46
+ #The event end date/time
47
+ attr_reader :end_time
48
+ #the event reference
49
+ attr_reader :event
50
+ #The date until which the event will be repeated
51
+ attr_reader :repeat_until
52
+ #The event frequency
53
+ attr_reader :frequency
54
+ #True if the event is all day (i.e. no start/end time)
55
+ attr_accessor :all_day
56
+
57
+ #Accepts an optional attributes hash or a string containing a properly formatted ISO 8601 recurrence rule. Returns a new Recurrence object
58
+ def initialize(vars = {})
59
+ if vars.is_a? Hash
60
+ vars.each do |key, value|
61
+ self.send("#{key}=", value)
62
+ end
63
+ elsif vars.is_a? String
64
+ self.load(vars)
65
+ end
66
+ @all_day ||= false
67
+ end
68
+
69
+ #Accepts a string containing a properly formatted ISO 8601 recurrence rule and loads it into the recurrence object.
70
+ #Contributed by John Paul Narowski.
71
+ def load(rec)
72
+ @frequency = {}
73
+ attrs = rec.split("\n")
74
+ attrs.each do |val|
75
+ break if val == "BEGIN:VTIMEZONE" # Ignoring the time zone for now
76
+ key, value = val.split(":")
77
+ if key == 'RRULE'
78
+ args = {}
79
+ value.split(";").each do |rr|
80
+ rr_key, rr_value = rr.split("=")
81
+ rr_key = rr_key.downcase.to_sym
82
+ unless @frequency.has_key?(rr_key)
83
+ if rr_key == :until
84
+ @repeat_until = Time.parse_complete(rr_value)
85
+ else
86
+ args[rr_key] = rr_value
87
+ end
88
+ end
89
+ end
90
+ case args[:freq]
91
+ when 'DAILY'
92
+ @frequency['daily'] = true
93
+ when 'WEEKLY'
94
+ @frequency['weekly'] = args[:byday].split(',')
95
+ when 'MONTHLY'
96
+ if args[:byday]
97
+ @frequency['monthly'] = args[:byday]
98
+ @frequency[:day_of_week] = true
99
+ else
100
+ @frequency['monthly'] = args[:bymonthday].to_i
101
+ end
102
+ when 'YEARLY'
103
+ @frequency['yearly'] = args[:byyearday].to_i
104
+ end
105
+ elsif key == 'INTERVAL'
106
+ @frequency[:interval] = value.to_i unless value.nil? || value.empty?
107
+ elsif key.include?('DTSTART;VALUE=DATE')
108
+ @start_time ||= Time.parse(value)
109
+ @all_day = true
110
+ elsif key.include?("DTSTART;TZID") or key.include?("DTSTART") or key.include?('DTSTART;VALUE=DATE-TIME')
111
+ @start_time ||= Time.parse_complete(value)
112
+ elsif key.include?('DTEND;VALUE=DATE')
113
+ @end_time ||= Time.parse(value)
114
+ elsif key.include?("DTEND;TZID") or key.include?("DTEND") or key.include?('DTEND;VALUE=DATE-TIME')
115
+ @end_time ||= Time.parse_complete(value)
116
+ end
117
+ end
118
+ @frequency[:interval] = 1 unless @frequency[:interval] && @frequency[:interval].to_i > 0
119
+ end
120
+
121
+ def to_s
122
+ output = ''
123
+ if @frequency
124
+ f = ''
125
+ i = ''
126
+ by = ''
127
+ @frequency.each do |key, v|
128
+ key = key.to_s.downcase
129
+
130
+ if v.is_a?(Array)
131
+ if v.size > 0
132
+ value = v.join(",")
133
+ else
134
+ value = nil
135
+ end
136
+ else
137
+ value = v
138
+ end
139
+ f += "#{key}" if key != 'interval'
140
+ case key
141
+ when "secondly"
142
+ by += " every #{value} second"
143
+ when "minutely"
144
+ by += " every #{value} minute"
145
+ when "hourly"
146
+ by += " every #{value} hour"
147
+ when "weekly"
148
+ by += " on #{value}" if value
149
+ when "monthly"
150
+ by += " on #{value}"
151
+ when "yearly"
152
+ by += " on the #{value} day of the year"
153
+ when 'interval'
154
+ i += " for #{value} times"
155
+ end
156
+ end
157
+ output += f+i+by
158
+ end
159
+ if @repeat_until
160
+ output += " and repeats until #{@repeat_until.strftime("%m/%d/%Y")}"
161
+ end
162
+ output
163
+ end
164
+
165
+ #Returns a string with the correctly formatted ISO 8601 recurrence rule
166
+ def to_recurrence_string
167
+ output = ''
168
+ if @all_day
169
+ output += "DTSTART;VALUE=DATE:#{@start_time.utc.strftime("%Y%m%d")}\n"
170
+ else
171
+ output += "DTSTART;VALUE=DATE-TIME:#{@start_time.utc.complete}\n"
172
+ end
173
+ if @all_day
174
+ output += "DTEND;VALUE=DATE:#{@end_time.utc.strftime("%Y%m%d")}\n"
175
+ else
176
+ output += "DTEND;VALUE=DATE-TIME:#{@end_time.utc.complete}\n"
177
+ end
178
+ output += "RRULE:"
179
+ if @frequency
180
+ f = 'FREQ='
181
+ i = ''
182
+ by = ''
183
+ day_of_week = @frequency.delete(:day_of_week)
184
+ @frequency.each do |key, v|
185
+ if v.is_a?(Array)
186
+ if v.size > 0
187
+ value = v.join(",")
188
+ else
189
+ value = nil
190
+ end
191
+ else
192
+ value = v
193
+ end
194
+ f += "#{key.to_s.upcase};" if key.to_s.downcase != 'interval'
195
+ case key.to_s.downcase
196
+ when "secondly"
197
+ by += "BYSECOND=#{value};"
198
+ when "minutely"
199
+ by += "BYMINUTE=#{value};"
200
+ when "hourly"
201
+ by += "BYHOUR=#{value};"
202
+ when "weekly"
203
+ by += "BYDAY=#{value};" if value
204
+ when "monthly"
205
+ if day_of_week
206
+ by += "BYDAY=#{value};"
207
+ else
208
+ by += "BYMONTHDAY=#{value};"
209
+ end
210
+ when "yearly"
211
+ by += "BYYEARDAY=#{value};"
212
+ when 'interval'
213
+ i += "INTERVAL=#{value};"
214
+ end
215
+ end
216
+ output += f+by+i
217
+ end
218
+ if @repeat_until
219
+ output += "UNTIL=#{@repeat_until.strftime("%Y%m%d")}"
220
+ end
221
+ output += "\n"
222
+ end
223
+
224
+ #Sets the start date/time. Must be a Time object.
225
+ def start_time=(s)
226
+ if not s.is_a?(Time)
227
+ raise RecurrenceValueError, "Start must be a date or a time"
228
+ else
229
+ @start_time = s
230
+ end
231
+ end
232
+
233
+ #Sets the end Date/Time. Must be a Time object.
234
+ def end_time=(e)
235
+ if not e.is_a?(Time)
236
+ raise RecurrenceValueError, "End must be a date or a time"
237
+ else
238
+ @end_time = e
239
+ end
240
+ end
241
+
242
+ #Sets the parent event reference
243
+ def event=(e)
244
+ if not e.is_a?(Event)
245
+ raise RecurrenceValueError, "Event must be an event"
246
+ else
247
+ @event = e
248
+ end
249
+ end
250
+
251
+ #Sets the end date for the recurrence
252
+ def repeat_until=(r)
253
+ if not r.is_a?(Date)
254
+ raise RecurrenceValueError, "Repeat_until must be a date"
255
+ else
256
+ @repeat_until = r
257
+ end
258
+ end
259
+
260
+ #Sets the frequency of the recurrence. Should be a hash with one of
261
+ #"SECONDLY", "MINUTELY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" as the key,
262
+ #and as the value, an array containing zero to n of the following:
263
+ #- *Secondly*: A value between 0 and 59. Causes the event to repeat on that second of each minut.
264
+ #- *Minutely*: A value between 0 and 59. Causes the event to repeat on that minute of every hour.
265
+ #- *Hourly*: A value between 0 and 23. Causes the even to repeat on that hour of every day.
266
+ #- *Daily*: A true value - will cause the event to repeat every day until the repeat_until date.
267
+ #- *Weekly*: A value of the first two letters of a day of the week. Causes the event to repeat on that day.
268
+ #- *Monthly*: A value of a positive or negative integer (i.e. +1) prepended to a day-of-week string ('TU') to indicate the position of the day within the month. E.g. +1TU would be the first tuesday of the month.
269
+ #- *Yearly*: A value of 1 to 366 indicating the day of the year. May be negative to indicate counting down from the last day of the year.
270
+ #
271
+ #Optionally, you may specific a second hash pair to set the interval the event repeats:
272
+ # "interval" => '2'
273
+ #If the interval is missing, it is assumed to be 1.
274
+ #
275
+ #===Examples
276
+ #Repeat event daily
277
+ # frequency = {"daily" => true}
278
+ #
279
+ #Repeat event every Tuesday:
280
+ # frequency = {"weekly" => ["TU"]}
281
+ #
282
+ #Repeat every first monday of the month
283
+ # frequency = {"monthly" => "+1MO", :day_of_week => true}
284
+ #
285
+ #Repeat on the 9th of each month regardless of the day
286
+ # frequency = {"monthly" => 9}
287
+ #
288
+ #Repeat on the last day of every year
289
+ # frequency = {"Yearly" => 366}
290
+ #
291
+ #Repeat every other week on Friday
292
+ # frequency = {"Weekly" => ["FR"], "interval" => "2"}
293
+
294
+ def frequency=(f)
295
+ if f.is_a?(Hash)
296
+ @frequency = f
297
+ else
298
+ raise RecurrenceValueError, "Frequency must be a hash (see documentation)"
299
+ end
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,161 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby'
19
+ require 'gdata4ruby/gdata_object'
20
+ require 'gdata4ruby/utils/utils'
21
+ require 'gdata4ruby/acl/access_rule'
22
+ require 'gcal4ruby/calendar'
23
+ require 'gcal4ruby/event'
24
+ require 'gcal4ruby/recurrence'
25
+ require 'rexml/document'
26
+
27
+ module GCal4Ruby
28
+ #The service class is the main handler for all direct interactions with the
29
+ #Google Calendar API. A service represents a single user account. Each user
30
+ #account can have multiple calendars, so you'll need to find the calendar you
31
+ #want from the service, using the Calendar#find class method.
32
+ #=Usage
33
+ #
34
+ #1. Authenticate
35
+ # service = Service.new
36
+ # service.authenticate("user@gmail.com", "password")
37
+ #
38
+ #2. Get Calendar List
39
+ # calendars = service.calendars
40
+ #
41
+ #3. Get Calendar List that the authenticated user has owner access level to
42
+ # calendars = service.calendars(:only_owner_access_level => true)
43
+ #
44
+ class Service < GData4Ruby::Service
45
+
46
+ #Convenience attribute contains the currently authenticated account name
47
+ attr_reader :account
48
+
49
+ # The token returned by the Google servers, used to authorize all subsequent messages
50
+ attr_reader :auth_token
51
+
52
+ # Determines whether GCal4Ruby ensures a calendar is public. Setting this to false can increase speeds by
53
+ # 50% but can cause errors if you try to do something to a calendar that is not public and you don't have
54
+ # adequate permissions
55
+ attr_accessor :check_public
56
+
57
+ #Accepts an optional attributes hash for initialization values
58
+ def initialize(attributes = {})
59
+ super(attributes)
60
+ attributes.each do |key, value|
61
+ self.send("#{key}=", value)
62
+ end
63
+ @check_public ||= true
64
+ end
65
+
66
+ # The authenticate method passes the username and password to google servers.
67
+ # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
68
+ def authenticate(username, password, service='cl')
69
+ super(username, password, service)
70
+ end
71
+
72
+ #Helper function to reauthenticate to a new Google service without having to re-set credentials.
73
+ def reauthenticate(service='cl')
74
+ authenticate(@account, @password, service)
75
+ end
76
+
77
+ #Returns an array of Calendar objects for each calendar associated with
78
+ #the authenticated account. An optional hash of options is the only parameter. The
79
+ #available options are:
80
+ #*:only_owner_access_level*:: A boolean flag that specifies whether to return only the list of calendars that the authenticated user has owner access to.
81
+ def calendars(options={})
82
+ if not @auth_token
83
+ raise NotAuthenticated
84
+ end
85
+ feed_url = options[:only_owner_access_level] ? GCal4Ruby::Calendar::OWN_CALENDARS_FEED : GCal4Ruby::Calendar::ALL_CALENDARS_FEED
86
+ ret = send_request(GData4Ruby::Request.new(:get, feed_url, nil, {"max-results" => "10000"}))
87
+ cals = []
88
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
89
+ entry = GData4Ruby::Utils.add_namespaces(entry)
90
+ cal = Calendar.new(self)
91
+ cal.load(entry.to_s)
92
+ cals << cal
93
+ end
94
+ return cals
95
+ end
96
+
97
+ #Returns an array of Event objects for each event in this account
98
+ def events
99
+ if not @auth_token
100
+ raise NotAuthenticated
101
+ end
102
+ ret = send_request(GData4Ruby::Request.new(:get, Event.event_feed_uri(@account), nil, {"max-results" => "10000"}))
103
+ events = []
104
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
105
+ entry = GData4Ruby::Utils.add_namespaces(entry)
106
+ event = Event.new(self)
107
+ event.load(entry.to_s)
108
+ events << event
109
+ end
110
+ return events
111
+ end
112
+
113
+ #Helper function to return a formatted iframe embedded google calendar. Parameters are:
114
+ #1. *cals*: either an array of calendar ids, or <em>:all</em> for all calendars, or <em>:first</em> for the first (usally default) calendar
115
+ #2. *params*: a hash of parameters that affect the display of the embedded calendar. Accepts any parameter that the google iframe recognizes. Here are the most common:
116
+ # height:: the height of the embedded calendar in pixels
117
+ # width:: the width of the embedded calendar in pixels
118
+ # title:: the title to display
119
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
120
+ # showTitle:: set to '0' to hide the title
121
+ # showDate:: set to '0' to hide the current date
122
+ # showNav:: set to '0 to hide the navigation tools
123
+ # showPrint:: set to '0' to hide the print icon
124
+ # showTabs:: set to '0' to hide the tabs
125
+ # showCalendars:: set to '0' to hide the calendars selection drop down
126
+ # showTz:: set to '0' to hide the timezone selection
127
+ # border:: the border width in pixels
128
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
129
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
130
+ # ctz:: The timezone to convert event times to
131
+ #3. *colors*: a hash of calendar ids as key and color values as associated hash values. Example: {'test@gmail.com' => '#7A367A'}
132
+ def to_iframe(cals, params = {}, colors = {})
133
+ params[:height] ||= "600"
134
+ params[:width] ||= "600"
135
+ params[:title] ||= (self.account ? self.account : '')
136
+ params[:bgcolor] ||= "#FFFFFF"
137
+ params[:border] ||= "0"
138
+ params.each{|key, value| params[key] = CGI::escape(value)}
139
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}&"
140
+
141
+ if cals.is_a?(Array)
142
+ for c in cals
143
+ output += "src=#{c}&"
144
+ if colors and colors[c]
145
+ output += "color=%23#{colors[c].gsub("#", "")}&"
146
+ end
147
+ end
148
+ elsif cals == :all
149
+ cal_list = calendars()
150
+ for c in cal_list
151
+ output += "src=#{c.id}&"
152
+ end
153
+ elsif cals == :first
154
+ cal_list = calendars()
155
+ output += "src=#{cal_list[0].id}&"
156
+ end
157
+
158
+ "<iframe src='http://www.google.com/calendar/embed?#{output}' style='#{params[:border]} px solid;' width='#{params[:width]}' height='#{params[:height]}' frameborder='#{params[:border]}' scrolling='no'></iframe>"
159
+ end
160
+ end
161
+ end
data/lib/gcal4ruby.rb ADDED
@@ -0,0 +1 @@
1
+ require "gcal4ruby/service"
data/test/unit.rb ADDED
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Prefix LOAD_PATH with lib sub-directory to ensure we're
4
+ # testing the intended version.
5
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
6
+
7
+ require 'rubygems'
8
+ require 'gcal4ruby'
9
+ include GCal4Ruby
10
+
11
+ @service = Service.new
12
+ @username = nil
13
+ @password = nil
14
+
15
+ def tester
16
+ if ARGV.include?("-d")
17
+ @service.debug = true
18
+ end
19
+ ARGV.each do |ar|
20
+ if ar.match("username=")
21
+ @username = ar.gsub("username=", "")
22
+ end
23
+ if ar.match("password=")
24
+ @password = ar.gsub("password=", "")
25
+ end
26
+ end
27
+ service_test
28
+ calendar_test
29
+ event_test
30
+ event_recurrence_test
31
+ all_day_recurrence_test
32
+ end
33
+
34
+ def service_test
35
+ puts "---Starting Service Test---"
36
+ puts "1. Authenticate"
37
+ if @service.authenticate(@username, @password)
38
+ successful
39
+ else
40
+ failed
41
+ end
42
+
43
+ puts "2. Calendar List"
44
+ cals = @service.calendars
45
+ if cals
46
+ successful "Calendars for this Account:"
47
+ cals.each do |cal|
48
+ puts cal.title
49
+ end
50
+ else
51
+ failed
52
+ end
53
+ end
54
+
55
+ def calendar_test
56
+ puts "---Starting Calendar Test---"
57
+
58
+ puts "1. Create Calendar"
59
+ cal = Calendar.new(@service)
60
+ cal.title = "test calendar"+Time.now.to_s
61
+ puts "Calender exists = "+cal.exists?.to_s
62
+ if cal.save
63
+ successful cal.to_xml
64
+ else
65
+ failed
66
+ end
67
+
68
+ puts "2. Edit Calendar"
69
+ cal.title = "renamed title"
70
+ if cal.save
71
+ successful cal.to_xml
72
+ else
73
+ puts "Test 2 Failed"
74
+ end
75
+
76
+ puts "3. Find Calendar by ID"
77
+ c = Calendar.find(@service, {:id => cal.id})
78
+ if c.title == cal.title
79
+ successful
80
+ else
81
+ failed "#{c.title} not equal to #{cal.title}"
82
+ end
83
+
84
+ puts "4. Delete Calendar"
85
+ if cal.delete and not cal.exists?
86
+ successful
87
+ else
88
+ failed
89
+ end
90
+ end
91
+
92
+ def event_test
93
+ puts "---Starting Event Test---"
94
+
95
+ puts "1. Create Event"
96
+ event = Event.new(@service)
97
+ event.calendar = @service.calendars[0]
98
+ event.title = "Test Event"
99
+ event.content = "Test event content"
100
+ event.start_time = Time.now+1800
101
+ event.end_time = Time.now+5400
102
+ if event.save
103
+ successful event.to_xml
104
+ else
105
+ failed
106
+ end
107
+
108
+ puts "2. Edit Event"
109
+ event.title = "Edited title"
110
+ if event.save
111
+ successful event.to_xml
112
+ else
113
+ failed
114
+ end
115
+
116
+ puts "3. Reload Event"
117
+ if event.reload
118
+ successful
119
+ end
120
+
121
+ puts "4. Find Event by id"
122
+ e = Event.find(@service, {:id => event.id})
123
+ if e.title == event.title
124
+ successful
125
+ else
126
+ failed "Found event doesn't match existing event"
127
+ end
128
+
129
+ puts "5. Delete Event"
130
+ if event.delete
131
+ successful
132
+ else
133
+ failed
134
+ end
135
+ end
136
+
137
+ def event_recurrence_test
138
+ puts "---Starting Event Recurrence Test---"
139
+
140
+ @first_start = Time.now
141
+ @first_end = Time.now+3600
142
+ @first_freq = {'weekly' => ['TU']}
143
+ @second_start = Time.now+86000
144
+ @second_end = Time.now+89600
145
+ @second_freq = {'weekly' => ['SA']}
146
+
147
+ puts "1. Create Recurring Event"
148
+ event = Event.new(@service)
149
+ event.calendar = @service.calendars[0]
150
+ event.title = "Test Recurring Event"
151
+ event.content = "Test event content"
152
+ event.recurrence = Recurrence.new({:start_time => @first_start, :end_time => @first_end, :frequency => @first_freq})
153
+ if event.save
154
+ successful event.to_xml
155
+ else
156
+ failed("recurrence = "+event.recurrence.to_s)
157
+ end
158
+
159
+ puts "2. Edit Recurrence"
160
+ event.title = "Edited recurring title"
161
+ event.recurrence = Recurrence.new({:start_time => @second_start, :end_time => @second_end, :frequency => @second_freq})
162
+ if event.save
163
+ successful event.to_xml
164
+ else
165
+ failed
166
+ end
167
+
168
+ puts "3. Delete Event"
169
+ if event.delete
170
+ successful
171
+ else
172
+ failed
173
+ end
174
+ end
175
+
176
+ def all_day_recurrence_test
177
+ puts "---Starting All Day Recurrence Test---"
178
+
179
+ start_time = Time.now
180
+ end_time = start_time + 60*60*24
181
+ freq = {'weekly' => ['MO','TU']}
182
+
183
+ puts "1. Create All Day Recurring Event"
184
+ event = Event.new(@service)
185
+ event.calendar = @service.calendars[0]
186
+ event.title = "Test All Day Recurring Event"
187
+ event.content = "Test all day event content"
188
+ event.recurrence = Recurrence.new({:start_time => start_time, :end_time => end_time, :frequency => freq, :all_day => true})
189
+ if event.save
190
+ successful event.to_xml
191
+ else
192
+ failed("recurrence = "+event.recurrence.to_s)
193
+ end
194
+
195
+ puts "2. Validate returned event is an all day event"
196
+ if event.recurrence.all_day
197
+ successful
198
+ else
199
+ failed("recurrence = "+event.recurrence.to_s)
200
+ end
201
+
202
+ puts "3. Validate frequency of event"
203
+ if event.recurrence.frequency['weekly'] == ['MO','TU']
204
+ successful
205
+ else
206
+ failed("recurrence = "+event.recurrence.to_s)
207
+ end
208
+
209
+ puts "4. Delete Event"
210
+ if event.delete
211
+ successful
212
+ else
213
+ failed
214
+ end
215
+ end
216
+
217
+ def failed(m = nil)
218
+ puts "Test Failed"
219
+ puts m if m
220
+ exit()
221
+ end
222
+
223
+ def successful(m = nil)
224
+ puts "Test Successful"
225
+ puts m if m
226
+ end
227
+
228
+ tester