2006-10-14 19:50:07 -04:00
#!/usr/bin/env ruby
2009-07-01 03:19:46 -04:00
# -*- coding: utf-8 -*-
2008-06-08 12:54:36 -04:00
require File . dirname ( __FILE__ ) + '/../test_helper'
2006-08-06 00:25:31 -04:00
2006-09-29 14:39:13 -04:00
class EngineTest < Test :: Unit :: TestCase
2008-08-29 20:40:59 -04:00
# A map of erroneous Haml documents to the error messages they should produce.
2008-04-24 16:47:59 -04:00
# The error messages may be arrays;
# if so, the second element should be the line number that should be reported for the error.
# If this isn't provided, the tests will assume the line number should be the last line of the document.
2008-04-18 14:08:49 -04:00
EXCEPTION_MAP = {
2008-04-18 14:43:29 -04:00
" !!! \n a " = > " Illegal nesting: nesting within a header command is illegal. " ,
" a \n b " = > " Illegal nesting: nesting within plain text is illegal. " ,
" / a \n b " = > " Illegal nesting: nesting within a tag that already has content is illegal. " ,
" % a " = > 'Invalid tag: "% a".' ,
" %p a \n b " = > " Illegal nesting: content can't be both given on the same line as %p and nested within it. " ,
2008-04-18 15:25:00 -04:00
" %p= " = > " There's no Ruby code for = to evaluate. " ,
" %p~ " = > " There's no Ruby code for ~ to evaluate. " ,
" ~ " = > " There's no Ruby code for ~ to evaluate. " ,
" = " = > " There's no Ruby code for = to evaluate. " ,
2008-04-18 15:54:15 -04:00
" %p/ \n a " = > " Illegal nesting: nesting within a self-closing tag is illegal. " ,
2008-04-24 16:47:59 -04:00
" :a \n b " = > [ 'Filter "a" is not defined.' , 1 ] ,
2008-04-18 14:43:29 -04:00
" :a= b " = > 'Invalid filter name ":a= b".' ,
2008-04-18 14:08:49 -04:00
" . " = > " Illegal element: classes and ids must have values. " ,
" . # " = > " Illegal element: classes and ids must have values. " ,
" .{} a " = > " Illegal element: classes and ids must have values. " ,
2009-05-19 17:28:34 -04:00
" .() a " = > " Illegal element: classes and ids must have values. " ,
2008-04-18 14:08:49 -04:00
" .= a " = > " Illegal element: classes and ids must have values. " ,
" %p..a " = > " Illegal element: classes and ids must have values. " ,
2008-04-18 15:54:15 -04:00
" %a/ b " = > " Self-closing tags can't have content. " ,
2008-05-29 16:47:40 -04:00
" %p{:a => 'b', \n :c => 'd'}/ e " = > [ " Self-closing tags can't have content. " , 2 ] ,
" %p{:a => 'b', \n :c => 'd'}= " = > [ " There's no Ruby code for = to evaluate. " , 2 ] ,
" %p.{:a => 'b', \n :c => 'd'} e " = > [ " Illegal element: classes and ids must have values. " , 1 ] ,
" %p{:a => 'b', \n :c => 'd', \n :e => 'f'} \n %p/ a " = > [ " Self-closing tags can't have content. " , 4 ] ,
" %p{:a => 'b', \n :c => 'd', \n :e => 'f'} \n - raise 'foo' " = > [ " foo " , 4 ] ,
" %p{:a => 'b', \n :c => raise('foo'), \n :e => 'f'} " = > [ " foo " , 2 ] ,
" %p{:a => 'b', \n :c => 'd', \n :e => raise('foo')} " = > [ " foo " , 3 ] ,
2008-05-29 22:07:12 -04:00
" %p foo " = > " Indenting at the beginning of the document is illegal. " ,
" %p foo " = > " Indenting at the beginning of the document is illegal. " ,
2008-08-29 20:40:59 -04:00
" - end " = > " You don't need to use \" - end \" in Haml. Use indentation instead: \n - if foo? \n %strong Foo! \n - else \n Not foo. " ,
2008-06-01 00:35:07 -04:00
" \n \t \n %p foo " = > [ " Indenting at the beginning of the document is illegal. " , 3 ] ,
2008-05-29 22:07:12 -04:00
" \n \n %p foo " = > [ " Indenting at the beginning of the document is illegal. " , 3 ] ,
2008-05-31 23:33:05 -04:00
" %p \n foo \n foo " = > [ " Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces. " , 3 ] ,
" %p \n foo \n %p \n foo " = > [ " Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces. " , 4 ] ,
" %p \n \t \t foo \n \t foo " = > [ " Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs. " , 3 ] ,
" %p \n foo \n foo " = > [ " Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces. " , 3 ] ,
" %p \n foo \n %p \n bar " = > [ " Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces. " , 4 ] ,
" %p \n :plain \n bar \n \t baz " = > [ 'Inconsistent indentation: " \t " was used for indentation, but the rest of the document was indented using 2 spaces.' , 4 ] ,
" %p \n foo \n %p \n bar " = > [ " The line was indented 2 levels deeper than the previous line. " , 4 ] ,
" %p \n foo \n %p \n bar " = > [ " The line was indented 3 levels deeper than the previous line. " , 4 ] ,
2008-06-01 01:03:28 -04:00
" %p \n \t foo " = > [ " Indentation can't use both tabs and spaces. " , 2 ] ,
2009-05-19 17:28:34 -04:00
" %p( " = > " Invalid attribute list: \" ( \" . " ,
" %p(foo= \n bar) " = > [ " Invalid attribute list: \" (foo= \" . " , 1 ] ,
" %p(foo=) " = > " Invalid attribute list: \" (foo=) \" . " ,
" %p(foo 'bar') " = > " Invalid attribute list: \" (foo 'bar') \" . " ,
" %p(foo 'bar' \n baz='bang') " = > [ " Invalid attribute list: \" (foo 'bar' \" . " , 1 ] ,
" %p(foo='bar' \n baz 'bang' \n bip='bop') " = > [ " Invalid attribute list: \" (foo='bar' baz 'bang' \" . " , 2 ] ,
2009-09-27 20:37:22 -04:00
" %p{:foo => 'bar' :bar => 'baz'} " = > :compile ,
2009-09-27 20:38:15 -04:00
" %p{:foo => } " = > :compile ,
" %p{=> 'bar'} " = > :compile ,
" %p{:foo => 'bar} " = > :compile ,
" %p{'foo => 'bar'} " = > :compile ,
" %p{:foo => 'bar \" } " = > :compile ,
2008-04-29 00:28:01 -04:00
# Regression tests
" - raise 'foo' \n \n \n \n bar " = > [ " foo " , 1 ] ,
2008-05-02 03:48:39 -04:00
" = 'foo' \n -raise 'foo' " = > [ " foo " , 2 ] ,
" \n \n \n - raise 'foo' " = > [ " foo " , 4 ] ,
2008-05-29 03:13:34 -04:00
" %p foo | \n bar | \n baz | \n bop \n - raise 'foo' " = > [ " foo " , 5 ] ,
2008-05-29 04:30:29 -04:00
" foo \n \n \n bar " = > [ " Illegal nesting: nesting within plain text is illegal. " , 4 ] ,
" %p/ \n \n bar " = > [ " Illegal nesting: nesting within a self-closing tag is illegal. " , 3 ] ,
" %p foo \n \n bar " = > [ " Illegal nesting: content can't be both given on the same line as %p and nested within it. " , 3 ] ,
" / foo \n \n bar " = > [ " Illegal nesting: nesting within a tag that already has content is illegal. " , 3 ] ,
" !!! \n \n bar " = > [ " Illegal nesting: nesting within a header command is illegal. " , 3 ] ,
2008-07-15 23:35:08 -04:00
" foo \n :ruby \n 1 \n 2 \n 3 \n - raise 'foo' " = > [ " foo " , 6 ] ,
2008-04-18 14:08:49 -04:00
}
2006-08-05 23:18:54 -04:00
2008-04-28 00:14:12 -04:00
User = Struct . new ( 'User' , :id )
2007-11-23 07:14:02 -05:00
def render ( text , options = { } , & block )
2007-11-24 03:35:10 -05:00
scope = options . delete ( :scope ) || Object . new
locals = options . delete ( :locals ) || { }
2008-08-29 20:40:59 -04:00
engine ( text , options ) . to_html ( scope , locals , & block )
2006-08-05 23:18:54 -04:00
end
2008-08-29 20:40:59 -04:00
def engine ( text , options = { } )
unless options [ :filename ]
# use caller method name as fake filename. useful for debugging
i = - 1
caller [ i += 1 ] =~ / `(.+?)' / until $1 and $1 . index ( 'test_' ) == 0
options [ :filename ] = " ( #{ $1 } ) "
end
Haml :: Engine . new ( text , options )
end
2008-11-22 19:54:02 -05:00
def test_empty_render
assert_equal " " , render ( " " )
end
2008-05-31 23:33:05 -04:00
def test_flexible_tabulation
assert_equal ( " <p> \n foo \n </p> \n <q> \n bar \n <a> \n baz \n </a> \n </q> \n " ,
render ( " %p \n foo \n %q \n bar \n %a \n baz " ) )
assert_equal ( " <p> \n foo \n </p> \n <q> \n bar \n <a> \n baz \n </a> \n </q> \n " ,
render ( " %p \n \t foo \n %q \n \t bar \n \t %a \n \t \t baz " ) )
assert_equal ( " <p> \n \t \t bar \n baz \n </p> \n " ,
render ( " %p \n :plain \n \t \t bar \n baz " ) )
end
2006-09-29 14:39:13 -04:00
def test_empty_render_should_remain_empty
assert_equal ( '' , render ( '' ) )
2006-08-05 23:18:54 -04:00
end
2006-09-29 14:39:13 -04:00
def test_attributes_should_render_correctly
2008-05-09 19:00:08 -04:00
assert_equal ( " <div class='atlantis' style='ugly'></div> " , render ( " .atlantis{:style => 'ugly'} " ) . chomp )
2006-08-05 23:18:54 -04:00
end
2009-09-18 04:14:53 -04:00
def test_css_id_as_attribute_should_be_appended_with_underscore
assert_equal ( " <div id='my_id_1'></div> " , render ( " # my_id{:id => '1'} " ) . chomp )
assert_equal ( " <div id='my_id_1'></div> " , render ( " # my_id{:id => 1} " ) . chomp )
end
2006-09-29 14:39:13 -04:00
def test_ruby_code_should_work_inside_attributes
author = 'hcatlin'
assert_equal ( " <p class='3'>foo</p> " , render ( " %p{:class => 1+2} foo " ) . chomp )
2006-08-05 23:18:54 -04:00
end
2006-09-29 14:39:13 -04:00
def test_nil_should_render_empty_tag
2008-05-09 19:00:08 -04:00
assert_equal ( " <div class='no_attributes'></div> " ,
2006-09-29 14:39:13 -04:00
render ( " .no_attributes{:nil => nil} " ) . chomp )
2006-08-05 23:18:54 -04:00
end
2006-09-29 14:39:13 -04:00
def test_strings_should_get_stripped_inside_tags
assert_equal ( " <div class='stripped'>This should have no spaces in front of it</div> " ,
render ( " .stripped This should have no spaces in front of it " ) . chomp )
2006-08-09 14:12:54 -04:00
end
2006-11-04 03:35:06 -05:00
2006-09-29 14:39:13 -04:00
def test_one_liner_should_be_one_line
assert_equal ( " <p>Hello</p> " , render ( '%p Hello' ) . chomp )
2006-08-13 18:02:04 -04:00
end
2006-08-13 18:10:05 -04:00
2008-04-24 22:14:52 -04:00
def test_one_liner_with_newline_shouldnt_be_one_line
assert_equal ( " <p> \n foo \n bar \n </p> " , render ( '%p= "foo\nbar"' ) . chomp )
2007-07-16 23:48:11 -04:00
end
2006-11-04 03:35:06 -05:00
2006-10-27 16:48:40 -04:00
def test_multi_render
2008-08-29 20:40:59 -04:00
engine = engine ( " %strong Hi there! " )
2006-10-27 16:48:40 -04:00
assert_equal ( " <strong>Hi there!</strong> \n " , engine . to_html )
assert_equal ( " <strong>Hi there!</strong> \n " , engine . to_html )
assert_equal ( " <strong>Hi there!</strong> \n " , engine . to_html )
end
2006-11-04 03:35:06 -05:00
2009-04-17 05:08:12 -04:00
def test_interpolation
assert_equal ( " <p>Hello World</p> \n " , render ( '%p Hello #{who}' , :locals = > { :who = > 'World' } ) )
assert_equal ( " <p> \n Hello World \n </p> \n " , render ( " %p \n Hello \# {who} " , :locals = > { :who = > 'World' } ) )
2007-05-07 14:16:24 -04:00
end
2009-04-17 05:08:12 -04:00
def test_interpolation_in_the_middle_of_a_string
2007-08-11 15:10:28 -04:00
assert_equal ( " \" title 'Title'. \" \n " ,
2009-04-17 05:08:12 -04:00
render ( " \" title ' \# { \" Title \" }'. \" " ) )
2007-08-11 15:10:28 -04:00
end
2009-04-17 05:14:38 -04:00
def test_interpolation_at_the_beginning_of_a_line
assert_equal ( " <p>2</p> \n " , render ( '%p #{1 + 1}' ) )
assert_equal ( " <p> \n 2 \n </p> \n " , render ( " %p \n \# {1 + 1} " ) )
end
2007-08-16 17:49:53 -04:00
def test_nil_tag_value_should_render_as_empty
assert_equal ( " <p></p> \n " , render ( " %p= nil " ) )
end
def test_tag_with_failed_if_should_render_as_empty
assert_equal ( " <p></p> \n " , render ( " %p= 'Hello' if false " ) )
end
2007-11-22 00:29:26 -05:00
def test_static_attributes_with_empty_attr
assert_equal ( " <img alt='' src='/foo.png' /> \n " , render ( " %img{:src => '/foo.png', :alt => ''} " ) )
end
def test_dynamic_attributes_with_empty_attr
assert_equal ( " <img alt='' src='/foo.png' /> \n " , render ( " %img{:width => nil, :src => '/foo.png', :alt => String.new} " ) )
end
2008-05-29 16:47:40 -04:00
def test_attribute_hash_with_newlines
assert_equal ( " <p a='b' c='d'>foop</p> \n " , render ( " %p{:a => 'b', \n :c => 'd'} foop " ) )
assert_equal ( " <p a='b' c='d'> \n foop \n </p> \n " , render ( " %p{:a => 'b', \n :c => 'd'} \n foop " ) )
assert_equal ( " <p a='b' c='d' /> \n " , render ( " %p{:a => 'b', \n :c => 'd'}/ " ) )
assert_equal ( " <p a='b' c='d' e='f'></p> \n " , render ( " %p{:a => 'b', \n :c => 'd', \n :e => 'f'} " ) )
end
2008-10-03 01:38:40 -04:00
def test_attr_hashes_not_modified
hash = { :color = > 'red' }
assert_equal ( <<HTML, render(<<HAML, :locals => {:hash => hash}))
< div color = 'red' > < / div>
< div class = 'special' color = 'red' > < / div>
< div color = 'red' > < / div>
HTML
% div { hash }
. special { hash }
% div { hash }
HAML
assert_equal ( hash , { :color = > 'red' } )
end
2008-01-09 15:54:36 -05:00
def test_end_of_file_multiline
assert_equal ( " <p>0</p> \n <p>1</p> \n <p>2</p> \n " , render ( " - for i in (0...3) \n %p= | \n i | " ) )
end
2008-01-31 01:21:24 -05:00
def test_cr_newline
assert_equal ( " <p>foo</p> \n <p>bar</p> \n <p>baz</p> \n <p>boom</p> \n " , render ( " %p foo \r %p bar \r \n %p baz \n \r %p boom " ) )
end
2008-03-02 19:12:57 -05:00
def test_textareas
2008-04-24 15:59:03 -04:00
assert_equal ( " <textarea>Foo& # x000A; bar& # x000A; baz</textarea> \n " ,
2008-03-02 19:12:57 -05:00
render ( '%textarea= "Foo\n bar\n baz"' ) )
2008-04-24 15:59:03 -04:00
assert_equal ( " <pre>Foo& # x000A; bar& # x000A; baz</pre> \n " ,
2008-03-02 19:24:47 -05:00
render ( '%pre= "Foo\n bar\n baz"' ) )
2008-03-02 19:12:57 -05:00
assert_equal ( " <textarea> #{ 'a' * 100 } </textarea> \n " ,
render ( " %textarea #{ 'a' * 100 } " ) )
2008-05-11 04:39:02 -04:00
assert_equal ( " <p> \n <textarea>Foo \n Bar \n Baz</textarea> \n </p> \n " , render ( <<SOURCE))
% p
% textarea
Foo
Bar
Baz
SOURCE
2008-03-02 19:12:57 -05:00
end
2009-10-05 22:25:13 -04:00
def test_pre_code
assert_equal ( <<HTML, render(<<HAML))
< pre > < code > Foo & #x000A; bar
 baz</code></pre>
HTML
% pre
% code
:preserve
Foo
bar
baz
HAML
end
2008-03-02 20:20:43 -05:00
def test_boolean_attributes
2008-05-09 19:00:08 -04:00
assert_equal ( " <p bar baz='true' foo='bar'></p> \n " ,
2008-03-02 20:20:43 -05:00
render ( " %p{:foo => 'bar', :bar => true, :baz => 'true'} " , :format = > :html4 ) )
2008-05-09 19:00:08 -04:00
assert_equal ( " <p bar='bar' baz='true' foo='bar'></p> \n " ,
2008-03-02 20:20:43 -05:00
render ( " %p{:foo => 'bar', :bar => true, :baz => 'true'} " , :format = > :xhtml ) )
2008-05-09 19:00:08 -04:00
assert_equal ( " <p baz='false' foo='bar'></p> \n " ,
2008-03-02 20:20:43 -05:00
render ( " %p{:foo => 'bar', :bar => false, :baz => 'false'} " , :format = > :html4 ) )
2008-05-09 19:00:08 -04:00
assert_equal ( " <p baz='false' foo='bar'></p> \n " ,
2008-03-02 20:20:43 -05:00
render ( " %p{:foo => 'bar', :bar => false, :baz => 'false'} " , :format = > :xhtml ) )
end
2008-05-10 06:23:47 -04:00
def test_both_whitespace_nukes_work_together
assert_equal ( <<RESULT, render(<<SOURCE))
< p > < q > Foo
Bar < / q>< / p >
RESULT
% p
% q > < = " Foo \\ nBar "
SOURCE
end
2009-01-23 13:48:35 -05:00
# Regression tests
2009-01-08 21:10:25 -05:00
def test_whitespace_nuke_with_both_newlines
assert_equal ( " <p>foo</p> \n " , render ( '%p<= "\nfoo\n"' ) )
assert_equal ( <<HTML, render(<<HAML))
< p >
< p > foo < / p>
< / p>
HTML
% p
% p < = " \\ nfoo \\ n "
HAML
end
2008-10-29 23:36:53 -04:00
def test_both_case_indentation_work_with_deeply_nested_code
result = <<RESULT
< h2 >
other
< / h2>
RESULT
assert_equal ( result , render ( <<HAML))
- case 'other'
- when 'test'
% h2
hi
- when 'other'
% h2
other
HAML
assert_equal ( result , render ( <<HAML))
- case 'other'
- when 'test'
% h2
hi
- when 'other'
% h2
other
HAML
end
2009-01-23 13:48:35 -05:00
def test_equals_block_with_ugly
2009-01-23 15:19:24 -05:00
assert_equal ( " foo \n " , render ( <<HAML, :ugly => true))
2009-01-23 13:48:35 -05:00
= capture_haml do
foo
HAML
end
2009-01-23 15:19:24 -05:00
def test_plain_equals_with_ugly
assert_equal ( " foo \n bar \n " , render ( <<HAML, :ugly => true))
= " foo "
bar
HAML
end
2009-02-26 15:59:28 -05:00
def test_inline_if
assert_equal ( <<HTML, render(<<HAML))
< p > One < / p>
< p > < / p>
< p > Three < / p>
HTML
- for name in [ " One " , " Two " , " Three " ]
% p = name unless name == " Two "
HAML
end
2009-03-15 22:06:43 -04:00
def test_end_with_method_call
assert_equal ( <<HTML, render(<<HAML))
2 | 3 | 4
b - a - r
HTML
= [ 1 , 2 , 3 ] . map do | i |
- i + 1
- end . join ( " | " )
= " bar " . gsub ( / . / ) do | s |
- s + " - "
- end . gsub ( / -$ / ) do | s |
- ''
HAML
end
2009-08-28 02:01:56 -04:00
def test_silent_end_with_stuff
assert_equal ( <<HTML, render(<<HAML))
e
d
c
b
a
HTML
- str = " abcde "
- if true
= str . slice! ( - 1 ) . chr
- end until str . empty?
HAML
assert_equal ( <<HTML, render(<<HAML))
< p > hi! < / p>
HTML
- if true
% p hi!
- end if " foo " . gsub ( / f / ) do
- " z "
- end + " bar "
HAML
end
2009-03-18 13:47:39 -04:00
def test_multiline_with_colon_after_filter
assert_equal ( <<HTML, render(<<HAML))
Foo
Bar
HTML
:plain
Foo
= { :a = > " Bar " , |
:b = > " Baz " } [ :a ] |
HAML
assert_equal ( <<HTML, render(<<HAML))
Bar
HTML
:plain
= { :a = > " Bar " , |
:b = > " Baz " } [ :a ] |
HAML
end
def test_multiline_in_filter
assert_equal ( <<HTML, render(<<HAML))
Foo |
Bar |
Baz
HTML
:plain
Foo |
Bar |
Baz
HAML
end
2009-03-28 03:19:13 -04:00
def test_curly_brace
assert_equal ( <<HTML, render(<<HAML))
Foo { Bar
HTML
== Foo { Bar
HAML
end
2009-07-10 15:35:42 -04:00
def test_escape_html
html = <<HTML
& amp ;
&
& amp ;
HTML
assert_equal ( html , render ( <<HAML, :escape_html => true))
& = " & "
!= " & "
= " & "
HAML
assert_equal ( html , render ( <<HAML, :escape_html => true))
& ~ " & "
!~ " & "
~ " & "
HAML
assert_equal ( html , render ( <<HAML, :escape_html => true))
& \ #{"&"}
! \ #{"&"}
\ #{"&"}
HAML
assert_equal ( html , render ( <<HAML, :escape_html => true))
& == \ #{"&"}
!= = \ #{"&"}
== \ #{"&"}
HAML
tag_html = <<HTML
< p > & amp ; < / p>
< p > & < / p>
< p > & amp ; < / p>
HTML
assert_equal ( tag_html , render ( <<HAML, :escape_html => true))
% p & = " & "
% p != " & "
% p = " & "
HAML
assert_equal ( tag_html , render ( <<HAML, :escape_html => true))
% p & ~ " & "
% p !~ " & "
% p ~ " & "
HAML
assert_equal ( tag_html , render ( <<HAML, :escape_html => true))
% p & \ #{"&"}
% p ! \ #{"&"}
% p \ #{"&"}
HAML
assert_equal ( tag_html , render ( <<HAML, :escape_html => true))
% p & == \ #{"&"}
% p != = \ #{"&"}
% p == \ #{"&"}
HAML
end
2009-07-12 10:36:47 -04:00
def test_new_attrs_with_hash
assert_equal ( " <a href=' # '></a> \n " , render ( '%a(href="#")' ) )
end
2009-07-19 19:26:43 -04:00
def test_javascript_filter_with_dynamic_interp_and_escape_html
assert_equal ( <<HTML, render(<<HAML, :escape_html => true))
< script type = 'text/javascript' >
/ / < ! [ CDATA [
& < > &
/ / ] ] >
< / script>
HTML
:javascript
& < > \ #{"&"}
HAML
end
2009-09-18 04:36:11 -04:00
def test_silent_script_with_hyphen_case
assert_equal ( " " , render ( " - 'foo-case-bar-case' " ) )
end
def test_silent_script_with_hyphen_end
assert_equal ( " " , render ( " - 'foo-end-bar-end' " ) )
end
def test_silent_script_with_hyphen_end_and_block
assert_equal ( <<HTML, render(<<HAML))
< p > foo - end < / p>
< p > bar - end < / p>
HTML
- " foo-end-bar-end " . gsub ( / \\ w+-end / ) do | s |
% p = s
HAML
end
2008-03-14 19:39:19 -04:00
# HTML escaping tests
2008-03-18 05:19:41 -04:00
def test_ampersand_equals_should_escape
2008-03-14 19:39:19 -04:00
assert_equal ( " <p> \n foo & bar \n </p> \n " , render ( " %p \n &= 'foo & bar' " , :escape_html = > false ) )
end
2008-03-18 05:19:41 -04:00
def test_ampersand_equals_inline_should_escape
2008-03-14 19:39:19 -04:00
assert_equal ( " <p>foo & bar</p> \n " , render ( " %p&= 'foo & bar' " , :escape_html = > false ) )
end
2008-08-04 01:04:50 -04:00
def test_ampersand_equals_should_escape_before_preserve
assert_equal ( " <textarea>foo& # x000A;bar</textarea> \n " , render ( '%textarea&= "foo\nbar"' , :escape_html = > false ) )
end
2008-03-18 05:19:41 -04:00
def test_bang_equals_should_not_escape
2008-03-14 19:39:19 -04:00
assert_equal ( " <p> \n foo & bar \n </p> \n " , render ( " %p \n != 'foo & bar' " , :escape_html = > true ) )
end
2008-03-18 05:19:41 -04:00
def test_bang_equals_inline_should_not_escape
2008-03-14 19:39:19 -04:00
assert_equal ( " <p>foo & bar</p> \n " , render ( " %p!= 'foo & bar' " , :escape_html = > true ) )
end
2008-03-18 05:19:41 -04:00
def test_static_attributes_should_be_escaped
assert_equal ( " <img class='atlantis' style='ugly&stupid' /> \n " ,
2008-07-27 20:44:02 -04:00
render ( " %img.atlantis{:style => 'ugly&stupid'} " ) )
2008-03-18 05:19:41 -04:00
assert_equal ( " <div class='atlantis' style='ugly&stupid'>foo</div> \n " ,
2008-07-27 20:44:02 -04:00
render ( " .atlantis{:style => 'ugly&stupid'} foo " ) )
2008-03-18 05:19:41 -04:00
assert_equal ( " <p class='atlantis' style='ugly&stupid'>foo</p> \n " ,
2008-07-27 20:44:02 -04:00
render ( " %p.atlantis{:style => 'ugly&stupid'}= 'foo' " ) )
2008-07-27 20:50:28 -04:00
assert_equal ( " <p class='atlantis' style='ugly& # x000A;stupid'></p> \n " ,
render ( " %p.atlantis{:style => \" ugly \\ nstupid \" } " ) )
2008-03-18 05:19:41 -04:00
end
def test_dynamic_attributes_should_be_escaped
2008-07-27 20:48:22 -04:00
assert_equal ( " <img alt='' src='&foo.png' /> \n " ,
render ( " %img{:width => nil, :src => '&foo.png', :alt => String.new} " ) )
assert_equal ( " <p alt='' src='&foo.png'>foo</p> \n " ,
render ( " %p{:width => nil, :src => '&foo.png', :alt => String.new} foo " ) )
assert_equal ( " <div alt='' src='&foo.png'>foo</div> \n " ,
render ( " %div{:width => nil, :src => '&foo.png', :alt => String.new}= 'foo' " ) )
2008-07-27 20:50:28 -04:00
assert_equal ( " <img alt='' src='foo& # x000A;.png' /> \n " ,
render ( " %img{:width => nil, :src => \" foo \\ n.png \" , :alt => String.new} " ) )
2008-03-18 05:19:41 -04:00
end
2008-12-11 16:46:14 -05:00
def test_string_double_equals_should_be_esaped
2008-12-11 13:26:46 -05:00
assert_equal ( " <p>4&3</p> \n " , render ( " %p== \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p== \# {2+2}& \# {2+1} " , :escape_html = > false ) )
2008-03-18 05:19:41 -04:00
end
2008-12-11 16:46:14 -05:00
def test_escaped_inline_string_double_equals
2008-11-25 02:53:10 -05:00
assert_equal ( " <p>4&3</p> \n " , render ( " %p&== \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p&== \# {2+2}& \# {2+1} " , :escape_html = > false ) )
2008-03-18 05:19:41 -04:00
end
2008-03-14 19:39:19 -04:00
2008-12-11 16:46:14 -05:00
def test_unescaped_inline_string_double_equals
2008-11-25 02:53:10 -05:00
assert_equal ( " <p>4&3</p> \n " , render ( " %p!== \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p!== \# {2+2}& \# {2+1} " , :escape_html = > false ) )
2008-03-18 05:19:41 -04:00
end
2008-12-11 16:46:14 -05:00
def test_escaped_string_double_equals
2008-11-25 02:53:10 -05:00
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n &== \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n &== \# {2+2}& \# {2+1} " , :escape_html = > false ) )
2008-03-18 05:19:41 -04:00
end
2008-12-11 16:46:14 -05:00
def test_unescaped_string_double_equals
2008-11-25 02:53:10 -05:00
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n !== \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n !== \# {2+2}& \# {2+1} " , :escape_html = > false ) )
2008-03-18 05:19:41 -04:00
end
2008-12-11 16:46:14 -05:00
def test_string_interpolation_should_be_esaped
assert_equal ( " <p>4&3</p> \n " , render ( " %p \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p \# {2+2}& \# {2+1} " , :escape_html = > false ) )
end
def test_escaped_inline_string_interpolation
assert_equal ( " <p>4&3</p> \n " , render ( " %p& \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p& \# {2+2}& \# {2+1} " , :escape_html = > false ) )
end
def test_unescaped_inline_string_interpolation
assert_equal ( " <p>4&3</p> \n " , render ( " %p! \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p>4&3</p> \n " , render ( " %p! \# {2+2}& \# {2+1} " , :escape_html = > false ) )
end
def test_escaped_string_interpolation
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n & \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n & \# {2+2}& \# {2+1} " , :escape_html = > false ) )
end
def test_unescaped_string_interpolation
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n ! \# {2+2}& \# {2+1} " , :escape_html = > true ) )
assert_equal ( " <p> \n 4&3 \n </p> \n " , render ( " %p \n ! \# {2+2}& \# {2+1} " , :escape_html = > false ) )
end
2008-03-18 05:19:41 -04:00
def test_scripts_should_respect_escape_html_option
2008-03-14 19:39:19 -04:00
assert_equal ( " <p> \n foo & bar \n </p> \n " , render ( " %p \n = 'foo & bar' " , :escape_html = > true ) )
assert_equal ( " <p> \n foo & bar \n </p> \n " , render ( " %p \n = 'foo & bar' " , :escape_html = > false ) )
end
2008-03-18 05:19:41 -04:00
def test_inline_scripts_should_respect_escape_html_option
2008-03-14 19:39:19 -04:00
assert_equal ( " <p>foo & bar</p> \n " , render ( " %p= 'foo & bar' " , :escape_html = > true ) )
assert_equal ( " <p>foo & bar</p> \n " , render ( " %p= 'foo & bar' " , :escape_html = > false ) )
end
2008-03-18 05:19:41 -04:00
def test_script_ending_in_comment_should_render_when_html_is_escaped
assert_equal ( " foo&bar \n " , render ( " = 'foo&bar' # comment " , :escape_html = > true ) )
end
2009-01-07 19:04:17 -05:00
def test_script_with_if_shouldnt_output
assert_equal ( <<HTML, render(<<HAML))
< p > foo < / p>
< p > < / p>
HTML
% p = " foo "
% p = " bar " if false
HAML
end
2006-11-04 03:35:06 -05:00
# Options tests
2008-05-02 02:54:10 -04:00
def test_filename_and_line
begin
render ( " \n \n = abc " , :filename = > 'test' , :line = > 2 )
rescue Exception = > e
assert_kind_of Haml :: SyntaxError , e
2008-08-29 20:40:59 -04:00
assert_match ( / test:4 / , e . backtrace . first )
2008-05-02 02:54:10 -04:00
end
begin
render ( " \n \n = 123 \n \n = nil[] " , :filename = > 'test' , :line = > 2 )
rescue Exception = > e
assert_kind_of NoMethodError , e
2008-08-29 20:40:59 -04:00
assert_match ( / test:6 / , e . backtrace . first )
2008-05-02 02:54:10 -04:00
end
end
2006-11-04 03:35:06 -05:00
def test_stop_eval
assert_equal ( " " , render ( " = 'Hello' " , :suppress_eval = > true ) )
2008-10-29 23:39:34 -04:00
assert_equal ( " " , render ( " - haml_concat 'foo' " , :suppress_eval = > true ) )
2007-06-02 06:45:24 -04:00
assert_equal ( " <div id='foo' yes='no' /> \n " , render ( " # foo{:yes => 'no'}/ " , :suppress_eval = > true ) )
assert_equal ( " <div id='foo' /> \n " , render ( " # foo{:yes => 'no', :call => a_function() }/ " , :suppress_eval = > true ) )
2007-04-09 13:03:12 -04:00
assert_equal ( " <div /> \n " , render ( " %div[1]/ " , :suppress_eval = > true ) )
2008-10-29 23:39:34 -04:00
assert_equal ( " " , render ( " :ruby \n Kernel.puts 'hello' " , :suppress_eval = > true ) )
2006-11-04 03:35:06 -05:00
end
2008-11-30 00:57:37 -05:00
def test_doctypes
assert_equal ( '<!DOCTYPE html>' ,
render ( '!!!' , :format = > :html5 ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' ,
render ( '!!! strict' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">' ,
render ( '!!! frameset' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">' ,
render ( '!!! mobile' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">' ,
render ( '!!! basic' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' ,
render ( '!!! transitional' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' ,
render ( '!!!' ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' ,
render ( '!!! strict' , :format = > :html4 ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">' ,
render ( '!!! frameset' , :format = > :html4 ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' ,
render ( '!!! transitional' , :format = > :html4 ) . strip )
assert_equal ( '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' ,
render ( '!!!' , :format = > :html4 ) . strip )
end
2006-11-04 03:35:06 -05:00
def test_attr_wrapper
2008-05-09 19:00:08 -04:00
assert_equal ( " <p strange=*attrs*></p> \n " , render ( " %p{ :strange => 'attrs'} " , :attr_wrapper = > '*' ) )
assert_equal ( " <p escaped='quo \" te'></p> \n " , render ( " %p{ :escaped => 'quo \" te'} " , :attr_wrapper = > '"' ) )
assert_equal ( " <p escaped= \" quo'te \" ></p> \n " , render ( " %p{ :escaped => 'quo \\ 'te'} " , :attr_wrapper = > '"' ) )
assert_equal ( " <p escaped= \" q'uo"te \" ></p> \n " , render ( " %p{ :escaped => 'q \\ 'uo \" te'} " , :attr_wrapper = > '"' ) )
2006-11-07 20:54:26 -05:00
assert_equal ( " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \n " , render ( " !!! XML " , :attr_wrapper = > '"' ) )
2006-11-04 03:35:06 -05:00
end
2007-06-02 06:45:24 -04:00
def test_attrs_parsed_correctly
2008-05-09 19:00:08 -04:00
assert_equal ( " <p boom=>biddly='bar => baz'></p> \n " , render ( " %p{'boom=>biddly' => 'bar => baz'} " ) )
assert_equal ( " <p foo,bar='baz, qux'></p> \n " , render ( " %p{'foo,bar' => 'baz, qux'} " ) )
2008-07-27 20:50:28 -04:00
assert_equal ( " <p escaped='quo& # x000A;te'></p> \n " , render ( " %p{ :escaped => \" quo \\ nte \" } " ) )
2008-05-09 19:00:08 -04:00
assert_equal ( " <p escaped='quo4te'></p> \n " , render ( " %p{ :escaped => \" quo \# {2 + 2}te \" } " ) )
2007-06-02 06:45:24 -04:00
end
2007-07-24 22:46:43 -04:00
2008-02-10 19:45:36 -05:00
def test_correct_parsing_with_brackets
assert_equal ( " <p class='foo'>{tada} foo</p> \n " , render ( " %p{:class => 'foo'} {tada} foo " ) )
assert_equal ( " <p class='foo'>deep {nested { things }}</p> \n " , render ( " %p{:class => 'foo'} deep {nested { things }} " ) )
assert_equal ( " <p class='bar foo'>{a { d</p> \n " , render ( " %p{{:class => 'foo'}, :class => 'bar'} {a { d " ) )
assert_equal ( " <p foo='bar'>a}</p> \n " , render ( " %p{:foo => 'bar'} a} " ) )
foo = [ ]
foo [ 0 ] = Struct . new ( 'Foo' , :id ) . new
assert_equal ( " <p class='struct_foo' id='struct_foo_new'>New User]</p> \n " ,
render ( " %p[foo[0]] New User] " , :locals = > { :foo = > foo } ) )
2008-04-10 06:37:22 -04:00
assert_equal ( " <p class='prefix_struct_foo' id='prefix_struct_foo_new'>New User]</p> \n " ,
render ( " %p[foo[0], :prefix] New User] " , :locals = > { :foo = > foo } ) )
foo [ 0 ] . id = 1
assert_equal ( " <p class='struct_foo' id='struct_foo_1'>New User]</p> \n " ,
render ( " %p[foo[0]] New User] " , :locals = > { :foo = > foo } ) )
assert_equal ( " <p class='prefix_struct_foo' id='prefix_struct_foo_1'>New User]</p> \n " ,
render ( " %p[foo[0], :prefix] New User] " , :locals = > { :foo = > foo } ) )
2008-02-10 19:45:36 -05:00
end
2007-07-24 22:46:43 -04:00
def test_empty_attrs
assert_equal ( " <p attr=''>empty</p> \n " , render ( " %p{ :attr => '' } empty " ) )
assert_equal ( " <p attr=''>empty</p> \n " , render ( " %p{ :attr => x } empty " , :locals = > { :x = > '' } ) )
end
def test_nil_attrs
assert_equal ( " <p>nil</p> \n " , render ( " %p{ :attr => nil } nil " ) )
assert_equal ( " <p>nil</p> \n " , render ( " %p{ :attr => x } nil " , :locals = > { :x = > nil } ) )
end
2007-06-02 06:45:24 -04:00
2008-01-10 03:40:00 -05:00
def test_nil_id_with_syntactic_id
assert_equal ( " <p id='foo'>nil</p> \n " , render ( " %p # foo{:id => nil} nil " ) )
assert_equal ( " <p id='foo_bar'>nil</p> \n " , render ( " %p # foo{{:id => 'bar'}, :id => nil} nil " ) )
assert_equal ( " <p id='foo_bar'>nil</p> \n " , render ( " %p # foo{{:id => nil}, :id => 'bar'} nil " ) )
end
def test_nil_class_with_syntactic_class
assert_equal ( " <p class='foo'>nil</p> \n " , render ( " %p.foo{:class => nil} nil " ) )
assert_equal ( " <p class='bar foo'>nil</p> \n " , render ( " %p.bar.foo{:class => nil} nil " ) )
assert_equal ( " <p class='bar foo'>nil</p> \n " , render ( " %p.foo{{:class => 'bar'}, :class => nil} nil " ) )
assert_equal ( " <p class='bar foo'>nil</p> \n " , render ( " %p.foo{{:class => nil}, :class => 'bar'} nil " ) )
end
2006-11-04 03:35:06 -05:00
def test_locals
assert_equal ( " <p>Paragraph!</p> \n " , render ( " %p= text " , :locals = > { :text = > " Paragraph! " } ) )
end
2007-05-10 04:12:20 -04:00
2007-08-26 13:12:22 -04:00
def test_dynamic_attrs_shouldnt_register_as_literal_values
2008-05-09 19:00:08 -04:00
assert_equal ( " <p a='b2c'></p> \n " , render ( '%p{:a => "b#{1 + 1}c"}' ) )
assert_equal ( " <p a='b2c'></p> \n " , render ( " %p{:a => 'b' + (1 + 1).to_s + 'c'} " ) )
2007-08-21 21:42:19 -04:00
end
2007-01-20 20:24:16 -05:00
2008-01-17 13:41:27 -05:00
def test_dynamic_attrs_with_self_closed_tag
assert_equal ( " <a b='2' /> \n c \n " , render ( " %a{'b' => 1 + 1}/ \n = 'c' \n " ) )
end
2009-09-27 21:20:50 -04:00
EXCEPTION_MAP . each do | key , value |
define_method ( " test_exception ( #{ key . inspect } ) " ) do
2007-01-27 05:29:14 -05:00
begin
2009-09-27 21:20:50 -04:00
render ( key , :filename = > __FILE__ )
2008-04-29 00:28:01 -04:00
rescue Exception = > err
2008-04-24 16:47:59 -04:00
value = [ value ] unless value . is_a? ( Array )
2008-08-29 20:40:59 -04:00
expected_message , line_no = value
line_no || = key . split ( " \n " ) . length
2008-04-24 16:47:59 -04:00
2009-09-27 20:37:22 -04:00
if expected_message == :compile
assert_match ( / ^compile error \ n / , err . message , " Line: #{ key } " )
else
assert_equal ( expected_message , err . message , " Line: #{ key } " )
end
2009-09-27 21:20:50 -04:00
assert_match ( / ^ #{ Regexp . escape ( __FILE__ ) } : #{ line_no } / , err . backtrace [ 0 ] , " Line: #{ key } " )
2007-01-27 05:29:14 -05:00
else
2008-04-29 00:28:01 -04:00
assert ( false , " Exception not raised for \n #{ key } " )
2007-01-27 05:29:14 -05:00
end
end
end
2008-04-18 14:08:49 -04:00
def test_exception_line
2007-11-24 03:35:10 -05:00
render ( " a \n b \n !!! \n c \n d " )
rescue Haml :: SyntaxError = > e
2008-08-29 20:40:59 -04:00
assert_equal ( " (test_exception_line):4 " , e . backtrace [ 0 ] )
2007-11-24 03:35:10 -05:00
else
assert ( false , '"a\nb\n!!!\n c\nd" doesn\'t produce an exception' )
end
2007-11-25 22:26:16 -05:00
def test_exception
render ( " %p \n hi \n %a= undefined \n = 12 " )
2007-11-24 03:35:10 -05:00
rescue Exception = > e
2008-08-29 20:40:59 -04:00
assert_match ( " (test_exception):3 " , e . backtrace [ 0 ] )
2007-11-24 03:35:10 -05:00
else
# Test failed... should have raised an exception
assert ( false )
2007-11-23 03:24:11 -05:00
end
2007-01-27 05:29:14 -05:00
def test_compile_error
2007-11-25 22:26:16 -05:00
render ( " a \n b \n - fee) \n c " )
2007-11-24 03:35:10 -05:00
rescue Exception = > e
2009-02-07 05:33:58 -05:00
assert_match ( / \ (test_compile_error \ ):3: syntax error /i , e . message )
2007-11-24 03:35:10 -05:00
else
assert ( false ,
2007-11-25 22:26:16 -05:00
'"a\nb\n- fee)\nc" doesn\'t produce an exception!' )
2007-01-27 05:29:14 -05:00
end
2007-01-31 01:38:23 -05:00
2007-11-25 20:36:57 -05:00
def test_unbalanced_brackets
2008-12-11 17:25:54 -05:00
render ( 'foo #{1 + 5} foo #{6 + 7 bar #{8 + 9}' )
2007-11-25 20:36:57 -05:00
rescue Haml :: SyntaxError = > e
assert_equal ( " Unbalanced brackets. " , e . message )
end
2008-04-28 23:59:43 -04:00
def test_balanced_conditional_comments
assert_equal ( " <!--[if !(IE 6)|(IE 7)]> Bracket: ] <![endif]--> \n " ,
render ( " /[if !(IE 6)|(IE 7)] Bracket: ] " ) )
end
2008-04-18 14:37:34 -04:00
def test_empty_filter
assert_equal ( <<END, render(':javascript'))
< script type = 'text/javascript' >
/ / < ! [ CDATA [
/ / ] ] >
< / script>
END
end
2008-07-10 23:38:39 -04:00
def test_ugly_filter
assert_equal ( <<END, render(":sass\n #foo\n bar: baz", :ugly => true))
#foo {
bar : baz ; }
END
end
2007-04-15 21:38:25 -04:00
def test_local_assigns_dont_modify_class
assert_equal ( " bar \n " , render ( " = foo " , :locals = > { :foo = > 'bar' } ) )
assert_equal ( nil , defined? ( foo ) )
end
2007-04-17 02:49:07 -04:00
def test_object_ref_with_nil_id
2008-04-28 00:14:12 -04:00
user = User . new
2007-04-17 02:49:07 -04:00
assert_equal ( " <p class='struct_user' id='struct_user_new'>New User</p> \n " ,
render ( " %p[user] New User " , :locals = > { :user = > user } ) )
end
2007-11-23 02:02:07 -05:00
2008-04-28 00:14:12 -04:00
def test_object_ref_before_attrs
user = User . new 42
assert_equal ( " <p class='struct_user' id='struct_user_42' style='width: 100px;'>New User</p> \n " ,
render ( " %p[user]{:style => 'width: 100px;'} New User " , :locals = > { :user = > user } ) )
end
2007-12-19 04:41:33 -05:00
def test_non_literal_attributes
assert_equal ( " <p a1='foo' a2='bar' a3='baz' /> \n " ,
render ( " %p{a2, a1, :a3 => 'baz'}/ " ,
:locals = > { :a1 = > { :a1 = > 'foo' } , :a2 = > { :a2 = > 'bar' } } ) )
end
2007-11-23 02:02:07 -05:00
def test_render_should_accept_a_binding_as_scope
string = " This is a string! "
string . instance_variable_set ( " @var " , " Instance variable " )
2007-11-23 02:42:59 -05:00
b = string . instance_eval do
var = " Local variable "
binding
end
2007-11-23 02:02:07 -05:00
2007-11-23 02:42:59 -05:00
assert_equal ( " <p>THIS IS A STRING!</p> \n <p>Instance variable</p> \n <p>Local variable</p> \n " ,
render ( " %p= upcase \n %p= @var \n %p= var " , :scope = > b ) )
2007-11-23 02:02:07 -05:00
end
2007-11-23 07:14:02 -05:00
def test_yield_should_work_with_binding
assert_equal ( " 12 \n FOO \n " , render ( " = yield \n = upcase " , :scope = > " foo " . instance_eval { binding } ) { 12 } )
end
2007-11-23 21:32:18 -05:00
def test_yield_should_work_with_def_method
s = " foo "
2008-08-29 20:40:59 -04:00
engine ( " = yield \n = upcase " ) . def_method ( s , :render )
2007-11-23 21:32:18 -05:00
assert_equal ( " 12 \n FOO \n " , s . render { 12 } )
end
def test_def_method_with_module
2008-08-29 20:40:59 -04:00
engine ( " = yield \n = upcase " ) . def_method ( String , :render_haml )
2007-11-23 21:32:18 -05:00
assert_equal ( " 12 \n FOO \n " , " foo " . render_haml { 12 } )
end
2007-11-24 03:35:10 -05:00
def test_def_method_locals
obj = Object . new
2008-08-29 20:40:59 -04:00
engine ( " %p= foo \n .bar{:baz => baz}= boom " ) . def_method ( obj , :render , :foo , :baz , :boom )
2007-11-24 03:35:10 -05:00
assert_equal ( " <p>1</p> \n <div baz='2' class='bar'>3</div> \n " , obj . render ( :foo = > 1 , :baz = > 2 , :boom = > 3 ) )
end
def test_render_proc_locals
2008-08-29 20:40:59 -04:00
proc = engine ( " %p= foo \n .bar{:baz => baz}= boom " ) . render_proc ( Object . new , :foo , :baz , :boom )
2007-11-24 03:35:10 -05:00
assert_equal ( " <p>1</p> \n <div baz='2' class='bar'>3</div> \n " , proc [ :foo = > 1 , :baz = > 2 , :boom = > 3 ] )
end
def test_render_proc_with_binding
2008-08-29 20:40:59 -04:00
assert_equal ( " FOO \n " , engine ( " = upcase " ) . render_proc ( " foo " . instance_eval { binding } ) . call )
2007-11-24 03:35:10 -05:00
end
2008-02-13 04:30:21 -05:00
def test_ugly_true
2008-02-13 23:13:12 -05:00
assert_equal ( " <div id='outer'> \n <div id='inner'> \n <p>hello world</p> \n </div> \n </div> \n " ,
render ( " # outer \n # inner \n %p hello world " , :ugly = > true ) )
assert_equal ( " <p> #{ 's' * 75 } </p> \n " ,
render ( " %p #{ 's' * 75 } " , :ugly = > true ) )
2008-02-13 04:30:21 -05:00
2008-02-13 23:13:12 -05:00
assert_equal ( " <p> #{ 's' * 75 } </p> \n " ,
render ( " %p= 's' * 75 " , :ugly = > true ) )
2008-02-13 04:30:21 -05:00
end
2008-02-24 17:10:30 -05:00
2008-05-27 15:16:24 -04:00
def test_auto_preserve_unless_ugly
assert_equal ( " <pre>foo& # x000A;bar</pre> \n " , render ( '%pre="foo\nbar"' ) )
assert_equal ( " <pre>foo \n bar</pre> \n " , render ( " %pre \n foo \n bar " ) )
assert_equal ( " <pre>foo \n bar</pre> \n " , render ( '%pre="foo\nbar"' , :ugly = > true ) )
assert_equal ( " <pre>foo \n bar</pre> \n " , render ( " %pre \n foo \n bar " , :ugly = > true ) )
end
2008-02-26 13:57:45 -05:00
def test_xhtml_output_option
2008-02-29 14:00:03 -05:00
assert_equal " <p> \n <br /> \n </p> \n " , render ( " %p \n %br " , :format = > :xhtml )
assert_equal " <a /> \n " , render ( " %a/ " , :format = > :xhtml )
2008-02-26 13:57:45 -05:00
end
def test_arbitrary_output_option
2008-08-29 20:40:59 -04:00
assert_raise ( Haml :: Error , " Invalid output format :html1 " ) { engine ( " %br " , :format = > :html1 ) }
2008-02-26 13:57:45 -05:00
end
2009-06-03 18:01:40 -04:00
def test_static_hashes
assert_equal ( " <a b='a => b'></a> \n " , render ( " %a{:b => 'a => b'} " , :suppress_eval = > true ) )
assert_equal ( " <a b='a, b'></a> \n " , render ( " %a{:b => 'a, b'} " , :suppress_eval = > true ) )
assert_equal ( " <a b='a \t b'></a> \n " , render ( '%a{:b => "a\tb"}' , :suppress_eval = > true ) )
assert_equal ( " <a b='a \# {foo}b'></a> \n " , render ( '%a{:b => "a\\#{foo}b"}' , :suppress_eval = > true ) )
end
2009-06-03 18:05:14 -04:00
def test_dynamic_hashes_with_suppress_eval
assert_equal ( " <a></a> \n " , render ( '%a{:b => "a #{1 + 1} b", :c => "d"}' , :suppress_eval = > true ) )
end
2008-02-26 13:43:37 -05:00
# HTML 4.0
def test_html_has_no_self_closing_tags
2008-02-29 14:00:03 -05:00
assert_equal " <p> \n <br> \n </p> \n " , render ( " %p \n %br " , :format = > :html4 )
assert_equal " <br> \n " , render ( " %br/ " , :format = > :html4 )
2008-02-26 13:43:37 -05:00
end
def test_html_renders_empty_node_with_closing_tag
2008-05-09 19:00:08 -04:00
assert_equal " <div class='foo'></div> \n " , render ( " .foo " , :format = > :html4 )
2008-02-26 13:43:37 -05:00
end
2008-10-06 12:46:09 -04:00
def test_html_doesnt_add_slash_to_self_closing_tags
assert_equal " <a> \n " , render ( " %a/ " , :format = > :html4 )
assert_equal " <a foo='2'> \n " , render ( " %a{:foo => 1 + 1}/ " , :format = > :html4 )
assert_equal " <meta> \n " , render ( " %meta " , :format = > :html4 )
assert_equal " <meta foo='2'> \n " , render ( " %meta{:foo => 1 + 1} " , :format = > :html4 )
2008-02-26 13:43:37 -05:00
end
def test_html_ignores_xml_prolog_declaration
2008-02-29 14:00:03 -05:00
assert_equal " " , render ( '!!! XML' , :format = > :html4 )
2008-02-26 13:43:37 -05:00
end
def test_html_has_different_doctype
assert_equal %{ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> \n } ,
2008-02-29 14:00:03 -05:00
render ( '!!!' , :format = > :html4 )
2008-02-24 17:10:30 -05:00
end
2008-02-27 09:16:21 -05:00
# because anything before the doctype triggers quirks mode in IE
def test_xml_prolog_and_doctype_dont_result_in_a_leading_whitespace_in_html
2008-08-29 20:40:59 -04:00
assert_no_match ( / ^ \ s+ / , render ( " !!! xml \n !!! " , :format = > :html4 ) )
2008-02-27 09:16:21 -05:00
end
2008-02-27 09:20:44 -05:00
# HTML5
def test_html5_doctype
2008-02-29 14:00:03 -05:00
assert_equal %{ <!DOCTYPE html> \n } , render ( '!!!' , :format = > :html5 )
2008-02-27 09:20:44 -05:00
end
2009-05-19 17:28:34 -04:00
# New attributes
def test_basic_new_attributes
assert_equal ( " <a>bar</a> \n " , render ( " %a() bar " ) )
assert_equal ( " <a href='foo'>bar</a> \n " , render ( " %a(href='foo') bar " ) )
assert_equal ( " <a b='c' c='d' d='e'>baz</a> \n " , render ( %q{ %a(b="c" c='d' d="e") baz } ) )
end
def test_new_attribute_ids
assert_equal ( " <div id='foo_bar'></div> \n " , render ( " # foo(id='bar') " ) )
assert_equal ( " <div id='foo_bar_baz'></div> \n " , render ( " # foo{:id => 'bar'}(id='baz') " ) )
assert_equal ( " <div id='foo_baz_bar'></div> \n " , render ( " # foo(id='baz'){:id => 'bar'} " ) )
foo = User . new ( 42 )
assert_equal ( " <div class='struct_user' id='foo_baz_bar_struct_user_42'></div> \n " ,
render ( " # foo(id='baz'){:id => 'bar'}[foo] " , :locals = > { :foo = > foo } ) )
assert_equal ( " <div class='struct_user' id='foo_baz_bar_struct_user_42'></div> \n " ,
render ( " # foo(id='baz')[foo]{:id => 'bar'} " , :locals = > { :foo = > foo } ) )
assert_equal ( " <div class='struct_user' id='foo_baz_bar_struct_user_42'></div> \n " ,
render ( " # foo[foo](id='baz'){:id => 'bar'} " , :locals = > { :foo = > foo } ) )
assert_equal ( " <div class='struct_user' id='foo_bar_baz_struct_user_42'></div> \n " ,
render ( " # foo[foo]{:id => 'bar'}(id='baz') " , :locals = > { :foo = > foo } ) )
end
def test_new_attribute_classes
assert_equal ( " <div class='bar foo'></div> \n " , render ( " .foo(class='bar') " ) )
assert_equal ( " <div class='bar baz foo'></div> \n " , render ( " .foo{:class => 'bar'}(class='baz') " ) )
assert_equal ( " <div class='bar baz foo'></div> \n " , render ( " .foo(class='baz'){:class => 'bar'} " ) )
foo = User . new ( 42 )
assert_equal ( " <div class='bar baz foo struct_user' id='struct_user_42'></div> \n " ,
render ( " .foo(class='baz'){:class => 'bar'}[foo] " , :locals = > { :foo = > foo } ) )
assert_equal ( " <div class='bar baz foo struct_user' id='struct_user_42'></div> \n " ,
render ( " .foo[foo](class='baz'){:class => 'bar'} " , :locals = > { :foo = > foo } ) )
assert_equal ( " <div class='bar baz foo struct_user' id='struct_user_42'></div> \n " ,
render ( " .foo[foo]{:class => 'bar'}(class='baz') " , :locals = > { :foo = > foo } ) )
end
def test_dynamic_new_attributes
assert_equal ( " <a href='12'>bar</a> \n " , render ( " %a(href=foo) bar " , :locals = > { :foo = > 12 } ) )
assert_equal ( " <a b='12' c='13' d='14'>bar</a> \n " , render ( " %a(b=b c='13' d=d) bar " , :locals = > { :b = > 12 , :d = > 14 } ) )
end
def test_new_attribute_interpolation
assert_equal ( " <a href='12'>bar</a> \n " , render ( '%a(href="1#{1 + 1}") bar' ) )
assert_equal ( " <a href='2: 2, 3: 3'>bar</a> \n " , render ( %q{ %a(href='2: # { 1 + 1 } , 3: # { foo } ') bar } , :locals = > { :foo = > 3 } ) )
assert_equal ( %Q{ <a href='1 \# { 1 + 1 } '>bar</a> \n } , render ( '%a(href="1\#{1 + 1}") bar' ) )
end
def test_truthy_new_attributes
assert_equal ( " <a href='href'>bar</a> \n " , render ( " %a(href) bar " ) )
assert_equal ( " <a bar='baz' href>bar</a> \n " , render ( " %a(href bar='baz') bar " , :format = > :html5 ) )
assert_equal ( " <a href='href'>bar</a> \n " , render ( " %a(href=true) bar " ) )
assert_equal ( " <a>bar</a> \n " , render ( " %a(href=false) bar " ) )
end
def test_new_attribute_parsing
assert_equal ( " <a a2='b2'>bar</a> \n " , render ( " %a(a2=b2) bar " , :locals = > { :b2 = > 'b2' } ) )
assert_equal ( %Q{ <a a='foo"bar'>bar</a> \n } , render ( %q{ %a(a=" # { 'foo"bar' } ") bar } ) ) #'
assert_equal ( %Q{ <a a="foo'bar">bar</a> \n } , render ( %q{ %a(a=" # { "foo'bar" } ") bar } ) ) #'
assert_equal ( %Q{ <a a='foo"bar'>bar</a> \n } , render ( %q{ %a(a='foo"bar') bar } ) )
assert_equal ( %Q{ <a a="foo'bar">bar</a> \n } , render ( %q{ %a(a="foo'bar") bar } ) )
assert_equal ( " <a a:b='foo'>bar</a> \n " , render ( " %a(a:b='foo') bar " ) )
assert_equal ( " <a a='foo' b='bar'>bar</a> \n " , render ( " %a(a = 'foo' b = 'bar') bar " ) )
assert_equal ( " <a a='foo' b='bar'>bar</a> \n " , render ( " %a(a = foo b = bar) bar " , :locals = > { :foo = > 'foo' , :bar = > 'bar' } ) )
assert_equal ( " <a a='foo'>(b='bar')</a> \n " , render ( " %a(a='foo')(b='bar') " ) )
assert_equal ( " <a a='foo)bar'>baz</a> \n " , render ( " %a(a='foo)bar') baz " ) )
assert_equal ( " <a a='foo'>baz</a> \n " , render ( " %a( a = 'foo' ) baz " ) )
end
def test_new_attribute_escaping
assert_equal ( %Q{ <a a='foo " bar'>bar</a> \n } , render ( %q{ %a(a="foo \ " bar") bar } ) )
assert_equal ( %Q{ <a a='foo \\ " bar'>bar</a> \n } , render ( %q{ %a(a="foo \\ \\ \ " bar") bar } ) )
assert_equal ( %Q{ <a a="foo ' bar">bar</a> \n } , render ( %q{ %a(a='foo \ ' bar') bar } ) )
assert_equal ( %Q{ <a a="foo \\ ' bar">bar</a> \n } , render ( %q{ %a(a='foo \\ \\ \ ' bar') bar } ) )
assert_equal ( %Q{ <a a='foo \\ bar'>bar</a> \n } , render ( %q{ %a(a="foo \\ \\ bar") bar } ) )
assert_equal ( %Q{ <a a='foo \# { 1 + 1 } bar'>bar</a> \n } , render ( %q{ %a(a="foo \ # { 1 + 1 } bar") bar } ) )
end
def test_multiline_new_attribute
assert_equal ( " <a a='b' c='d'>bar</a> \n " , render ( " %a(a='b' \n c='d') bar " ) )
assert_equal ( " <a a='b' b='c' c='d' d='e' e='f' f='j'>bar</a> \n " ,
render ( " %a(a='b' b='c' \n c='d' d=e \n e='f' f='j') bar " , :locals = > { :e = > 'e' } ) )
end
def test_new_and_old_attributes
assert_equal ( " <a a='b' c='d'>bar</a> \n " , render ( " %a(a='b'){:c => 'd'} bar " ) )
assert_equal ( " <a a='b' c='d'>bar</a> \n " , render ( " %a{:c => 'd'}(a='b') bar " ) )
assert_equal ( " <a a='b' c='d'>bar</a> \n " , render ( " %a(c='d'){:a => 'b'} bar " ) )
assert_equal ( " <a a='b' c='d'>bar</a> \n " , render ( " %a{:a => 'b'}(c='d') bar " ) )
assert_equal ( " <a a='d'>bar</a> \n " , render ( " %a{:a => 'b'}(a='d') bar " ) )
assert_equal ( " <a a='b'>bar</a> \n " , render ( " %a(a='d'){:a => 'b'} bar " ) )
assert_equal ( " <a a='b' b='c' c='d' d='e'>bar</a> \n " ,
render ( " %a{:a => 'b', \n :b => 'c'}(c='d' \n d='e') bar " ) )
end
2009-07-01 03:19:46 -04:00
# Encodings
unless Haml :: Util . ruby1_8?
def test_default_encoding
assert_equal ( Encoding . find ( " utf-8 " ) , render ( <<HAML.encode("us-ascii")).encoding)
HTML
% p bar
% p foo
HAML
end
def test_convert_template_render
assert_equal ( <<HTML, render(<<HAML.encode("iso-8859-1"), :encoding => "utf-8"))
< p > bâr < / p>
< p > föö < / p>
HTML
% p bâr
% p föö
HAML
end
def test_convert_template_render_proc
assert_converts_template_properly { | e | e . render_proc . call }
end
def test_convert_template_render
assert_converts_template_properly { | e | e . render }
end
def test_convert_template_def_method
assert_converts_template_properly do | e |
o = Object . new
e . def_method ( o , :render )
o . render
end
end
end
private
def assert_converts_template_properly
engine = Haml :: Engine . new ( <<HAML.encode("iso-8859-1"), :encoding => "utf-8")
% p bâr
% p föö
HAML
assert_equal ( <<HTML, yield(engine))
< p > bâr < / p>
< p > föö < / p>
HTML
end
2006-06-30 11:14:44 -04:00
end