erector-rails4 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +5 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +143 -0
  10. data/README.md +4 -0
  11. data/Rakefile +24 -0
  12. data/erector-rails4.gemspec +36 -0
  13. data/erector-rails4.sublimeproject +20 -0
  14. data/lib/erector/abstract_widget.rb +231 -0
  15. data/lib/erector/after_initialize.rb +29 -0
  16. data/lib/erector/attributes.rb +29 -0
  17. data/lib/erector/cache.rb +37 -0
  18. data/lib/erector/caching.rb +65 -0
  19. data/lib/erector/convenience.rb +98 -0
  20. data/lib/erector/dependencies.rb +24 -0
  21. data/lib/erector/dependency.rb +31 -0
  22. data/lib/erector/element.rb +113 -0
  23. data/lib/erector/externals.rb +104 -0
  24. data/lib/erector/html.rb +12 -0
  25. data/lib/erector/html_widget.rb +220 -0
  26. data/lib/erector/inline.rb +37 -0
  27. data/lib/erector/jquery.rb +28 -0
  28. data/lib/erector/mixin.rb +12 -0
  29. data/lib/erector/needs.rb +95 -0
  30. data/lib/erector/output.rb +144 -0
  31. data/lib/erector/promise.rb +141 -0
  32. data/lib/erector/rails/form_builder.rb +44 -0
  33. data/lib/erector/rails/railtie.rb +13 -0
  34. data/lib/erector/rails/template_handler.rb +16 -0
  35. data/lib/erector/rails/widget_renderer.rb +6 -0
  36. data/lib/erector/rails.rb +221 -0
  37. data/lib/erector/raw_string.rb +12 -0
  38. data/lib/erector/sass.rb +32 -0
  39. data/lib/erector/tag.rb +66 -0
  40. data/lib/erector/text.rb +123 -0
  41. data/lib/erector/unicode.rb +18185 -0
  42. data/lib/erector/unicode_builder.rb +67 -0
  43. data/lib/erector/version.rb +5 -0
  44. data/lib/erector/widget.rb +94 -0
  45. data/lib/erector/widgets.rb +5 -0
  46. data/lib/erector/xml_widget.rb +131 -0
  47. data/lib/erector.rb +28 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/controllers/application.rb +6 -0
  50. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  51. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  52. data/spec/dummy/app/views/layouts/erb_as_layout.html.erb +2 -0
  53. data/spec/dummy/app/views/layouts/widget_as_layout.rb +8 -0
  54. data/spec/dummy/app/views/test/_erb.erb +1 -0
  55. data/spec/dummy/app/views/test/_erector.rb +5 -0
  56. data/spec/dummy/app/views/test/_partial_with_locals.rb +7 -0
  57. data/spec/dummy/app/views/test/bare.rb +5 -0
  58. data/spec/dummy/app/views/test/erb_from_erector.html.rb +5 -0
  59. data/spec/dummy/app/views/test/erector_from_erb.html.erb +1 -0
  60. data/spec/dummy/app/views/test/erector_with_locals_from_erb.html.erb +6 -0
  61. data/spec/dummy/app/views/test/implicit_assigns.html.rb +5 -0
  62. data/spec/dummy/app/views/test/needs.html.rb +7 -0
  63. data/spec/dummy/app/views/test/needs_subclass.html.rb +5 -0
  64. data/spec/dummy/app/views/test/protected_instance_variable.html.rb +5 -0
  65. data/spec/dummy/app/views/test/render_default.html.rb +5 -0
  66. data/spec/dummy/app/views/test/render_default_erb_with_layout.html.erb +1 -0
  67. data/spec/dummy/app/views/test/render_default_widget_with_layout.html.rb +5 -0
  68. data/spec/dummy/app/views/test/render_partial.html.rb +5 -0
  69. data/spec/dummy/app/views/test/render_with_widget_as_layout.rb +5 -0
  70. data/spec/dummy/app/views/test/render_with_widget_as_layout_using_content_for.rb +8 -0
  71. data/spec/dummy/config/application.rb +44 -0
  72. data/spec/dummy/config/boot.rb +10 -0
  73. data/spec/dummy/config/database.yml +22 -0
  74. data/spec/dummy/config/environment.rb +5 -0
  75. data/spec/dummy/config/environments/development.rb +22 -0
  76. data/spec/dummy/config/environments/production.rb +49 -0
  77. data/spec/dummy/config/environments/test.rb +36 -0
  78. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  79. data/spec/dummy/config/initializers/inflections.rb +10 -0
  80. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  81. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  82. data/spec/dummy/config/initializers/session_store.rb +8 -0
  83. data/spec/dummy/config/locales/en.yml +5 -0
  84. data/spec/dummy/config/routes.rb +3 -0
  85. data/spec/dummy/config.ru +4 -0
  86. data/spec/dummy/db/seeds.rb +7 -0
  87. data/spec/dummy/script/rails +6 -0
  88. data/spec/dummy/spec/form_builder_spec.rb +21 -0
  89. data/spec/dummy/spec/rails_helpers_spec.rb +236 -0
  90. data/spec/dummy/spec/rails_spec_helper.rb +10 -0
  91. data/spec/dummy/spec/rails_widget_spec.rb +83 -0
  92. data/spec/dummy/spec/render_spec.rb +369 -0
  93. data/spec/erector/after_initialize_spec.rb +45 -0
  94. data/spec/erector/cache_spec.rb +133 -0
  95. data/spec/erector/caching_spec.rb +184 -0
  96. data/spec/erector/convenience_spec.rb +250 -0
  97. data/spec/erector/dependency_spec.rb +67 -0
  98. data/spec/erector/hello_from_readme.rb +18 -0
  99. data/spec/erector/hello_from_readme_spec.rb +11 -0
  100. data/spec/erector/html_spec.rb +585 -0
  101. data/spec/erector/indentation_spec.rb +211 -0
  102. data/spec/erector/inline_spec.rb +94 -0
  103. data/spec/erector/jquery_spec.rb +35 -0
  104. data/spec/erector/mixin_spec.rb +65 -0
  105. data/spec/erector/needs_spec.rb +141 -0
  106. data/spec/erector/output_spec.rb +293 -0
  107. data/spec/erector/promise_spec.rb +173 -0
  108. data/spec/erector/sample-file.txt +1 -0
  109. data/spec/erector/sass_spec.rb +57 -0
  110. data/spec/erector/tag_spec.rb +67 -0
  111. data/spec/erector/unicode_builder_spec.rb +75 -0
  112. data/spec/erector/widget_spec.rb +310 -0
  113. data/spec/erector/xml_widget_spec.rb +73 -0
  114. data/spec/spec_helper.rb +31 -0
  115. metadata +368 -0
@@ -0,0 +1,67 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ require 'benchmark'
3
+ require 'active_support' # for Symbol#to_proc
4
+
5
+ module DependencySpec
6
+ describe Erector::Dependency do
7
+ it "can be constructed with type and text" do
8
+ x = Erector::Dependency.new(:foo, "abc")
9
+ x.type.should == :foo
10
+ x.text.should == "abc"
11
+ x.options.should == {}
12
+ end
13
+
14
+ it "can be constructed with type, text, and options" do
15
+ x = Erector::Dependency.new(:foo, "abc", {:bar => 7})
16
+ x.options.should == {:bar => 7}
17
+ end
18
+
19
+ it "can be constructed with a file" do
20
+ file = File.new("#{File.dirname(__FILE__)}/sample-file.txt")
21
+ x = Erector::Dependency.new(:foo, file)
22
+ x.text.should == "sample file contents, 2 + 2 = \#{2 + 2}\n"
23
+ end
24
+
25
+ it "can be constructed with a file and interpolate the text" do
26
+ file = File.new("#{File.dirname(__FILE__)}/sample-file.txt")
27
+ x = Erector::Dependency.new(:foo, file, :interpolate => true)
28
+ x.text.should == "sample file contents, 2 + 2 = 4\n"
29
+ end
30
+
31
+ describe "comparison methods" do
32
+ before do
33
+ @castor = Erector::Dependency.new(:foo, "abc", {:bar => 7})
34
+ @pollux = Erector::Dependency.new(:foo, "abc", {:bar => 7})
35
+ @leo = Erector::Dependency.new(:foo, "abc")
36
+ @pisces = Erector::Dependency.new(:foo, "xyz", {:bar => 7})
37
+ end
38
+
39
+ it "is equal to an identical external" do
40
+ @castor.should == @pollux
41
+ [@castor].should include(@pollux)
42
+ @castor.eql?(@pollux).should be_true
43
+ @castor.hash.should == @pollux.hash
44
+ end
45
+
46
+ it "is not equal to an otherwise identical external with different options" do
47
+ @castor.should_not == @leo
48
+ [@castor].should_not include(@leo)
49
+ @castor.eql?(@leo).should_not be_true
50
+ @castor.hash.should_not == @leo.hash
51
+ end
52
+
53
+ it "is not equal to a different external with the same options" do
54
+ @castor.should_not == @pisces
55
+ [@castor].should_not include(@pisces)
56
+ @castor.eql?(@pisces).should_not be_true
57
+ @castor.hash.should_not == @pisces.hash
58
+ end
59
+
60
+ # see http://blog.nathanielbibler.com/post/73525836/using-the-ruby-array-uniq-with-custom-classes
61
+ it "works with uniq" do
62
+ [@castor, @pollux, @leo].uniq.should == [@castor, @leo]
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,18 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+ $: << "#{here}/../../lib"
3
+
4
+ require "erector"
5
+
6
+ class Hello < Erector::Widget
7
+ def content
8
+ html do
9
+ head do
10
+ title "Welcome page"
11
+ end
12
+ body do
13
+ p "Hello, world"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ puts Hello.new.to_html
@@ -0,0 +1,11 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+ require File.expand_path("#{here}/../spec_helper")
3
+
4
+ describe "Hello World example from README" do
5
+ it "works" do
6
+ Dir.chdir('/tmp') do
7
+ html = `ruby #{File.join(here,'hello_from_readme.rb')} 2>&1`
8
+ html.should == "<html><head><title>Welcome page</title></head><body><p>Hello, world</p></body></html>\n"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,585 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ require 'nokogiri'
3
+
4
+ describe Erector::HTML do
5
+ include Erector::Mixin
6
+
7
+ describe "#instruct" do
8
+ it "when passed no arguments; returns an XML declaration with version 1 and utf-8" do
9
+ # version must precede encoding, per XML 1.0 4th edition (section 2.8)
10
+ erector { instruct }.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
11
+ end
12
+ end
13
+
14
+ describe "#element" do
15
+ context "when receiving one argument" do
16
+ it "returns an empty element" do
17
+ erector { element('div') }.should == "<div></div>"
18
+ end
19
+ end
20
+
21
+ context "with a attribute hash" do
22
+ it "returns an empty element with the attributes" do
23
+ html = erector do
24
+ element(
25
+ 'div',
26
+ :class => "foo bar",
27
+ :style => "display: none; color: white; float: left;",
28
+ :nil_attribute => nil
29
+ )
30
+ end
31
+ doc = Nokogiri::HTML(html)
32
+ div = doc.at('div')
33
+ div[:class].should == "foo bar"
34
+ div[:style].should == "display: none; color: white; float: left;"
35
+ div[:nil_attribute].should be_nil
36
+ end
37
+ end
38
+
39
+ context "with an array of CSS classes" do
40
+ it "returns a tag with the classes separated" do
41
+ erector do
42
+ element('div', :class => [:foo, :bar])
43
+ end.should == "<div class=\"foo bar\"></div>";
44
+ end
45
+ end
46
+
47
+ context "with an array of CSS classes as strings" do
48
+ it "returns a tag with the classes separated" do
49
+ erector do
50
+ element('div', :class => ['foo', 'bar'])
51
+ end.should == "<div class=\"foo bar\"></div>";
52
+ end
53
+ end
54
+
55
+ context "with a CSS class which is a string" do
56
+ it "just use that as the attribute value" do
57
+ erector do
58
+ element('div', :class => "foo bar")
59
+ end.should == "<div class=\"foo bar\"></div>";
60
+ end
61
+ end
62
+
63
+ context "with an empty array of CSS classes" do
64
+ it "does not emit a class attribute" do
65
+ erector do
66
+ element('div', :class => [])
67
+ end.should == "<div></div>"
68
+ end
69
+ end
70
+
71
+ context "with many attributes" do
72
+ it "should emit them in the order they are given" do
73
+ erector do
74
+ empty_element('foo', :alpha => "", :betty => "5", :aardvark => "tough")
75
+ end.should == "<foo alpha=\"\" betty=\"5\" aardvark=\"tough\" />"
76
+ end
77
+ end
78
+
79
+ context "with boolean attributes" do
80
+ it "should emit HTML5-style true attributes" do
81
+ erector do
82
+ empty_element('foo', :alpha => true)
83
+ end.should == "<foo alpha />"
84
+ end
85
+
86
+ it "should emit nothing for false or nil attributes" do
87
+ erector do
88
+ empty_element('foo', :alpha => false)
89
+ end.should == "<foo />"
90
+
91
+ erector do
92
+ empty_element('foo', :alpha => nil)
93
+ end.should == "<foo />"
94
+ end
95
+ end
96
+
97
+ context "with underscored attributes" do
98
+ context "without hyphenize_underscores" do
99
+ it "keeps class names as underscored" do
100
+ erector do
101
+ empty_element('foo').max_thingie
102
+ end.should == '<foo class="max_thingie" />'
103
+ end
104
+
105
+ it "also keeps classes specified as attributes as underscored" do
106
+ erector do
107
+ empty_element('foo', :class => "max_thingie")
108
+ end.should == '<foo class="max_thingie" />'
109
+ end
110
+ end
111
+
112
+ context "with hyphenize_underscores" do
113
+ before do
114
+ Erector::Widget.hyphenize_underscores = true
115
+ end
116
+
117
+ it "turns underscores in class names into hyphens" do
118
+ erector do
119
+ empty_element('foo').max_thingie
120
+ end.should == '<foo class="max-thingie" />'
121
+ end
122
+
123
+ it "lets you pick underscores or hyphens when specifying a class as an attribute" do
124
+ erector do
125
+ empty_element('foo', :class => "max_thingie")
126
+ end.should == '<foo class="max_thingie" />'
127
+ end
128
+ end
129
+ end
130
+
131
+ context "with inner tags" do
132
+ it "returns nested tags" do
133
+ erector do
134
+ element 'div' do
135
+ element 'div'
136
+ end
137
+ end.should == '<div><div></div></div>'
138
+ end
139
+ end
140
+
141
+ context "with text" do
142
+ it "returns element with inner text" do
143
+ erector do
144
+ element 'div', 'test text'
145
+ end.should == "<div>test text</div>"
146
+ end
147
+ end
148
+
149
+ context "with a widget" do
150
+ it "renders the widget inside the element" do
151
+ erector do
152
+ element 'div', Erector.inline { p "foo" }
153
+ end.should == '<div><p>foo</p></div>'
154
+ end
155
+ end
156
+
157
+ context "with object other than hash" do
158
+ it "returns element with inner text == object.to_s" do
159
+ object = ['a', 'b']
160
+ erector do
161
+ element 'div', object
162
+ end.should == "<div>#{CGI.escapeHTML object.to_s}</div>"
163
+ end
164
+ end
165
+
166
+ context "with parameters and block" do
167
+ it "returns element with inner html and attributes" do
168
+ erector do
169
+ element 'div', 'class' => "foobar" do
170
+ element 'span', 'style' => 'display: none;'
171
+ end
172
+ end.should == '<div class="foobar"><span style="display: none;"></span></div>'
173
+ end
174
+ end
175
+
176
+ context "with content and parameters" do
177
+ it "returns element with content as inner html and attributes" do
178
+ erector do
179
+ element 'div', 'test text', :style => "display: none;"
180
+ end.should == '<div style="display: none;">test text</div>'
181
+ end
182
+ end
183
+
184
+ context "with more than three arguments" do
185
+ it "raises ArgumentError" do
186
+ proc do
187
+ erector do
188
+ element 'div', 'foobar', {}, 'fourth'
189
+ end
190
+ end.should raise_error(ArgumentError)
191
+ end
192
+ end
193
+
194
+ it "renders the proper full tags" do
195
+ Erector::HTMLWidget.full_tags.each do |tag_name|
196
+ expected = "<#{tag_name}></#{tag_name}>"
197
+ actual = erector { send(tag_name) }
198
+ begin
199
+ actual.should == expected
200
+ rescue Spec::Expectations::ExpectationNotMetError => e
201
+ puts "Expected #{tag_name} to be a full element. Expected #{expected}, got #{actual}"
202
+ raise e
203
+ end
204
+ end
205
+ end
206
+
207
+ describe "quoting" do
208
+ context "when outputting text" do
209
+ it "quotes it" do
210
+ erector do
211
+ element 'div', 'test &<>text'
212
+ end.should == "<div>test &amp;&lt;&gt;text</div>"
213
+ end
214
+ end
215
+
216
+ context "when outputting text via text" do
217
+ it "quotes it" do
218
+ erector do
219
+ element 'div' do
220
+ text "test &<>text"
221
+ end
222
+ end.should == "<div>test &amp;&lt;&gt;text</div>"
223
+ end
224
+ end
225
+
226
+ context "when outputting attribute value" do
227
+ it "quotes it" do
228
+ erector do
229
+ element 'a', :href => "foo.cgi?a&b"
230
+ end.should == "<a href=\"foo.cgi?a&amp;b\"></a>"
231
+ end
232
+ end
233
+
234
+ context "with raw text" do
235
+ it "does not quote it" do
236
+ erector do
237
+ element 'div' do
238
+ text raw("<b>bold</b>")
239
+ end
240
+ end.should == "<div><b>bold</b></div>"
241
+ end
242
+ end
243
+
244
+ context "with raw text and no block" do
245
+ it "does not quote it" do
246
+ erector do
247
+ element 'div', raw("<b>bold</b>")
248
+ end.should == "<div><b>bold</b></div>"
249
+ end
250
+ end
251
+
252
+ context "with raw attribute" do
253
+ it "does not quote it" do
254
+ erector do
255
+ element 'a', :href => raw("foo?x=&nbsp;")
256
+ end.should == "<a href=\"foo?x=&nbsp;\"></a>"
257
+ end
258
+ end
259
+
260
+ context "with quote in attribute" do
261
+ it "quotes it" do
262
+ erector do
263
+ element 'a', :onload => "alert(\"foo\")"
264
+ end.should == "<a onload=\"alert(&quot;foo&quot;)\"></a>"
265
+ end
266
+ end
267
+ end
268
+
269
+ context "with a non-string, non-raw" do
270
+ it "calls to_s and quotes" do
271
+ array = [7, "foo&bar"]
272
+ erector do
273
+ element 'a' do
274
+ text array
275
+ end
276
+ end.should == "<a>#{CGI.escapeHTML array.to_s}</a>"
277
+ end
278
+ end
279
+ end
280
+
281
+ describe "#empty_element" do
282
+ context "when receiving attributes" do
283
+ it "renders an empty element with the attributes" do
284
+ erector do
285
+ empty_element 'input', :name => 'foo[bar]'
286
+ end.should == '<input name="foo[bar]" />'
287
+ end
288
+ end
289
+
290
+ context "when not receiving attributes" do
291
+ it "renders an empty element without attributes" do
292
+ erector do
293
+ empty_element 'br'
294
+ end.should == '<br />'
295
+ end
296
+ end
297
+
298
+ it "renders the proper empty-element tags" do
299
+ Erector::HTMLWidget.self_closing_tags.each do |tag_name|
300
+ expected = "<#{tag_name} />"
301
+ actual = erector { send(tag_name) }
302
+ begin
303
+ actual.should == expected
304
+ rescue Spec::Expectations::ExpectationNotMetError => e
305
+ puts "Expected #{tag_name} to be an empty-element tag. Expected #{expected}, got #{actual}"
306
+ raise e
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+ describe "#comment" do
313
+ it "emits a single line comment when receiving a string" do
314
+ erector do
315
+ comment "foo"
316
+ end.should == "<!--foo-->\n"
317
+ end
318
+
319
+ it "emits a multiline comment when receiving a block" do
320
+ erector do
321
+ comment do
322
+ text "Hello"
323
+ text " world!"
324
+ end
325
+ end.should == "<!--\nHello world!\n-->\n"
326
+ end
327
+
328
+ it "emits a multiline comment when receiving a string and a block" do
329
+ erector do
330
+ comment "Hello" do
331
+ text " world!"
332
+ end
333
+ end.should == "<!--Hello\n world!\n-->\n"
334
+ end
335
+
336
+ # see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
337
+ it "does not HTML-escape character references" do
338
+ erector do
339
+ comment "&nbsp;"
340
+ end.should == "<!--&nbsp;-->\n"
341
+ end
342
+
343
+ # see http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4
344
+ # "Authors should avoid putting two or more adjacent hyphens inside comments."
345
+ it "warns if there's two hyphens in a row" do
346
+ capturing_output do
347
+ erector do
348
+ comment "he was -- awesome!"
349
+ end.should == "<!--he was -- awesome!-->\n"
350
+ end.should == "Warning: Authors should avoid putting two or more adjacent hyphens inside comments.\n"
351
+ end
352
+
353
+ it "renders an IE conditional comment with endif when receiving an if IE" do
354
+ erector do
355
+ comment "[if IE]" do
356
+ text "Hello IE!"
357
+ end
358
+ end.should == "<!--[if IE]>\nHello IE!\n<![endif]-->\n"
359
+ end
360
+
361
+ it "doesn't render an IE conditional comment if there's just some text in brackets" do
362
+ erector do
363
+ comment "[puppies are cute]"
364
+ end.should == "<!--[puppies are cute]-->\n"
365
+ end
366
+
367
+ end
368
+
369
+ describe "#nbsp" do
370
+ it "turns consecutive spaces into consecutive non-breaking spaces" do
371
+ erector do
372
+ text nbsp("a b")
373
+ end.should == "a&#160;&#160;b"
374
+ end
375
+
376
+ it "works in text context" do
377
+ erector do
378
+ element 'a' do
379
+ text nbsp("&<> foo")
380
+ end
381
+ end.should == "<a>&amp;&lt;&gt;&#160;foo</a>"
382
+ end
383
+
384
+ it "works in attribute value context" do
385
+ erector do
386
+ element 'a', :href => nbsp("&<> foo")
387
+ end.should == "<a href=\"&amp;&lt;&gt;&#160;foo\"></a>"
388
+ end
389
+
390
+ it "defaults to a single non-breaking space if given no argument" do
391
+ erector do
392
+ text nbsp
393
+ end.should == "&#160;"
394
+ end
395
+
396
+ end
397
+
398
+ describe "#character" do
399
+ it "renders a character given the codepoint number" do
400
+ erector do
401
+ text character(160)
402
+ end.should == "&#xa0;"
403
+ end
404
+
405
+ it "renders a character given the unicode name" do
406
+ erector do
407
+ text character(:right_arrow)
408
+ end.should == "&#x2192;"
409
+ end
410
+
411
+ it "renders a character above 0xffff" do
412
+ erector do
413
+ text character(:old_persian_sign_ka)
414
+ end.should == "&#x103a3;"
415
+ end
416
+
417
+ it "throws an exception if a name is not recognized" do
418
+ lambda {
419
+ erector { text character(:no_such_character_name) }
420
+ }.should raise_error("Unrecognized character no_such_character_name")
421
+ end
422
+
423
+ it "throws an exception if passed something besides a symbol or integer" do
424
+ # Perhaps calling to_s would be more ruby-esque, but that seems like it might
425
+ # be pretty confusing when this method can already take either a name or number
426
+ lambda {
427
+ erector { text character([]) }
428
+ }.should raise_error("Unrecognized argument to character: #{[].to_s}")
429
+ end
430
+ end
431
+
432
+ describe '#h' do
433
+ before do
434
+ @widget = Erector::Widget.new
435
+ end
436
+
437
+ it "escapes regular strings" do
438
+ @widget.h("&").should == "&amp;"
439
+ end
440
+
441
+ it "does not escape raw strings" do
442
+ @widget.h(@widget.raw("&")).should == "&"
443
+ end
444
+ end
445
+
446
+ describe 'escaping' do
447
+ plain = 'if (x < y && x > z) alert("don\'t stop");'
448
+ escaped = "if (x &lt; y &amp;&amp; x &gt; z) alert(&quot;don&#39;t stop&quot;);"
449
+
450
+ describe "#text" do
451
+ it "does HTML escape its param" do
452
+ erector { text plain }.should == escaped
453
+ end
454
+
455
+ it "doesn't escape pre-escaped strings" do
456
+ erector { text h(plain) }.should == escaped
457
+ end
458
+ end
459
+
460
+ describe "#rawtext" do
461
+ it "doesn't HTML escape its param" do
462
+ erector { rawtext plain }.should == plain
463
+ end
464
+ end
465
+ describe "#text!" do
466
+ it "doesn't HTML escape its param" do
467
+ erector { text! plain }.should == plain
468
+ end
469
+ end
470
+ describe "#element" do
471
+ it "does HTML escape its param" do
472
+ erector { element "foo", plain }.should == "<foo>#{escaped}</foo>"
473
+ end
474
+ end
475
+ end
476
+
477
+ describe "#javascript" do
478
+ context "when receiving a block" do
479
+ it "renders the content inside of script text/javascript tags" do
480
+ expected = <<-EXPECTED
481
+ <script type="text/javascript">
482
+ // <![CDATA[
483
+ if (x < y && x > z) alert("don't stop");
484
+ // ]]>
485
+ </script>
486
+ EXPECTED
487
+ expected.gsub!(/^ /, '')
488
+ erector do
489
+ javascript do
490
+ rawtext 'if (x < y && x > z) alert("don\'t stop");'
491
+ end
492
+ end.should == expected
493
+ end
494
+ end
495
+
496
+ it "renders the raw content inside script tags when given text" do
497
+ expected = <<-EXPECTED
498
+ <script type="text/javascript">
499
+ // <![CDATA[
500
+ alert("&<>'hello");
501
+ // ]]>
502
+ </script>
503
+ EXPECTED
504
+ expected.gsub!(/^ /, '')
505
+ erector do
506
+ javascript('alert("&<>\'hello");')
507
+ end.should == expected
508
+ end
509
+
510
+ context "when receiving a params hash" do
511
+ it "renders a source file" do
512
+ html = erector do
513
+ javascript(:src => "/my/js/file.js")
514
+ end
515
+ doc = Nokogiri::HTML(html)
516
+ doc.at("script")[:src].should == "/my/js/file.js"
517
+ end
518
+ end
519
+
520
+ context "when receiving text and a params hash" do
521
+ it "renders a source file" do
522
+ html = erector do
523
+ javascript('alert("&<>\'hello");', :src => "/my/js/file.js")
524
+ end
525
+ doc = Nokogiri::HTML(html)
526
+ script_tag = doc.at('script')
527
+ script_tag[:src].should == "/my/js/file.js"
528
+ script_tag.inner_html.should include('alert("&<>\'hello");')
529
+ end
530
+ end
531
+
532
+ context "with too many arguments" do
533
+ it "raises ArgumentError" do
534
+ proc do
535
+ erector do
536
+ javascript 'foobar', {}, 'fourth'
537
+ end
538
+ end.should raise_error(ArgumentError)
539
+ end
540
+ end
541
+ end
542
+
543
+ describe "exception handling" do
544
+ class RenderWithReturn < Erector::Widget
545
+ def content
546
+ h2 do
547
+ return "returned_value"
548
+ text "don't get here"
549
+ end
550
+ end
551
+ end
552
+
553
+ it "closes tags when a block returns" do
554
+ RenderWithReturn.new.to_html.should == "<h2></h2>"
555
+ end
556
+
557
+ it "closes tags when a block throws and the exception is caught" do
558
+ erector do
559
+ begin
560
+ div do
561
+ raise "no way"
562
+ text "not reached"
563
+ end
564
+ rescue
565
+ end
566
+ end.should == "<div></div>"
567
+ end
568
+
569
+ it "closes tags when throwing block versus text exception" do
570
+ erector do
571
+ begin
572
+ div do
573
+ span "a value" do
574
+ text "a block"
575
+ end
576
+ end
577
+ rescue ArgumentError => e
578
+ e.to_s.should include(
579
+ "You can't pass both a block and a value to span")
580
+ end
581
+ end.should == "<div></div>"
582
+ end
583
+ end
584
+
585
+ end