honkster-erector 0.8.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/README.txt +116 -0
- data/VERSION.yml +4 -0
- data/bin/erector +14 -0
- data/lib/erector.rb +34 -0
- data/lib/erector/abstract_widget.rb +172 -0
- 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 +30 -0
- data/lib/erector/erect/erect.rb +160 -0
- data/lib/erector/erect/erected.rb +75 -0
- data/lib/erector/erect/indenting.rb +36 -0
- data/lib/erector/erect/rhtml.treetop +233 -0
- data/lib/erector/errors.rb +12 -0
- data/lib/erector/extensions/hash.rb +21 -0
- data/lib/erector/extensions/object.rb +18 -0
- data/lib/erector/externals.rb +97 -0
- data/lib/erector/html.rb +352 -0
- data/lib/erector/inline.rb +37 -0
- data/lib/erector/jquery.rb +36 -0
- data/lib/erector/mixin.rb +12 -0
- data/lib/erector/needs.rb +94 -0
- data/lib/erector/output.rb +117 -0
- data/lib/erector/rails.rb +27 -0
- data/lib/erector/rails/extensions/action_controller.rb +16 -0
- data/lib/erector/rails/extensions/rails_helpers.rb +159 -0
- data/lib/erector/rails/extensions/rails_widget.rb +126 -0
- data/lib/erector/rails/rails_form_builder.rb +24 -0
- data/lib/erector/rails/rails_version.rb +6 -0
- data/lib/erector/rails/template_handlers/ert_handler.rb +32 -0
- data/lib/erector/rails/template_handlers/rb_handler.rb +52 -0
- data/lib/erector/raw_string.rb +8 -0
- data/lib/erector/sass.rb +22 -0
- data/lib/erector/unicode.rb +18185 -0
- data/lib/erector/unicode_builder.rb +67 -0
- data/lib/erector/version.rb +12 -0
- data/lib/erector/widget.rb +54 -0
- data/lib/erector/widgets.rb +6 -0
- data/lib/erector/widgets/environment_badge.rb +29 -0
- data/lib/erector/widgets/external_renderer.rb +51 -0
- data/lib/erector/widgets/field_table.rb +110 -0
- data/lib/erector/widgets/form.rb +30 -0
- data/lib/erector/widgets/page.rb +165 -0
- data/lib/erector/widgets/table.rb +104 -0
- data/rails/init.rb +4 -0
- data/spec/erect/erect_rails_spec.rb +114 -0
- data/spec/erect/erect_spec.rb +175 -0
- data/spec/erect/erected_spec.rb +164 -0
- data/spec/erect/rhtml_parser_spec.rb +361 -0
- data/spec/erector/caching_spec.rb +269 -0
- data/spec/erector/convenience_spec.rb +259 -0
- data/spec/erector/dependency_spec.rb +67 -0
- data/spec/erector/externals_spec.rb +236 -0
- data/spec/erector/html_spec.rb +509 -0
- data/spec/erector/indentation_spec.rb +211 -0
- data/spec/erector/inline_spec.rb +94 -0
- data/spec/erector/jquery_spec.rb +35 -0
- data/spec/erector/mixin_spec.rb +65 -0
- 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/unicode_builder_spec.rb +75 -0
- data/spec/erector/widget_spec.rb +250 -0
- data/spec/erector/widgets/field_table_spec.rb +133 -0
- data/spec/erector/widgets/form_spec.rb +31 -0
- data/spec/erector/widgets/page_spec.rb +85 -0
- data/spec/erector/widgets/table_spec.rb +99 -0
- data/spec/spec_helper.rb +95 -0
- metadata +191 -0
@@ -0,0 +1,361 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
require "erector/erect/erect"
|
4
|
+
|
5
|
+
module ParserTestHelper
|
6
|
+
def assert_evals_to_self(input)
|
7
|
+
assert_evals_to(input, input)
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(input)
|
11
|
+
result = @parser.parse(input)
|
12
|
+
if result
|
13
|
+
result.set_indent(0) if result.respond_to? :set_indent
|
14
|
+
else
|
15
|
+
puts @parser.failure_reason
|
16
|
+
puts @parser.terminal_failures.join("\n")
|
17
|
+
result.should_not be_nil
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe RhtmlParser do
|
24
|
+
include ParserTestHelper
|
25
|
+
|
26
|
+
before :each do
|
27
|
+
@parser = RhtmlParser.new
|
28
|
+
end
|
29
|
+
|
30
|
+
it "converts text" do
|
31
|
+
parse("hello").convert.should == "text 'hello'\n"
|
32
|
+
parse("hello maude!").convert.should == "text 'hello maude!'\n"
|
33
|
+
parse(" hello ").convert.should == "text 'hello'\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "unescapes HTML entities in text" do
|
37
|
+
parse("<").convert.should == "text '<'\n"
|
38
|
+
parse("5 > 2").convert.should == "text '5 > 2'\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "converts self-closing tags" do
|
42
|
+
parse("<br/>").convert.should == "br\n"
|
43
|
+
parse("<br />").convert.should == "br\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "converts open tag" do
|
47
|
+
parse("<div>").convert.should == "div do\n"
|
48
|
+
parse("<h1>").convert.should == "h1 do\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "converts close tag" do
|
52
|
+
parse("</div>").convert.should == "end\n"
|
53
|
+
parse("</h1>").convert.should == "end\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "converts two nested divs" do
|
57
|
+
parse("<div><div></div></div>").convert.should ==
|
58
|
+
"div do\n" +
|
59
|
+
" div do\n" +
|
60
|
+
" end\n" +
|
61
|
+
"end\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "converts two nested divs with whitespace" do
|
65
|
+
parse("<div> <div> </div> </div>").convert.should ==
|
66
|
+
"div do\n" +
|
67
|
+
" div do\n" +
|
68
|
+
" end\n" +
|
69
|
+
"end\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "converts no open, text, and no close tag" do
|
73
|
+
parse("hello</div>").convert.should == "text 'hello'\nend\n"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "converts open, text, and no close tag" do
|
77
|
+
parse("<div>hello").convert.should == "div do\n text 'hello'\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "converts open, text, close" do
|
81
|
+
parse("<div>hello</div>").convert.should == "div do\n text 'hello'\nend\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "autocloses an img tag" do
|
85
|
+
parse("<img src='foo'>").convert.should == "img :src => 'foo'\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "converts a scriptlet" do
|
89
|
+
parse("<% foo %>").convert.should == "foo\n"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "converts open, text, scriptlet, text, close" do
|
93
|
+
parse("<div>hello <% 5.times do %> very <% end %> much</div>").convert.should ==
|
94
|
+
"div do\n" +
|
95
|
+
" text 'hello'\n" +
|
96
|
+
" 5.times do\n" +
|
97
|
+
" text 'very'\n" +
|
98
|
+
" end\n" +
|
99
|
+
" text 'much'\n" +
|
100
|
+
"end\n"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "converts open, scriptlet, text, close" do
|
104
|
+
parse("<div><% 5.times do %> very <% end %> much</div>").convert.should ==
|
105
|
+
"div do\n" +
|
106
|
+
" 5.times do\n" +
|
107
|
+
" text 'very'\n" +
|
108
|
+
" end\n" +
|
109
|
+
" text 'much'\n" +
|
110
|
+
"end\n"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "converts open, text, scriptlet, close" do
|
114
|
+
parse("<div>hello <% 5.times do %> very <% end %></div>").convert.should ==
|
115
|
+
"div do\n" +
|
116
|
+
" text 'hello'\n" +
|
117
|
+
" 5.times do\n" +
|
118
|
+
" text 'very'\n" +
|
119
|
+
" end\n" +
|
120
|
+
"end\n"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "converts printlets into rawtext statements" do
|
124
|
+
parse("<%= 1+1 %>").convert.should == "rawtext 1+1\n"
|
125
|
+
parse("<%= link_to \"mom\" %>").convert.should == "rawtext link_to(\"mom\")\n"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "converts h-printlets into text statements" do
|
129
|
+
parse("<%=h foo %>").convert.should == "text foo\n"
|
130
|
+
parse("<%= h \"mom\" %>").convert.should == "text \"mom\"\n"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "allows naked percent signs inside scriptlets" do
|
134
|
+
parse("<% x = 10 % 5 %>").convert.should == "x = 10 % 5\n"
|
135
|
+
end
|
136
|
+
|
137
|
+
it "indents" do
|
138
|
+
i = Erector::Indenting.new(nil, nil)
|
139
|
+
i.line("foo").should == "foo\n"
|
140
|
+
i.line_in("bar").should == "bar\n"
|
141
|
+
i.line_in("baz").should == " baz\n"
|
142
|
+
i.line("baf").should == " baf\n"
|
143
|
+
i.line_out("end").should == " end\n"
|
144
|
+
i.line_out("end").should == "end\n"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "indents extra when told to" do
|
148
|
+
parse("<div>hello</div>").set_indent(2).convert.should ==
|
149
|
+
" div do\n" +
|
150
|
+
" text 'hello'\n" +
|
151
|
+
" end\n"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "indents scriptlets ending with do and end" do
|
155
|
+
parse("<% form_for :foo do |x,y| %><% 5.times do %>hello<% end %><% end %>bye").convert.should ==
|
156
|
+
"form_for :foo do |x,y|\n" +
|
157
|
+
" 5.times do\n" +
|
158
|
+
" text 'hello'\n" +
|
159
|
+
" end\n" +
|
160
|
+
"end\n" +
|
161
|
+
"text 'bye'\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
it "converts HTML attributes" do
|
165
|
+
parse("<div id='foo'/>").convert.should == "div :id => 'foo'\n"
|
166
|
+
parse("<div id='foo' class='bar'/>").convert.should == "div :id => 'foo', :class => 'bar'\n"
|
167
|
+
parse("<div id='foo'>bar</div>").convert.should == "div :id => 'foo' do\n text 'bar'\nend\n"
|
168
|
+
end
|
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
|
+
|
175
|
+
it "escapes single quotes inside attribute values" do
|
176
|
+
@parser.root = :attribute
|
177
|
+
parse("a=\"don't worry\"").convert.should == ":a => 'don\\'t worry'"
|
178
|
+
end
|
179
|
+
|
180
|
+
it "escapes single quotes inside text strings" do
|
181
|
+
parse("isn't she lovely").convert.should == "text 'isn" + "\\" + "'t she lovely'\n"
|
182
|
+
end
|
183
|
+
|
184
|
+
it "allows newlines where whitespace is allowed" do
|
185
|
+
parse("<img src='foo' \nalt='bar' />").convert.should == "img :src => 'foo', :alt => 'bar'\n"
|
186
|
+
end
|
187
|
+
|
188
|
+
it "treats tab characters the same as spaces" do
|
189
|
+
parse("<div \t />").convert.should == "div\n"
|
190
|
+
end
|
191
|
+
|
192
|
+
it "deals with HTML entities in text" do
|
193
|
+
parse("<").convert.should == "text '<'\n"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "deals with a naked less-than or greater-than sign inside text" do
|
197
|
+
parse("if x > 2 or x< 5 then").convert.should == "text 'if x > 2 or x< 5 then'\n"
|
198
|
+
end
|
199
|
+
|
200
|
+
it "wraps printlets in parens if necessary, to avoid warning: parenthesize argument(s) for future version" do
|
201
|
+
parse("<%= h \"mom\" %>").convert.should == "text \"mom\"\n"
|
202
|
+
parse("<%= h hi \"mom\" %>").convert.should == "text hi(\"mom\")\n"
|
203
|
+
|
204
|
+
parse("<%= \"mom\" %>").convert.should == "rawtext \"mom\"\n"
|
205
|
+
parse("<%= \"hi mom\" %>").convert.should == "rawtext \"hi mom\"\n"
|
206
|
+
parse("<%= hi \"mom\" %>").convert.should == "rawtext hi(\"mom\")\n"
|
207
|
+
|
208
|
+
parse("<%= link_to blah %>").convert.should == "rawtext link_to(blah)\n"
|
209
|
+
parse("<%= link_to blah blah %>").convert.should == "rawtext link_to(blah blah)\n"
|
210
|
+
parse("<%= link_to blah(blah) %>").convert.should == "rawtext link_to(blah(blah))\n"
|
211
|
+
|
212
|
+
parse("<%= link_to(blah) %>").convert.should == "rawtext link_to(blah)\n"
|
213
|
+
end
|
214
|
+
|
215
|
+
it "won't parenthesize expressions" do
|
216
|
+
parse("<%= h foo / bar %>").convert.should == "text foo / bar\n"
|
217
|
+
end
|
218
|
+
|
219
|
+
it "understands a varname" do
|
220
|
+
@parser.root = :varname
|
221
|
+
parse("head").text_value.should == "head"
|
222
|
+
end
|
223
|
+
|
224
|
+
it "converts yield printlet into a use of @content_for_layout, commented for your edification" do
|
225
|
+
parse("<%= yield %>").convert.should == "rawtext @content_for_layout # Note: you must define @content_for_layout elsewhere\n"
|
226
|
+
parse("<%= yield :head %>").convert.should == "rawtext @content_for_head # Note: you must define @content_for_head elsewhere\n"
|
227
|
+
parse("<%= \"yield\" %>").convert.should == "rawtext \"yield\"\n"
|
228
|
+
parse("<%= \"the yield is good\" %>").convert.should == "rawtext \"the yield is good\"\n"
|
229
|
+
end
|
230
|
+
|
231
|
+
it "parses quoted strings" do
|
232
|
+
@parser.root = :quoted
|
233
|
+
parse("'foo'").value.should == "foo"
|
234
|
+
parse("\"foo\"").value.should == "foo"
|
235
|
+
end
|
236
|
+
|
237
|
+
it "quotes empty strings" do
|
238
|
+
@parser.root = :quoted
|
239
|
+
parse("''").convert.should == "''"
|
240
|
+
end
|
241
|
+
|
242
|
+
it "converts attributes in isolation" do
|
243
|
+
@parser.root = :attribute
|
244
|
+
parse("a='foo'").convert.should == ":a => 'foo'"
|
245
|
+
parse("a=\"foo\"").convert.should == ":a => 'foo'"
|
246
|
+
end
|
247
|
+
|
248
|
+
it "parses a set of attributes" do
|
249
|
+
@parser.root = :attributes
|
250
|
+
parse("a='foo' b='bar'").convert.should == " :a => 'foo', :b => 'bar'"
|
251
|
+
end
|
252
|
+
|
253
|
+
it "works with namespaced attributes" do
|
254
|
+
@parser.root = :attribute
|
255
|
+
parse('xml:lang="en"').convert.should == "'xml:lang' => 'en'"
|
256
|
+
end
|
257
|
+
|
258
|
+
it "deals with HTML entities in attribute values" do
|
259
|
+
@parser.root = :attribute
|
260
|
+
parse("foo='b<r'").convert.should == ":foo => 'b<r'"
|
261
|
+
parse("foo='b<r'").convert.should == ":foo => 'b<r'"
|
262
|
+
end
|
263
|
+
|
264
|
+
it "converts DOCTYPEs" do
|
265
|
+
html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
266
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
267
|
+
parse(html).convert.should == "rawtext '#{html}'\n"
|
268
|
+
end
|
269
|
+
|
270
|
+
["<!--[if IE]>", "<![endif]-->", "<![if !IE]>", "<![endif]>", "<!--[if IE 5.5000]>", "<!--[if IE 6]>"].each do |html|
|
271
|
+
it "converts IE directive '#{html}'" do
|
272
|
+
parse(html).convert.should == "rawtext '#{html}'\n"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
## More functional-type specs below here
|
277
|
+
|
278
|
+
it "ignores spaces, tabs and newlines" do
|
279
|
+
parse(" <div>\t\n" + "\thello !" + "\n\t</div>").convert.should ==
|
280
|
+
"div do\n" +
|
281
|
+
" text 'hello !'\n" +
|
282
|
+
"end\n"
|
283
|
+
end
|
284
|
+
|
285
|
+
it "parses some scaffolding" do
|
286
|
+
parse("<p>
|
287
|
+
<b>Name:</b>
|
288
|
+
<%=h @foo.name %>
|
289
|
+
</p>").convert.should ==
|
290
|
+
"p do\n" +
|
291
|
+
" b do\n" +
|
292
|
+
" text 'Name:'\n" +
|
293
|
+
" end\n" +
|
294
|
+
" text @foo.name\n" +
|
295
|
+
"end\n"
|
296
|
+
end
|
297
|
+
|
298
|
+
it "parses edit.erb.html" do
|
299
|
+
parse("<h1>Editing foo</h1>
|
300
|
+
|
301
|
+
<%= error_messages_for :foo %>
|
302
|
+
|
303
|
+
<% form_for(@foo) do |f| %>
|
304
|
+
<p>
|
305
|
+
<b>Name</b><br />
|
306
|
+
<%= f.text_field :name %>
|
307
|
+
</p>
|
308
|
+
|
309
|
+
<p>
|
310
|
+
<b>Age</b><br />
|
311
|
+
<%= f.text_field :age %>
|
312
|
+
</p>
|
313
|
+
|
314
|
+
<p>
|
315
|
+
<%= f.submit \"Update\" %>
|
316
|
+
</p>
|
317
|
+
<% end %>
|
318
|
+
|
319
|
+
<%= link_to 'Show', @foo %> |
|
320
|
+
<%= link_to 'Back', foos_path %>
|
321
|
+
")
|
322
|
+
end
|
323
|
+
|
324
|
+
it "parses show.html.erb" do
|
325
|
+
parse("<p>
|
326
|
+
<b>Name:</b>
|
327
|
+
<%=h @foo.name %>
|
328
|
+
</p>
|
329
|
+
|
330
|
+
<p>
|
331
|
+
<b>Age:</b>
|
332
|
+
<%=h @foo.age %>
|
333
|
+
</p>
|
334
|
+
|
335
|
+
|
336
|
+
<%= link_to 'Edit', edit_foo_path(@foo) %> |
|
337
|
+
<%= link_to 'Back', foos_path %>
|
338
|
+
")
|
339
|
+
end
|
340
|
+
|
341
|
+
it "does meta" do
|
342
|
+
parse('<meta http-equiv="content-type" content="text/html;charset=UTF-8" />').convert.should ==
|
343
|
+
"meta 'http-equiv' => 'content-type', :content => 'text/html;charset=UTF-8'\n"
|
344
|
+
end
|
345
|
+
|
346
|
+
it "parses JayTee's IE and DOCTYPE test file" do
|
347
|
+
parse <<-HTML
|
348
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
349
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
350
|
+
<head>
|
351
|
+
<!--[if IE]><link href="custom.css" rel="stylesheet" type="text/css" /><![endif]-->
|
352
|
+
<!--[if IE]><link href="custom.css" rel="stylesheet" type="text/css" /><![endif]-->
|
353
|
+
<script language="javascript" type="text/javascript"> /* <![CDATA[ */
|
354
|
+
var myJavascriptCode = 1; /*]]>*/ </script>
|
355
|
+
</head>
|
356
|
+
<body>
|
357
|
+
</body>
|
358
|
+
</html>
|
359
|
+
HTML
|
360
|
+
end
|
361
|
+
end
|
@@ -0,0 +1,269 @@
|
|
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" do
|
235
|
+
pending
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe '#widget' do
|
240
|
+
|
241
|
+
it "caches rendered widgets" do
|
242
|
+
Family.new.to_html
|
243
|
+
@cache[Cash, {:name => "Johnny"}].to_s.should == "<p>Johnny Cash</p>"
|
244
|
+
@cache[Cash, {:name => "June"}].to_s.should == "<p>June Cash</p>"
|
245
|
+
end
|
246
|
+
|
247
|
+
it "uses the cached value" do
|
248
|
+
@cache[Cash, {:name => "Johnny"}] = "JOHNNY CACHED"
|
249
|
+
Family.new.to_html.should == "JOHNNY CACHED<p>June Cash</p>"
|
250
|
+
end
|
251
|
+
|
252
|
+
class WidgetWithBlock < Erector::Widget
|
253
|
+
def content
|
254
|
+
call_block
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
it "doesn't cache widgets initialized with a block (yet)" do
|
259
|
+
erector {
|
260
|
+
w = WidgetWithBlock.new do
|
261
|
+
text "in block"
|
262
|
+
end
|
263
|
+
widget w
|
264
|
+
}.should == "in block"
|
265
|
+
@cache[WidgetWithBlock].should be_nil
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
end
|