Skip to content

Commit

Permalink
Implement feature tests for anonymous function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
bartblast committed Nov 13, 2024
1 parent 8816545 commit 53ada69
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 1 deletion.
196 changes: 196 additions & 0 deletions test/features/app/pages/function_calls/anonymous_function_page.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
defmodule HologramFeatureTests.FunctionCalls.AnonymousFunctionPage do
use Hologram.Page

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

route "/function-calls/anonymous-function"

layout HologramFeatureTests.Components.DefaultLayout

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

def template do
~H"""
<p>
<button $click="reset"> Reset </button>
</p>
<p>
<button $click="basic_case"> Basic case </button>
<button $click="single_arg"> Single arg </button>
<button $click="multiple_args"> Multiple args </button>
<button $click="multiple_clauses"> Multiple clauses </button>
<button $click="multiple_expression_body"> Multiple-expression body </button>
<button $click="single_guard"> Single guard </button>
<button $click="multiple_guards"> Multiple guards </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="no_matching_clause"> No matching clause </button>
<button $click="error_in_body"> Error in body </button>
</p>
<p>
Result: <strong id="result"><code>{inspect(@result)}</code></strong>
</p>
"""
end

# no args / single clause / single-expression body
def action(:basic_case, _params, component) do
fun = fn -> :a end
result = fun.()

put_state(component, :result, result)
end

def action(:single_arg, _params, component) do
fun = fn x -> x end
result = fun.(1)

put_state(component, :result, result)
end

def action(:multiple_args, _params, component) do
fun = fn x, y -> {x, y} end
result = fun.(1, 2)

put_state(component, :result, result)
end

def action(:multiple_clauses, _params, component) do
fun = fn
1, x -> {1, x}
2, x -> {2, x}
3, x -> {3, x}
end

result =
2
|> wrap_term()
|> fun.(3)

put_state(component, :result, result)
end

def action(:multiple_expression_body, _params, component) do
fun = fn ->
:a
:b
end

result = fun.()

put_state(component, :result, result)
end

def action(:single_guard, _params, component) do
fun = fn
x when x == 1 -> :a
x when x == 2 -> :b
x when x == 3 -> :c
end

result =
2
|> wrap_term()
|> fun.()

put_state(component, :result, result)
end

def action(:multiple_guards, _params, component) do
fun = fn
x when x > 0 and x < 10 -> :a
x when x > 10 and x < 20 -> :b
x when x > 10 and x < 30 -> :c
x when x > 10 and x < 40 -> :d
end

result =
25
|> wrap_term()
|> fun.()

put_state(component, :result, result)
end

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

fun = fn
z, y = 4 ->
{z, y}

x = 5, y = 6 ->
x = x + 10
{x, y, z}
end

result = fun.(5, wrap_term(6))

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

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

anon_fun = fn -> {x, y} end

result = local_fun(anon_fun)

put_state(component, :result, result)
end

def action(:arity_invalid_called_with_no_args, _params, _component) do
fun = fn x, y -> {x, y} end
fun.()
end

def action(:arity_invalid_called_with_single_arg, _params, _component) do
fun = fn x, y -> {x, y} end
fun.(:a)
end

def action(:arity_invalid_called_with_multple_args, _params, _component) do
fun = fn x -> x end
fun.(:a, :b)
end

def action(:no_matching_clause, _params, component) do
fun = fn
1, 2 -> :a
3, 4 -> :b
end

result =
5
|> wrap_term()
|> fun.(6)

put_state(component, :result, result)
end

def action(:error_in_body, _params, _component) do
fun = fn -> raise RuntimeError, "my message" end
fun.()
end

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

defp local_fun(anon_fun) do
x = 3
y = 4

{x, y, anon_fun.()}
end
end
2 changes: 1 addition & 1 deletion test/features/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"hologram": {:git, "https://github.com/bartblast/hologram.git", "290a31a9e77cd02b9c68afc211e09740035e590d", []},
"hologram": {:git, "https://github.com/bartblast/hologram.git", "07e3f2207b70bf9d1c475633ad3ca554dd53f8a6", []},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
Expand Down
123 changes: 123 additions & 0 deletions test/features/test/function_calls/anonymous_function_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
defmodule HologramFeatureTests.FunctionCalls.AnonymousFunctionTest do
use HologramFeatureTests.TestCase, async: true
alias HologramFeatureTests.FunctionCalls.AnonymousFunctionPage

# no args / single clause / single-expression body
feature "basic case", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Basic case"))
|> assert_text(css("#result"), ":a")
end

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

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

feature "multiple clauses", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Multiple clauses"))
|> assert_text(css("#result"), "{2, 3}")
end

feature "multiple-expression body", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Multiple-expression body"))
|> assert_text(css("#result"), ":b")
end

feature "single guard", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Single guard"))
|> assert_text(css("#result"), ":b")
end

feature "multiple guards", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Multiple guards"))
|> assert_text(css("#result"), ":c")
end

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

feature "closure", %{session: session} do
session
|> visit(AnonymousFunctionPage)
|> click(button("Closure"))
|> assert_text(css("#result"), "{3, 4, {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(AnonymousFunctionPage)
|> 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(AnonymousFunctionPage)
|> 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(AnonymousFunctionPage)
|> click(button("Arity invalid, called with multiple args"))
end
end

feature "no matching clause", %{session: session} do
assert_client_error session,
FunctionClauseError,
build_function_clause_error_msg("anonymous fn/2", [5, 6]),
fn ->
session
|> visit(AnonymousFunctionPage)
|> click(button("No matching clause"))
end
end

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

0 comments on commit 53ada69

Please sign in to comment.