ess 0.9.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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +448 -0
- data/Rakefile +5 -0
- data/ess.gemspec +21 -0
- data/lib/ess/dtd.rb +491 -0
- data/lib/ess/element.rb +266 -0
- data/lib/ess/ess.rb +8 -0
- data/lib/ess/examples.rb +432 -0
- data/lib/ess/helpers.rb +22 -0
- data/lib/ess/maker.rb +24 -0
- data/lib/ess/postprocessing.rb +69 -0
- data/lib/ess/pusher.rb +63 -0
- data/lib/ess/validation.rb +797 -0
- data/lib/ess/version.rb +3 -0
- data/lib/ess.rb +13 -0
- data/spec/ess/element_spec.rb +796 -0
- data/spec/ess/full_spec.rb +47 -0
- data/spec/ess/maker_spec.rb +30 -0
- data/spec/spec_helper.rb +5 -0
- metadata +88 -0
@@ -0,0 +1,796 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'ess/helpers'
|
4
|
+
|
5
|
+
module ESS
|
6
|
+
describe Element do
|
7
|
+
|
8
|
+
describe '#new' do
|
9
|
+
it 'should require a name and a DTD argument' do
|
10
|
+
expect { Element.new }.to raise_error
|
11
|
+
expect { Element.new :tag_name }.to raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should accept a hash with both :attributes and :tags keys' do
|
15
|
+
lambda {
|
16
|
+
Element.new(:tag_name, {:attributes => "", :tags => ""})
|
17
|
+
}.should_not raise_error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#text!' do
|
22
|
+
let(:element) { Element.new(:tag_name, {:attributes => "", :tags => ""}) }
|
23
|
+
|
24
|
+
context 'when text was not preset' do
|
25
|
+
context 'without parameters' do
|
26
|
+
it 'should return an empty string' do
|
27
|
+
element.text!.should == ""
|
28
|
+
end
|
29
|
+
end
|
30
|
+
context 'with parameters' do
|
31
|
+
it 'should accept one parameter' do
|
32
|
+
lambda {
|
33
|
+
element.text!("Example text")
|
34
|
+
}.should_not raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should set the text value of the element to that parameter' do
|
38
|
+
element.text! "Example text"
|
39
|
+
element.text!.should == "Example text"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when text was preset' do
|
45
|
+
before(:each) { element.text! "Example text" }
|
46
|
+
|
47
|
+
context 'without parameters' do
|
48
|
+
it 'should return that text' do
|
49
|
+
element.text!.should == "Example text"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
context 'with parameters' do
|
53
|
+
it 'should accept one parameter' do
|
54
|
+
lambda {
|
55
|
+
element.text!("Example text")
|
56
|
+
}.should_not raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should set the text value of the element to that parameter' do
|
60
|
+
element.text! "Example text"
|
61
|
+
element.text!.should == "Example text"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'element with one tag' do
|
68
|
+
let(:element) { Element.new(:tags, DTD::TAGS) }
|
69
|
+
|
70
|
+
it 'should return an error when trying to set an invalid tag' do
|
71
|
+
expect { element.bad "Example text" }.to raise_error
|
72
|
+
expect { element.bad }.to raise_error
|
73
|
+
expect { element.add_bad "Example text" }.to raise_error
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#tag' do
|
77
|
+
context 'called for the first time without parameters' do
|
78
|
+
it 'should return an Element instance with a proper DTD and no text' do
|
79
|
+
element.tag.class.should == Element
|
80
|
+
element.tag.dtd.should == DTD::BASIC_ELEMENT
|
81
|
+
element.tag.text!.should == ""
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'called a second time' do
|
86
|
+
it 'should return the same object' do
|
87
|
+
tag_tag = element.tag
|
88
|
+
tag_tag.object_id.should == element.tag.object_id
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'called with a string' do
|
93
|
+
it 'should set the new elements text with that value' do
|
94
|
+
element.tag "Example text"
|
95
|
+
element.tag.text!.should == "Example text"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'called with a block' do
|
100
|
+
it 'should yield that block with the "tag" element as an argument' do
|
101
|
+
lambda {
|
102
|
+
element.tag { |tag| tag.text! "Example text" }
|
103
|
+
}.should_not raise_error
|
104
|
+
element.tag.text!.should == "Example text"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#tag_list' do
|
110
|
+
context 'when no "tag" tags have been added' do
|
111
|
+
it 'should return an empty list' do
|
112
|
+
element.tag_list.should == []
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when one tag has been added with the #tag method' do
|
117
|
+
it 'should return a list with one element' do
|
118
|
+
element.tag "Example text"
|
119
|
+
element.tag_list.length.should == 1
|
120
|
+
element.tag_list[0].class.should == Element
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#add_tag' do
|
126
|
+
context 'when no tags preset' do
|
127
|
+
it 'should create that one tag' do
|
128
|
+
element.add_tag "Example text"
|
129
|
+
element.tag.text!.should == "Example text"
|
130
|
+
element.tag_list.length.should == 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when called a second time' do
|
135
|
+
before(:each) { element.add_tag "Example text 1" }
|
136
|
+
it 'should add another tag of the same type' do
|
137
|
+
element.add_tag "Example text 2"
|
138
|
+
element.tag_list.length.should == 2
|
139
|
+
element.tag_list[0].text!.should == "Example text 1"
|
140
|
+
element.tag_list[1].text!.should == "Example text 2"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'called with a block' do
|
145
|
+
it 'should yield that block with the new "tag" element as an argument' do
|
146
|
+
lambda {
|
147
|
+
element.add_tag { |tag| tag.text! "Example text" }
|
148
|
+
}.should_not raise_error
|
149
|
+
element.tag.text!.should == "Example text"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with attributes, ESS tag for example' do
|
156
|
+
let(:element) { Element.new(:ess, DTD::ESS) }
|
157
|
+
|
158
|
+
describe '#xmlns_attr' do
|
159
|
+
it 'should return an empty string if it was not yet set' do
|
160
|
+
element.xmlns_attr.should == ""
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should return the preset value if the attribute was set' do
|
164
|
+
element.xmlns_attr "Example value"
|
165
|
+
element.xmlns_attr.should == "Example value"
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should allow redefining the value of the attribute' do
|
169
|
+
element.xmlns_attr "Example value"
|
170
|
+
element.xmlns_attr "Another example value"
|
171
|
+
element.xmlns_attr.should == "Another example value"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '#to_xml!' do
|
176
|
+
it 'should include the attribute value in xml' do
|
177
|
+
element.xmlns_attr "Example value"
|
178
|
+
element.to_xml!.should include('<ess xmlns="Example value"></ess>')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should include values for multiple attributes in xml' do
|
182
|
+
element.xmlns_attr "xmlns value"
|
183
|
+
element.version_attr "Version value"
|
184
|
+
element.to_xml!.should include('xmlns="xmlns value"')
|
185
|
+
element.to_xml!.should include('version="Version value"')
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'with a child tag with attributes, CATEGORIES tag for example' do
|
191
|
+
let(:element) { Element.new(:categories, DTD::CATEGORIES) }
|
192
|
+
|
193
|
+
describe '#item' do
|
194
|
+
it 'should accept setting of the attribute value in a hash argument' do
|
195
|
+
element.item :type => "competition"
|
196
|
+
element.item.type_attr.should == "competition"
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'should accept setting both text and attributes at the same time' do
|
200
|
+
element.item "Example text", :type => "competition"
|
201
|
+
element.item.type_attr.should == "competition"
|
202
|
+
element.item.text!.should == "Example text"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe '#add_item' do
|
207
|
+
it 'should accept setting both text and attributes in a hash argument at the same time' do
|
208
|
+
element.add_item "Example text", :type => "competition"
|
209
|
+
element.item.type_attr.should == "competition"
|
210
|
+
element.item.text!.should == "Example text"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '#to_xml!' do
|
216
|
+
let(:element) { Element.new(:channel, DTD::CHANNEL) }
|
217
|
+
|
218
|
+
it 'should return a string' do
|
219
|
+
element.to_xml!.class.should == String
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'when the element is completely empty' do
|
223
|
+
it 'should return at least the starting and ending tags' do
|
224
|
+
element.to_xml!.should include("<channel></channel>")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'when the element has text preset' do
|
229
|
+
before(:each) { element.text! "Example text" }
|
230
|
+
it 'should return the starting and ending tags with the text between them' do
|
231
|
+
element.to_xml!.should include("<channel>Example text</channel>")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'when the element has child elements' do
|
236
|
+
before(:each) { element.generator "ruby" }
|
237
|
+
it 'should return the starting and ending tags, and the same for the child tag' do
|
238
|
+
element.to_xml!.should include("<channel><generator>ruby</generator></channel>")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context 'with attributes with restricted value, for example DATE_ITEM' do
|
244
|
+
let(:element) { Element.new(:item, DTD::DATE_ITEM) }
|
245
|
+
|
246
|
+
it 'should allow valid value for that attribute' do
|
247
|
+
lambda {
|
248
|
+
element.type_attr "standalone"
|
249
|
+
}.should_not raise_error
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should raise error if an invalid value was used for an attribute' do
|
253
|
+
expect { element.type_attr "bad_value" }.to raise_error
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should allow multiple comma separated valid values' do
|
257
|
+
lambda {
|
258
|
+
element.selected_day_attr "friday,saturday"
|
259
|
+
}.should_not raise_error
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should raise error if one value is valid and the other is not' do
|
263
|
+
expect {
|
264
|
+
element.selected_day_attr "friday,bad"
|
265
|
+
}.to raise_error
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#valid?' do
|
270
|
+
context 'called on an element with one mandatory tag with infinite number' do
|
271
|
+
let(:element) { Element.new :tags, DTD::TAGS }
|
272
|
+
|
273
|
+
it 'should return false if that mandatory tag was not defined' do
|
274
|
+
element.should_not be_valid
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'should return true if there is one mandatory tag defined' do
|
278
|
+
element.tag "Example text"
|
279
|
+
element.should be_valid
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'should return true if there are more then one instances of that tag' do
|
283
|
+
element.add_tag "Example text 1"
|
284
|
+
element.add_tag "Example text 2"
|
285
|
+
element.should be_valid
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'called on an element with mandatory tags and counter restricted' do
|
290
|
+
let(:element) do
|
291
|
+
element = Element.new :tags, DTD::RELATION_ITEM
|
292
|
+
element.type_attr "related"
|
293
|
+
element
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should return true if all tags presents and within limits' do
|
297
|
+
element.name "Example name"
|
298
|
+
element.uri "Example uri"
|
299
|
+
element.id "Example id"
|
300
|
+
element.should be_valid
|
301
|
+
end
|
302
|
+
it 'should return false if at least one tag has too many elements' do
|
303
|
+
element.add_name "Example name 1"
|
304
|
+
element.add_name "Example name 2"
|
305
|
+
element.uri "Example uri"
|
306
|
+
element.id "Example id"
|
307
|
+
element.should_not be_valid
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'when child elements need to be tested too' do
|
312
|
+
let(:element) do
|
313
|
+
element = Element.new :feed, DTD::FEED
|
314
|
+
element.title "A title"
|
315
|
+
element.id "An ID"
|
316
|
+
element.access "PUBLIC"
|
317
|
+
element.description "desc"
|
318
|
+
element.published Time.now.to_s
|
319
|
+
element.uri "http://example.com/"
|
320
|
+
element.categories.add_item :type => "award" do |item|
|
321
|
+
item.name "A name"
|
322
|
+
item.id "An ID"
|
323
|
+
end
|
324
|
+
element.dates.add_item :type => "standalone" do |item|
|
325
|
+
item.name "A name"
|
326
|
+
item.start Time.now.to_s
|
327
|
+
end
|
328
|
+
element.places.add_item :type => "fixed" do |item|
|
329
|
+
item.name "A name"
|
330
|
+
end
|
331
|
+
element
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'should return true if a valid element was generated' do
|
335
|
+
element.should be_valid
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should return false if a child of the element is not valid' do
|
339
|
+
# Creating a places item without a name tag to make it invalid
|
340
|
+
element.places.add_item
|
341
|
+
element.should_not be_valid
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
describe 'tag valid values' do
|
347
|
+
let(:element) { Element.new :feed, DTD::FEED }
|
348
|
+
|
349
|
+
describe '#access' do
|
350
|
+
it 'should allow PUBLIC and PRIVATE values' do
|
351
|
+
lambda {
|
352
|
+
element.access "PUBLIC"
|
353
|
+
element.access "PRIVATE"
|
354
|
+
}.should_not raise_error
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'should not allow other values' do
|
358
|
+
expect { element.access "bad" }.to raise_error
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe 'postprocessing' do
|
364
|
+
describe 'Feed element' do
|
365
|
+
let(:element) { Element.new(:feed, DTD::FEED) }
|
366
|
+
|
367
|
+
describe '#id' do
|
368
|
+
it 'should replace id with a regular event uuid when receiving regular text' do
|
369
|
+
element.id "Some text"
|
370
|
+
element.id.text!.should == Helpers::uuid("Some text", 'EVENTID:')
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
context 'when no id set' do
|
375
|
+
describe '#title' do
|
376
|
+
it 'should automatically set the feed id to a uuid(title)' do
|
377
|
+
a_title = "A title"
|
378
|
+
puts element.id.text!
|
379
|
+
element.title a_title
|
380
|
+
element.id.text!.should == Helpers::uuid(a_title, 'EVENTID:')
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
describe '#add_title' do
|
385
|
+
it 'should automatically set the feed id to a uuid(title)' do
|
386
|
+
a_title = "A title"
|
387
|
+
element.add_title a_title
|
388
|
+
element.id.text!.should == Helpers::uuid(a_title, 'EVENTID:')
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
describe '#uri' do
|
393
|
+
it 'should automatically set the feed id to a uuid(uri)' do
|
394
|
+
an_uri = "http://event/uri/"
|
395
|
+
element.uri an_uri
|
396
|
+
element.id.text!.should == Helpers::uuid(an_uri, 'EVENTID:')
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
describe '#add_uri' do
|
401
|
+
it 'should automatically set the feed id to a uuid(uri)' do
|
402
|
+
an_uri = "http://event/uri/"
|
403
|
+
element.add_uri an_uri
|
404
|
+
element.id.text!.should == Helpers::uuid(an_uri, 'EVENTID:')
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
context 'when id was set' do
|
410
|
+
let(:an_id) { Helpers::uuid("Some text", 'EVENTID:') }
|
411
|
+
before(:each) { element.id an_id }
|
412
|
+
|
413
|
+
describe '#title' do
|
414
|
+
it 'should not automatically set the feed id to a uuid(title)' do
|
415
|
+
a_title = "A title"
|
416
|
+
element.title a_title
|
417
|
+
element.id.text!.should == an_id
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
describe '#add_title' do
|
422
|
+
it 'should not automatically set the feed id to a uuid(title)' do
|
423
|
+
a_title = "A title"
|
424
|
+
element.add_title a_title
|
425
|
+
element.id.text!.should == an_id
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
describe '#uri' do
|
430
|
+
it 'should not automatically set the feed id to a uuid(uri)' do
|
431
|
+
an_uri = "http://event/uri/"
|
432
|
+
element.uri an_uri
|
433
|
+
element.id.text!.should == an_id
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
describe '#add_uri' do
|
438
|
+
it 'should not automatically set the feed id to a uuid(uri)' do
|
439
|
+
an_uri = "http://event/uri/"
|
440
|
+
element.add_uri an_uri
|
441
|
+
element.id.text!.should == an_id
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
describe '#published' do
|
447
|
+
it 'should accept Time objects and return a string in ISO8601 format' do
|
448
|
+
current_time = Time.now
|
449
|
+
element.published current_time
|
450
|
+
element.published.text!.should == current_time.iso8601
|
451
|
+
end
|
452
|
+
|
453
|
+
it 'should accept string in ISO8601 format and keep them the same' do
|
454
|
+
current_time = Time.now.iso8601
|
455
|
+
element.published current_time
|
456
|
+
element.published.text!.should == current_time
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
describe 'Description element' do
|
462
|
+
let(:element) { Element.new :description, DTD::DESCRIPTION }
|
463
|
+
it 'should strip unwanted tags from the description' do
|
464
|
+
desc = "<p> About this feed... </p> <script src=\"test.js\"></script>"
|
465
|
+
element.text! desc
|
466
|
+
element.text!.should == "<p> About this feed... </p>"
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
describe 'Channel element' do
|
471
|
+
let(:element) { Element.new(:channel, DTD::CHANNEL) }
|
472
|
+
|
473
|
+
context 'when no id set' do
|
474
|
+
describe '#title' do
|
475
|
+
it 'should automatically set the channel id to a uuid(title)' do
|
476
|
+
a_title = "A title"
|
477
|
+
element.title a_title
|
478
|
+
element.id.text!.should == Helpers::uuid(a_title, 'ESSID:')
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
describe '#add_title' do
|
483
|
+
it 'should automatically set the channel id to a uuid(title)' do
|
484
|
+
a_title = "A title"
|
485
|
+
element.add_title a_title
|
486
|
+
element.id.text!.should == Helpers::uuid(a_title, 'ESSID:')
|
487
|
+
end
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
context 'when id was set' do
|
492
|
+
let(:an_id) { Helpers::uuid("Some text", 'ESSID:') }
|
493
|
+
|
494
|
+
describe '#title' do
|
495
|
+
it 'should not automatically set the channel id to a uuid(title)' do
|
496
|
+
element.id an_id
|
497
|
+
a_title = "A title"
|
498
|
+
element.title a_title
|
499
|
+
element.id.text!.should == an_id
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
describe '#add_title' do
|
504
|
+
it 'should not automatically set the channel id to a uuid(title)' do
|
505
|
+
element.id an_id
|
506
|
+
a_title = "A title"
|
507
|
+
element.add_title a_title
|
508
|
+
element.id.text!.should == an_id
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
describe 'Validation' do
|
516
|
+
context 'an empty element which should not be empty' do
|
517
|
+
let(:element) do
|
518
|
+
element = Element.new :description, DTD::BASIC_ELEMENT
|
519
|
+
element.text! " "
|
520
|
+
element
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'should be invalid' do
|
524
|
+
element.should_not be_valid
|
525
|
+
end
|
526
|
+
|
527
|
+
it 'should be valid if fixed' do
|
528
|
+
element.text! "Sample text"
|
529
|
+
element.should be_valid
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
context 'an URL element' do
|
534
|
+
let(:element) { Element.new :logo, DTD::URL_ELEMENT }
|
535
|
+
|
536
|
+
it 'should be invalid if a bad URL is set' do
|
537
|
+
element.text! "bad url"
|
538
|
+
element.should_not be_valid
|
539
|
+
end
|
540
|
+
|
541
|
+
it 'should be valid if valid URL is set' do
|
542
|
+
element.text! "http://Example.com:8000/"
|
543
|
+
element.should be_valid
|
544
|
+
end
|
545
|
+
|
546
|
+
it 'should be valid if valid IP address is set' do
|
547
|
+
element.text! "192.168.0.1"
|
548
|
+
element.should be_valid
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
context 'an latitude element' do
|
553
|
+
let(:element) { Element.new :latitude, DTD::LATITUDE }
|
554
|
+
|
555
|
+
it 'should be invalid if not a floating point number' do
|
556
|
+
element.text! "bad"
|
557
|
+
element.should_not be_valid
|
558
|
+
end
|
559
|
+
|
560
|
+
it 'should be invalid if above limits' do
|
561
|
+
element.text! "1000.000"
|
562
|
+
element.should_not be_valid
|
563
|
+
end
|
564
|
+
|
565
|
+
it 'should be valid if within limit' do
|
566
|
+
element.text! "70.31"
|
567
|
+
element.should be_valid
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
context 'an longitude element' do
|
572
|
+
let(:element) { Element.new :longitude, DTD::LONGITUDE }
|
573
|
+
|
574
|
+
it 'should be invalid if not a floating point number' do
|
575
|
+
element.text! "bad"
|
576
|
+
element.should_not be_valid
|
577
|
+
end
|
578
|
+
|
579
|
+
it 'should be invalid if above limits' do
|
580
|
+
element.text! "1000.000"
|
581
|
+
element.should_not be_valid
|
582
|
+
end
|
583
|
+
|
584
|
+
it 'should be valid if within limit' do
|
585
|
+
element.text! "90.31"
|
586
|
+
element.should be_valid
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
context 'a country code element' do
|
591
|
+
let(:element) { Element.new :country_code, DTD::COUNTRY_CODE }
|
592
|
+
|
593
|
+
it 'should be invalid if not a valid country code' do
|
594
|
+
element.text! "bad"
|
595
|
+
element.should_not be_valid
|
596
|
+
end
|
597
|
+
|
598
|
+
it 'should be valid if valid country code' do
|
599
|
+
element.text! "US"
|
600
|
+
element.should be_valid
|
601
|
+
end
|
602
|
+
|
603
|
+
it 'should be valid if valid country code but lower case is used' do
|
604
|
+
element.text! "us"
|
605
|
+
element.should be_valid
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
context 'a currency element' do
|
610
|
+
let(:element) { Element.new :currency, DTD::CURRENCY }
|
611
|
+
|
612
|
+
it 'should be invalid if not a valid currency' do
|
613
|
+
element.text! "bad"
|
614
|
+
element.should_not be_valid
|
615
|
+
end
|
616
|
+
|
617
|
+
it 'should be valid if valid currency' do
|
618
|
+
element.text! "USD"
|
619
|
+
element.should be_valid
|
620
|
+
end
|
621
|
+
|
622
|
+
it 'should be valid if valid currency but lower case is used' do
|
623
|
+
element.text! "usd"
|
624
|
+
element.should be_valid
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
context 'a price item with a value tag, but without a currency tag' do
|
629
|
+
let(:element) do
|
630
|
+
element = Element.new :item, DTD::PRICE_ITEM
|
631
|
+
element.type_attr "standalone"
|
632
|
+
element.mode_attr "fixed"
|
633
|
+
element.name "Example name"
|
634
|
+
element
|
635
|
+
end
|
636
|
+
|
637
|
+
context 'when value is 0' do
|
638
|
+
before(:each) { element.value 0 }
|
639
|
+
|
640
|
+
it 'should not raise error' do
|
641
|
+
lambda {
|
642
|
+
element.validate
|
643
|
+
}.should_not raise_error
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
context 'when value is not 0' do
|
648
|
+
before(:each) { element.value 5 }
|
649
|
+
|
650
|
+
it 'should raise an error' do
|
651
|
+
lambda {
|
652
|
+
element.validate
|
653
|
+
}.should raise_error
|
654
|
+
end
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
658
|
+
context 'attributes' do
|
659
|
+
describe 'an element with a mandatory attribute' do
|
660
|
+
let(:element) do
|
661
|
+
element = Element.new :item, DTD::PRICE_ITEM
|
662
|
+
element.name "Example name"
|
663
|
+
element.value 0
|
664
|
+
element
|
665
|
+
end
|
666
|
+
|
667
|
+
context 'when the mandatory attribute is missing' do
|
668
|
+
it 'should be invalid' do
|
669
|
+
element.should_not be_valid
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
context 'when the mandatory attribute is set' do
|
674
|
+
it 'should be valid' do
|
675
|
+
element.type_attr "standalone"
|
676
|
+
element.mode_attr "fixed"
|
677
|
+
element.should be_valid
|
678
|
+
end
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
describe 'an element with an attribute with one value limit' do
|
683
|
+
let(:element) do
|
684
|
+
element = Element.new :item, DTD::PRICE_ITEM
|
685
|
+
element.mode_attr "fixed"
|
686
|
+
element.name "Example name"
|
687
|
+
element.value 0
|
688
|
+
element
|
689
|
+
end
|
690
|
+
|
691
|
+
context 'when single value is set' do
|
692
|
+
before(:each) { element.type_attr "standalone" }
|
693
|
+
|
694
|
+
it 'should be valid' do
|
695
|
+
element.should be_valid
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
context 'when a multiple value is set' do
|
700
|
+
before(:each) { element.type_attr "standalone,recurrent" }
|
701
|
+
|
702
|
+
it 'should not be valid' do
|
703
|
+
element.should_not be_valid
|
704
|
+
end
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
describe 'lang attribute in ESS tag' do
|
709
|
+
let(:element) { Examples.ring_cycle }
|
710
|
+
|
711
|
+
context 'when attribute has a valid value' do
|
712
|
+
it 'should be valid' do
|
713
|
+
element.lang_attr "zu"
|
714
|
+
element.should be_valid
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
context 'when attribute has an invalid value' do
|
719
|
+
it 'should not be valid' do
|
720
|
+
element.lang_attr "bad"
|
721
|
+
element.should_not be_valid
|
722
|
+
end
|
723
|
+
end
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
context "a date item" do
|
728
|
+
let(:element) do
|
729
|
+
element = Element.new(:item, DTD::DATE_ITEM)
|
730
|
+
element.name "An example date"
|
731
|
+
element.start Time.now
|
732
|
+
element
|
733
|
+
end
|
734
|
+
|
735
|
+
context 'type is recurrent' do
|
736
|
+
before(:each) { element.type_attr "recurrent" }
|
737
|
+
context 'unit type is defined' do
|
738
|
+
it 'should be valid' do
|
739
|
+
element.unit_attr "month"
|
740
|
+
element.should be_valid
|
741
|
+
end
|
742
|
+
end
|
743
|
+
context 'unit type is not defined' do
|
744
|
+
it 'should not be valid' do
|
745
|
+
element.should_not be_valid
|
746
|
+
end
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
context 'type is standalone' do
|
751
|
+
before(:each) { element.type_attr "standalone" }
|
752
|
+
|
753
|
+
it 'should be valid without unit attr' do
|
754
|
+
element.should be_valid
|
755
|
+
end
|
756
|
+
end
|
757
|
+
end
|
758
|
+
|
759
|
+
context "a price item" do
|
760
|
+
let(:element) do
|
761
|
+
element = Element.new(:item, DTD::PRICE_ITEM)
|
762
|
+
element.mode_attr "fixed"
|
763
|
+
element.name "An example price"
|
764
|
+
element.value 10
|
765
|
+
element.currency "USD"
|
766
|
+
element.start Time.now
|
767
|
+
element
|
768
|
+
end
|
769
|
+
|
770
|
+
context 'type is recurrent' do
|
771
|
+
before(:each) { element.type_attr "recurrent" }
|
772
|
+
context 'unit type is defined' do
|
773
|
+
it 'should be valid' do
|
774
|
+
element.unit_attr "month"
|
775
|
+
element.should be_valid
|
776
|
+
end
|
777
|
+
end
|
778
|
+
context 'unit type is not defined' do
|
779
|
+
it 'should not be valid' do
|
780
|
+
element.should_not be_valid
|
781
|
+
end
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
context 'type is standalone' do
|
786
|
+
before(:each) { element.type_attr "standalone" }
|
787
|
+
|
788
|
+
it 'should be valid without unit attr' do
|
789
|
+
element.should be_valid
|
790
|
+
end
|
791
|
+
end
|
792
|
+
end
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|