better_html 1.0.1 → 1.0.2

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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/lib/better_html/ast/iterator.rb +3 -3
  3. data/lib/better_html/ast/node.rb +6 -2
  4. data/lib/better_html/errors.rb +2 -11
  5. data/lib/better_html/test_helper/ruby_node.rb +103 -0
  6. data/lib/better_html/test_helper/safe_erb/allowed_script_type.rb +29 -0
  7. data/lib/better_html/test_helper/safe_erb/base.rb +56 -0
  8. data/lib/better_html/test_helper/safe_erb/no_javascript_tag_helper.rb +34 -0
  9. data/lib/better_html/test_helper/safe_erb/no_statements.rb +40 -0
  10. data/lib/better_html/test_helper/safe_erb/script_interpolation.rb +65 -0
  11. data/lib/better_html/test_helper/safe_erb/tag_interpolation.rb +163 -0
  12. data/lib/better_html/test_helper/safe_erb_tester.rb +32 -285
  13. data/lib/better_html/tokenizer/location.rb +1 -1
  14. data/lib/better_html/version.rb +1 -1
  15. data/test/better_html/errors_test.rb +13 -0
  16. data/test/better_html/test_helper/ruby_node_test.rb +288 -0
  17. data/test/better_html/test_helper/safe_erb/allowed_script_type_test.rb +45 -0
  18. data/test/better_html/test_helper/safe_erb/no_javascript_tag_helper_test.rb +37 -0
  19. data/test/better_html/test_helper/safe_erb/no_statements_test.rb +128 -0
  20. data/test/better_html/test_helper/safe_erb/script_interpolation_test.rb +149 -0
  21. data/test/better_html/test_helper/safe_erb/tag_interpolation_test.rb +295 -0
  22. data/test/test_helper.rb +1 -0
  23. metadata +23 -7
  24. data/lib/better_html/test_helper/ruby_expr.rb +0 -117
  25. data/test/better_html/test_helper/ruby_expr_test.rb +0 -283
  26. data/test/better_html/test_helper/safe_erb_tester_test.rb +0 -450
@@ -1,450 +0,0 @@
1
- require 'test_helper'
2
- require 'better_html/test_helper/safe_erb_tester'
3
-
4
- module BetterHtml
5
- module TestHelper
6
- class SafeErbTesterTest < ActiveSupport::TestCase
7
- setup do
8
- @config = BetterHtml::Config.new(
9
- javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
10
- javascript_attribute_names: [/\Aon/i, 'data-eval'],
11
- )
12
- end
13
-
14
- test "multi line erb comments in text" do
15
- errors = parse(<<-EOF).errors
16
- text
17
- <%#
18
- this is a nice comment
19
- !@\#{$%?&*()}
20
- %>
21
- EOF
22
-
23
- assert_predicate errors, :empty?
24
- end
25
-
26
- test "multi line erb comments in html attribute" do
27
- errors = parse(<<-EOF).errors
28
- <div title="
29
- <%#
30
- this is a comment right in the middle of an attribute for some reason
31
- %>
32
- ">
33
- EOF
34
-
35
- assert_predicate errors, :empty?
36
- end
37
-
38
- test "string without interpolation is safe" do
39
- errors = parse(<<-EOF).errors
40
- <a onclick="alert('<%= "something" %>')">
41
- EOF
42
-
43
- assert_equal 0, errors.size
44
- end
45
-
46
- test "string with interpolation" do
47
- errors = parse(<<-EOF).errors
48
- <a onclick="<%= "hello \#{name}" %>">
49
- EOF
50
-
51
- assert_equal 1, errors.size
52
- assert_equal '"hello #{name}"', errors.first.location.source
53
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
54
- end
55
-
56
- test "string with interpolation and ternary" do
57
- errors = parse(<<-EOF).errors
58
- <a onclick="<%= "hello \#{foo ? bar : baz}" if bla? %>">
59
- EOF
60
-
61
- assert_equal 2, errors.size
62
-
63
- assert_equal '"hello #{foo ? bar : baz}" if bla?', errors.first.location.source
64
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
65
-
66
- assert_equal '"hello #{foo ? bar : baz}" if bla?', errors.first.location.source
67
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
68
- end
69
-
70
- test "plain erb tag in html attribute" do
71
- errors = parse(<<-EOF).errors
72
- <a onclick="method(<%= unsafe %>)">
73
- EOF
74
-
75
- assert_equal 1, errors.size
76
- assert_equal 'unsafe', errors.first.location.source
77
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
78
- end
79
-
80
- test "to_json is safe in html attribute" do
81
- errors = parse(<<-EOF).errors
82
- <a onclick="method(<%= unsafe.to_json %>)">
83
- EOF
84
- assert_predicate errors, :empty?
85
- end
86
-
87
- test "ternary with safe javascript escaping" do
88
- errors = parse(<<-EOF).errors
89
- <a onclick="method(<%= foo ? bar.to_json : j(baz) %>)">
90
- EOF
91
- assert_predicate errors, :empty?
92
- end
93
-
94
- test "ternary with unsafe javascript escaping" do
95
- errors = parse(<<-EOF).errors
96
- <a onclick="method(<%= foo ? bar : j(baz) %>)">
97
- EOF
98
-
99
- assert_equal 1, errors.size
100
- assert_equal 'foo ? bar : j(baz)', errors.first.location.source
101
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
102
- end
103
-
104
- test "j is safe in html attribute" do
105
- errors = parse(<<-EOF).errors
106
- <a onclick="method('<%= j unsafe %>')">
107
- EOF
108
- assert_predicate errors, :empty?
109
- end
110
-
111
- test "j() is safe in html attribute" do
112
- errors = parse(<<-EOF).errors
113
- <a onclick="method('<%= j(unsafe) %>')">
114
- EOF
115
- assert_predicate errors, :empty?
116
- end
117
-
118
- test "escape_javascript is safe in html attribute" do
119
- errors = parse(<<-EOF).errors
120
- <a onclick="method(<%= escape_javascript unsafe %>)">
121
- EOF
122
- assert_predicate errors, :empty?
123
- end
124
-
125
- test "escape_javascript() is safe in html attribute" do
126
- errors = parse(<<-EOF).errors
127
- <a onclick="method(<%= escape_javascript(unsafe) %>)">
128
- EOF
129
- assert_predicate errors, :empty?
130
- end
131
-
132
- test "html_safe is never safe in html attribute, even non javascript attributes like href" do
133
- errors = parse(<<-EOF).errors
134
- <a href="<%= unsafe.html_safe %>">
135
- EOF
136
-
137
- assert_equal 1, errors.size
138
- assert_equal 'unsafe.html_safe', errors.first.location.source
139
- assert_equal "erb interpolation with '<%= (...).html_safe %>' inside html attribute is never safe", errors.first.message
140
- end
141
-
142
- test "html_safe is never safe in html attribute, even with to_json" do
143
- errors = parse(<<-EOF).errors
144
- <a onclick="method(<%= unsafe.to_json.html_safe %>)">
145
- EOF
146
-
147
- assert_equal 1, errors.size
148
- assert_equal 'unsafe.to_json.html_safe', errors.first.location.source
149
- assert_equal "erb interpolation with '<%= (...).html_safe %>' inside html attribute is never safe", errors.first.message
150
- end
151
-
152
- test "<%== is never safe in html attribute, even non javascript attributes like href" do
153
- errors = parse(<<-EOF).errors
154
- <a href="<%== unsafe %>">
155
- EOF
156
-
157
- assert_equal 1, errors.size
158
- assert_equal '<%== unsafe %>', errors.first.location.source
159
- assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
160
- end
161
-
162
- test "<%== is never safe in html attribute, even with to_json" do
163
- errors = parse(<<-EOF).errors
164
- <a onclick="method(<%== unsafe.to_json %>)">
165
- EOF
166
-
167
- assert_equal 1, errors.size
168
- assert_equal '<%== unsafe.to_json %>', errors.first.location.source
169
- assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
170
- end
171
-
172
- test "raw is never safe in html attribute, even non javascript attributes like href" do
173
- errors = parse(<<-EOF).errors
174
- <a href="<%= raw unsafe %>">
175
- EOF
176
-
177
- assert_equal 1, errors.size
178
- assert_equal 'raw unsafe', errors.first.location.source
179
- assert_equal "erb interpolation with '<%= raw(...) %>' inside html attribute is never safe", errors.first.message
180
- end
181
-
182
- test "raw is never safe in html attribute, even with to_json" do
183
- errors = parse(<<-EOF).errors
184
- <a onclick="method(<%= raw unsafe.to_json %>)">
185
- EOF
186
-
187
- assert_equal 1, errors.size
188
- assert_equal 'raw unsafe.to_json', errors.first.location.source
189
- assert_equal "erb interpolation with '<%= raw(...) %>' inside html attribute is never safe", errors.first.message
190
- end
191
-
192
- test "unsafe erb in <script> tag without type" do
193
- errors = parse(<<-EOF).errors
194
- <script>
195
- if (a < 1) { <%= unsafe %> }
196
- </script>
197
- EOF
198
-
199
- assert_equal 1, errors.size
200
- assert_equal '<%= unsafe %>', errors.first.location.source
201
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
202
- end
203
-
204
- test "unsafe erb in javascript template" do
205
- errors = parse(<<-JS, template_language: :javascript).errors
206
- if (a < 1) { <%= unsafe %> }
207
- JS
208
-
209
- assert_equal 1, errors.size
210
- assert_equal '<%= unsafe %>', errors.first.location.source
211
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
212
- end
213
-
214
- test "<script> tag without calls is unsafe" do
215
- errors = parse(<<-EOF).errors
216
- <script type="text/javascript">
217
- if (a < 1) { <%= "unsafe" %> }
218
- </script>
219
- EOF
220
-
221
- assert_equal 1, errors.size
222
- assert_equal '<%= "unsafe" %>', errors.first.location.source
223
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
224
- end
225
-
226
- test "javascript template without calls is unsafe" do
227
- errors = parse(<<-JS, template_language: :javascript).errors
228
- if (a < 1) { <%= "unsafe" %> }
229
- JS
230
-
231
- assert_equal 1, errors.size
232
- assert_equal '<%= "unsafe" %>', errors.first.location.source
233
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
234
- end
235
-
236
- test "unsafe erb in javascript_tag" do
237
- errors = parse(<<-EOF).errors
238
- <%= javascript_tag do %>
239
- if (a < 1) { <%= unsafe %> }
240
- <% end %>
241
- EOF
242
-
243
- assert_equal 1, errors.size
244
- assert_equal '<%= javascript_tag do %>', errors.first.location.source
245
- assert_includes "'javascript_tag do' syntax is deprecated; use inline <script> instead", errors.first.message
246
- end
247
-
248
- test "unsafe erb in <script> tag with text/javascript content type" do
249
- errors = parse(<<-EOF).errors
250
- <script type="text/javascript">
251
- if (a < 1) { <%= unsafe %> }
252
- </script>
253
- EOF
254
-
255
- assert_equal 1, errors.size
256
- assert_equal '<%= unsafe %>', errors.first.location.source
257
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
258
- end
259
-
260
- test "<script> tag with non executable content type is ignored" do
261
- errors = parse(<<-EOF).errors
262
- <script type="text/html">
263
- <a onclick="<%= unsafe %>">
264
- </script>
265
- EOF
266
-
267
- assert_predicate errors, :empty?
268
- end
269
-
270
- test "statements not allowed in script tags" do
271
- errors = parse(<<-EOF).errors
272
- <script type="text/javascript">
273
- <% if foo? %>
274
- bla
275
- <% end %>
276
- </script>
277
- EOF
278
-
279
- assert_equal 1, errors.size
280
- assert_equal "<% if foo? %>", errors.first.location.source
281
- assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
282
- end
283
-
284
- test "disallowed script types" do
285
- errors = parse(<<-EOF).errors
286
- <script type="text/bogus">
287
- </script>
288
- EOF
289
-
290
- assert_equal 1, errors.size
291
- assert_equal 'type="text/bogus"', errors.first.location.source
292
- assert_equal "text/bogus is not a valid type, valid types are text/javascript, text/template, text/html", errors.first.message
293
- end
294
-
295
- test "statements not allowed in javascript template" do
296
- errors = parse(<<-JS, template_language: :javascript).errors
297
- <% if foo %>
298
- bla
299
- <% end %>
300
- JS
301
-
302
- assert_equal 1, errors.size
303
- assert_equal "<% if foo %>", errors.first.location.source
304
- assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
305
- end
306
-
307
- test "erb comments allowed in scripts" do
308
- errors = parse(<<-EOF).errors
309
- <script type="text/javascript">
310
- <%# comment %>
311
- </script>
312
- EOF
313
-
314
- assert_predicate errors, :empty?
315
- end
316
-
317
- test "script tag without content" do
318
- errors = parse(<<-EOF).errors
319
- <script type="text/javascript"></script>
320
- EOF
321
-
322
- assert_predicate errors, :empty?
323
- end
324
-
325
- test "statement after script regression" do
326
- errors = parse(<<-EOF).errors
327
- <script type="text/javascript">
328
- foo()
329
- </script>
330
- <% if condition? %>
331
- EOF
332
-
333
- assert_predicate errors, :empty?
334
- end
335
-
336
- test "<script> with to_json is safe" do
337
- errors = parse(<<-EOF).errors
338
- <script type="text/javascript">
339
- <%= unsafe.to_json %>
340
- </script>
341
- EOF
342
-
343
- assert_predicate errors, :empty?
344
- end
345
-
346
- test "javascript template with to_json is safe" do
347
- errors = parse(<<-JS, template_language: :javascript).errors
348
- <%= unsafe.to_json %>
349
- JS
350
-
351
- assert_predicate errors, :empty?
352
- end
353
-
354
- test "<script> with raw and to_json is safe" do
355
- errors = parse(<<-EOF).errors
356
- <script type="text/javascript">
357
- <%= raw unsafe.to_json %>
358
- </script>
359
- EOF
360
-
361
- assert_predicate errors, :empty?
362
- end
363
-
364
- test "javascript template with raw and to_json is safe" do
365
- errors = parse(<<-JS, template_language: :javascript).errors
366
- <%= raw unsafe.to_json %>
367
- JS
368
-
369
- assert_predicate errors, :empty?
370
- end
371
-
372
- test "end statements are allowed in script tags" do
373
- errors = parse(<<-EOF).errors
374
- <script type="text/template">
375
- <%= ui_form do %>
376
- <div></div>
377
- <% end %>
378
- </script>
379
- EOF
380
-
381
- assert_predicate errors, :empty?
382
- end
383
-
384
- test "statements are allowed in text/html tags" do
385
- errors = parse(<<-EOF).errors
386
- <script type="text/html">
387
- <% if condition? %>
388
- <div></div>
389
- <% end %>
390
- </script>
391
- EOF
392
-
393
- assert_predicate errors, :empty?
394
- end
395
-
396
- test "unsafe javascript methods in helper calls with new hash syntax" do
397
- errors = parse(<<-EOF).errors
398
- <%= ui_my_helper(:foo, onclick: "alert(\#{unsafe})", onmouseover: "alert(\#{unsafe.to_json})") %>
399
- EOF
400
-
401
- assert_equal 1, errors.size
402
- assert_equal "\#{unsafe}", errors[0].location.source
403
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors[0].message
404
- end
405
-
406
- test "unsafe javascript methods in helper calls with old hash syntax" do
407
- errors = parse(<<-EOF).errors
408
- <%= ui_my_helper(:foo, :onclick => "alert(\#{unsafe})") %>
409
- EOF
410
-
411
- assert_equal 1, errors.size
412
- assert_equal "\#{unsafe}", errors.first.location.source
413
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
414
- end
415
-
416
- test "unsafe javascript methods in helper calls with string as key" do
417
- errors = parse(<<-EOF).errors
418
- <%= ui_my_helper(:foo, 'data-eval' => "alert(\#{unsafe})") %>
419
- EOF
420
-
421
- assert_equal 1, errors.size
422
- assert_equal "\#{unsafe}", errors.first.location.source
423
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
424
- end
425
-
426
- test "unsafe javascript methods in helper calls with nested data key" do
427
- errors = parse(<<-EOF).errors
428
- <%= ui_my_helper(:foo, data: { eval: "alert(\#{unsafe})" }) %>
429
- EOF
430
-
431
- assert_equal 1, errors.size
432
- assert_equal "\#{unsafe}", errors.first.location.source
433
- assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
434
- end
435
-
436
- test "ivar missing .to_json is unsafe" do
437
- errors = parse('<script><%= @feature.html_safe %></script>').errors
438
-
439
- assert_equal 1, errors.size
440
- assert_equal "<%= @feature.html_safe %>", errors.first.location.source
441
- assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
442
- end
443
-
444
- private
445
- def parse(data, template_language: :html)
446
- SafeErbTester::Tester.new(data, config: @config, template_language: template_language)
447
- end
448
- end
449
- end
450
- end