erector 0.7.2 → 0.8.0
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/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
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
2
|
|
3
|
-
require "erector/erect"
|
3
|
+
require "erector/erect/erect"
|
4
4
|
|
5
5
|
module ParserTestHelper
|
6
6
|
def assert_evals_to_self(input)
|
@@ -167,6 +167,11 @@ describe RhtmlParser do
|
|
167
167
|
parse("<div id='foo'>bar</div>").convert.should == "div :id => 'foo' do\n text 'bar'\nend\n"
|
168
168
|
end
|
169
169
|
|
170
|
+
it "processes ERb escapes in attributes, and adds parentheses when required" do
|
171
|
+
parse("<div id=\"<%= bar %>\" />").convert.should == "div :id => bar\n"
|
172
|
+
parse("<div id=\"foo_<%= bar %>_baz\" />").convert.should == "div(:id => ('foo_' + bar + '_baz'))\n"
|
173
|
+
end
|
174
|
+
|
170
175
|
it "escapes single quotes inside attribute values" do
|
171
176
|
@parser.root = :attribute
|
172
177
|
parse("a=\"don't worry\"").convert.should == ":a => 'don\\'t worry'"
|
@@ -228,6 +233,11 @@ describe RhtmlParser do
|
|
228
233
|
parse("'foo'").value.should == "foo"
|
229
234
|
parse("\"foo\"").value.should == "foo"
|
230
235
|
end
|
236
|
+
|
237
|
+
it "quotes empty strings" do
|
238
|
+
@parser.root = :quoted
|
239
|
+
parse("''").convert.should == "''"
|
240
|
+
end
|
231
241
|
|
232
242
|
it "converts attributes in isolation" do
|
233
243
|
@parser.root = :attribute
|
@@ -0,0 +1,267 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
describe Erector::Cache do
|
4
|
+
before do
|
5
|
+
@cache = Erector::Cache.new
|
6
|
+
end
|
7
|
+
|
8
|
+
class Johnny < Erector::Widget
|
9
|
+
end
|
10
|
+
|
11
|
+
class June < Erector::Widget
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'caches a class with no parameters' do
|
15
|
+
@cache[Johnny] = "ring of fire"
|
16
|
+
@cache[Johnny].should == "ring of fire"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'caches two classes with no parameters' do
|
20
|
+
@cache[Johnny] = "ring of fire"
|
21
|
+
@cache[June] = "wildwood flower"
|
22
|
+
@cache[Johnny].should == "ring of fire"
|
23
|
+
@cache[June].should == "wildwood flower"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "stores different slots for the same class with different parameters" do
|
27
|
+
@cache[Johnny, {:flames => "higher"}] = "ring of fire"
|
28
|
+
@cache[Johnny, {:working => "in a coal mine"}] = "my daddy died young"
|
29
|
+
|
30
|
+
@cache[Johnny, {:flames => "higher"}].should == "ring of fire"
|
31
|
+
@cache[Johnny, {:working => "in a coal mine"}].should == "my daddy died young"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "stores different slots for the same class with same parameters and different content methods" do
|
35
|
+
@cache[Johnny, {}, :foo] = "ring of fire"
|
36
|
+
@cache[Johnny, {}, :bar] = "my daddy died young"
|
37
|
+
|
38
|
+
@cache[Johnny, {}, :foo].should == "ring of fire"
|
39
|
+
@cache[Johnny, {}, :bar].should == "my daddy died young"
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'after storing a widget with one parameter' do
|
43
|
+
before do
|
44
|
+
@cache[Johnny, {:flames => "higher"}] = "ring of fire"
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'doesn\'t get it when passed the class alone' do
|
48
|
+
@cache[Johnny].should be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'doesn\'t get it when passed a different class' do
|
52
|
+
@cache[June].should be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'gets it' do
|
56
|
+
@cache[Johnny, {:flames => "higher"}].should == "ring of fire"
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'doesn\'t get it when passed a different parameter key' do
|
60
|
+
@cache[Johnny, {:working => "coal mine"}].should be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'doesn\'t get it when passed a different parameter value' do
|
64
|
+
@cache[Johnny, {:flames => "lower"}].should be_nil
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'doesn\'t get it when passed an extra parameter key' do
|
68
|
+
@cache[Johnny, {:flames => "higher", :working => "coal mine"}].should be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'after storing a widget with more than one parameter' do
|
73
|
+
before do
|
74
|
+
@cache[Johnny, {:flames => "higher", :working => "coal mine"}] = "ring of fire"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "gets it" do
|
78
|
+
@cache[Johnny, {:flames => "higher", :working => "coal mine"}].should == "ring of fire"
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'doesn\'t get it when passed the class alone' do
|
82
|
+
@cache[Johnny].should be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it "doesn't get it when passed a partial parameter set" do
|
86
|
+
@cache[Johnny, {:flames => "higher"}].should be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'doesn\'t get it when passed a different class' do
|
90
|
+
@cache[June].should be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'doesn\'t get it when passed different a parameter value' do
|
94
|
+
@cache[Johnny, {:flames => "lower", :working => "coal mine"}].should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'doesn\'t get it when passed an extra parameter key' do
|
98
|
+
@cache[Johnny, {:flames => "higher", :working => "coal mine", :hear => "train a' comin'"}].should be_nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "expires" do
|
103
|
+
it 'a class with no parameters' do
|
104
|
+
@cache[Johnny] = "ring of fire"
|
105
|
+
@cache.delete(Johnny)
|
106
|
+
@cache[Johnny].should be_nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'all versions of a class' do
|
110
|
+
@cache[Johnny] = "i fell in"
|
111
|
+
@cache[Johnny, {:flames => "higher"}] = "ring of fire"
|
112
|
+
@cache[Johnny, {:working => "in a coal mine"}] = "my daddy died young"
|
113
|
+
|
114
|
+
@cache.delete_all(Johnny)
|
115
|
+
|
116
|
+
@cache[Johnny].should be_nil
|
117
|
+
@cache[Johnny, {:flames => "higher"}].should be_nil
|
118
|
+
@cache[Johnny, {:working => "in a coal mine"}].should be_nil
|
119
|
+
end
|
120
|
+
|
121
|
+
it '...but not other cached values' do
|
122
|
+
@cache[Johnny] = "ring of fire"
|
123
|
+
@cache[Johnny, {:flames => 'higher'}] = "higher fire"
|
124
|
+
@cache[June] = "wildwood flower"
|
125
|
+
@cache.delete(Johnny)
|
126
|
+
@cache[Johnny].should be_nil
|
127
|
+
@cache[Johnny, {:flames => 'higher'}].should == "higher fire"
|
128
|
+
@cache[June].should == "wildwood flower"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe Erector::Caching do
|
134
|
+
include Erector::Mixin
|
135
|
+
|
136
|
+
class Cash < Erector::Widget
|
137
|
+
needs :name
|
138
|
+
cachable
|
139
|
+
|
140
|
+
def content
|
141
|
+
p do
|
142
|
+
text @name
|
143
|
+
text " Cash"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class Family < Erector::Widget
|
149
|
+
cacheable
|
150
|
+
|
151
|
+
def content
|
152
|
+
widget Cash, :name => "Johnny"
|
153
|
+
widget Cash, :name => "June"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class NotCachable < Erector::Widget
|
158
|
+
def content
|
159
|
+
text "CONTENT"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
before do
|
164
|
+
@cache = Erector::Cache.new
|
165
|
+
Erector::Widget.cache = @cache
|
166
|
+
end
|
167
|
+
|
168
|
+
after do
|
169
|
+
Erector::Widget.cache = nil
|
170
|
+
end
|
171
|
+
|
172
|
+
it "has a global cache" do
|
173
|
+
Erector::Widget.cache.should == @cache
|
174
|
+
end
|
175
|
+
|
176
|
+
it '-- a widget is not cachable by default' do
|
177
|
+
Erector::Widget.cachable?.should be_false
|
178
|
+
end
|
179
|
+
|
180
|
+
it '-- a widget is cachable if you say so in the class definition' do
|
181
|
+
Cash.cachable?.should be_true
|
182
|
+
end
|
183
|
+
|
184
|
+
it '-- can be declared cachable using the alternate spelling "cacheable"' do
|
185
|
+
Family.cachable?.should be_true
|
186
|
+
end
|
187
|
+
|
188
|
+
describe '#to_html' do
|
189
|
+
|
190
|
+
it "caches a rendered widget" do
|
191
|
+
Cash.new(:name => "Johnny").to_html
|
192
|
+
@cache[Cash, {:name => "Johnny"}].to_s.should == "<p>Johnny Cash</p>"
|
193
|
+
end
|
194
|
+
|
195
|
+
it "uses the cached value" do
|
196
|
+
@cache[Cash, {:name => "Johnny"}] = "CACHED"
|
197
|
+
Cash.new(:name => "Johnny").to_html.should == "CACHED"
|
198
|
+
end
|
199
|
+
|
200
|
+
it "doesn't use the cached value for widgets not declared cachable" do
|
201
|
+
@cache[NotCachable] = "CACHED"
|
202
|
+
NotCachable.new.to_html.should == "CONTENT"
|
203
|
+
end
|
204
|
+
|
205
|
+
it "doesn't cache widgets not declared cachable" do
|
206
|
+
NotCachable.new.to_html
|
207
|
+
@cache[NotCachable].should be_nil
|
208
|
+
end
|
209
|
+
|
210
|
+
it "doesn't cache widgets initialized with a block (yet)" do
|
211
|
+
Cash.new(:name => "June") do
|
212
|
+
text "whatever"
|
213
|
+
end.to_html
|
214
|
+
@cache[Cash, {:name => "June"}].should be_nil
|
215
|
+
end
|
216
|
+
|
217
|
+
it "caches distinct values when using :content_method_name" do
|
218
|
+
widget = Class.new(Erector::Widget) do
|
219
|
+
cacheable
|
220
|
+
|
221
|
+
def foo
|
222
|
+
text "foo"
|
223
|
+
end
|
224
|
+
|
225
|
+
def bar
|
226
|
+
text "bar"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
widget.new.to_html(:content_method_name => :foo).should == "foo"
|
231
|
+
widget.new.to_html(:content_method_name => :bar).should == "bar"
|
232
|
+
end
|
233
|
+
|
234
|
+
it "works when passing an existing output as a parameter to to_html"
|
235
|
+
end
|
236
|
+
|
237
|
+
describe '#widget' do
|
238
|
+
|
239
|
+
it "caches rendered widgets" do
|
240
|
+
Family.new.to_html
|
241
|
+
@cache[Cash, {:name => "Johnny"}].to_s.should == "<p>Johnny Cash</p>"
|
242
|
+
@cache[Cash, {:name => "June"}].to_s.should == "<p>June Cash</p>"
|
243
|
+
end
|
244
|
+
|
245
|
+
it "uses the cached value" do
|
246
|
+
@cache[Cash, {:name => "Johnny"}] = "JOHNNY CACHED"
|
247
|
+
Family.new.to_html.should == "JOHNNY CACHED<p>June Cash</p>"
|
248
|
+
end
|
249
|
+
|
250
|
+
class WidgetWithBlock < Erector::Widget
|
251
|
+
def content
|
252
|
+
call_block
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
it "doesn't cache widgets initialized with a block (yet)" do
|
257
|
+
erector {
|
258
|
+
w = WidgetWithBlock.new do
|
259
|
+
text "in block"
|
260
|
+
end
|
261
|
+
widget w
|
262
|
+
}.should == "in block"
|
263
|
+
@cache[WidgetWithBlock].should be_nil
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
describe Erector::Convenience do
|
4
|
+
include Erector::Mixin
|
5
|
+
|
6
|
+
describe "#to_pretty" do
|
7
|
+
it "calls to_html with :prettyprint => true" do
|
8
|
+
widget = Erector.inline do
|
9
|
+
div "foo"
|
10
|
+
end
|
11
|
+
mock(widget).to_html({:prettyprint => true})
|
12
|
+
widget.to_pretty
|
13
|
+
end
|
14
|
+
|
15
|
+
it "passes extra options through to to_html" do
|
16
|
+
widget = Erector.inline do
|
17
|
+
div "foo"
|
18
|
+
end
|
19
|
+
mock(widget).to_html({:prettyprint => true, :extra => "yay"})
|
20
|
+
widget.to_pretty(:extra => "yay")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#to_s" do
|
25
|
+
it "returns html" do
|
26
|
+
capturing_stderr do
|
27
|
+
Erector.inline do
|
28
|
+
div "foo"
|
29
|
+
end.to_s.should == "<div>foo</div>"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_html" do
|
35
|
+
it "returns html" do
|
36
|
+
Erector.inline do
|
37
|
+
div "foo"
|
38
|
+
end.to_html.should == "<div>foo</div>"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#to_text" do
|
43
|
+
it "strips tags" do
|
44
|
+
Erector.inline do
|
45
|
+
div "foo"
|
46
|
+
end.to_text.should == "foo"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "unescapes named entities" do
|
50
|
+
s = "my \"dog\" has fleas & <ticks>"
|
51
|
+
Erector.inline do
|
52
|
+
text s
|
53
|
+
end.to_text.should == s
|
54
|
+
end
|
55
|
+
|
56
|
+
it "ignores >s inside attribute strings" do
|
57
|
+
Erector.inline do
|
58
|
+
a "foo", :href => "http://example.com/x>y"
|
59
|
+
end.to_text.should == "foo"
|
60
|
+
end
|
61
|
+
|
62
|
+
def with_prettyprint_default(value = true)
|
63
|
+
old_default = Erector::Widget.new.prettyprint_default
|
64
|
+
begin
|
65
|
+
Erector::Widget.prettyprint_default = value
|
66
|
+
yield
|
67
|
+
ensure
|
68
|
+
Erector::Widget.prettyprint_default = old_default
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "doesn't inherit unwanted pretty-printed whitespace (i.e. it turns off prettyprinting)" do
|
73
|
+
with_prettyprint_default(true) do
|
74
|
+
Erector.inline do
|
75
|
+
div { div { div "foo" } }
|
76
|
+
end.to_text.should == "foo"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "passes extra attributes through to to_s" do
|
81
|
+
class Funny < Erector::Widget
|
82
|
+
def content
|
83
|
+
div "foo"
|
84
|
+
end
|
85
|
+
|
86
|
+
def funny
|
87
|
+
div "haha"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
Funny.new.to_text(:content_method_name => :funny).should == "haha"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "doesn't turn a p into a newline if it's at the beginning of the string" do
|
94
|
+
Erector.inline do
|
95
|
+
p "hi"
|
96
|
+
end.to_text.should == "hi\n"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "puts a blank line (two newlines) after a /p tag" do
|
100
|
+
Erector.inline do
|
101
|
+
p "first paragraph"
|
102
|
+
p "second paragraph"
|
103
|
+
end.to_text.should == "first paragraph\n\nsecond paragraph\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
it "separates p tags with attributes" do
|
107
|
+
Erector.inline do
|
108
|
+
p "first paragraph", :class => "first"
|
109
|
+
p "second paragraph", :class => "second"
|
110
|
+
end.to_text.should == "first paragraph\n\nsecond paragraph\n"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "puts a newline after a br tag" do
|
114
|
+
Erector.inline do
|
115
|
+
text "first line"
|
116
|
+
br
|
117
|
+
text "second line"
|
118
|
+
end.to_text.should == "first line\nsecond line"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "formats a UL (unordered list) using asterisks for bullets" do
|
122
|
+
Erector.inline do
|
123
|
+
ul do
|
124
|
+
li "vanilla"
|
125
|
+
li "chocolate"
|
126
|
+
li "strawberry"
|
127
|
+
end
|
128
|
+
end.to_text.should == "\n* vanilla\n* chocolate\n* strawberry\n"
|
129
|
+
end
|
130
|
+
|
131
|
+
# it's too hard to keep track of numbers with a regexp munger, so just use asterisks for bullets
|
132
|
+
# todo: integrate text output into core rendering code
|
133
|
+
it "formats an OL (ordered list)" do
|
134
|
+
Erector.inline do
|
135
|
+
ol do
|
136
|
+
li "vanilla"
|
137
|
+
li "chocolate"
|
138
|
+
li "strawberry"
|
139
|
+
end
|
140
|
+
end.to_text.should == "\n* vanilla\n* chocolate\n* strawberry\n"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#join" do
|
145
|
+
it "empty array means nothing to join" do
|
146
|
+
erector do
|
147
|
+
join [], Erector::Widget.new { text "x" }
|
148
|
+
end.should == ""
|
149
|
+
end
|
150
|
+
|
151
|
+
it "larger example with two tabs" do
|
152
|
+
erector do
|
153
|
+
tab1 =
|
154
|
+
Erector.inline do
|
155
|
+
a "Upload document", :href => "/upload"
|
156
|
+
end
|
157
|
+
tab2 =
|
158
|
+
Erector.inline do
|
159
|
+
a "Logout", :href => "/logout"
|
160
|
+
end
|
161
|
+
join [tab1, tab2],
|
162
|
+
Erector::Widget.new { text nbsp(" |"); text " " }
|
163
|
+
end.should ==
|
164
|
+
'<a href="/upload">Upload document</a> | <a href="/logout">Logout</a>'
|
165
|
+
end
|
166
|
+
|
167
|
+
it "plain string as join separator means pass it to text" do
|
168
|
+
erector do
|
169
|
+
join [
|
170
|
+
Erector::Widget.new { text "x" },
|
171
|
+
Erector::Widget.new { text "y" }
|
172
|
+
], "<>"
|
173
|
+
end.should == "x<>y"
|
174
|
+
end
|
175
|
+
|
176
|
+
it "plain string as item to join means pass it to text" do
|
177
|
+
erector do
|
178
|
+
join [
|
179
|
+
"<",
|
180
|
+
"&"
|
181
|
+
], Erector::Widget.new { text " + " }
|
182
|
+
end.should == "< + &"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#css" do
|
187
|
+
it "makes a link when passed a string" do
|
188
|
+
erector do
|
189
|
+
css "erector.css"
|
190
|
+
end.should == "<link href=\"erector.css\" rel=\"stylesheet\" type=\"text/css\" />"
|
191
|
+
end
|
192
|
+
|
193
|
+
it "accepts a media attribute" do
|
194
|
+
erector do
|
195
|
+
css "print.css", :media => "print"
|
196
|
+
end.should == "<link href=\"print.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\" />"
|
197
|
+
end
|
198
|
+
|
199
|
+
it "passes extra attributes through" do
|
200
|
+
erector { css "foo.css", :title => 'Foo' }.should == "<link href=\"foo.css\" rel=\"stylesheet\" title=\"Foo\" type=\"text/css\" />"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "#url" do
|
205
|
+
it "renders an anchor tag with the same href and text" do
|
206
|
+
erector do
|
207
|
+
url "http://example.com"
|
208
|
+
end.should == "<a href=\"http://example.com\">http://example.com</a>"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "accepts extra attributes" do
|
212
|
+
erector do
|
213
|
+
url "http://example.com", :onclick=>"alert('foo')"
|
214
|
+
end.should == "<a href=\"http://example.com\" onclick=\"alert('foo')\">http://example.com</a>"
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "#dom_id" do
|
220
|
+
class DOMIDWidget < Erector::Widget
|
221
|
+
def content
|
222
|
+
div :id => dom_id
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
it "makes a unique id based on the widget's class name and object id" do
|
227
|
+
widget = DOMIDWidget.new
|
228
|
+
widget.dom_id.should include("#{widget.object_id}")
|
229
|
+
widget.dom_id.should include("DOMIDWidget")
|
230
|
+
end
|
231
|
+
|
232
|
+
it "can be used as an HTML id" do
|
233
|
+
widget = DOMIDWidget.new
|
234
|
+
widget.to_html.should == "<div id=\"#{widget.dom_id}\"></div>"
|
235
|
+
end
|
236
|
+
|
237
|
+
describe 'for a namespaced widget class' do
|
238
|
+
|
239
|
+
module ::ErectorConvenienceSpec
|
240
|
+
class NestedWidget < Erector::Widget
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'is colon escaped' do
|
245
|
+
g = ErectorConvenienceSpec::NestedWidget.new
|
246
|
+
g.dom_id.should_not =~ /:/
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'combines all parent namespaces' do
|
250
|
+
g = ErectorConvenienceSpec::NestedWidget.new
|
251
|
+
g.dom_id.should == "ErectorConvenienceSpec_NestedWidget_#{g.object_id}"
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|