ess 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+