better_html 1.0.16 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -0
  3. data/Rakefile +19 -14
  4. data/ext/better_html_ext/better_html.h +1 -0
  5. data/ext/better_html_ext/extconf.rb +16 -0
  6. data/ext/better_html_ext/html_tokenizer.c +12 -0
  7. data/ext/better_html_ext/html_tokenizer.h +7 -0
  8. data/ext/better_html_ext/parser.c +793 -0
  9. data/ext/better_html_ext/parser.h +93 -0
  10. data/ext/better_html_ext/tokenizer.c +717 -0
  11. data/ext/better_html_ext/tokenizer.h +80 -0
  12. data/lib/better_html/ast/iterator.rb +14 -9
  13. data/lib/better_html/ast/node.rb +4 -2
  14. data/lib/better_html/better_erb/erubi_implementation.rb +43 -39
  15. data/lib/better_html/better_erb/runtime_checks.rb +140 -133
  16. data/lib/better_html/better_erb/validated_output_buffer.rb +30 -22
  17. data/lib/better_html/better_erb.rb +58 -54
  18. data/lib/better_html/config.rb +7 -4
  19. data/lib/better_html/errors.rb +4 -2
  20. data/lib/better_html/helpers.rb +7 -3
  21. data/lib/better_html/html_attributes.rb +6 -2
  22. data/lib/better_html/parser.rb +21 -14
  23. data/lib/better_html/railtie.rb +8 -4
  24. data/lib/better_html/test_helper/ruby_node.rb +15 -10
  25. data/lib/better_html/test_helper/safe_erb/allowed_script_type.rb +8 -4
  26. data/lib/better_html/test_helper/safe_erb/base.rb +12 -9
  27. data/lib/better_html/test_helper/safe_erb/no_javascript_tag_helper.rb +7 -3
  28. data/lib/better_html/test_helper/safe_erb/no_statements.rb +7 -3
  29. data/lib/better_html/test_helper/safe_erb/script_interpolation.rb +9 -4
  30. data/lib/better_html/test_helper/safe_erb/tag_interpolation.rb +23 -20
  31. data/lib/better_html/test_helper/safe_erb_tester.rb +33 -31
  32. data/lib/better_html/test_helper/safe_lodash_tester.rb +36 -35
  33. data/lib/better_html/test_helper/safety_error.rb +2 -0
  34. data/lib/better_html/tokenizer/base_erb.rb +14 -10
  35. data/lib/better_html/tokenizer/html_erb.rb +3 -2
  36. data/lib/better_html/tokenizer/html_lodash.rb +22 -14
  37. data/lib/better_html/tokenizer/javascript_erb.rb +3 -1
  38. data/lib/better_html/tokenizer/location.rb +17 -6
  39. data/lib/better_html/tokenizer/token.rb +2 -0
  40. data/lib/better_html/tokenizer/token_array.rb +8 -8
  41. data/lib/better_html/tree/attribute.rb +10 -6
  42. data/lib/better_html/tree/attributes_list.rb +9 -5
  43. data/lib/better_html/tree/tag.rb +10 -6
  44. data/lib/better_html/version.rb +3 -1
  45. data/lib/better_html.rb +19 -17
  46. data/lib/tasks/better_html_tasks.rake +1 -0
  47. metadata +39 -147
  48. data/lib/better_html/better_erb/erubis_implementation.rb +0 -44
  49. data/test/better_html/better_erb/implementation_test.rb +0 -406
  50. data/test/better_html/errors_test.rb +0 -13
  51. data/test/better_html/helpers_test.rb +0 -49
  52. data/test/better_html/parser_test.rb +0 -314
  53. data/test/better_html/test_helper/ruby_node_test.rb +0 -288
  54. data/test/better_html/test_helper/safe_erb/allowed_script_type_test.rb +0 -46
  55. data/test/better_html/test_helper/safe_erb/no_javascript_tag_helper_test.rb +0 -37
  56. data/test/better_html/test_helper/safe_erb/no_statements_test.rb +0 -129
  57. data/test/better_html/test_helper/safe_erb/script_interpolation_test.rb +0 -149
  58. data/test/better_html/test_helper/safe_erb/tag_interpolation_test.rb +0 -303
  59. data/test/better_html/test_helper/safe_lodash_tester_test.rb +0 -90
  60. data/test/better_html/tokenizer/html_erb_test.rb +0 -180
  61. data/test/better_html/tokenizer/html_lodash_test.rb +0 -98
  62. data/test/better_html/tokenizer/location_test.rb +0 -75
  63. data/test/better_html/tokenizer/token_array_test.rb +0 -146
  64. data/test/better_html/tokenizer/token_test.rb +0 -15
  65. data/test/dummy/README.rdoc +0 -28
  66. data/test/dummy/Rakefile +0 -6
  67. data/test/dummy/app/assets/javascripts/application.js +0 -13
  68. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  69. data/test/dummy/app/controllers/application_controller.rb +0 -5
  70. data/test/dummy/app/helpers/application_helper.rb +0 -2
  71. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  72. data/test/dummy/bin/bundle +0 -3
  73. data/test/dummy/bin/rails +0 -4
  74. data/test/dummy/bin/rake +0 -4
  75. data/test/dummy/bin/setup +0 -29
  76. data/test/dummy/config/application.rb +0 -26
  77. data/test/dummy/config/boot.rb +0 -5
  78. data/test/dummy/config/database.yml +0 -25
  79. data/test/dummy/config/environment.rb +0 -5
  80. data/test/dummy/config/environments/development.rb +0 -41
  81. data/test/dummy/config/environments/production.rb +0 -79
  82. data/test/dummy/config/environments/test.rb +0 -42
  83. data/test/dummy/config/initializers/assets.rb +0 -11
  84. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  85. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  86. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  87. data/test/dummy/config/initializers/inflections.rb +0 -16
  88. data/test/dummy/config/initializers/mime_types.rb +0 -4
  89. data/test/dummy/config/initializers/session_store.rb +0 -3
  90. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  91. data/test/dummy/config/locales/en.yml +0 -23
  92. data/test/dummy/config/routes.rb +0 -56
  93. data/test/dummy/config/secrets.yml +0 -22
  94. data/test/dummy/config.ru +0 -4
  95. data/test/dummy/public/404.html +0 -67
  96. data/test/dummy/public/422.html +0 -67
  97. data/test/dummy/public/500.html +0 -66
  98. data/test/dummy/public/favicon.ico +0 -0
  99. data/test/test_helper.rb +0 -29
@@ -1,406 +0,0 @@
1
- require 'test_helper'
2
- require 'ostruct'
3
- require 'better_html/better_erb'
4
- require 'json'
5
-
6
- class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
7
- test "simple template rendering" do
8
- assert_equal "<foo>some value<foo>",
9
- render("<foo><%= bar %><foo>", locals: { bar: 'some value' })
10
- end
11
-
12
- test "html_safe interpolation" do
13
- assert_equal "<foo><bar /><foo>",
14
- render("<foo><%= bar %><foo>", locals: { bar: '<bar />'.html_safe })
15
- end
16
-
17
- test "non html_safe interpolation" do
18
- assert_equal "<foo>&lt;bar /&gt;<foo>",
19
- render("<foo><%= bar %><foo>", locals: { bar: '<bar />' })
20
- end
21
-
22
- test "interpolate non-html_safe inside attribute is escaped" do
23
- assert_equal "<a href=\" &#39;&quot;&gt;x \">",
24
- render("<a href=\"<%= value %>\">", locals: { value: ' \'">x ' })
25
- end
26
-
27
- test "interpolate html_safe inside attribute is magically force-escaped" do
28
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
29
- render("<a href=\"<%= value %>\">", locals: { value: ' \'">x '.html_safe })
30
- end
31
- assert_equal "Detected invalid characters as part of the interpolation "\
32
- "into a quoted attribute value. The value cannot contain the character \".", e.message
33
- end
34
-
35
- test "interpolate html_safe inside single quoted attribute" do
36
- config = build_config(allow_single_quoted_attributes: true)
37
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
38
- render("<a href=\'<%= value %>\'>", config: config, locals: { value: ' \'">x '.html_safe })
39
- end
40
- assert_equal "Detected invalid characters as part of the interpolation "\
41
- "into a quoted attribute value. The value cannot contain the character '.", e.message
42
- end
43
-
44
- test "interpolate in attribute name" do
45
- assert_equal "<a data-safe-foo>",
46
- render("<a data-<%= value %>-foo>", locals: { value: "safe" })
47
- end
48
-
49
- test "interpolate in attribute name with unsafe value with spaces" do
50
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
51
- render("<a data-<%= value %>-foo>", locals: { value: "un safe" })
52
- end
53
- assert_equal "Detected invalid characters as part of the interpolation "\
54
- "into a attribute name around 'data-<%= value %>'.", e.message
55
- end
56
-
57
- test "interpolate in attribute name with unsafe value with equal sign" do
58
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
59
- render("<a data-<%= value %>-foo>", locals: { value: "un=safe" })
60
- end
61
- assert_equal "Detected invalid characters as part of the "\
62
- "interpolation into a attribute name around 'data-<%= value %>'.", e.message
63
- end
64
-
65
- test "interpolate in attribute name with unsafe value with quote" do
66
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
67
- render("<a data-<%= value %>-foo>", locals: { value: "un\"safe" })
68
- end
69
- assert_equal "Detected invalid characters as part of the "\
70
- "interpolation into a attribute name around 'data-<%= value %>'.", e.message
71
- end
72
-
73
- test "interpolate after an attribute name without a value" do
74
- assert_equal '<a data-foo foo="bar">',
75
- render("<a data-foo <%= html_attributes(foo: 'bar') %>>")
76
- end
77
-
78
- test "interpolate after an attribute name with equal sign" do
79
- config = build_config(allow_unquoted_attributes: true)
80
- e = assert_raises(BetterHtml::DontInterpolateHere) do
81
- render("<a data-foo= <%= html_attributes(foo: 'bar') %>>", config: config)
82
- end
83
- assert_equal "Do not interpolate without quotes after "\
84
- "attribute around 'data-foo=<%= html_attributes(foo: 'bar') %>'.", e.message
85
- end
86
-
87
- test "interpolate after an attribute value" do
88
- e = assert_raises(BetterHtml::DontInterpolateHere) do
89
- render("<a foo=\"xx\"<%= html_attributes(foo: 'bar') %>>")
90
- end
91
- assert_equal "Add a space after this attribute value. "\
92
- "Instead of <a foo=\"xx\"<%= html_attributes(foo: 'bar') %>>"\
93
- " try <a foo=\"xx\" <%= html_attributes(foo: 'bar') %>>.", e.message
94
- end
95
-
96
- test "interpolate in attribute without quotes" do
97
- config = build_config(allow_unquoted_attributes: true)
98
- e = assert_raises(BetterHtml::DontInterpolateHere) do
99
- render("<a href=<%= value %>>", config: config, locals: { value: "un safe" })
100
- end
101
- assert_equal "Do not interpolate without quotes after "\
102
- "attribute around 'href=<%= value %>'.", e.message
103
- end
104
-
105
- test "interpolate in attribute after value" do
106
- config = build_config(allow_unquoted_attributes: true)
107
- e = assert_raises(BetterHtml::DontInterpolateHere) do
108
- render("<a href=something<%= value %>>", config: config, locals: { value: "" })
109
- end
110
- assert_equal "Do not interpolate without quotes around this "\
111
- "attribute value. Instead of <a href=something<%= value %>> "\
112
- "try <a href=\"something<%= value %>\">.", e.message
113
- end
114
-
115
- test "interpolate in tag name" do
116
- assert_equal "<tag-safe-foo>",
117
- render("<tag-<%= value %>-foo>", locals: { value: "safe" })
118
- end
119
-
120
- test "interpolate in tag name with space" do
121
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
122
- render("<tag-<%= value %>-foo>", locals: { value: "un safe" })
123
- end
124
- assert_equal "Detected invalid characters as part of the interpolation "\
125
- "into a tag name around: <tag-<%= value %>>.", e.message
126
- end
127
-
128
- test "interpolate in tag name with slash" do
129
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
130
- render("<tag-<%= value %>-foo>", locals: { value: "un/safe" })
131
- end
132
- assert_equal "Detected invalid characters as part of the interpolation "\
133
- "into a tag name around: <tag-<%= value %>>.", e.message
134
- end
135
-
136
- test "interpolate in tag name with end of tag" do
137
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
138
- render("<tag-<%= value %>-foo>", locals: { value: "><script>" })
139
- end
140
- assert_equal "Detected invalid characters as part of the interpolation "\
141
- "into a tag name around: <tag-<%= value %>>.", e.message
142
- end
143
-
144
- test "interpolate in comment" do
145
- assert_equal "<!-- safe -->",
146
- render("<!-- <%= value %> -->", locals: { value: "safe" })
147
- end
148
-
149
- test "interpolate in comment with end-of-comment" do
150
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
151
- render("<!-- <%= value %> -->", locals: { value: "-->".html_safe })
152
- end
153
- assert_equal "Detected invalid characters as part of the interpolation "\
154
- "into a html comment around: <!-- <%= value %>.", e.message
155
- end
156
-
157
- test "non html_safe interpolation into comment tag" do
158
- assert_equal "<!-- --&gt; -->",
159
- render("<!-- <%= value %> -->", locals: { value: '-->' })
160
- end
161
-
162
- test "interpolate in script tag" do
163
- assert_equal "<script> foo safe bar<script>",
164
- render("<script> foo <%= value %> bar<script>", locals: { value: "safe" })
165
- end
166
-
167
- test "interpolate in script tag with start of comment" do
168
- skip "skip for now; causing problems"
169
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
170
- render("<script> foo <%= value %> bar<script>", locals: { value: "<!--".html_safe })
171
- end
172
- assert_equal "Detected invalid characters as part of the interpolation "\
173
- "into a script tag around: <script> foo <%= value %>. "\
174
- "A script tag cannot contain <script or </script anywhere inside of it.", e.message
175
- end
176
-
177
- test "interpolate in script tag with start of script" do
178
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
179
- render("<script> foo <%= value %> bar<script>", locals: { value: "<script".html_safe })
180
- end
181
- assert_equal "Detected invalid characters as part of the interpolation "\
182
- "into a script tag around: <script> foo <%= value %>. "\
183
- "A script tag cannot contain <script or </script anywhere inside of it.", e.message
184
- end
185
-
186
- test "interpolate in script tag with raw interpolation" do
187
- assert_equal "<script> x = \"foo\" </script>",
188
- render("<script> x = <%== value %> </script>", locals: { value: JSON.dump("foo") })
189
- end
190
-
191
- test "interpolate in script tag with start of script case insensitive" do
192
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
193
- render("<script> foo <%= value %> bar<script>", locals: { value: "<ScRIpT".html_safe })
194
- end
195
- assert_equal "Detected invalid characters as part of the interpolation "\
196
- "into a script tag around: <script> foo <%= value %>. "\
197
- "A script tag cannot contain <script or </script anywhere inside of it.", e.message
198
- end
199
-
200
- test "interpolate in script tag with end of script" do
201
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
202
- render("<script> foo <%= value %> bar<script>", locals: { value: "</script".html_safe })
203
- end
204
- assert_equal "Detected invalid characters as part of the interpolation "\
205
- "into a script tag around: <script> foo <%= value %>. "\
206
- "A script tag cannot contain <script or </script anywhere inside of it.", e.message
207
- end
208
-
209
- test "interpolate html_attributes" do
210
- assert_equal "<a foo=\"bar\">",
211
- render("<a <%= html_attributes(foo: 'bar') %>>")
212
- end
213
-
214
- test "interpolate without html_attributes" do
215
- e = assert_raises(BetterHtml::DontInterpolateHere) do
216
- render("<a <%= 'foo=\"bar\"' %>>")
217
- end
218
- assert_equal "Do not interpolate String in a tag. Instead "\
219
- "of <a <%= 'foo=\"bar\"' %>> please try <a <%= html_attributes(attr: value) %>>.", e.message
220
- end
221
-
222
- test "non html_safe interpolation into rawtext tag" do
223
- assert_equal "<title>&lt;/title&gt;</title>",
224
- render("<title><%= value %></title>", locals: { value: '</title>' })
225
- end
226
-
227
- test "html_safe interpolation into rawtext tag" do
228
- assert_equal "<title><safe></title>",
229
- render("<title><%= value %></title>", locals: { value: '<safe>'.html_safe })
230
- end
231
-
232
- test "html_safe interpolation terminating the current tag" do
233
- e = assert_raises(BetterHtml::UnsafeHtmlError) do
234
- render("<title><%= value %></title>", locals: { value: '</title>'.html_safe })
235
- end
236
- assert_equal "Detected invalid characters as part of the interpolation "\
237
- "into a title tag around: <title><%= value %>.", e.message
238
- end
239
-
240
- test "interpolate block in middle of tag" do
241
- e = assert_raises(BetterHtml::DontInterpolateHere) do
242
- render(<<-HTML)
243
- <a href="" <%= something do %>
244
- foo
245
- <% end %>
246
- HTML
247
- end
248
- assert_equal "Ruby statement not allowed.\n"\
249
- "In 'tag' on line 1 column 19:\n"\
250
- " <a href=\"\" <%= something do %>\n"\
251
- " ^^^^^^^^^^^^^^^^^^^", e.message
252
- end
253
-
254
- test "interpolate with output block is valid syntax" do
255
- assert_nothing_raised do
256
- render(<<-HTML)
257
- <%= capture do %>
258
- <foo>
259
- <% end %>
260
- HTML
261
- end
262
- end
263
-
264
- test "interpolate with statement block is valid syntax" do
265
- assert_nothing_raised do
266
- render(<<-HTML)
267
- <% capture do %>
268
- <foo>
269
- <% end %>
270
- HTML
271
- end
272
- end
273
-
274
- test "can interpolate method calls without parenthesis" do
275
- assert_equal "<div>foo</div>",
276
- render("<div><%= send 'value' %></div>", locals: { value: 'foo' })
277
- end
278
-
279
- test "tag names are validated against tag_name_pattern regexp" do
280
- e = assert_raises(BetterHtml::HtmlError) do
281
- render("<foo~bar></foo~bar>")
282
- end
283
- assert_equal "Invalid tag name \"foo~bar\" does not match regular expression /\\A[a-z0-9\\-\\:]+\\z/\n"\
284
- "On line 1 column 1:\n"\
285
- "<foo~bar></foo~bar>\n"\
286
- " ^^^^^^^", e.message
287
- end
288
-
289
- test "attribute names are validated against attribute_name_pattern regexp" do
290
- e = assert_raises(BetterHtml::HtmlError) do
291
- render("<foo bar_baz=\"1\">")
292
- end
293
- assert_equal "Invalid attribute name \"bar_baz\" does not match regular expression #{build_config.partial_attribute_name_pattern.inspect}\n"\
294
- "On line 1 column 5:\n"\
295
- "<foo bar_baz=\"1\">\n"\
296
- " ^^^^^^^", e.message
297
- end
298
-
299
- test "single quotes are disallowed when allow_single_quoted_attributes=false" do
300
- config = build_config(allow_single_quoted_attributes: false)
301
- e = assert_raises(BetterHtml::HtmlError) do
302
- render("<foo bar='1'>", config: config)
303
- end
304
- assert_equal "Single-quoted attributes are not allowed\n"\
305
- "On line 1 column 9:\n"\
306
- "<foo bar='1'>\n"\
307
- " ^", e.message
308
- end
309
-
310
- test "single quotes are allowed when allow_single_quoted_attributes=true" do
311
- config = build_config(allow_single_quoted_attributes: true)
312
- assert_nothing_raised do
313
- render("<foo bar='1'>", config: config)
314
- end
315
- end
316
-
317
- test "unquoted values are disallowed when allow_unquoted_attributes=false" do
318
- config = build_config(allow_unquoted_attributes: false)
319
- e = assert_raises(BetterHtml::HtmlError) do
320
- render("<foo bar=1>", config: config)
321
- end
322
- assert_equal "Unquoted attribute values are not allowed\n"\
323
- "On line 1 column 9:\n"\
324
- "<foo bar=1>\n"\
325
- " ^", e.message
326
- end
327
-
328
- test "unquoted values are allowed when allow_unquoted_attributes=true" do
329
- config = build_config(allow_unquoted_attributes: true)
330
- assert_nothing_raised do
331
- render("<foo bar=1>", config: config)
332
- end
333
- end
334
-
335
- test "capture works as intended" do
336
- output = render(<<-HTML)
337
- <%- foo = capture do -%>
338
- <foo>
339
- <%- end -%>
340
- <bar><%= foo %></bar>
341
- HTML
342
-
343
- assert_equal " <bar> <foo>\n</bar>\n", output
344
- end
345
-
346
- test "validate! raises when tag is not terminated at end of document" do
347
- document = compile("<foo")
348
- e = assert_raises(BetterHtml::HtmlError) do
349
- document.validate!
350
- end
351
- assert_equal "Detected an open tag at the end of this document.", e.message
352
- end
353
-
354
- test "validate! raises when rawtext tag is not terminated at end of document" do
355
- document = compile("<script>")
356
- e = assert_raises(BetterHtml::HtmlError) do
357
- document.validate!
358
- end
359
- assert_equal "Detected an open tag at the end of this document.", e.message
360
- end
361
-
362
- test "validate! raises parsing error for attribute name" do
363
- document = compile("<foo bar~baz=\"1\">")
364
- e = assert_raises(BetterHtml::HtmlError) do
365
- document.validate!
366
- end
367
- assert_equal "expected whitespace, '>', attribute name or value\n"\
368
- "On line 1 column 8:\n"\
369
- "<foo bar~baz=\"1\">\n"\
370
- " ^^^^^^^^^", e.message
371
- end
372
-
373
- private
374
-
375
- class ViewContext < OpenStruct
376
- include(ActionView::Helpers)
377
- include(BetterHtml::Helpers)
378
- attr_accessor :output_buffer
379
-
380
- def get_binding
381
- binding
382
- end
383
- end
384
-
385
- def build_config(**options)
386
- BetterHtml::Config.new(**options)
387
- end
388
-
389
- def render(source, config: build_config, locals: {})
390
- context = ViewContext.new(locals)
391
- impl = compile(source, config: config)
392
- if ActionView.version < Gem::Version.new("5.1")
393
- impl.result(context.get_binding)
394
- else
395
- impl.evaluate(context)
396
- end
397
- end
398
-
399
- def compile(source, config: build_config)
400
- if ActionView.version < Gem::Version.new("5.1")
401
- BetterHtml::BetterErb::ErubisImplementation.new(source, config: config)
402
- else
403
- BetterHtml::BetterErb::ErubiImplementation.new(source, config: config)
404
- end
405
- end
406
- end
@@ -1,13 +0,0 @@
1
- require 'test_helper'
2
- require 'better_html/errors'
3
-
4
- module BetterHtml
5
- class ErrorsTest < ActiveSupport::TestCase
6
- test "add" do
7
- e = Errors.new
8
- e.add("foo")
9
- assert_equal 1, e.size
10
- assert_equal "foo", e.first
11
- end
12
- end
13
- end
@@ -1,49 +0,0 @@
1
- require 'test_helper'
2
-
3
- class BetterHtml::HelpersTest < ActiveSupport::TestCase
4
- include BetterHtml::Helpers
5
-
6
- test "html_attributes return a HtmlAttributes object" do
7
- assert_equal BetterHtml::HtmlAttributes, html_attributes(foo: "bar").class
8
- end
9
-
10
- test "html_attributes are formatted as string" do
11
- assert_equal 'foo="bar" baz="qux"',
12
- html_attributes(foo: "bar", baz: "qux").to_s
13
- end
14
-
15
- test "html_attributes keys cannot contain invalid characters" do
16
- e = assert_raises(ArgumentError) do
17
- html_attributes("invalid key": "bar", baz: "qux").to_s
18
- end
19
- assert_equal "Attribute names must match the pattern /\\A[a-zA-Z0-9\\-\\:]+\\z/", e.message
20
- end
21
-
22
- test "#html_attributes does not accept incorrectly escaped html_safe values" do
23
- e = assert_raises(ArgumentError) do
24
- html_attributes('something': 'with "> double quote'.html_safe).to_s
25
- end
26
- assert_equal "The value provided for attribute 'something' contains a `\"` character which is not allowed. "\
27
- "Did you call .html_safe without properly escaping this data?", e.message
28
- end
29
-
30
- test "#html_attributes accepts correctly escaped html_safe values" do
31
- assert_equal 'something="with &quot;&gt; double quote"',
32
- html_attributes('something': CGI.escapeHTML('with "> double quote').html_safe).to_s
33
- end
34
-
35
- test "#html_attributes escapes non-html_safe values" do
36
- assert_equal 'something="with &quot;&gt; double quote"',
37
- html_attributes('something': 'with "> double quote').to_s
38
- end
39
-
40
- test "#html_attributes accepts nil values as value-less attributes" do
41
- assert_equal 'data-thing data-other-thing',
42
- html_attributes('data-thing': nil, 'data-other-thing': nil).to_s
43
- end
44
-
45
- test "#html_attributes empty string value is output" do
46
- assert_equal 'data-thing="" data-other-thing=""',
47
- html_attributes('data-thing': "", 'data-other-thing': "").to_s
48
- end
49
- end