2022-04-20 03:56:46 +00:00
defmodule Temple.RendererTest do
use ExUnit.Case , async : true
2023-01-21 11:44:29 +00:00
use Temple.Support.Component
import Temple.Support.Components
2022-04-20 03:56:46 +00:00
require Temple.Renderer
alias Temple.Renderer
2023-01-21 11:44:29 +00:00
import Temple.Support.Helpers
2022-04-20 03:56:46 +00:00
describe " compile/1 " do
test " produces renders a text node " do
result =
Renderer . compile do
" hello world "
end
2023-08-06 17:29:06 +00:00
assert_html " hello world " , result
2022-04-20 03:56:46 +00:00
end
test " produces renders a div " do
result =
Renderer . compile do
div class : " hello world " do
" hello world "
span id : " name " , do : " bob "
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div class="hello world">hello world<span id="name">bob</span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " produces renders a void elements " do
result =
Renderer . compile do
div class : " hello world " do
" hello world "
input type : " button " , value : " Submit "
input type : " button " , value : " Submit "
end
end
# html
2023-08-06 17:12:51 +00:00
expected =
~S| <div class="hello world">hello world<input type="button" value="Submit"><input type="button" value="Submit"></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " a match does not emit " do
result =
Renderer . compile do
div class : " hello world " do
_ = " hello world "
span id : " name " , do : " bob "
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div class="hello world"><span id="name">bob</span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " handles simple expression inside attributes " do
assigns = %{ statement : " hello world " , color : " green " }
result =
Renderer . compile do
div class : @color do
@statement
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div class="green">hello world</div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
2023-01-21 11:44:29 +00:00
test " handles simple expression are the entire attributes " do
assigns = %{ statement : " hello world " , attributes : [ class : " green " ] }
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
result =
Renderer . compile do
div @attributes do
@statement
end
end
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
# html
2023-08-06 17:29:06 +00:00
expected = ~S| <div class="green">hello world</div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
end
2022-04-20 03:56:46 +00:00
test " handles simple expression with @ assign " do
assigns = %{ statement : " hello world " }
result =
Renderer . compile do
div do
@statement
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div>hello world</div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " handles multi line expression " do
assigns = %{ names : [ " alice " , " bob " , " carol " ] }
result =
Renderer . compile do
div do
for name <- @names do
span class : " name " , do : name
end
end
end
# html
2023-08-06 17:12:51 +00:00
expected =
~S| <div><span class="name">alice</span><span class="name">bob</span><span class="name">carol</span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " if expression " do
for val <- [ true , false ] do
assigns = %{ value : val }
result =
Renderer . compile do
div do
if @value do
span do : " true "
else
span do : " false "
end
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~s| <div><span> #{ val } </span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
end
test " with expression " do
for val <- [ true , false , " bobby " ] do
assigns = %{ value : val }
result =
Renderer . compile do
div do
with false <- @value ,
true <- " motch " not in [ " lame " , " not funny " ] do
span do : " false "
else
true ->
span do : true
_ ->
span do : " bobby "
end
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~s| <div><span> #{ val } </span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
end
test " handles case expression " do
assigns = %{ name : " alice " }
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div><span id="correct answer">alice is the best</span></div> |
2022-04-20 03:56:46 +00:00
result =
Renderer . compile do
div do
case @name do
" bob " ->
span do : " bob is cool "
" alice " ->
span id : " correct answer " , do : " alice is the best "
_ ->
span do : " everyone is lame "
end
end
end
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " handles anonymous functions " do
assigns = %{ names : [ " alice " , " bob " , " carol " ] }
result =
Renderer . compile do
div do
Enum . map ( @names , fn name ->
span class : " name " , do : name
end )
end
end
# html
2023-08-06 17:12:51 +00:00
expected =
~S| <div><span class="name">alice</span><span class="name">bob</span><span class="name">carol</span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
def super_map ( enumerable , func , _extra_args ) do
Enum . map ( enumerable , func )
end
test " handles anonymous functions with subsequent args " do
assigns = %{ names : [ " alice " , " bob " , " carol " ] }
result =
Renderer . compile do
div do
super_map (
@names ,
fn name ->
span class : " name " , do : name
end ,
" hello world "
)
end
end
# html
2023-08-06 17:12:51 +00:00
expected =
~S| <div><span class="name">alice</span><span class="name">bob</span><span class="name">carol</span></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " basic component " do
result =
Renderer . compile do
div do
c & basic_component / 1
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div><div>I am a basic component</div></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " component with default slot " do
2022-10-12 13:17:23 +00:00
assigns = %{ }
2022-04-20 03:56:46 +00:00
result =
Renderer . compile do
div do
c & default_slot / 1 do
span do : " i'm a slot "
end
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div><div>I am above the slot<span>i'm a slot</span></div></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " component with a named slot " do
2022-10-12 13:17:23 +00:00
assigns = %{ label : " i'm a slot attribute " }
2022-04-20 03:56:46 +00:00
result =
Renderer . compile do
div do
c & named_slot / 1 , name : " motchy boi " do
span do : " i'm a slot "
2023-01-21 11:44:29 +00:00
slot :footer , let! : %{ name : name } , label : @label , expr : 1 + 1 do
2022-04-20 03:56:46 +00:00
p do
" #{ name } 's in the footer! "
end
end
end
end
end
# heex
2023-08-06 17:12:51 +00:00
expected =
2023-08-06 17:29:06 +00:00
~S| <div><div>motchy boi is above the slot<span>i'm a slot</span></div><footer><span>i'm a slot attribute</span><p>motchy boi's in the footer!</p></footer></div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
end
describe " special attribute stuff " do
test " class object syntax " do
result =
Renderer . compile do
div class : [ " hello world " : false , " text-red " : true ] do
" hello world "
end
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <div class="text-red">hello world</div> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " boolean attributes only emit correctly with truthy values " do
result =
Renderer . compile do
input type : " text " , disabled : true , placeholder : " Enter some text... "
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <input type="text" disabled placeholder="Enter some text..."> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
test " boolean attributes don't emit with falsy values " do
result =
Renderer . compile do
input type : " text " , disabled : false , placeholder : " Enter some text... "
end
# html
2023-08-06 17:12:51 +00:00
expected = ~S| <input type="text" placeholder="Enter some text..."> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-11-12 03:28:05 +00:00
end
test " runtime boolean attributes emit the right values " do
truthy = true
falsey = false
result =
Renderer . compile do
input type : " text " , disabled : falsey , checked : truthy , placeholder : " Enter some text... "
end
# html
2023-08-06 17:29:06 +00:00
expected = ~S| <input type="text" checked placeholder="Enter some text..."> |
2022-04-20 03:56:46 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
2022-10-12 13:17:23 +00:00
test " multiple slots " do
assigns = %{ }
result =
Renderer . compile do
div do
c & named_slot / 1 , name : " motchy boi " do
span do : " i'm a slot "
2023-01-21 11:44:29 +00:00
slot :footer , let! : %{ name : name } do
2022-10-12 13:17:23 +00:00
p do
" #{ name } 's in the footer! "
end
end
2023-01-21 11:44:29 +00:00
slot :footer , let! : %{ name : name } do
2022-10-12 13:17:23 +00:00
p do
" #{ name } is the second footer! "
end
end
end
end
end
# heex
2023-08-06 17:29:06 +00:00
expected =
~S| <div><div>motchy boi is above the slot<span>i'm a slot</span></div><footer><span></span><p>motchy boi's in the footer!</p><span></span><p>motchy boi is the second footer!</p></footer></div> |
2022-10-12 13:17:23 +00:00
2023-01-21 11:44:29 +00:00
assert_html expected , result
end
test " rest! attribute can mix in dynamic attrs with the static attrs " do
assigns = %{
rest : [
class : " font-bold " ,
disabled : true
]
}
result =
Renderer . compile do
div id : " foo " , rest! : @rest do
" hi "
end
end
# heex
2023-08-06 17:29:06 +00:00
expected = ~S| <div id="foo" class="font-bold" disabled>hi</div> |
2023-01-21 11:44:29 +00:00
assert_html expected , result
end
test " rest! attribute can mix in dynamic assigns to components " do
assigns = %{
rest : [
class : " font-bold "
]
}
result =
Renderer . compile do
c & rest_component / 1 , id : " foo " , rest! : @rest
end
# heex
2023-08-06 17:29:06 +00:00
expected = ~S| <div>I am a basic foo with font-bold</div> |
2023-01-21 11:44:29 +00:00
assert_html expected , result
end
test " rest! attribute can mix in dynamic attributes to slots " do
assigns = %{
rest : [
class : " font-bold "
]
}
result =
Renderer . compile do
c & rest_slot / 1 do
slot :foo ,
id : " passed-into-slot " ,
rest! : @rest ,
let! : %{ slot_class : class , slot_id : id } do
" id is #{ id } and class is #{ class } "
end
end
end
# heex
2023-08-06 17:29:06 +00:00
expected = ~S| <div>id is passed-into-slot and class is font-bold</div> |
2023-01-21 11:44:29 +00:00
assert_html expected , result
2022-04-20 03:56:46 +00:00
end
end
end