Skip to content

Commit

Permalink
Implement feature tests for local function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
bartblast committed Nov 18, 2024
1 parent 72be04b commit d64e4d9
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 0 deletions.
6 changes: 6 additions & 0 deletions test/elixir/hologram/ex_js_consistency/interpreter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ defmodule Hologram.ExJsConsistency.InterpreterTest do
# TODO: implement
# describe "call function capture"

# IMPORTANT!
# Keep consistent with feature tests in:
# * test/features/test/function_calls/local_function_test.exs
# * test/features/test/function_calls/remote_function_test.exs
# TODO: split into "call local function" and "call remote function"
# TODO: reimplement to be consistent with aforementioned feature tests
describe "call named function" do
test "remote private function call" do
expected_msg =
Expand Down
182 changes: 182 additions & 0 deletions test/features/app/pages/function_calls/local_function_page.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
defmodule HologramFeatureTests.FunctionCalls.LocalFunctionPage do
use Hologram.Page

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

route "/function-calls/local-function"

layout HologramFeatureTests.Components.DefaultLayout

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

def template do
~H"""
<p>
<button $click="basic_case"> Basic case </button>
<button $click="private_function"> Private function </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="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>
<p>
<button $click="reset"> Reset </button>
</p>
"""
end

# public funciton / no args / single clause / single-expression body
def action(:basic_case, _params, component) do
result = local_fun_1()

put_state(component, :result, result)
end

def action(:private_function, _params, component) do
result = local_fun_10()

put_state(component, :result, result)
end

def action(:single_arg, _params, component) do
result = local_fun_2(:a)

put_state(component, :result, result)
end

def action(:multiple_args, _params, component) do
result = local_fun_3(:a, :b)

put_state(component, :result, result)
end

def action(:multiple_clauses, _params, component) do
result = local_fun_4(2, :a)

put_state(component, :result, result)
end

def action(:multiple_expression_body, _params, component) do
result = local_fun_5()

put_state(component, :result, result)
end

def action(:single_guard, _params, component) do
result = local_fun_6(2)

put_state(component, :result, result)
end

def action(:multiple_guards, _params, component) do
result = local_fun_7(25)

put_state(component, :result, result)
end

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

result = local_fun_8(x, 5)

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

def action(:no_matching_clause, _params, _component) do
local_fun_4(4, 5)
end

def action(:error_in_body, _params, _component) do
local_fun_9()
end

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

def local_fun_1 do
:a
end

def local_fun_2(x) do
x
end

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

def local_fun_4(1, x) do
{1, x}
end

def local_fun_4(2, x) do
{2, x}
end

def local_fun_4(3, x) do
{3, x}
end

def local_fun_5 do
:a
:b
end

def local_fun_6(x) when x == 1 do
:a
end

def local_fun_6(x) when x == 2 do
:b
end

def local_fun_6(x) when x == 3 do
:c
end

def local_fun_7(x) when x > 0 and x < 10 do
:a
end

def local_fun_7(x) when x > 10 and x < 20 do
:b
end

def local_fun_7(x) when x > 10 and x < 30 do
:c
end

def local_fun_7(x) when x > 10 and x < 40 do
:d
end

def local_fun_8(x = 3, y = 4) do
{x, y}
end

def local_fun_8(x, y) do
x = x + 10
{x, y}
end

def local_fun_9 do
raise RuntimeError, "my message"
end

defp local_fun_10 do
:a
end
end
98 changes: 98 additions & 0 deletions test/features/test/function_calls/local_function_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
defmodule HologramFeatureTests.FunctionCalls.LocalFunctionTest do
use HologramFeatureTests.TestCase, async: true
alias HologramFeatureTests.FunctionCalls.LocalFunctionPage

# IMPORTANT!
# Keep consistent with Elixir/JavaScript consistency tests
# in test/elixir/hologram/ex_js_consistency/interpreter_test.exs (call local function section).

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

feature "private function", %{session: session} do
session
|> visit(LocalFunctionPage)
|> click(button("Private function"))
|> assert_text(css("#result"), ":a")
end

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

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

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

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

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

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

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

# # TODO: client error message for this case is inconsistent with server error message
feature "no matching clause", %{session: session} do
assert_client_error session,
FunctionClauseError,
build_function_clause_error_msg(
"HologramFeatureTests.FunctionCalls.LocalFunctionPage.local_fun_4/2",
[4, 5]
),
fn ->
session
|> visit(LocalFunctionPage)
|> click(button("No matching clause"))
end
end

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

0 comments on commit d64e4d9

Please sign in to comment.