This repository has been archived on 2023-08-07. You can view files and clone it, but cannot push or open issues or pull requests.
temple/test/temple/ast/components_test.exs

221 lines
5.3 KiB
Elixir
Raw Normal View History

defmodule Temple.Ast.ComponentsTest do
use ExUnit.Case, async: true
alias Temple.Ast.Components
alias Temple.Ast.Slottable
2021-01-02 18:21:48 +00:00
describe "applicable?/1" do
test "runs when using the `c` ast with a block" do
ast =
quote do
c &SomeModule.render/1, foo: :bar do
2021-01-02 18:21:48 +00:00
div do
"hello"
end
end
end
assert Components.applicable?(ast)
end
test "runs when using the `c` ast with an inline block" do
ast =
quote do
c &SomeModule.render/1, foo: :bar do
"hello"
end
end
assert Components.applicable?(ast)
end
2021-01-02 18:21:48 +00:00
test "runs when using the `c` ast without a block" do
ast =
quote do
c &SomeModule.render/1, foo: :bar
2021-01-02 18:21:48 +00:00
end
assert Components.applicable?(ast)
end
end
describe "run/2" do
setup do
[func: quote(do: &SomeModule.render/1)]
end
test "adds a node to the buffer", %{func: func} do
2021-03-15 04:46:16 +00:00
raw_ast =
quote do
c unquote(func) do
2021-03-15 04:46:16 +00:00
aside class: "foobar" do
"I'm a component!"
end
end
end
2021-01-02 18:21:48 +00:00
2021-03-15 04:46:16 +00:00
ast = Components.run(raw_ast)
2021-04-09 03:04:26 +00:00
assert %Components{
function: ^func,
arguments: []
2021-03-15 04:46:16 +00:00
} = ast
end
test "runs when using the `c` ast with an inline block", %{func: func} do
ast =
quote do
c unquote(func), foo: :bar, do: "hello"
end
ast = Components.run(ast)
assert %Components{
function: ^func,
arguments: [foo: :bar]
} = ast
end
test "adds a node to the buffer that takes args", %{func: func} do
2021-03-15 04:46:16 +00:00
raw_ast =
2021-01-02 18:21:48 +00:00
quote do
c unquote(func), foo: :bar do
2021-01-02 18:21:48 +00:00
aside class: "foobar" do
"I'm a component!"
end
end
end
2021-03-15 04:46:16 +00:00
ast = Components.run(raw_ast)
2021-01-02 18:21:48 +00:00
2021-04-09 03:04:26 +00:00
assert %Components{
function: ^func,
arguments: [foo: :bar]
2021-03-15 04:46:16 +00:00
} = ast
2021-01-02 18:21:48 +00:00
end
2021-04-09 03:04:26 +00:00
test "adds a node to the buffer that without a block", %{func: func} do
2021-04-09 03:04:26 +00:00
raw_ast =
quote do
c unquote(func), foo: :bar
2021-04-09 03:04:26 +00:00
end
ast = Components.run(raw_ast)
assert %Components{
function: ^func,
arguments: [foo: :bar]
2021-04-09 03:04:26 +00:00
} = ast
end
test "gathers all slots", %{func: func} do
raw_ast =
quote do
c unquote(func), foo: :bar do
Dynamic Attributes (#190) * Move directories for ast tests to match convention * feat!: Rename `:let` to `:let!` We use the "bang" style as the reserved keyword to differentiate it from other possible attributes. * feat: use Phoenix.HTML as the default engine I am choosing to leverage this library in order to quickly get dynamic attributes (see #183) up and running. This also ensures that folks who wish to use Temple outside of a Phoenix project with get some nice HTML functions as well as properly escaped HTML out of the box. This can be made optional if Temple becomes decoupled from the render and it including HTML specific packages becomes a strange. * feat: Allow user to make their own Component module The component module is essentially to defer compiling functions that the user might not need. The component, render_slot, and inner_block functions are only mean to be used when there isn't another implementation. In the case of a LiveView application, LiveView is providing the component runtime implementation. This was causing some compile time warnings for temple, because it was using the LiveView engine at compile time (for Temple, not the user's application) and LiveView hadn't been compiled or loaded. So, now we defer this to the user to make their own module and import it where necessary. * feat: Pass dynamic attributes with the :rest! attribute The :rest! attribute can be used to pass in a dynamic list of attributes to be mixed into the static ones at runtime. Since this cannot be properly escaped by any engine, we have to mark it as safe and then allow the function to escape it for us. I decided to leverage the `attributes_escape/1` function from `phoenix_html`. There isn't really any point in making my own version of this or vendoring it. Now you can also pass a variable as the attributes as well if you only want to pass through attributes from a calling component. The :rest! attribute also works with components, allowing you to pass a dynamic list of args into them. Fixes #183 * Move test components to their own file. * docs(components): Update documentation on Temple.Components * docs(guides): Mention attributes_escape/1 function in the guides * chore(test): Move helper to it's own module * feat: rest! support for slots * docs(guides): Dynamic attributes * ci: downgrade runs-on to support OTP 23
2023-01-21 11:44:29 +00:00
slot :foo, let!: %{form: form} do
"in the slot"
end
end
end
ast = Components.run(raw_ast)
assert %Components{
function: ^func,
arguments: [foo: :bar],
slots: [
%Slottable{
name: :foo,
content: [%Temple.Ast.Text{}],
parameter: {:%{}, _, [form: _]}
}
]
} = ast
end
test "slot attributes", %{func: func} do
raw_ast =
quote do
c unquote(func), foo: :bar do
Dynamic Attributes (#190) * Move directories for ast tests to match convention * feat!: Rename `:let` to `:let!` We use the "bang" style as the reserved keyword to differentiate it from other possible attributes. * feat: use Phoenix.HTML as the default engine I am choosing to leverage this library in order to quickly get dynamic attributes (see #183) up and running. This also ensures that folks who wish to use Temple outside of a Phoenix project with get some nice HTML functions as well as properly escaped HTML out of the box. This can be made optional if Temple becomes decoupled from the render and it including HTML specific packages becomes a strange. * feat: Allow user to make their own Component module The component module is essentially to defer compiling functions that the user might not need. The component, render_slot, and inner_block functions are only mean to be used when there isn't another implementation. In the case of a LiveView application, LiveView is providing the component runtime implementation. This was causing some compile time warnings for temple, because it was using the LiveView engine at compile time (for Temple, not the user's application) and LiveView hadn't been compiled or loaded. So, now we defer this to the user to make their own module and import it where necessary. * feat: Pass dynamic attributes with the :rest! attribute The :rest! attribute can be used to pass in a dynamic list of attributes to be mixed into the static ones at runtime. Since this cannot be properly escaped by any engine, we have to mark it as safe and then allow the function to escape it for us. I decided to leverage the `attributes_escape/1` function from `phoenix_html`. There isn't really any point in making my own version of this or vendoring it. Now you can also pass a variable as the attributes as well if you only want to pass through attributes from a calling component. The :rest! attribute also works with components, allowing you to pass a dynamic list of args into them. Fixes #183 * Move test components to their own file. * docs(components): Update documentation on Temple.Components * docs(guides): Mention attributes_escape/1 function in the guides * chore(test): Move helper to it's own module * feat: rest! support for slots * docs(guides): Dynamic attributes * ci: downgrade runs-on to support OTP 23
2023-01-21 11:44:29 +00:00
slot :foo, let!: %{form: form}, label: the_label do
"in the slot"
end
end
end
ast = Components.run(raw_ast)
assert %Components{
function: ^func,
arguments: [foo: :bar],
slots: [
%Slottable{
name: :foo,
content: [%Temple.Ast.Text{}],
parameter: {:%{}, _, [form: _]},
attributes: [label: {:the_label, [], Temple.Ast.ComponentsTest}]
}
]
} = ast
end
test "slots should only be assigned to the component root" do
card = quote do: &Card.render/1
footer = quote do: &Card.Footer.render/1
list = quote do: &LinkList.render/1
raw_ast =
quote do
c unquote(card) do
c unquote(footer) do
c unquote(list), socials: @user.socials do
"hello"
Dynamic Attributes (#190) * Move directories for ast tests to match convention * feat!: Rename `:let` to `:let!` We use the "bang" style as the reserved keyword to differentiate it from other possible attributes. * feat: use Phoenix.HTML as the default engine I am choosing to leverage this library in order to quickly get dynamic attributes (see #183) up and running. This also ensures that folks who wish to use Temple outside of a Phoenix project with get some nice HTML functions as well as properly escaped HTML out of the box. This can be made optional if Temple becomes decoupled from the render and it including HTML specific packages becomes a strange. * feat: Allow user to make their own Component module The component module is essentially to defer compiling functions that the user might not need. The component, render_slot, and inner_block functions are only mean to be used when there isn't another implementation. In the case of a LiveView application, LiveView is providing the component runtime implementation. This was causing some compile time warnings for temple, because it was using the LiveView engine at compile time (for Temple, not the user's application) and LiveView hadn't been compiled or loaded. So, now we defer this to the user to make their own module and import it where necessary. * feat: Pass dynamic attributes with the :rest! attribute The :rest! attribute can be used to pass in a dynamic list of attributes to be mixed into the static ones at runtime. Since this cannot be properly escaped by any engine, we have to mark it as safe and then allow the function to escape it for us. I decided to leverage the `attributes_escape/1` function from `phoenix_html`. There isn't really any point in making my own version of this or vendoring it. Now you can also pass a variable as the attributes as well if you only want to pass through attributes from a calling component. The :rest! attribute also works with components, allowing you to pass a dynamic list of args into them. Fixes #183 * Move test components to their own file. * docs(components): Update documentation on Temple.Components * docs(guides): Mention attributes_escape/1 function in the guides * chore(test): Move helper to it's own module * feat: rest! support for slots * docs(guides): Dynamic attributes * ci: downgrade runs-on to support OTP 23
2023-01-21 11:44:29 +00:00
slot :foo, let!: %{text: text, url: url} do
a class: "text-blue-500 hover:underline", href: url do
text
end
end
end
end
end
end
ast = Components.run(raw_ast)
assert [
%Slottable{
name: :inner_block,
parameter: nil
}
] = ast.slots
assert %Components{
slots: [
%Slottable{
content: [
%Components{
slots: [
%Slottable{
content: [
%Components{
slots: [
%Slottable{
name: :inner_block
},
%Slottable{
name: :foo
}
]
}
]
}
]
}
]
}
]
} = ast
end
2021-04-09 03:04:26 +00:00
end
2021-01-02 18:21:48 +00:00
end