Packages

Boa-powered JavaScript runtimes for Elixir with BEAM dispatch hooks.

Current section

Files

Jump to
boam test boam_test.exs
Raw

test/boam_test.exs

defmodule BoamTest do
use ExUnit.Case, async: false
alias Boam.JS
alias Boam.Runtime
doctest Boam
test "evaluates JavaScript values through the runtime wrapper" do
runtime = start_supervised!({Runtime, []})
assert {:ok, 3} = Runtime.eval(runtime, "1 + 2")
assert {:ok, :undefined} = Runtime.eval(runtime, "undefined")
assert {:ok, %{"nested" => [1, true, nil]}} =
Runtime.eval(runtime, "({ nested: [1, true, null] })")
end
test "dispatches into exported BEAM handlers" do
runtime =
start_supervised!(
{Runtime,
[
exports: %{
sum: fn [left, right] -> left + right end
}
]}
)
assert {:ok, 5} = Runtime.eval(runtime, "beam.call('sum', 2, 3)")
end
test "uses a fallback matcher for unregistered names" do
runtime =
start_supervised!(
{Runtime,
[
fallback: fn name, args -> "#{name}:#{Enum.join(args, ",")}" end
]}
)
assert {:ok, "echo:1,two"} = Runtime.eval(runtime, "beam.call('echo', 1, 'two')")
end
test "turns dispatcher crashes into JavaScript errors instead of hanging" do
runtime =
start_supervised!(
{Runtime,
[
exports: %{
explode: fn _args -> raise "boom" end
}
]}
)
assert {:error, message} = Runtime.eval(runtime, "beam.call('explode')")
assert message =~ "boom"
end
test "rejects unsupported bridge arguments loudly" do
runtime =
start_supervised!(
{Runtime,
[
exports: %{
noop: fn _args -> :ok end
}
]}
)
assert {:error, message} = Runtime.eval(runtime, "beam.call('noop', undefined)")
assert message =~ "undefined"
end
test "returns a descriptive error for missing handlers" do
runtime = start_supervised!({Runtime, []})
assert {:error, message} = Runtime.eval(runtime, "beam.call('missing')")
assert message =~ "no handler registered"
end
test "runs prelude code during startup" do
runtime =
start_supervised!(
{Runtime,
[
prelude: "globalThis.console = { prefix: 'ready:' };"
]}
)
assert {:ok, "ready:ok"} = Runtime.eval(runtime, "console.prefix + 'ok'")
end
test "exposes nested Elixir handlers as JS functions" do
runtime =
start_supervised!(
{Runtime,
[
expose: %{
console: %{
log: fn [message] -> "logged:" <> message end,
warn: {:dispatch, "logger.warn", fn [message] -> "warn:" <> message end}
}
}
]}
)
assert {:ok, "logged:hello"} = Runtime.eval(runtime, "console.log('hello')")
assert {:ok, "warn:careful"} = Runtime.eval(runtime, "console.warn('careful')")
end
test "can use a manually generated shim prelude" do
runtime =
start_supervised!(
{Runtime,
[
fallback: fn name, args ->
"#{name}:#{Enum.join(Enum.map(args, &to_string/1), ",")}"
end,
prelude: JS.export_prelude(%{console: %{log: true}})
]}
)
assert {:ok, "console.log:1,two"} = Runtime.eval(runtime, "console.log(1, 'two')")
end
test "fails startup when the prelude is invalid JavaScript" do
{pid, monitor} =
spawn_monitor(fn ->
Runtime.start_link(prelude: "let = ;")
end)
assert_receive {:DOWN, ^monitor, :process, ^pid, {:startup_prelude_failed, message}}
assert message != ""
end
test "rejects automatic exposure when an external dispatcher is supplied" do
dispatcher = start_supervised!({Boam.Dispatcher, []})
{pid, monitor} =
spawn_monitor(fn ->
Runtime.start_link(
dispatcher: dispatcher,
expose: %{console: %{log: fn _args -> :ok end}}
)
end)
assert_receive {:DOWN, ^monitor, :process, ^pid, message}
assert message =~ "cannot use :expose"
end
end