erector 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +17 -3
- data/VERSION.yml +2 -2
- data/bin/erector +1 -1
- data/lib/erector.rb +22 -2
- data/lib/erector/after_initialize.rb +34 -0
- data/lib/erector/caching.rb +93 -0
- data/lib/erector/convenience.rb +58 -0
- data/lib/erector/dependencies.rb +24 -0
- data/lib/erector/dependency.rb +21 -0
- data/lib/erector/{erect.rb → erect/erect.rb} +14 -4
- data/lib/erector/{erected.rb → erect/erected.rb} +6 -4
- data/lib/erector/{indenting.rb → erect/indenting.rb} +0 -0
- data/lib/erector/{rhtml.treetop → erect/rhtml.treetop} +51 -11
- data/lib/erector/errors.rb +12 -0
- data/lib/erector/extensions/hash.rb +21 -0
- data/lib/erector/externals.rb +88 -24
- data/lib/erector/html.rb +352 -0
- data/lib/erector/inline.rb +5 -5
- data/lib/erector/jquery.rb +36 -0
- data/lib/erector/mixin.rb +3 -5
- data/lib/erector/needs.rb +94 -0
- data/lib/erector/output.rb +117 -0
- data/lib/erector/rails.rb +2 -2
- data/lib/erector/rails/extensions/action_controller.rb +5 -3
- data/lib/erector/rails/extensions/rails_helpers.rb +159 -0
- data/lib/erector/rails/extensions/rails_widget.rb +98 -56
- data/lib/erector/rails/rails_form_builder.rb +8 -4
- data/lib/erector/rails/rails_version.rb +2 -2
- data/lib/erector/rails/template_handlers/ert_handler.rb +1 -1
- data/lib/erector/rails/template_handlers/rb_handler.rb +42 -1
- data/lib/erector/raw_string.rb +2 -2
- data/lib/erector/sass.rb +22 -0
- data/lib/erector/widget.rb +100 -653
- data/lib/erector/widgets.rb +1 -0
- data/lib/erector/widgets/external_renderer.rb +51 -0
- data/lib/erector/widgets/page.rb +45 -63
- data/lib/erector/widgets/table.rb +9 -1
- data/spec/erect/erect_rails_spec.rb +19 -17
- data/spec/erect/erect_spec.rb +11 -1
- data/spec/erect/erected_spec.rb +76 -5
- data/spec/erect/rhtml_parser_spec.rb +11 -1
- data/spec/erector/caching_spec.rb +267 -0
- data/spec/erector/convenience_spec.rb +258 -0
- data/spec/erector/dependency_spec.rb +46 -0
- data/spec/erector/externals_spec.rb +233 -0
- data/spec/erector/html_spec.rb +508 -0
- data/spec/erector/indentation_spec.rb +84 -24
- data/spec/erector/inline_spec.rb +19 -8
- data/spec/erector/jquery_spec.rb +35 -0
- data/spec/erector/mixin_spec.rb +1 -1
- data/spec/erector/needs_spec.rb +120 -0
- data/spec/erector/output_spec.rb +199 -0
- data/spec/erector/sample-file.txt +1 -0
- data/spec/erector/sass_spec.rb +33 -0
- data/spec/erector/widget_spec.rb +113 -932
- data/spec/erector/widgets/field_table_spec.rb +6 -6
- data/spec/erector/widgets/form_spec.rb +3 -3
- data/spec/erector/widgets/page_spec.rb +52 -6
- data/spec/erector/widgets/table_spec.rb +4 -4
- data/spec/spec_helper.rb +70 -29
- metadata +56 -19
- data/lib/erector/rails/extensions/rails_widget/rails_helpers.rb +0 -137
- data/spec/core_spec_suite.rb +0 -3
- data/spec/erector/external_spec.rb +0 -110
- data/spec/rails_spec_suite.rb +0 -3
- data/spec/spec.opts +0 -1
- data/spec/spec_suite.rb +0 -40
@@ -0,0 +1 @@
|
|
1
|
+
sample file contents, 2 + 2 = #{2 + 2}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
if !Object.const_defined?(:Sass)
|
4
|
+
puts "Skipping Sass spec... run 'gem install haml' to enable these tests."
|
5
|
+
else
|
6
|
+
module CacheSpec
|
7
|
+
describe Erector::Sass do
|
8
|
+
include Erector::Mixin
|
9
|
+
it "works" do
|
10
|
+
erector {sass SAMPLE_SASS}.should == SAMPLE_CSS
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
SAMPLE_SASS =<<-SASS
|
17
|
+
h1
|
18
|
+
height: 118px
|
19
|
+
margin-top: 1em
|
20
|
+
|
21
|
+
.tagline
|
22
|
+
font-size: 26px
|
23
|
+
text-align: right
|
24
|
+
SASS
|
25
|
+
|
26
|
+
SAMPLE_CSS ="""<style>h1 {
|
27
|
+
height: 118px;
|
28
|
+
margin-top: 1em; }
|
29
|
+
|
30
|
+
.tagline {
|
31
|
+
font-size: 26px;
|
32
|
+
text-align: right; }
|
33
|
+
</style>"""
|
data/spec/erector/widget_spec.rb
CHANGED
@@ -3,163 +3,119 @@ require 'benchmark'
|
|
3
3
|
|
4
4
|
module WidgetSpec
|
5
5
|
describe Erector::Widget do
|
6
|
-
|
7
|
-
it "returns set of full and empty tags" do
|
8
|
-
Erector::Widget.all_tags.class.should == Array
|
9
|
-
Erector::Widget.all_tags.should == Erector::Widget.full_tags + Erector::Widget.empty_tags
|
10
|
-
end
|
11
|
-
end
|
6
|
+
include Erector::Mixin
|
12
7
|
|
13
|
-
describe "#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
div "Hello"
|
19
|
-
end
|
20
|
-
mock.proxy(widget).content
|
21
|
-
widget.to_s.should == "<div>Hello</div>"
|
8
|
+
describe "#to_html" do
|
9
|
+
it "invokes #content and returns the string representation of the rendered widget" do
|
10
|
+
Class.new(Erector::Widget) do
|
11
|
+
def content
|
12
|
+
text "Hello"
|
22
13
|
end
|
23
|
-
end
|
14
|
+
end.new.to_html.should == "Hello"
|
24
15
|
end
|
25
16
|
|
26
|
-
|
27
|
-
|
17
|
+
it "supports other content methods via :content_method_name" do
|
18
|
+
Class.new(Erector::Widget) do
|
19
|
+
def alternate
|
20
|
+
text "Alternate"
|
21
|
+
end
|
22
|
+
end.new.to_html(:content_method_name => :alternate).should == "Alternate"
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
|
25
|
+
it "returns an HTML-safe string" do
|
26
|
+
Erector::Widget.new.to_html.should be_html_safe
|
32
27
|
end
|
33
28
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
div "Hello from Alternate Write"
|
40
|
-
end
|
41
|
-
mock.proxy(widget).alternate_content
|
42
|
-
end
|
43
|
-
|
44
|
-
it "invokes the passed in method name and returns the string representation of the rendered widget" do
|
45
|
-
widget.to_s(:content_method_name => :alternate_content).should == "<div>Hello from Alternate Write</div>"
|
46
|
-
end
|
29
|
+
it "accepts an existing string as an output buffer" do
|
30
|
+
s = "foo"
|
31
|
+
Erector.inline { text "bar" }.to_html(:output => s)
|
32
|
+
s.should == "foobar"
|
33
|
+
end
|
47
34
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
35
|
+
it "accepts an existing Output as an output buffer" do
|
36
|
+
output = Erector::Output.new
|
37
|
+
output << "foo"
|
38
|
+
Erector.inline { text "bar" }.to_html(:output => output)
|
39
|
+
output.to_s.should == "foobar"
|
52
40
|
end
|
53
41
|
end
|
54
42
|
|
55
43
|
describe "#to_a" do
|
56
44
|
it "returns an array" do
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
widget.to_a.should == ["<div>", "Hello", "</div>"]
|
61
|
-
end
|
62
|
-
|
63
|
-
# removing this, since oddly, when i run this test solo it works, but when
|
64
|
-
# i run it as part of a rake suite, i get the opposite result -Alex
|
65
|
-
# it "runs faster than using a string as the output" do
|
66
|
-
# widget = Erector.inline do
|
67
|
-
# 1000.times do |i|
|
68
|
-
# div "Lorem ipsum dolor sit amet #{i}, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est #{i} laborum."
|
69
|
-
# end
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# times = 20
|
73
|
-
# time_for_to_a = Benchmark.measure { times.times { widget.to_a } }.total
|
74
|
-
# # puts "to_a: #{time_for_to_a}"
|
75
|
-
# time_for_string = Benchmark.measure { times.times { widget.to_s(:output => "") } }.total
|
76
|
-
# # puts "to_s(''): #{time_for_string}"
|
77
|
-
#
|
78
|
-
# percent_faster = (((time_for_string - time_for_to_a) / time_for_string)*100)
|
79
|
-
# # puts ("%.1f%%" % percent_faster)
|
80
|
-
#
|
81
|
-
# (time_for_to_a <= time_for_string).should be_true
|
82
|
-
# end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe "#instruct" do
|
86
|
-
it "when passed no arguments; returns an XML declaration with version 1 and utf-8" do
|
87
|
-
html = Erector.inline do
|
88
|
-
instruct
|
89
|
-
# version must precede encoding, per XML 1.0 4th edition (section 2.8)
|
90
|
-
end.to_s.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
45
|
+
a = Erector.inline { div "Hello" }.to_a
|
46
|
+
a.should be_an(Array)
|
47
|
+
a.join.should == "<div>Hello</div>"
|
91
48
|
end
|
92
49
|
end
|
93
50
|
|
94
51
|
describe '#widget' do
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
widget Child do
|
101
|
-
text 2
|
102
|
-
third
|
103
|
-
end
|
104
|
-
end
|
52
|
+
class Orphan < Erector::Widget
|
53
|
+
def content
|
54
|
+
p @name
|
55
|
+
end
|
56
|
+
end
|
105
57
|
|
106
|
-
|
107
|
-
|
108
|
-
|
58
|
+
it "renders a widget class" do
|
59
|
+
erector do
|
60
|
+
div do
|
61
|
+
widget Orphan, :name => "Annie"
|
109
62
|
end
|
63
|
+
end.should == "<div><p>Annie</p></div>"
|
64
|
+
end
|
110
65
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
66
|
+
it "renders a widget instance" do
|
67
|
+
erector do
|
68
|
+
div do
|
69
|
+
widget Orphan.new(:name => "Oliver")
|
115
70
|
end
|
116
|
-
end
|
117
|
-
|
118
|
-
it "renders nested widgets in the correct order" do
|
119
|
-
Parent.new.to_s.should == '123'
|
120
|
-
end
|
71
|
+
end.should == "<div><p>Oliver</p></div>"
|
121
72
|
end
|
122
|
-
|
123
|
-
end
|
124
73
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
74
|
+
it "adds the widget to the parent's output widgets" do
|
75
|
+
inner = Class.new(Erector::Widget)
|
76
|
+
outer = Erector.inline { widget inner }
|
77
|
+
outer.to_html
|
78
|
+
outer.output.widgets.should include(inner)
|
130
79
|
end
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
div do
|
136
|
-
widget Orphan, :name => "Annie"
|
137
|
-
end
|
138
|
-
end.to_s.should == "<div><p>Annie</p></div>"
|
80
|
+
|
81
|
+
it "supports specifying content_method_name" do
|
82
|
+
inner = Class.new(Erector::Widget) do
|
83
|
+
def foo; text "foo"; end
|
139
84
|
end
|
85
|
+
erector do
|
86
|
+
widget inner, {}, :content_method_name => :foo
|
87
|
+
end.should == "foo"
|
140
88
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
89
|
+
|
90
|
+
it "renders nested widgets in the correct order" do
|
91
|
+
class Parent < Erector::Widget
|
92
|
+
def content
|
93
|
+
text 1
|
94
|
+
widget Erector::Widget do
|
95
|
+
text 2
|
96
|
+
third
|
147
97
|
end
|
148
|
-
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def third
|
101
|
+
text 3
|
102
|
+
end
|
149
103
|
end
|
104
|
+
|
105
|
+
Parent.new.to_html.should == '123'
|
150
106
|
end
|
151
107
|
|
152
108
|
context "when nested" do
|
153
|
-
|
154
|
-
|
109
|
+
module WhenNested
|
110
|
+
class Parent < Erector::Widget
|
155
111
|
def content
|
156
112
|
div :id => "parent_widget" do
|
157
113
|
super
|
158
114
|
end
|
159
115
|
end
|
160
116
|
end
|
161
|
-
|
162
|
-
|
117
|
+
|
118
|
+
class Child < Erector::Widget
|
163
119
|
def content
|
164
120
|
div :id => "child_widget" do
|
165
121
|
super
|
@@ -167,7 +123,7 @@ module WidgetSpec
|
|
167
123
|
end
|
168
124
|
end
|
169
125
|
|
170
|
-
|
126
|
+
class Grandchild < Erector::Widget
|
171
127
|
needs :parent_widget, :child_widget
|
172
128
|
def content
|
173
129
|
widget(@parent_widget) do
|
@@ -177,24 +133,31 @@ module WidgetSpec
|
|
177
133
|
end
|
178
134
|
end
|
179
135
|
end
|
136
|
+
end
|
180
137
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
" <div id=\"grandchild\"></div>\n" +
|
188
|
-
" </div>\n" +
|
189
|
-
"</div>"
|
190
|
-
end
|
138
|
+
it "renders the tag around the rest of the block" do
|
139
|
+
WhenNested::Grandchild.new(
|
140
|
+
:parent_widget => WhenNested::Parent,
|
141
|
+
:child_widget => WhenNested::Child
|
142
|
+
).to_html.should == '<div id="parent_widget"><div id="child_widget"><div id="grandchild"></div></div></div>'
|
143
|
+
end
|
191
144
|
|
145
|
+
it "renders the tag around the rest of the block with proper indentation" do
|
146
|
+
WhenNested::Grandchild.new(
|
147
|
+
:parent_widget => WhenNested::Parent,
|
148
|
+
:child_widget => WhenNested::Child
|
149
|
+
).to_pretty.should ==
|
150
|
+
"<div id=\"parent_widget\">\n" +
|
151
|
+
" <div id=\"child_widget\">\n" +
|
152
|
+
" <div id=\"grandchild\"></div>\n" +
|
153
|
+
" </div>\n" +
|
154
|
+
"</div>\n"
|
192
155
|
end
|
193
|
-
|
156
|
+
|
194
157
|
it "passes a pointer to the child object back into the parent object's block" do
|
195
158
|
child_widget = Erector::Widget.new
|
196
|
-
|
197
|
-
class
|
159
|
+
|
160
|
+
class Parent2 < Erector::Widget
|
198
161
|
needs :child_widget
|
199
162
|
def content
|
200
163
|
div do
|
@@ -204,14 +167,12 @@ module WidgetSpec
|
|
204
167
|
end
|
205
168
|
end
|
206
169
|
end
|
207
|
-
|
208
|
-
|
209
|
-
|
170
|
+
|
171
|
+
Parent2.new(:child_widget => child_widget).to_html.should == "<div><b>#{child_widget.dom_id}</b></div>"
|
210
172
|
end
|
211
|
-
|
212
173
|
end
|
213
174
|
end
|
214
|
-
|
175
|
+
|
215
176
|
describe "#call_block" do
|
216
177
|
it "calls the block with a pointer to self" do
|
217
178
|
inside_arg = nil
|
@@ -227,624 +188,28 @@ module WidgetSpec
|
|
227
188
|
end
|
228
189
|
end
|
229
190
|
|
230
|
-
describe "#element" do
|
231
|
-
context "when receiving one argument" do
|
232
|
-
it "returns an empty element" do
|
233
|
-
Erector.inline do
|
234
|
-
element('div')
|
235
|
-
end.to_s.should == "<div></div>"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
context "with a attribute hash" do
|
240
|
-
it "returns an empty element with the attributes" do
|
241
|
-
html = Erector.inline do
|
242
|
-
element(
|
243
|
-
'div',
|
244
|
-
:class => "foo bar",
|
245
|
-
:style => "display: none; color: white; float: left;",
|
246
|
-
:nil_attribute => nil
|
247
|
-
)
|
248
|
-
end.to_s
|
249
|
-
doc = Nokogiri::HTML(html)
|
250
|
-
div = doc.at('div')
|
251
|
-
div[:class].should == "foo bar"
|
252
|
-
div[:style].should == "display: none; color: white; float: left;"
|
253
|
-
div[:nil_attribute].should be_nil
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
context "with an array of CSS classes" do
|
258
|
-
it "returns a tag with the classes separated" do
|
259
|
-
Erector.inline do
|
260
|
-
element('div', :class => [:foo, :bar])
|
261
|
-
end.to_s.should == "<div class=\"foo bar\"></div>";
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context "with an array of CSS classes as strings" do
|
266
|
-
it "returns a tag with the classes separated" do
|
267
|
-
Erector.inline do
|
268
|
-
element('div', :class => ['foo', 'bar'])
|
269
|
-
end.to_s.should == "<div class=\"foo bar\"></div>";
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
context "with a CSS class which is a string" do
|
274
|
-
it "just use that as the attribute value" do
|
275
|
-
Erector.inline do
|
276
|
-
element('div', :class => "foo bar")
|
277
|
-
end.to_s.should == "<div class=\"foo bar\"></div>";
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
context "with an empty array of CSS classes" do
|
282
|
-
it "does not emit a class attribute" do
|
283
|
-
Erector.inline do
|
284
|
-
element('div', :class => [])
|
285
|
-
end.to_s.should == "<div></div>"
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
context "with many attributes" do
|
290
|
-
it "alphabetize them" do
|
291
|
-
Erector.inline do
|
292
|
-
empty_element('foo', :alpha => "", :betty => "5", :aardvark => "tough",
|
293
|
-
:carol => "", :demon => "", :erector => "", :pi => "3.14", :omicron => "", :zebra => "", :brain => "")
|
294
|
-
end.to_s.should == "<foo aardvark=\"tough\" alpha=\"\" betty=\"5\" brain=\"\" carol=\"\" demon=\"\" " \
|
295
|
-
"erector=\"\" omicron=\"\" pi=\"3.14\" zebra=\"\" />";
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
context "with inner tags" do
|
300
|
-
it "returns nested tags" do
|
301
|
-
widget = Erector.inline do
|
302
|
-
element 'div' do
|
303
|
-
element 'div'
|
304
|
-
end
|
305
|
-
end
|
306
|
-
widget.to_s.should == '<div><div></div></div>'
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
context "with text" do
|
311
|
-
it "returns element with inner text" do
|
312
|
-
Erector.inline do
|
313
|
-
element 'div', 'test text'
|
314
|
-
end.to_s.should == "<div>test text</div>"
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
context "with object other than hash" do
|
319
|
-
it "returns element with inner text == object.to_s" do
|
320
|
-
object = ['a', 'b']
|
321
|
-
Erector.inline do
|
322
|
-
element 'div', object
|
323
|
-
end.to_s.should == "<div>#{object.to_s}</div>"
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
context "with parameters and block" do
|
328
|
-
it "returns element with inner html and attributes" do
|
329
|
-
Erector.inline do
|
330
|
-
element 'div', 'class' => "foobar" do
|
331
|
-
element 'span', 'style' => 'display: none;'
|
332
|
-
end
|
333
|
-
end.to_s.should == '<div class="foobar"><span style="display: none;"></span></div>'
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
context "with content and parameters" do
|
338
|
-
it "returns element with content as inner html and attributes" do
|
339
|
-
Erector.inline do
|
340
|
-
element 'div', 'test text', :style => "display: none;"
|
341
|
-
end.to_s.should == '<div style="display: none;">test text</div>'
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
context "with more than three arguments" do
|
346
|
-
it "raises ArgumentError" do
|
347
|
-
proc do
|
348
|
-
Erector.inline do
|
349
|
-
element 'div', 'foobar', {}, 'fourth'
|
350
|
-
end.to_s
|
351
|
-
end.should raise_error(ArgumentError)
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
it "renders the proper full tags" do
|
356
|
-
Erector::Widget.full_tags.each do |tag_name|
|
357
|
-
expected = "<#{tag_name}></#{tag_name}>"
|
358
|
-
actual = Erector.inline do
|
359
|
-
send(tag_name)
|
360
|
-
end.to_s
|
361
|
-
begin
|
362
|
-
actual.should == expected
|
363
|
-
rescue Spec::Expectations::ExpectationNotMetError => e
|
364
|
-
puts "Expected #{tag_name} to be a full element. Expected #{expected}, got #{actual}"
|
365
|
-
raise e
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
describe "quoting" do
|
371
|
-
context "when outputting text" do
|
372
|
-
it "quotes it" do
|
373
|
-
Erector.inline do
|
374
|
-
element 'div', 'test &<>text'
|
375
|
-
end.to_s.should == "<div>test &<>text</div>"
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
context "when outputting text via text" do
|
380
|
-
it "quotes it" do
|
381
|
-
Erector.inline do
|
382
|
-
element 'div' do
|
383
|
-
text "test &<>text"
|
384
|
-
end
|
385
|
-
end.to_s.should == "<div>test &<>text</div>"
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
context "when outputting attribute value" do
|
390
|
-
it "quotes it" do
|
391
|
-
Erector.inline do
|
392
|
-
element 'a', :href => "foo.cgi?a&b"
|
393
|
-
end.to_s.should == "<a href=\"foo.cgi?a&b\"></a>"
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
context "with raw text" do
|
398
|
-
it "does not quote it" do
|
399
|
-
Erector.inline do
|
400
|
-
element 'div' do
|
401
|
-
text raw("<b>bold</b>")
|
402
|
-
end
|
403
|
-
end.to_s.should == "<div><b>bold</b></div>"
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
context "with raw text and no block" do
|
408
|
-
it "does not quote it" do
|
409
|
-
Erector.inline do
|
410
|
-
element 'div', raw("<b>bold</b>")
|
411
|
-
end.to_s.should == "<div><b>bold</b></div>"
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
context "with raw attribute" do
|
416
|
-
it "does not quote it" do
|
417
|
-
Erector.inline do
|
418
|
-
element 'a', :href => raw("foo?x= ")
|
419
|
-
end.to_s.should == "<a href=\"foo?x= \"></a>"
|
420
|
-
end
|
421
|
-
end
|
422
|
-
|
423
|
-
context "with quote in attribute" do
|
424
|
-
it "quotes it" do
|
425
|
-
Erector.inline do
|
426
|
-
element 'a', :onload => "alert(\"foo\")"
|
427
|
-
end.to_s.should == "<a onload=\"alert("foo")\"></a>"
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
|
432
|
-
context "with a non-string, non-raw" do
|
433
|
-
it "calls to_s and quotes" do
|
434
|
-
Erector.inline do
|
435
|
-
element 'a' do
|
436
|
-
text [7, "foo&bar"]
|
437
|
-
end
|
438
|
-
end.to_s.should == "<a>7foo&bar</a>"
|
439
|
-
end
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
describe "#empty_element" do
|
444
|
-
context "when receiving attributes" do
|
445
|
-
it "renders an empty element with the attributes" do
|
446
|
-
Erector.inline do
|
447
|
-
empty_element 'input', :name => 'foo[bar]'
|
448
|
-
end.to_s.should == '<input name="foo[bar]" />'
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
context "when not receiving attributes" do
|
453
|
-
it "renders an empty element without attributes" do
|
454
|
-
Erector.inline do
|
455
|
-
empty_element 'br'
|
456
|
-
end.to_s.should == '<br />'
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
it "renders the proper empty-element tags" do
|
461
|
-
Erector::Widget.empty_tags.each do |tag_name|
|
462
|
-
expected = "<#{tag_name} />"
|
463
|
-
actual = Erector.inline do
|
464
|
-
send(tag_name)
|
465
|
-
end.to_s
|
466
|
-
begin
|
467
|
-
actual.should == expected
|
468
|
-
rescue Spec::Expectations::ExpectationNotMetError => e
|
469
|
-
puts "Expected #{tag_name} to be an empty-element tag. Expected #{expected}, got #{actual}"
|
470
|
-
raise e
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
def capturing_output
|
477
|
-
output = StringIO.new
|
478
|
-
$stdout = output
|
479
|
-
yield
|
480
|
-
output.string
|
481
|
-
ensure
|
482
|
-
$stdout = STDOUT
|
483
|
-
end
|
484
|
-
|
485
|
-
describe "#comment" do
|
486
|
-
it "emits a single line comment when receiving a string" do
|
487
|
-
Erector.inline do
|
488
|
-
comment "foo"
|
489
|
-
end.to_s.should == "<!--foo-->\n"
|
490
|
-
end
|
491
|
-
|
492
|
-
it "emits a multiline comment when receiving a block" do
|
493
|
-
Erector.inline do
|
494
|
-
comment do
|
495
|
-
text "Hello"
|
496
|
-
text " world!"
|
497
|
-
end
|
498
|
-
end.to_s.should == "<!--\nHello world!\n-->\n"
|
499
|
-
end
|
500
|
-
|
501
|
-
it "emits a multiline comment when receiving a string and a block" do
|
502
|
-
Erector.inline do
|
503
|
-
comment "Hello" do
|
504
|
-
text " world!"
|
505
|
-
end
|
506
|
-
end.to_s.should == "<!--Hello\n world!\n-->\n"
|
507
|
-
end
|
508
|
-
|
509
|
-
# see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
|
510
|
-
it "does not HTML-escape character references" do
|
511
|
-
Erector.inline do
|
512
|
-
comment " "
|
513
|
-
end.to_s.should == "<!-- -->\n"
|
514
|
-
end
|
515
|
-
|
516
|
-
# see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
|
517
|
-
# "Authors should avoid putting two or more adjacent hyphens inside comments."
|
518
|
-
it "warns if there's two hyphens in a row" do
|
519
|
-
capturing_output do
|
520
|
-
Erector.inline do
|
521
|
-
comment "he was -- awesome!"
|
522
|
-
end.to_s.should == "<!--he was -- awesome!-->\n"
|
523
|
-
end.should == "Warning: Authors should avoid putting two or more adjacent hyphens inside comments.\n"
|
524
|
-
end
|
525
|
-
|
526
|
-
it "renders an IE conditional comment with endif when receiving an if IE" do
|
527
|
-
Erector.inline do
|
528
|
-
comment "[if IE]" do
|
529
|
-
text "Hello IE!"
|
530
|
-
end
|
531
|
-
end.to_s.should == "<!--[if IE]>\nHello IE!\n<![endif]-->\n"
|
532
|
-
end
|
533
|
-
|
534
|
-
it "doesn't render an IE conditional comment if there's just some text in brackets" do
|
535
|
-
Erector.inline do
|
536
|
-
comment "[puppies are cute]"
|
537
|
-
end.to_s.should == "<!--[puppies are cute]-->\n"
|
538
|
-
end
|
539
|
-
|
540
|
-
end
|
541
|
-
|
542
|
-
describe "#nbsp" do
|
543
|
-
it "turns consecutive spaces into consecutive non-breaking spaces" do
|
544
|
-
Erector.inline do
|
545
|
-
text nbsp("a b")
|
546
|
-
end.to_s.should == "a  b"
|
547
|
-
end
|
548
|
-
|
549
|
-
it "works in text context" do
|
550
|
-
Erector.inline do
|
551
|
-
element 'a' do
|
552
|
-
text nbsp("&<> foo")
|
553
|
-
end
|
554
|
-
end.to_s.should == "<a>&<> foo</a>"
|
555
|
-
end
|
556
|
-
|
557
|
-
it "works in attribute value context" do
|
558
|
-
Erector.inline do
|
559
|
-
element 'a', :href => nbsp("&<> foo")
|
560
|
-
end.to_s.should == "<a href=\"&<> foo\"></a>"
|
561
|
-
end
|
562
|
-
|
563
|
-
it "defaults to a single non-breaking space if given no argument" do
|
564
|
-
Erector.inline do
|
565
|
-
text nbsp
|
566
|
-
end.to_s.should == " "
|
567
|
-
end
|
568
|
-
|
569
|
-
end
|
570
|
-
|
571
|
-
describe "#character" do
|
572
|
-
it "renders a character given the codepoint number" do
|
573
|
-
Erector.inline do
|
574
|
-
text character(160)
|
575
|
-
end.to_s.should == " "
|
576
|
-
end
|
577
|
-
|
578
|
-
it "renders a character given the unicode name" do
|
579
|
-
Erector.inline do
|
580
|
-
text character(:right_arrow)
|
581
|
-
end.to_s.should == "→"
|
582
|
-
end
|
583
|
-
|
584
|
-
it "renders a character above 0xffff" do
|
585
|
-
Erector.inline do
|
586
|
-
text character(:old_persian_sign_ka)
|
587
|
-
end.to_s.should == "𐎣"
|
588
|
-
end
|
589
|
-
|
590
|
-
it "throws an exception if a name is not recognized" do
|
591
|
-
lambda {
|
592
|
-
Erector.inline do
|
593
|
-
text character(:no_such_character_name)
|
594
|
-
end.to_s
|
595
|
-
}.should raise_error("Unrecognized character no_such_character_name")
|
596
|
-
end
|
597
|
-
|
598
|
-
it "throws an exception if passed something besides a symbol or integer" do
|
599
|
-
# Perhaps calling to_s would be more ruby-esque, but that seems like it might
|
600
|
-
# be pretty confusing when this method can already take either a name or number
|
601
|
-
lambda {
|
602
|
-
Erector.inline do
|
603
|
-
text character([])
|
604
|
-
end.to_s
|
605
|
-
}.should raise_error("Unrecognized argument to character: ")
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
describe "#join" do
|
610
|
-
|
611
|
-
it "empty array means nothing to join" do
|
612
|
-
Erector.inline do
|
613
|
-
join [], Erector::Widget.new { text "x" }
|
614
|
-
end.to_s.should == ""
|
615
|
-
end
|
616
|
-
|
617
|
-
it "larger example with two tabs" do
|
618
|
-
Erector.inline do
|
619
|
-
tab1 =
|
620
|
-
Erector.inline do
|
621
|
-
a "Upload document", :href => "/upload"
|
622
|
-
end
|
623
|
-
tab2 =
|
624
|
-
Erector.inline do
|
625
|
-
a "Logout", :href => "/logout"
|
626
|
-
end
|
627
|
-
join [tab1, tab2],
|
628
|
-
Erector::Widget.new { text nbsp(" |"); text " " }
|
629
|
-
end.to_s.should ==
|
630
|
-
'<a href="/upload">Upload document</a> | <a href="/logout">Logout</a>'
|
631
|
-
end
|
632
|
-
|
633
|
-
it "plain string as join separator means pass it to text" do
|
634
|
-
Erector.inline do
|
635
|
-
join [
|
636
|
-
Erector::Widget.new { text "x" },
|
637
|
-
Erector::Widget.new { text "y" }
|
638
|
-
], "<>"
|
639
|
-
end.to_s.should == "x<>y"
|
640
|
-
end
|
641
|
-
|
642
|
-
it "plain string as item to join means pass it to text" do
|
643
|
-
Erector.inline do
|
644
|
-
join [
|
645
|
-
"<",
|
646
|
-
"&"
|
647
|
-
], Erector::Widget.new { text " + " }
|
648
|
-
end.to_s.should == "< + &"
|
649
|
-
end
|
650
|
-
|
651
|
-
end
|
652
|
-
|
653
|
-
describe '#h' do
|
654
|
-
before do
|
655
|
-
@widget = Erector::Widget.new
|
656
|
-
end
|
657
|
-
|
658
|
-
it "escapes regular strings" do
|
659
|
-
@widget.h("&").should == "&"
|
660
|
-
end
|
661
|
-
|
662
|
-
it "does not escape raw strings" do
|
663
|
-
@widget.h(@widget.raw("&")).should == "&"
|
664
|
-
end
|
665
|
-
end
|
666
|
-
|
667
|
-
describe 'escaping' do
|
668
|
-
plain = 'if (x < y && x > z) alert("don\'t stop");'
|
669
|
-
escaped = "if (x < y && x > z) alert("don't stop");"
|
670
|
-
|
671
|
-
describe "#text" do
|
672
|
-
it "does HTML escape its param" do
|
673
|
-
Erector.inline { text plain }.to_s.should == escaped
|
674
|
-
end
|
675
|
-
end
|
676
|
-
describe "#rawtext" do
|
677
|
-
it "doesn't HTML escape its param" do
|
678
|
-
Erector.inline { rawtext plain }.to_s.should == plain
|
679
|
-
end
|
680
|
-
end
|
681
|
-
describe "#text!" do
|
682
|
-
it "doesn't HTML escape its param" do
|
683
|
-
Erector.inline { text! plain }.to_s.should == plain
|
684
|
-
end
|
685
|
-
end
|
686
|
-
describe "#element" do
|
687
|
-
it "does HTML escape its param" do
|
688
|
-
Erector.inline { element "foo", plain }.to_s.should == "<foo>#{escaped}</foo>"
|
689
|
-
end
|
690
|
-
end
|
691
|
-
describe "#element!" do
|
692
|
-
it "doesn't HTML escape its param" do
|
693
|
-
Erector.inline { element! "foo", plain }.to_s.should == "<foo>#{plain}</foo>"
|
694
|
-
end
|
695
|
-
end
|
696
|
-
end
|
697
|
-
|
698
|
-
describe "#javascript" do
|
699
|
-
context "when receiving a block" do
|
700
|
-
it "renders the content inside of script text/javascript tags" do
|
701
|
-
expected = <<-EXPECTED
|
702
|
-
<script type="text/javascript">
|
703
|
-
// <![CDATA[
|
704
|
-
if (x < y && x > z) alert("don't stop");
|
705
|
-
// ]]>
|
706
|
-
</script>
|
707
|
-
EXPECTED
|
708
|
-
expected.gsub!(/^ /, '')
|
709
|
-
Erector.inline do
|
710
|
-
javascript do
|
711
|
-
rawtext 'if (x < y && x > z) alert("don\'t stop");'
|
712
|
-
end
|
713
|
-
end.to_s.should == expected
|
714
|
-
end
|
715
|
-
end
|
716
|
-
|
717
|
-
it "renders the raw content inside script tags when given text" do
|
718
|
-
expected = <<-EXPECTED
|
719
|
-
<script type="text/javascript">
|
720
|
-
// <![CDATA[
|
721
|
-
alert("&<>'hello");
|
722
|
-
// ]]>
|
723
|
-
</script>
|
724
|
-
EXPECTED
|
725
|
-
expected.gsub!(/^ /, '')
|
726
|
-
Erector.inline do
|
727
|
-
javascript('alert("&<>\'hello");')
|
728
|
-
end.to_s.should == expected
|
729
|
-
end
|
730
|
-
|
731
|
-
context "when receiving a params hash" do
|
732
|
-
it "renders a source file" do
|
733
|
-
html = Erector.inline do
|
734
|
-
javascript(:src => "/my/js/file.js")
|
735
|
-
end.to_s
|
736
|
-
doc = Nokogiri::HTML(html)
|
737
|
-
doc.at("script")[:src].should == "/my/js/file.js"
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
context "when receiving text and a params hash" do
|
742
|
-
it "renders a source file" do
|
743
|
-
html = Erector.inline do
|
744
|
-
javascript('alert("&<>\'hello");', :src => "/my/js/file.js")
|
745
|
-
end.to_s
|
746
|
-
doc = Nokogiri::HTML(html)
|
747
|
-
script_tag = doc.at('script')
|
748
|
-
script_tag[:src].should == "/my/js/file.js"
|
749
|
-
script_tag.inner_html.should include('alert("&<>\'hello");')
|
750
|
-
end
|
751
|
-
end
|
752
|
-
|
753
|
-
context "with too many arguments" do
|
754
|
-
it "raises ArgumentError" do
|
755
|
-
proc do
|
756
|
-
Erector.inline do
|
757
|
-
javascript 'foobar', {}, 'fourth'
|
758
|
-
end.to_s
|
759
|
-
end.should raise_error(ArgumentError)
|
760
|
-
end
|
761
|
-
end
|
762
|
-
end
|
763
|
-
|
764
|
-
describe "#css" do
|
765
|
-
it "makes a link when passed a string" do
|
766
|
-
Erector.inline do
|
767
|
-
css "erector.css"
|
768
|
-
end.to_s.should == "<link href=\"erector.css\" rel=\"stylesheet\" type=\"text/css\" />"
|
769
|
-
end
|
770
|
-
|
771
|
-
it "accepts a media attribute" do
|
772
|
-
Erector.inline do
|
773
|
-
css "print.css", :media => "print"
|
774
|
-
end.to_s.should == "<link href=\"print.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\" />"
|
775
|
-
end
|
776
|
-
end
|
777
|
-
|
778
|
-
describe "#to_text" do
|
779
|
-
it "strips tags" do
|
780
|
-
Erector.inline do
|
781
|
-
div "foo"
|
782
|
-
end.to_text.should == "foo"
|
783
|
-
end
|
784
|
-
|
785
|
-
it "unescapes named entities" do
|
786
|
-
s = "my \"dog\" has fleas & <ticks>"
|
787
|
-
Erector.inline do
|
788
|
-
text s
|
789
|
-
end.to_text.should == s
|
790
|
-
end
|
791
|
-
|
792
|
-
it "ignores >s inside attribute strings" do
|
793
|
-
Erector.inline do
|
794
|
-
a "foo", :href => "http://example.com/x>y"
|
795
|
-
end.to_text.should == "foo"
|
796
|
-
end
|
797
|
-
|
798
|
-
it "doesn't inherit unwanted pretty-printed whitespace (i.e. it turns off prettyprinting)" do
|
799
|
-
old_default = Erector::Widget.new.prettyprint_default
|
800
|
-
begin
|
801
|
-
Erector::Widget.prettyprint_default = true
|
802
|
-
Erector.inline do
|
803
|
-
div { div { div "foo" } }
|
804
|
-
end.to_text.should == "foo"
|
805
|
-
ensure
|
806
|
-
Erector::Widget.prettyprint_default = old_default
|
807
|
-
end
|
808
|
-
end
|
809
|
-
end
|
810
|
-
|
811
|
-
describe "#url" do
|
812
|
-
it "renders an anchor tag with the same href and text" do
|
813
|
-
Erector.inline do
|
814
|
-
url "http://example.com"
|
815
|
-
end.to_s.should == "<a href=\"http://example.com\">http://example.com</a>"
|
816
|
-
end
|
817
|
-
|
818
|
-
it "accepts extra attributes" do
|
819
|
-
Erector.inline do
|
820
|
-
url "http://example.com", :onclick=>"alert('foo')"
|
821
|
-
end.to_s.should == "<a href=\"http://example.com\" onclick=\"alert('foo')\">http://example.com</a>"
|
822
|
-
end
|
823
|
-
end
|
824
|
-
|
825
191
|
describe '#capture' do
|
826
192
|
it "should return content rather than write it to the buffer" do
|
827
|
-
|
193
|
+
erector do
|
828
194
|
captured = capture do
|
829
195
|
p 'Captured Content'
|
830
196
|
end
|
831
197
|
div do
|
832
198
|
text captured
|
833
199
|
end
|
834
|
-
end
|
835
|
-
widget.to_s.should == '<div><p>Captured Content</p></div>'
|
200
|
+
end.should == '<div><p>Captured Content</p></div>'
|
836
201
|
end
|
837
202
|
|
838
203
|
it "returns a RawString" do
|
839
204
|
captured = nil
|
840
|
-
|
205
|
+
erector do
|
841
206
|
captured = capture {}
|
842
|
-
end.
|
843
|
-
captured.should be_a_kind_of
|
207
|
+
end.should == ""
|
208
|
+
captured.should be_a_kind_of(Erector::RawString)
|
844
209
|
end
|
845
210
|
|
846
211
|
it "works with nested captures" do
|
847
|
-
|
212
|
+
erector do
|
848
213
|
captured = capture do
|
849
214
|
captured = capture do
|
850
215
|
p 'Nested Capture'
|
@@ -855,215 +220,31 @@ module WidgetSpec
|
|
855
220
|
div do
|
856
221
|
text captured
|
857
222
|
end
|
858
|
-
end
|
859
|
-
widget.to_s.should == '<div><p>Captured Content</p><p>Nested Capture</p></div>'
|
860
|
-
end
|
861
|
-
end
|
862
|
-
|
863
|
-
describe 'nested' do
|
864
|
-
it "can insert another widget without raw" do
|
865
|
-
inner = Erector.inline do
|
866
|
-
p "foo"
|
867
|
-
end
|
868
|
-
|
869
|
-
outer = Erector.inline do
|
870
|
-
div inner
|
871
|
-
end.to_s.should == '<div><p>foo</p></div>'
|
223
|
+
end.should == '<div><p>Captured Content</p><p>Nested Capture</p></div>'
|
872
224
|
end
|
873
225
|
end
|
874
226
|
|
875
|
-
describe '#
|
876
|
-
|
877
|
-
|
878
|
-
p "A"
|
879
|
-
end
|
880
|
-
end
|
881
|
-
|
882
|
-
it "renders to a widget's doc" do
|
883
|
-
class B < Erector::Widget
|
884
|
-
def content
|
885
|
-
text "B"
|
886
|
-
A.new.write_via(self)
|
887
|
-
text "B"
|
888
|
-
end
|
889
|
-
end
|
890
|
-
b = B.new
|
891
|
-
b.to_s.should == "B<p>A</p>B"
|
892
|
-
end
|
893
|
-
|
894
|
-
it "passing a widget to text method renders it" do
|
895
|
-
Erector.inline do
|
227
|
+
describe '#text' do
|
228
|
+
it "renders a widget" do
|
229
|
+
erector do
|
896
230
|
text "B"
|
897
|
-
text A
|
231
|
+
text Erector.inline { p "A" }
|
898
232
|
text "B"
|
899
|
-
end.
|
233
|
+
end.should == "B<p>A</p>B"
|
900
234
|
end
|
901
|
-
|
902
235
|
end
|
903
|
-
|
904
|
-
describe "assigning instance variables" do
|
905
|
-
it "attempting to overwrite a reserved instance variable raises error" do
|
906
|
-
lambda {
|
907
|
-
Erector::Widget.new(:output => "foo")
|
908
|
-
}.should raise_error(ArgumentError)
|
909
|
-
end
|
910
236
|
|
237
|
+
describe "assigning instance variables" do
|
911
238
|
it "handles instance variable names with and without '@' in the beginning" do
|
912
239
|
html = Erector.inline(:foo => "bar", '@baz' => 'quux') do
|
913
240
|
div do
|
914
241
|
p @foo
|
915
242
|
p @baz
|
916
243
|
end
|
917
|
-
end.
|
244
|
+
end.to_html
|
918
245
|
doc = Nokogiri::HTML(html)
|
919
246
|
doc.css("p").map {|p| p.inner_html}.should == ["bar", "quux"]
|
920
247
|
end
|
921
248
|
end
|
922
|
-
|
923
|
-
context "when declaring parameters with the 'needs' macro" do
|
924
|
-
it "doesn't complain if there aren't any needs declared" do
|
925
|
-
class Thing1 < Erector::Widget
|
926
|
-
end
|
927
|
-
Thing1.new
|
928
|
-
end
|
929
|
-
|
930
|
-
it "allows you to say that you don't want any parameters" do
|
931
|
-
class Thing2 < Erector::Widget
|
932
|
-
needs nil
|
933
|
-
end
|
934
|
-
lambda { Thing2.new }.should_not raise_error
|
935
|
-
lambda { Thing2.new(:foo => 1) }.should raise_error
|
936
|
-
end
|
937
|
-
|
938
|
-
it "doesn't complain if you pass it a declared parameter" do
|
939
|
-
class Thing2b < Erector::Widget
|
940
|
-
needs :foo
|
941
|
-
end
|
942
|
-
lambda { Thing2b.new(:foo => 1) }.should_not raise_error
|
943
|
-
end
|
944
|
-
|
945
|
-
it "complains if you pass it an undeclared parameter" do
|
946
|
-
class Thing3 < Erector::Widget
|
947
|
-
needs :foo
|
948
|
-
end
|
949
|
-
lambda { Thing3.new(:bar => 1) }.should raise_error
|
950
|
-
end
|
951
|
-
|
952
|
-
it "allows multiple declared parameters" do
|
953
|
-
class Thing4 < Erector::Widget
|
954
|
-
needs :foo, :bar
|
955
|
-
end
|
956
|
-
lambda { Thing4.new(:foo => 1, :bar => 2) }.should_not raise_error
|
957
|
-
end
|
958
|
-
|
959
|
-
it "complains when passing in an extra parameter after declaring many parameters" do
|
960
|
-
class Thing5 < Erector::Widget
|
961
|
-
needs :foo, :bar
|
962
|
-
end
|
963
|
-
lambda { Thing5.new(:foo => 1, :bar => 2, :baz => 3) }.should raise_error
|
964
|
-
end
|
965
|
-
|
966
|
-
it "complains when you forget to pass in a needed parameter" do
|
967
|
-
class Thing6 < Erector::Widget
|
968
|
-
needs :foo, :bar
|
969
|
-
end
|
970
|
-
lambda { Thing6.new(:foo => 1) }.should raise_error
|
971
|
-
end
|
972
|
-
|
973
|
-
it "doesn't complain if you omit a parameter with a default value" do
|
974
|
-
class Thing7 < Erector::Widget
|
975
|
-
needs :foo
|
976
|
-
needs :bar => 7
|
977
|
-
needs :baz => 8
|
978
|
-
end
|
979
|
-
lambda {
|
980
|
-
thing = Thing7.new(:foo => 1, :baz => 3)
|
981
|
-
thing.instance_variable_get(:@bar).should equal(7)
|
982
|
-
thing.instance_variable_get(:@baz).should equal(3)
|
983
|
-
}.should_not raise_error
|
984
|
-
end
|
985
|
-
|
986
|
-
it "allows multiple values on a line, including default values at the end of the line" do
|
987
|
-
class Thing8 < Erector::Widget
|
988
|
-
needs :foo, :bar => 7, :baz => 8
|
989
|
-
end
|
990
|
-
lambda {
|
991
|
-
thing = Thing8.new(:foo => 1, :baz => 2)
|
992
|
-
thing.instance_variable_get(:@foo).should equal(1)
|
993
|
-
thing.instance_variable_get(:@bar).should equal(7)
|
994
|
-
thing.instance_variable_get(:@baz).should equal(2)
|
995
|
-
}.should_not raise_error
|
996
|
-
end
|
997
|
-
|
998
|
-
it "allows nil to be a default value" do
|
999
|
-
class Thing9 < Erector::Widget
|
1000
|
-
needs :foo => nil
|
1001
|
-
end
|
1002
|
-
lambda {
|
1003
|
-
thing = Thing9.new
|
1004
|
-
thing.instance_variable_get(:@foo).should be_nil
|
1005
|
-
}.should_not raise_error
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
it "accumulates needs across the inheritance chain even with modules mixed in" do
|
1009
|
-
module Something
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
class Vehicle < Erector::Widget
|
1013
|
-
needs :wheels
|
1014
|
-
end
|
1015
|
-
|
1016
|
-
class Car < Vehicle
|
1017
|
-
include Something
|
1018
|
-
needs :engine
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
lambda { Car.new(:engine => 'V-8', :wheels => 4) }.should_not raise_error
|
1022
|
-
lambda { Car.new(:engine => 'V-8') }.should raise_error
|
1023
|
-
lambda { Car.new(:wheels => 4) }.should raise_error
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
it "no longer defines accessors for each of the needed variables" do
|
1027
|
-
class NeedfulThing < Erector::Widget
|
1028
|
-
needs :love
|
1029
|
-
end
|
1030
|
-
thing = NeedfulThing.new(:love => "all we need")
|
1031
|
-
lambda {thing.love}.should raise_error(NoMethodError)
|
1032
|
-
end
|
1033
|
-
|
1034
|
-
it "no longer complains if you attempt to 'need' a variable whose name overlaps with an existing method" do
|
1035
|
-
class ThingWithOverlap < Erector::Widget
|
1036
|
-
needs :text
|
1037
|
-
end
|
1038
|
-
lambda { ThingWithOverlap.new(:text => "alas") }.should_not raise_error(ArgumentError)
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
end
|
1042
|
-
|
1043
|
-
describe "#close_tag" do
|
1044
|
-
it "works when it's all alone, even though it messes with the indent level" do
|
1045
|
-
Erector.inline { close_tag :foo }.to_s.should == "</foo>"
|
1046
|
-
Erector.inline { close_tag :foo; close_tag :bar }.to_s.should == "</foo></bar>"
|
1047
|
-
end
|
1048
|
-
end
|
1049
|
-
|
1050
|
-
describe "#dom_id" do
|
1051
|
-
class NiceWidget < Erector::Widget
|
1052
|
-
def content
|
1053
|
-
div :id => dom_id
|
1054
|
-
end
|
1055
|
-
end
|
1056
|
-
|
1057
|
-
it "makes a unique id based on the widget's class name and object id" do
|
1058
|
-
widget = NiceWidget.new
|
1059
|
-
widget.dom_id.should include("#{widget.object_id}")
|
1060
|
-
widget.dom_id.should include("NiceWidget")
|
1061
|
-
end
|
1062
|
-
|
1063
|
-
it "can be used as an HTML id" do
|
1064
|
-
widget = NiceWidget.new
|
1065
|
-
widget.to_s.should == "<div id=\"#{widget.dom_id}\"></div>"
|
1066
|
-
end
|
1067
|
-
end
|
1068
249
|
end
|
1069
250
|
end
|