ess 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,8 @@
1
1
  module ESS
2
2
  module Examples
3
+ ##
4
+ # Example feeds for documentation and testing.
5
+ #
3
6
 
4
7
  def self.from_essfeeds_org_home
5
8
  ess = Maker.make do |ess|
@@ -45,7 +48,7 @@ module ESS
45
48
  item.selected_day_attr "saturday,sunday"
46
49
 
47
50
  item.name "Match Date"
48
- item.start "2011-12-13T18:30:02Z"
51
+ item.start "2011-12-17T18:30:02Z"
49
52
  item.duration "10800"
50
53
  end
51
54
 
@@ -129,7 +132,7 @@ module ESS
129
132
  item.country_code "US"
130
133
  item.logo "http://sample.com/logo_120x60.png"
131
134
  item.icon "http://sample.com/icon_64x64.png"
132
- item.email "contact@sample.com"
135
+ item.email "contact@example.com"
133
136
  item.phone "+001 (646) 234-5566"
134
137
  end
135
138
 
@@ -261,7 +264,7 @@ module ESS
261
264
 
262
265
  feed.dates.add_item :type => "recurrent", :unit => "month", :limit => 6, :selected_day => "saturday", :selected_week => "first,last" do |item|
263
266
  item.name "Course the first and last Saturdays of every month"
264
- item.start "2013-10-25T15:30:00Z"
267
+ item.start "2013-10-05T15:30:00Z"
265
268
  item.duration "21600"
266
269
  end
267
270
 
@@ -3,6 +3,9 @@ require 'digest/md5'
3
3
 
4
4
  module ESS
5
5
  module Helpers
6
+ ##
7
+ # Generates an UUID with the prefix specified, using the kay passed to it.
8
+ #
6
9
  def self.uuid key=nil, prefix='ESSID:'
7
10
  new_id = nil
8
11
  if key.nil?
@@ -1,12 +1,37 @@
1
1
  module ESS
2
2
  class Maker
3
- DEFAULT_OPTIONS = {
4
- :version => "0.9",
5
- :lang => "en",
6
- :validate => true,
7
- :push => false
8
- }
9
3
 
4
+ ##
5
+ # Create a new ESS document. See README for examples on how it should
6
+ # be used.
7
+ #
8
+ # === Yields
9
+ #
10
+ # [ESS::ESS] object representing the "ess" root tag of an ESS document
11
+ #
12
+ # === Options
13
+ #
14
+ # Currently, the following options are defined:
15
+ #
16
+ # ==== :push
17
+ #
18
+ # Whether to push the resulting document to aggregators before returning
19
+ # from the method. Default is false.
20
+ #
21
+ # ==== :validate
22
+ #
23
+ # Validate resulting document before returning from the method. Default
24
+ # is true.
25
+ #
26
+ # ==== :version
27
+ #
28
+ # Set a different value for the "version" attribute of the "ess" tag.
29
+ # Default is "0.9".
30
+ #
31
+ # ==== :lang
32
+ #
33
+ # Set a value for the "lang" attribute of the "ess" tag. Default is "en".
34
+ #
10
35
  def self.make options={}, &block
11
36
  options = DEFAULT_OPTIONS.merge options
12
37
  ess = ESS.new
@@ -19,6 +44,15 @@ module ESS
19
44
  ess.push_to_aggregators(options) if options[:push] || options[:aggregators]
20
45
  return ess
21
46
  end
47
+
48
+ private
49
+
50
+ DEFAULT_OPTIONS = {
51
+ :version => "0.9",
52
+ :lang => "en",
53
+ :validate => true,
54
+ :push => false
55
+ }
22
56
  end
23
57
  end
24
58
 
@@ -0,0 +1,31 @@
1
+ require "ess"
2
+ require "rexml/document"
3
+
4
+ module ESS
5
+ class Parser
6
+ def self.parse data
7
+ doc = REXML::Document.new data
8
+ ess = doc.root
9
+ if ess.nil?
10
+ raise ArgumentError, "the argument has to contain a valid xml document"
11
+ end
12
+ new_ess = ESS.new
13
+ new_ess.disable_postprocessing
14
+ parse_element(ess, new_ess)
15
+ new_ess.enable_postprocessing
16
+ new_ess
17
+ end
18
+
19
+ def self.parse_element element, new_element=nil
20
+ element.attributes.each_pair do |attr, value|
21
+ new_element.send(attr + "_attr", value)
22
+ end
23
+ element.elements.each do |element|
24
+ new_element.send("add_" + element.name, element.text) do |new_element|
25
+ parse_element element, new_element
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
@@ -4,6 +4,10 @@ require 'date'
4
4
 
5
5
  module ESS
6
6
  module Postprocessing
7
+ ##
8
+ # Varous classes for postprocessing tag values. Should not be used directly,
9
+ # instances of it's classes are part of the DTD.
10
+ #
7
11
  class FeedTitle
8
12
  def process feed_tag, title_tag
9
13
  feed_tag.id(title_tag.text!) if feed_tag.id.text! == ""
@@ -5,15 +5,53 @@ require 'uri'
5
5
 
6
6
  module ESS
7
7
  module Pusher
8
+ ##
9
+ # Sets the default aggregator services. Accepts a list of links in strings.
10
+ #
8
11
  def self.aggregators= aggs
9
12
  raise ArgumentError, "this method requires a list of links" if aggs.class != Array
10
13
  @@aggregators = aggs
11
14
  end
12
15
 
16
+ ##
17
+ # Returns the aggregator services currently set as default.
18
+ #
13
19
  def self.aggregators
14
20
  @@aggregators ||= ["http://api.hypecal.com/v1/ess/aggregator.json"]
15
21
  end
16
22
 
23
+ ##
24
+ # Pushes the feed to aggregators.
25
+ #
26
+ # === Options
27
+ #
28
+ # ==== :data
29
+ #
30
+ # A string, with an XML document representing the feed that needs to be
31
+ # pushed.
32
+ #
33
+ # ==== :feed
34
+ #
35
+ # This is an alternative to the :data option. This method accepts the feed
36
+ # link instead of the whole document. The aggregator service will pull the
37
+ # feed using this link.
38
+ #
39
+ # ==== :request
40
+ #
41
+ # This should be the request object that generated this feed. It can be
42
+ # useful for the aggregator service to receive some of th information
43
+ # from this object for crawling purposes.
44
+ #
45
+ # ==== :aggregators
46
+ #
47
+ # Intead of using the default aggregator services, this options can be used
48
+ # to specify what aggregators should the document be pushed to.
49
+ #
50
+ # ==== :ignore_errors
51
+ #
52
+ # The method will ignore any response from the aggregator services if this
53
+ # option is true. Default is false.
54
+ #
17
55
  def self.push_to_aggregators options={}
18
56
  options = { :aggregators => Pusher::aggregators,
19
57
  :feed => nil,
@@ -1,10 +1,20 @@
1
1
  require 'ess/helpers'
2
2
  require 'time'
3
+ require 'resolv'
3
4
 
4
5
  module ESS
5
6
  module Validation
7
+ ##
8
+ # Varous classes for validation of tag values. Should not be used directly,
9
+ # instances of it's classes are part of the DTD.
10
+ #
6
11
 
7
12
  class ValidationError < StandardError
13
+ ##
14
+ # This exception is generated when the validator find an error
15
+ # in the document. It should contain a message describing what
16
+ # was the value which caused it to be raised.
17
+ #
8
18
  end
9
19
 
10
20
  class TextIsNotNull
@@ -17,7 +27,32 @@ module ESS
17
27
 
18
28
  class TextIsValidEmail
19
29
  def validate tag
20
- # TODO: Doing this is not recommended, check if realy necessary
30
+ return if valid_domain?(tag.text!)
31
+ raise InvalidValueError, "the email \"#{tag.text!}\" could not be validated"
32
+ end
33
+
34
+ EMAIL_PATTERN = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
35
+ SERVER_TIMEOUT = 10
36
+
37
+ def valid_domain?(email)
38
+ domain = email.match(EMAIL_PATTERN)[2]
39
+ dns = Resolv::DNS.new
40
+ Timeout::timeout(SERVER_TIMEOUT) do
41
+
42
+ # Check the MX record
43
+ mx_records = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
44
+
45
+ mx_records.sort_by {|mx| mx.preference}.each do |mx|
46
+ a_records = dns.getresources(mx.exchange.to_s, Resolv::DNS::Resource::IN::A)
47
+ return true if a_records.any?
48
+ end
49
+
50
+ #Try a straight A record
51
+ a_records = dns.getresources(domain, Resolv::DNS::Resource::IN::A)
52
+ a_records.any?
53
+ end
54
+ rescue Timeout::Error, Errno::ECONNREFUSED
55
+ false
21
56
  end
22
57
  end
23
58
 
@@ -1,3 +1,3 @@
1
1
  module ESS
2
- VERSION = "0.9.3"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,350 @@
1
+ require 'spec_helper'
2
+
3
+ module ESS
4
+ describe "ESS" do
5
+ let(:future_year) { Time.now.year + 2 }
6
+
7
+ context 'feed with one item with standalone date' do
8
+ let(:ess) do
9
+ ess = ESS.new
10
+ ess.channel.add_feed do |feed|
11
+ feed.title "Feed 1"
12
+ feed.dates.add_item do |item|
13
+ item.type_attr "standalone"
14
+ item.name "Date 1"
15
+ item.start Time.parse("#{future_year}-01-01T00:00:00Z")
16
+ end
17
+ end
18
+ ess
19
+ end
20
+
21
+ describe '#find_coming' do
22
+ it 'should return that one item in an array' do
23
+ feeds = ess.find_coming
24
+ feeds.length.should == 1
25
+ feeds[0][:feed].title.text!.should == "Feed 1"
26
+ end
27
+ end
28
+
29
+ describe '#find_between' do
30
+ it 'should return that one item in an array if it\'s between the two moments in time' do
31
+ feeds = ess.find_between(Time.parse("#{future_year-1}-12-31T23:59:00Z"), Time.parse("#{future_year}-01-01T00:01:00Z"))
32
+ feeds.length.should == 1
33
+ feeds[0][:feed].title.text!.should == "Feed 1"
34
+ end
35
+
36
+ it 'should return an empty array if the item event is not between the two moments in time' do
37
+ feeds = ess.find_between(Time.parse("#{future_year}-01-01T00:01:00Z"), Time.parse("#{future_year}-01-01T00:03:00Z"))
38
+ feeds.length.should == 0
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'ESS channel with two feeds with future standalone dates' do
44
+ let(:ess) do
45
+ ess = ESS.new
46
+ ess.channel.add_feed do |feed|
47
+ feed.title "Feed 1"
48
+ feed.dates.add_item do |item|
49
+ item.type_attr "standalone"
50
+ item.name "Date 1"
51
+ item.start Time.parse("#{future_year}-01-01T00:00:00Z")
52
+ end
53
+ end
54
+ ess.channel.add_feed do |feed|
55
+ feed.title "Feed 2"
56
+ feed.dates.add_item do |item|
57
+ item.type_attr "standalone"
58
+ item.name "Date 1"
59
+ item.start Time.parse("#{future_year}-01-08T00:00:00Z")
60
+ end
61
+ end
62
+ ess
63
+ end
64
+
65
+ describe '#find_coming' do
66
+ it 'should return both items in an array if no parameters were specified' do
67
+ feeds = ess.find_coming
68
+ feeds.length.should == 2
69
+ feeds[0][:feed].title.text!.should == "Feed 1"
70
+ feeds[1][:feed].title.text!.should == "Feed 2"
71
+ end
72
+
73
+ it 'should return the first feed in an array if passed the number 1' do
74
+ feeds = ess.find_coming(1)
75
+ feeds.length.should == 1
76
+ feeds[0][:feed].title.text!.should == "Feed 1"
77
+ end
78
+
79
+ it 'should return both items in an array if passed the number 2' do
80
+ feeds = ess.find_coming(2)
81
+ feeds.length.should == 2
82
+ feeds[0][:feed].title.text!.should == "Feed 1"
83
+ feeds[1][:feed].title.text!.should == "Feed 2"
84
+ end
85
+
86
+ it 'should return both items in an array if passed the number 2, sorted by asc. date/time' do
87
+ feeds = ess.channel.feed_list
88
+ tmp1 = feeds[0]
89
+ tmp2 = feeds[1]
90
+ ess.channel.feed_list.clear
91
+ ess.channel.feed_list << tmp2
92
+ ess.channel.feed_list << tmp1
93
+ feeds = ess.find_coming(2)
94
+ feeds.length.should == 2
95
+ feeds[0][:feed].title.text!.should == "Feed 1"
96
+ feeds[1][:feed].title.text!.should == "Feed 2"
97
+ end
98
+ it 'should return both items in an array if passed the number 3' do
99
+ feeds = ess.find_coming(3)
100
+ feeds.length.should == 2
101
+ feeds[0][:feed].title.text!.should == "Feed 1"
102
+ feeds[1][:feed].title.text!.should == "Feed 2"
103
+ end
104
+ end
105
+
106
+ describe '#find_between' do
107
+ it 'should return an empty list if none of the events is between two moments in time' do
108
+ feeds = ess.find_between(Time.parse("#{future_year-1}-12-21T23:59:00Z"), Time.parse("#{future_year-1}-12-31T00:01:00Z"))
109
+ feeds.length.should == 0
110
+ feeds = ess.find_between(Time.parse("#{future_year}-01-10T23:59:00Z"), Time.parse("#{future_year}-01-13T00:01:00Z"))
111
+ feeds.length.should == 0
112
+ end
113
+
114
+ it 'should return the first feed if it is happening between the two dates' do
115
+ feeds = ess.find_between(Time.parse("#{future_year-1}-12-21T23:59:00Z"), Time.parse("#{future_year}-01-05T00:01:00Z"))
116
+ feeds.length.should == 1
117
+ feeds[0][:feed].title.text!.should == "Feed 1"
118
+ end
119
+
120
+ it 'should return the second feed if it is happening between the two dates' do
121
+ feeds = ess.find_between(Time.parse("#{future_year}-01-01T00:02:00Z"), Time.parse("#{future_year}-01-09T00:01:00Z"))
122
+ feeds.length.should == 1
123
+ feeds[0][:feed].title.text!.should == "Feed 2"
124
+ end
125
+
126
+ it 'should return both items if they both happen in the interval' do
127
+ feeds = ess.find_between(Time.parse("#{future_year}-01-01T00:00:00Z"), Time.parse("#{future_year}-01-09T00:01:00Z"))
128
+ feeds.length.should == 2
129
+ feeds[0][:feed].title.text!.should == "Feed 1"
130
+ feeds[1][:feed].title.text!.should == "Feed 2"
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'one feed with two date items with standalone values' do
136
+ let(:ess) do
137
+ ess = ESS.new
138
+ ess.channel.add_feed do |feed|
139
+ feed.title "Feed 1"
140
+ feed.dates.add_item do |item|
141
+ item.type_attr "standalone"
142
+ item.name "Date 2"
143
+ item.start Time.parse("#{future_year}-01-01T00:15:00Z")
144
+ end
145
+ feed.dates.add_item do |item|
146
+ item.type_attr "standalone"
147
+ item.name "Date 1"
148
+ item.start Time.parse("#{future_year}-01-01T00:00:00Z")
149
+ end
150
+ end
151
+ ess
152
+ end
153
+
154
+ describe "#find_coming" do
155
+ it 'should return two items in a list, if no arguments are passed' do
156
+ ess.find_coming.length.should == 2
157
+ end
158
+
159
+ it 'should return one item in a list, if the only argument is a 1' do
160
+ ess.find_coming(1).length.should == 1
161
+ end
162
+
163
+ it 'should return a list of dicts, with keys :time and :feed' do
164
+ feeds = ess.find_coming
165
+ feeds.each do |feed|
166
+ feed[:time].should_not be_nil
167
+ feed[:feed].should_not be_nil
168
+ end
169
+ end
170
+
171
+ it 'should return a list of discts sorted by ascending order of time' do
172
+ feeds = ess.find_coming
173
+ feeds[0][:time].should == Time.parse("#{future_year}-01-01T00:00:00Z")
174
+ feeds[0][:feed].title.text!.should == "Feed 1"
175
+ feeds[1][:time].should == Time.parse("#{future_year}-01-01T00:15:00Z")
176
+ feeds[1][:feed].title.text!.should == "Feed 1"
177
+ end
178
+ end
179
+
180
+ describe "#find_between" do
181
+ it 'should return two items in a list, if both date items are within the time period' do
182
+ feeds = ess.find_between(Time.parse("#{future_year}-01-01T00:00:00Z"), Time.parse("#{future_year}-01-09T00:01:00Z"))
183
+ feeds.length == 2
184
+ end
185
+
186
+ it 'should return two hashes in a list, with :time and :feed values defined' do
187
+ feeds = ess.find_between(Time.parse("#{future_year}-01-01T00:00:00Z"), Time.parse("#{future_year}-01-09T00:01:00Z"))
188
+ feeds.each do |feed|
189
+ feed[:time].should_not be_nil
190
+ feed[:feed].should_not be_nil
191
+ end
192
+ end
193
+
194
+ it 'should return a list of dicts sorted by ascending order of time' do
195
+ feeds = ess.find_coming
196
+ feeds[0][:time].should == Time.parse("#{future_year}-01-01T00:00:00Z")
197
+ feeds[0][:feed].title.text!.should == "Feed 1"
198
+ feeds[1][:time].should == Time.parse("#{future_year}-01-01T00:15:00Z")
199
+ feeds[1][:feed].title.text!.should == "Feed 1"
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'feed with one item with recurring date with a limit attribute' do
205
+ let(:ess) do
206
+ ess = ESS.new
207
+ ess.channel.add_feed do |feed|
208
+ feed.title "Feed 1"
209
+ feed.dates.add_item do |item|
210
+ item.type_attr "recurrent"
211
+ item.unit_attr "month"
212
+ item.limit_attr "5"
213
+ item.name "Date 1"
214
+ item.start Time.parse("#{future_year}-01-01T00:00:00Z")
215
+ end
216
+ end
217
+ ess
218
+ end
219
+
220
+ describe "#find_coming" do
221
+ it 'should return the array with as much elements, as there will be separate events' do
222
+ ess.find_coming.length.should == 5
223
+ end
224
+
225
+ it 'should return a list of feeds, sorted by starting date/time' do
226
+ feeds = ess.find_coming
227
+ feeds[0][:time].should == Time.parse("#{future_year}-01-01T00:00:00Z")
228
+ feeds[1][:time].should == Time.parse("#{future_year}-02-01T00:00:00Z")
229
+ feeds[2][:time].should == Time.parse("#{future_year}-03-01T00:00:00Z")
230
+ feeds[3][:time].should == Time.parse("#{future_year}-04-01T00:00:00Z")
231
+ feeds[4][:time].should == Time.parse("#{future_year}-05-01T00:00:00Z")
232
+ end
233
+ end
234
+
235
+ describe "#find_coming" do
236
+ it 'should return a list of event instances within time boundaries' do
237
+ feeds = ess.find_between(Time.parse("#{future_year}-02-11T00:00:00Z"), Time.parse("#{future_year}-07-11T12:00:00Z"))
238
+ feeds.length.should == 3
239
+ feeds[0][:time].should == Time.parse("#{future_year}-03-01T00:00:00Z")
240
+ feeds[1][:time].should == Time.parse("#{future_year}-04-01T00:00:00Z")
241
+ feeds[2][:time].should == Time.parse("#{future_year}-05-01T00:00:00Z")
242
+ end
243
+ end
244
+ end
245
+
246
+ context 'feed with one item with recurring date with a limit attribute and an interval attribute' do
247
+ let(:ess) do
248
+ ess = ESS.new
249
+ ess.channel.add_feed do |feed|
250
+ feed.title "Feed 1"
251
+ feed.dates.add_item do |item|
252
+ item.type_attr "recurrent"
253
+ item.unit_attr "month"
254
+ item.interval_attr "2"
255
+ item.limit_attr "5"
256
+ item.name "Date 1"
257
+ item.start Time.parse("#{future_year}-01-01T00:00:00Z")
258
+ end
259
+ end
260
+ ess
261
+ end
262
+
263
+ describe "#find_coming" do
264
+ it 'should return the array with as much elements, as there will be separate events' do
265
+ ess.find_coming.length.should == 5
266
+ end
267
+
268
+ it 'should return a list of feeds, sorted by starting date/time' do
269
+ feeds = ess.find_coming
270
+ feeds[0][:time].should == Time.parse("#{future_year}-01-01T00:00:00Z")
271
+ feeds[1][:time].should == Time.parse("#{future_year}-03-01T00:00:00Z")
272
+ feeds[2][:time].should == Time.parse("#{future_year}-05-01T00:00:00Z")
273
+ feeds[3][:time].should == Time.parse("#{future_year}-07-01T00:00:00Z")
274
+ feeds[4][:time].should == Time.parse("#{future_year}-09-01T00:00:00Z")
275
+ end
276
+ end
277
+
278
+ describe "#find_between" do
279
+ it 'should return a list of feeds between the two dates it received as parameters' do
280
+ feeds = ess.find_between(Time.parse("#{future_year}-03-11T00:00:00Z"), Time.parse("#{future_year}-10-11T00:00:00Z"))
281
+ feeds.length.should == 3
282
+ feeds[0][:time].should == Time.parse("#{future_year}-05-01T00:00:00Z")
283
+ feeds[1][:time].should == Time.parse("#{future_year}-07-01T00:00:00Z")
284
+ feeds[2][:time].should == Time.parse("#{future_year}-09-01T00:00:00Z")
285
+ end
286
+ end
287
+ end
288
+
289
+ context 'feed with one item with recurring date with a limit attribute and a selected_day attribute' do
290
+ let(:ess) do
291
+ ess = ESS.new
292
+ ess.channel.add_feed do |feed|
293
+ feed.title "Feed 1"
294
+ feed.dates.add_item do |item|
295
+ item.type_attr "recurrent"
296
+ item.unit_attr "month"
297
+ item.limit_attr "5"
298
+ item.selected_day_attr "2"
299
+ item.name "Date 1"
300
+ item.start Time.parse("#{future_year}-01-02T00:00:00Z")
301
+ end
302
+ end
303
+ ess
304
+ end
305
+
306
+ describe "#find_coming" do
307
+ it 'should return events only on those days specified in the selected_day attribute' do
308
+ feeds = ess.find_coming
309
+ feeds.length.should == 5
310
+ feeds[0][:time].should == Time.parse("#{future_year}-01-02T00:00:00Z")
311
+ feeds[1][:time].should == Time.parse("#{future_year}-02-02T00:00:00Z")
312
+ feeds[2][:time].should == Time.parse("#{future_year}-03-02T00:00:00Z")
313
+ feeds[3][:time].should == Time.parse("#{future_year}-04-02T00:00:00Z")
314
+ feeds[4][:time].should == Time.parse("#{future_year}-05-02T00:00:00Z")
315
+ end
316
+
317
+ it 'should support using day names' do
318
+ ess.channel.feed.dates.item.selected_day_attr "monday"
319
+ feeds = ess.find_coming(30)
320
+ feeds.length.should be > 19
321
+ feeds.length.should be < 26
322
+ feeds.each do |event|
323
+ event[:time].wday.should == 1
324
+ end
325
+ end
326
+ end
327
+
328
+ describe "#find_between" do
329
+ it 'should return events only on those days specified in the selected_day attribute' do
330
+ feeds = ess.find_between(Time.parse("#{future_year}-01-05 00:00"), Time.parse("#{future_year}-04-06T00:00:00Z"))
331
+ feeds.length.should == 3
332
+ feeds[0][:time].should == Time.parse("#{future_year}-02-02T00:00:00Z")
333
+ feeds[1][:time].should == Time.parse("#{future_year}-03-02T00:00:00Z")
334
+ feeds[2][:time].should == Time.parse("#{future_year}-04-02T00:00:00Z")
335
+ end
336
+
337
+ it 'should support using day names' do
338
+ ess.channel.feed.dates.item.selected_day_attr "monday"
339
+ feeds = ess.find_between(Time.parse("#{future_year}-02-01T00:00:00Z"), Time.parse("#{future_year}-04-30T00:00:00Z"))
340
+ feeds.length.should be > 11
341
+ feeds.length.should be < 16
342
+ feeds.each do |event|
343
+ event[:time].wday.should == 1
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+