Skip to content

Commit

Permalink
Implement feature tests for function capture calls
Browse files Browse the repository at this point in the history
  • Loading branch information
bartblast committed Nov 17, 2024
1 parent d176a16 commit 21435f5
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 0 deletions.
9 changes: 9 additions & 0 deletions test/features/app/module_fixture.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule HologramFeatureTests.ModuleFixture do
defp private_fun(x, y) do
{x, y}
end

def public_fun(x, y) do
private_fun(x, y)
end
end
183 changes: 183 additions & 0 deletions test/features/app/pages/function_calls/function_capture_page.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
defmodule HologramFeatureTests.FunctionCalls.FunctionCapturePage do
use Hologram.Page

import Hologram.Commons.KernelUtils, only: [inspect: 1]
import Hologram.Commons.TestUtils, only: [wrap_term: 1]
import Kernel, except: [inspect: 1]

alias HologramFeatureTests.ModuleFixture

route "/function-calls/function-capture"

layout HologramFeatureTests.Components.DefaultLayout

def init(_params, component, _server) do
put_state(component, :result, nil)
end

def template do
~H"""
<p>
<button $click="single_arg"> Single arg </button>
<button $click="multiple_args"> Multiple args </button>
<button $click="local_private_function_capture"> Local private function capture </button>
<button $click="local_public_function_capture"> Local public function capture </button>
<button $click="remote_private_elixir_function_capture"> Remote private Elixir function capture </button>
<button $click="remote_public_elixir_function_capture"> Remote public Elixir function capture </button>
<button $click="remote_erlang_function_capture"> Remote Erlang function capture </button>
<button $click="partially_applied_local_function_capture"> Partially applied local function capture </button>
<button $click="partially_applied_remote_elixir_function_capture"> Partially applied remote Elixir function capture </button>
<button $click="partially_applied_remote_erlang_function_capture"> Partially applied remote Erlang function capture </button>
<button $click="vars_scoping"> Vars scoping </button>
<button $click="closure"> Closure </button>
<button $click="arity_invalid_called_with_no_args"> Arity invalid, called with no args </button>
<button $click="arity_invalid_called_with_single_arg"> Arity invalid, called with single arg </button>
<button $click="arity_invalid_called_with_multple_args"> Arity invalid, called with multiple args </button>
<button $click="error_in_body"> Error in body </button>
</p>
<p>
Result: <strong id="result"><code>{inspect(@result)}</code></strong>
</p>
<p>
<button $click="reset"> Reset </button>
</p>
"""
end

def action(:single_arg, _params, component) do
fun = & &1
result = fun.(:a)

put_state(component, :result, result)
end

def action(:multiple_args, _params, component) do
fun = &{&1, &2}
result = fun.(:a, :b)

put_state(component, :result, result)
end

def action(:local_private_function_capture, _params, component) do
fun = &local_private_fun/2
result = fun.(:a, :b)

put_state(component, :result, result)
end

def action(:local_public_function_capture, _params, component) do
fun = &local_public_fun/2
result = fun.(:a, :b)

put_state(component, :result, result)
end

def action(:remote_private_elixir_function_capture, _params, component) do
module = wrap_term(ModuleFixture)
fun = &module.private_fun/2
result = fun.(:a, :b)

put_state(component, :result, result)
end

def action(:remote_public_elixir_function_capture, _params, component) do
fun = &ModuleFixture.public_fun/2
result = fun.(:a, :b)

put_state(component, :result, result)
end

def action(:remote_erlang_function_capture, _params, component) do
fun = &:lists.member/2
result = fun.(:b, [:a, :b])

put_state(component, :result, result)
end

def action(:partially_applied_local_function_capture, _params, component) do
fun = &local_public_fun(&1, :b)
result = fun.(:a)

put_state(component, :result, result)
end

def action(:partially_applied_remote_elixir_function_capture, _params, component) do
fun = &ModuleFixture.public_fun(&1, :b)
result = fun.(:a)

put_state(component, :result, result)
end

def action(:partially_applied_remote_erlang_function_capture, _params, component) do
fun = &:lists.member(&1, [:a, :b])
result = fun.(:b)

put_state(component, :result, result)
end

def action(:vars_scoping, _params, component) do
x = 1
y = 2

fun =
&{&1,
(
x = 4
x
), y}

result = fun.(3)

put_state(component, :result, {x, y, result})
end

def action(:closure, _params, component) do
x = 1
y = 2

fun_capture = &{&1, x, y}

result = local_fun_2(fun_capture)

put_state(component, :result, result)
end

def action(:arity_invalid_called_with_no_args, _params, _component) do
fun = &{&1, &2}
fun.()
end

def action(:arity_invalid_called_with_single_arg, _params, _component) do
fun = &{&1, &2}
fun.(:a)
end

def action(:arity_invalid_called_with_multple_args, _params, _component) do
fun = & &1
fun.(:a, :b)
end

def action(:error_in_body, _params, _component) do
fun = &{&1, raise(RuntimeError, "my message")}
fun.(:a)
end

def action(:reset, _params, component) do
put_state(component, :result, nil)
end

def local_public_fun(x, y) do
{x, y}
end

def local_fun_2(fun_capture) do
x = 3
y = 4

{x, y, fun_capture.(5)}
end

defp local_private_fun(x, y) do
{x, y}
end
end
136 changes: 136 additions & 0 deletions test/features/test/function_calls/function_capture_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
defmodule HologramFeatureTests.FunctionCalls.FunctionCaptureTest do
use HologramFeatureTests.TestCase, async: true
alias HologramFeatureTests.FunctionCalls.FunctionCapturePage

feature "single arg", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Single arg"))
|> assert_text(css("#result"), ":a")
end

feature "multiple args", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Multiple args"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "local private function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Local private function capture"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "local public function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Local public function capture"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "remote private Elixir function capture", %{session: session} do
assert_client_error session,
UndefinedFunctionError,
"function HologramFeatureTests.ModuleFixture.private_fun/2 is undefined or private",
fn ->
session
|> visit(FunctionCapturePage)
|> click(button("Remote private Elixir function capture"))
end
end

feature "remote public Elixir function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Remote public Elixir function capture"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "remote Erlang function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Remote Erlang function capture"))
|> assert_text(css("#result"), "true")
end

feature "partially applied local function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Partially applied local function capture"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "partially applied remote Elixir function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Partially applied remote Elixir function capture"))
|> assert_text(css("#result"), "{:a, :b}")
end

feature "partially applied remote Erlang function capture", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Partially applied remote Erlang function capture"))
|> assert_text(css("#result"), "true")
end

feature "vars scoping", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Vars scoping"))
|> assert_text(css("#result"), "{1, 2, {3, 4, 2}}")
end

feature "closure", %{session: session} do
session
|> visit(FunctionCapturePage)
|> click(button("Closure"))
|> assert_text(css("#result"), "{3, 4, {5, 1, 2}}")
end

feature "arity invalid, called with no args", %{session: session} do
assert_client_error session,
BadArityError,
"anonymous function with arity 2 called with no arguments",
fn ->
session
|> visit(FunctionCapturePage)
|> click(button("Arity invalid, called with no args"))
end
end

feature "arity invalid, called with single arg", %{session: session} do
assert_client_error session,
BadArityError,
"anonymous function with arity 2 called with 1 argument (:a)",
fn ->
session
|> visit(FunctionCapturePage)
|> click(button("Arity invalid, called with single arg"))
end
end

feature "arity invalid, called with multiple args", %{session: session} do
assert_client_error session,
BadArityError,
"anonymous function with arity 1 called with 2 arguments (:a, :b)",
fn ->
session
|> visit(FunctionCapturePage)
|> click(button("Arity invalid, called with multiple args"))
end
end

feature "Error in body", %{session: session} do
assert_client_error session,
RuntimeError,
"my message",
fn ->
session
|> visit(FunctionCapturePage)
|> click(button("Error in body"))
end
end
end

0 comments on commit 21435f5

Please sign in to comment.