@@ -255,4 +255,261 @@ def test_table_row_does_not_leak_interrupts
255255 template ,
256256 )
257257 end
258+
259+ def test_tablerow_with_cols_attribute_in_rigid_mode
260+ template = <<~LIQUID . chomp
261+ {% tablerow i in (1..6) cols: 3 %}{{ i }}{% endtablerow %}
262+ LIQUID
263+
264+ expected = <<~OUTPUT
265+ <tr class="row1">
266+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
267+ <tr class="row2"><td class="col1">4</td><td class="col2">5</td><td class="col3">6</td></tr>
268+ OUTPUT
269+
270+ result = Template . parse ( template , environment : rigid_environment ) . render
271+ assert_equal ( expected , result )
272+ end
273+
274+ def test_tablerow_with_limit_attribute_in_rigid_mode
275+ template = <<~LIQUID . chomp
276+ {% tablerow i in (1..10) limit: 3 %}{{ i }}{% endtablerow %}
277+ LIQUID
278+
279+ expected = <<~OUTPUT
280+ <tr class="row1">
281+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
282+ OUTPUT
283+
284+ result = Template . parse ( template , environment : rigid_environment ) . render
285+ assert_equal ( expected , result )
286+ end
287+
288+ def test_tablerow_with_offset_attribute_in_rigid_mode
289+ template = <<~LIQUID . chomp
290+ {% tablerow i in (1..5) offset: 2 %}{{ i }}{% endtablerow %}
291+ LIQUID
292+
293+ expected = <<~OUTPUT
294+ <tr class="row1">
295+ <td class="col1">3</td><td class="col2">4</td><td class="col3">5</td></tr>
296+ OUTPUT
297+
298+ result = Template . parse ( template , environment : rigid_environment ) . render
299+ assert_equal ( expected , result )
300+ end
301+
302+ def test_tablerow_with_range_attribute_in_rigid_mode
303+ template = <<~LIQUID . chomp
304+ {% tablerow i in (1..3) range: (1..10) %}{{ i }}{% endtablerow %}
305+ LIQUID
306+
307+ expected = <<~OUTPUT
308+ <tr class="row1">
309+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
310+ OUTPUT
311+
312+ result = Template . parse ( template , environment : rigid_environment ) . render
313+ assert_equal ( expected , result )
314+ end
315+
316+ def test_tablerow_with_multiple_attributes_in_rigid_mode
317+ template = <<~LIQUID . chomp
318+ {% tablerow i in (1..10) cols: 2, limit: 4, offset: 1 %}{{ i }}{% endtablerow %}
319+ LIQUID
320+
321+ expected = <<~OUTPUT
322+ <tr class="row1">
323+ <td class="col1">2</td><td class="col2">3</td></tr>
324+ <tr class="row2"><td class="col1">4</td><td class="col2">5</td></tr>
325+ OUTPUT
326+
327+ result = Template . parse ( template , environment : rigid_environment ) . render
328+ assert_equal ( expected , result )
329+ end
330+
331+ def test_tablerow_with_variable_collection_in_rigid_mode
332+ template = <<~LIQUID . chomp
333+ {% tablerow n in numbers cols: 2 %}{{ n }}{% endtablerow %}
334+ LIQUID
335+
336+ expected = <<~OUTPUT
337+ <tr class="row1">
338+ <td class="col1">1</td><td class="col2">2</td></tr>
339+ <tr class="row2"><td class="col1">3</td><td class="col2">4</td></tr>
340+ OUTPUT
341+
342+ result = Template . parse ( template , environment : rigid_environment ) . render ( 'numbers' => [ 1 , 2 , 3 , 4 ] )
343+ assert_equal ( expected , result )
344+ end
345+
346+ def test_tablerow_with_dotted_access_in_rigid_mode
347+ template = <<~LIQUID . chomp
348+ {% tablerow n in obj.numbers cols: 2 %}{{ n }}{% endtablerow %}
349+ LIQUID
350+
351+ expected = <<~OUTPUT
352+ <tr class="row1">
353+ <td class="col1">1</td><td class="col2">2</td></tr>
354+ <tr class="row2"><td class="col1">3</td><td class="col2">4</td></tr>
355+ OUTPUT
356+
357+ result = Template . parse ( template , environment : rigid_environment ) . render ( 'obj' => { 'numbers' => [ 1 , 2 , 3 , 4 ] } )
358+ assert_equal ( expected , result )
359+ end
360+
361+ def test_tablerow_with_bracketed_access_in_rigid_mode
362+ template = <<~LIQUID . chomp
363+ {% tablerow n in obj["numbers"] cols: 2 %}{{ n }}{% endtablerow %}
364+ LIQUID
365+
366+ expected = <<~OUTPUT
367+ <tr class="row1">
368+ <td class="col1">10</td><td class="col2">20</td></tr>
369+ OUTPUT
370+
371+ result = Template . parse ( template , environment : rigid_environment ) . render ( 'obj' => { 'numbers' => [ 10 , 20 ] } )
372+ assert_equal ( expected , result )
373+ end
374+
375+ def test_tablerow_without_attributes_in_rigid_mode
376+ template = <<~LIQUID . chomp
377+ {% tablerow i in (1..3) %}{{ i }}{% endtablerow %}
378+ LIQUID
379+
380+ expected = <<~OUTPUT
381+ <tr class="row1">
382+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
383+ OUTPUT
384+
385+ result = Template . parse ( template , environment : rigid_environment ) . render
386+ assert_equal ( expected , result )
387+ end
388+
389+ def test_tablerow_with_trailing_comma_in_rigid_mode
390+ template = <<~LIQUID . chomp
391+ {% tablerow i in (1..3) cols: 2, %}{{ i }}{% endtablerow %}
392+ LIQUID
393+
394+ expected = <<~OUTPUT
395+ <tr class="row1">
396+ <td class="col1">1</td><td class="col2">2</td></tr>
397+ <tr class="row2"><td class="col1">3</td></tr>
398+ OUTPUT
399+
400+ result = Template . parse ( template , environment : rigid_environment ) . render
401+ assert_equal ( expected , result )
402+ end
403+
404+ def test_tablerow_with_invalid_attribute_name_in_rigid_mode
405+ template = '{% tablerow i in (1..10) invalid_attr: 5 %}{{ i }}{% endtablerow %}'
406+ error = assert_raises ( SyntaxError ) do
407+ Template . parse ( template , environment : rigid_environment )
408+ end
409+ assert_equal ( "Liquid syntax error: Invalid attribute 'invalid_attr' in tablerow loop. Valid attributes are cols, limit, offset, and range in \" i in (1..10) invalid_attr: 5\" " , error . message )
410+ end
411+
412+ def test_tablerow_with_invalid_expression_in_limit_in_rigid_mode
413+ template = '{% tablerow i in (1..10) limit: foo=>bar %}{{ i }}{% endtablerow %}'
414+ error = assert_raises ( SyntaxError ) do
415+ Template . parse ( template , environment : rigid_environment )
416+ end
417+ assert_equal ( "Liquid syntax error: Unexpected character = in \" i in (1..10) limit: foo=>bar\" " , error . message )
418+ end
419+
420+ def test_tablerow_with_invalid_expression_in_offset_in_rigid_mode
421+ template = '{% tablerow i in (1..10) offset: foo=>bar %}{{ i }}{% endtablerow %}'
422+ error = assert_raises ( SyntaxError ) do
423+ Template . parse ( template , environment : rigid_environment )
424+ end
425+ assert_equal ( "Liquid syntax error: Unexpected character = in \" i in (1..10) offset: foo=>bar\" " , error . message )
426+ end
427+
428+ def test_tablerow_with_invalid_expression_in_cols_in_rigid_mode
429+ template = '{% tablerow i in (1..10) cols: foo=>bar %}{{ i }}{% endtablerow %}'
430+ error = assert_raises ( SyntaxError ) do
431+ Template . parse ( template , environment : rigid_environment )
432+ end
433+ assert_equal ( "Liquid syntax error: Unexpected character = in \" i in (1..10) cols: foo=>bar\" " , error . message )
434+ end
435+
436+ def test_tablerow_with_invalid_expression_in_range_in_rigid_mode
437+ template = '{% tablerow i in (1..10) range: foo=>bar %}{{ i }}{% endtablerow %}'
438+ error = assert_raises ( SyntaxError ) do
439+ Template . parse ( template , environment : rigid_environment )
440+ end
441+ assert_equal ( "Liquid syntax error: Unexpected character = in \" i in (1..10) range: foo=>bar\" " , error . message )
442+ end
443+
444+ def test_tablerow_without_in_keyword_in_rigid_mode
445+ template = '{% tablerow i (1..10) %}{{ i }}{% endtablerow %}'
446+ error = assert_raises ( SyntaxError ) do
447+ Template . parse ( template , environment : rigid_environment )
448+ end
449+ assert_equal ( "Liquid syntax error: For loops require an 'in' clause in \" i (1..10)\" " , error . message )
450+ end
451+
452+ def test_tablerow_with_multiple_invalid_attributes_reports_first_in_rigid_mode
453+ template = '{% tablerow i in (1..10) invalid1: 5, invalid2: 10 %}{{ i }}{% endtablerow %}'
454+ error = assert_raises ( SyntaxError ) do
455+ Template . parse ( template , environment : rigid_environment )
456+ end
457+ assert_equal ( "Liquid syntax error: Invalid attribute 'invalid1' in tablerow loop. Valid attributes are cols, limit, offset, and range in \" i in (1..10) invalid1: 5, invalid2: 10\" " , error . message )
458+ end
459+
460+ def test_tablerow_with_empty_collection_in_rigid_mode
461+ template = <<~LIQUID . chomp
462+ {% tablerow i in empty_array cols: 2 %}{{ i }}{% endtablerow %}
463+ LIQUID
464+
465+ expected = <<~OUTPUT
466+ <tr class="row1">
467+ </tr>
468+ OUTPUT
469+
470+ result = Template . parse ( template , environment : rigid_environment ) . render ( 'empty_array' => [ ] )
471+ assert_equal ( expected , result )
472+ end
473+
474+ def test_tablerow_lax_mode_still_accepts_invalid_attributes
475+ template = <<~LIQUID . chomp
476+ {% tablerow i in (1..3) invalid_attr: 5 %}{{ i }}{% endtablerow %}
477+ LIQUID
478+
479+ expected = <<~OUTPUT
480+ <tr class="row1">
481+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
482+ OUTPUT
483+
484+ result = Template . parse ( template , environment : lax_environment ) . render
485+ assert_equal ( expected , result )
486+ end
487+
488+ def test_tablerow_strict_mode_still_accepts_invalid_attributes
489+ template = <<~LIQUID . chomp
490+ {% tablerow i in (1..3) invalid_attr: 5 %}{{ i }}{% endtablerow %}
491+ LIQUID
492+
493+ expected = <<~OUTPUT
494+ <tr class="row1">
495+ <td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>
496+ OUTPUT
497+
498+ result = Template . parse ( template , environment : strict_environment ) . render
499+ assert_equal ( expected , result )
500+ end
501+
502+ private
503+
504+ def rigid_environment
505+ Environment . build ( error_mode : :rigid )
506+ end
507+
508+ def strict_environment
509+ Environment . build ( error_mode : :strict )
510+ end
511+
512+ def lax_environment
513+ Environment . build ( error_mode : :lax )
514+ end
258515end
0 commit comments