require 'spec_helper'
RSpec.describe 'Attributes rendering', type: :render do
it 'parses attributes' do
expect(render_string('%span{class: "x"} hello')).to eq(%Q{hello\n})
end
it 'parses attributes' do
expect(render_string('%span{class: "x", "old" => 2} hello')).to eq(%Q{hello\n})
end
it 'renders attributes with symbol literal' do
expect(render_string("%span{foo: 'baz'}")).to eq("\n")
expect(render_string("%span{:foo => 'baz'}")).to eq("\n")
expect(render_string("%span{:'foo-bar' => 'baz'}")).to eq("\n")
end
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0')
it 'renders attributes with 2.2-style symbol literals' do
expect(render_string(%q|%span{"foo": 'bar'}|)).to eq("\n")
expect(render_string(%Q|- x = 'bar'\n%span{"foo": x}|)).to eq("\n")
expect(render_string(%q|%span{'foo': 'bar'}|)).to eq("\n")
expect(render_string(%Q|- x = 'bar'\n%span{'foo': x}|)).to eq("\n")
end
end
it 'renders dynamic attributes' do
expect(render_string(%q|%span#main{class: "na#{'ni'}ka"} hello|)).to eq(%Q{hello\n})
end
it 'renders array class' do
expect(render_string('%span.c2{class: "c1"}')).to eq("\n")
expect(render_string('%span.c2{class: ["c1", "c3", :c2]}')).to eq("\n")
end
it 'renders boolean attributes' do
expect(render_string('%input{checked: true}')).to eq("\n")
expect(render_string('%input{checked: false}')).to eq("\n")
expect(render_string('%input{checked: nil}')).to eq("\n")
expect(render_string('%input{checked: "a" == "a"}')).to eq("\n")
expect(render_string('%input{checked: "a" != "a"}')).to eq("\n")
expect(render_string("- x = nil\n%input{checked: x}")).to eq("\n")
expect(render_string("- h = {checked: true}\n%input{h}")).to eq("\n")
expect(render_string("- h = {checked: false}\n%input{h}")).to eq("\n")
expect(render_string("- h = {checked: nil}\n%input{h}")).to eq("\n")
end
it 'merges classes' do
expect(render_string(<hello\n")
- h1 = {class: 'c1', id: ['id1', 'id3']}
- h2 = {class: [{}, 'c2'], id: 'id2'}
%span#main.content{h1, h2} hello
HAML
end
it 'strigify non-string classes' do
expect(render_string('%span.foo{class: :bar} hello')).to eq("hello\n")
expect(render_string('%span.foo{class: 1} hello')).to eq("hello\n")
end
it 'remove duplicated classes' do
expect(render_string('%span.foo{class: :foo}')).to eq("\n")
expect(render_string('%span.foo{class: "foo bar"}')).to eq("\n")
expect(render_string('%span.foo{class: %w[foo bar]}')).to eq("\n")
end
it 'skips empty array class' do
expect(render_string('%span{class: []}')).to eq("\n")
end
it 'skips falsey array elements in class' do
expect(render_string('%span{class: [1, nil, false, true]}')).to eq("\n")
expect(render_string("- v = [1, nil, false, true]\n%span{class: v}")).to eq("\n")
expect(render_string("- h = { class: [1, nil, false, true] }\n%span{h}")).to eq("\n")
end
it 'strigify non-string ids' do
expect(render_string('%span#foo{id: :bar} hello')).to eq("hello\n")
end
it 'skips empty array class' do
expect(render_string('%span{id: []}')).to eq("\n")
end
it 'skips falsey array elements in id' do
expect(render_string('%span{id: [1, nil, false, true]}')).to eq("\n")
expect(render_string("- v = [1, nil, false, true]\n%span{id: v}")).to eq("\n")
expect(render_string("- h = { id: [1, nil, false, true] }\n%span{h}")).to eq("\n")
end
it 'escapes' do
expect(render_string(%q|%span{class: "x\"y'z"} hello|)).to eq(%Q{hello\n})
end
it 'does not escape slash' do
expect(render_string(%q|%a{ href: 'http://example.com/' }|)).to eq(%Q{\n})
expect(render_string(%q|%a{ {}, href: 'http://example.com/' }|)).to eq(%Q{\n})
end
it 'renders only name if value is true' do
expect(render_string(%q|%span{foo: true, bar: 1} hello|)).to eq(%Q{hello\n})
end
it 'raises error when unparsable Ruby code is given' do
expect { render_string('%span{x ==== 2}') }.to raise_error(Faml::Compiler::UnparsableRubyCode)
end
context 'with xhtml format' do
it 'renders name="name" if value is true' do
expect(render_string(%q|%span{foo: true, bar: 1} hello|, format: :xhtml)).to eq(%Q{hello\n})
expect(render_string(%Q|- foo = true\n%span{foo: foo, bar: 1} hello|, format: :xhtml)).to eq(%Q{hello\n})
expect(render_string(%Q|- h = {foo: true, bar: 1}\n%span{h} hello|, format: :xhtml)).to eq(%Q{hello\n})
end
end
it 'renders nested attributes' do
expect(render_string(%q|%span{foo: {bar: 1+2}} hello|)).to eq(%Q|hello\n|)
end
it 'renders code attributes' do
expect(render_string(<hello\n|)
- attrs = { foo: 1, bar: { hoge: :fuga }, baz: true }
%span{attrs} hello
HAML
end
it 'renders dstr attributes' do
expect(render_string(<hello\n|)
- data = { foo: 1 }
%span{data: "x\#{data}y"} hello
HAML
end
it 'renders nested dstr attributes' do
expect(render_string(<<'HAML')).to eq(%Q|hello\n|)
- data = { foo: 1 }
%span{foo: {bar: "x#{1}y"}} hello
HAML
end
it 'optimize send case' do
expect(render_string('%span{foo: {bar: 1+2}} hello')).to eq("hello\n")
end
it 'merges static id' do
expect(render_string('#foo{id: "bar"} baz')).to eq("
\n")
end
it 'merges static class' do
expect(render_string('.foo{class: "bar"} baz')).to eq("
baz
\n")
expect(render_string(<<'HAML')).to eq("
baz
\n")
- bar = 'bar'
.foo{class: "#{bar}"} baz
HAML
end
it 'converts underscore to hyphen in data attributes' do
expect(render_string("%span{data: {foo_bar: 'baz'}}")).to eq("\n")
expect(render_string("- h = {foo_bar: 'baz'}\n%span{data: h}")).to eq("\n")
end
context 'with data attributes' do
it 'renders nested attributes' do
expect(render_string(%q|%span{data: {foo: 1, bar: 'baz', :hoge => :fuga, k1: { k2: 'v3' }}} hello|)).to eq(%Q{hello\n})
end
it 'renders nested dynamic attributes' do
expect(render_string(%q|%span{data: {foo: "b#{'a'}r"}} hello|)).to eq(%Q{hello\n})
end
it 'renders nested attributes' do
expect(render_string(%q|%span{data: {foo: 1, bar: 2+3}} hello|)).to eq(%Q{hello\n})
end
it 'renders nested code attributes' do
expect(render_string(<hello\n})
- data = { foo: 1, bar: 2 }
%span{data: data} hello
HAML
end
it 'skips falsey data attributes' do
expect(render_string('%span{data: { foo: nil }}')).to eq("\n")
expect(render_string("- v = nil\n%span{data: { foo: v }}")).to eq("\n")
end
it 'renders true data attributes' do
expect(render_string('%span{data: { foo: true }}')).to eq("\n")
expect(render_string("- v = true\n%span{data: { foo: v }}")).to eq("\n")
end
end
it 'renders __LINE__ correctly' do
expect(render_string(<\n")
%span{b: __LINE__,
a: __LINE__}
HAML
end
it 'allows NUL characters' do
expect(render_string('%span{"foo\0bar" => "hello"}')).to eq("\n")
expect(render_string(<<'HAML')).to eq("\n")
- val = "hello"
%span{"foo\0bar" => val}
HAML
expect(render_string(<<'HAML')).to eq("\n")
- key = "foo\0bar"
- val = "hello"
%span{key => val}
HAML
end
end