Packages

Gleam TestContainers wrapper around Elixir TestContainers

Current section

Files

Jump to
testcontainers_gleam src testcontainers_gleam.erl
Raw

src/testcontainers_gleam.erl

-module(testcontainers_gleam).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/testcontainers_gleam.gleam").
-export([start_link/0, start_container/1, stop_container/1]).
-export_type([container_error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Gleam wrapper for the Elixir\n"
" [testcontainers](https://hex.pm/packages/testcontainers) library.\n"
"\n"
" Provides functions to start and stop Docker containers in tests.\n"
" Use `testcontainers_gleam/container` to build a container definition,\n"
" then pass it to `start_container` to run it.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import testcontainers_gleam\n"
" import testcontainers_gleam/container\n"
"\n"
" let c =\n"
" container.new(\"redis:7.4-alpine\")\n"
" |> container.with_exposed_port(6379)\n"
"\n"
" let assert Ok(running) = testcontainers_gleam.start_container(c)\n"
" let id = container.container_id(running)\n"
" let assert Ok(port) = container.mapped_port(running, 6379)\n"
"\n"
" let assert Ok(Nil) = testcontainers_gleam.stop_container(id)\n"
" ```\n"
).
-type container_error() :: {http_error, integer()} |
failed_to_pull_image |
failed_to_create_container |
failed_to_start_container |
failed_to_get_container |
wait_strategy_failed |
unknown.
-file("src/testcontainers_gleam.gleam", 124).
?DOC(" Decode an error tuple from the Elixir library into a `ContainerError`.\n").
-spec decode_error(gleam@dynamic:dynamic_()) -> container_error().
decode_error(Raw) ->
Tag_decoder = gleam@dynamic@decode:at([0], gleam@erlang@atom:decoder()),
case gleam@dynamic@decode:run(Raw, Tag_decoder) of
{ok, Tag} ->
case erlang:atom_to_binary(Tag) of
<<"http_error"/utf8>> ->
Status_decoder = gleam@dynamic@decode:at(
[1],
{decoder, fun gleam@dynamic@decode:decode_int/1}
),
Status = case gleam@dynamic@decode:run(Raw, Status_decoder) of
{ok, S} ->
S;
{error, _} ->
0
end,
{http_error, Status};
<<"failed_to_pull_image"/utf8>> ->
failed_to_pull_image;
<<"failed_to_create_container"/utf8>> ->
failed_to_create_container;
<<"failed_to_start_container"/utf8>> ->
failed_to_start_container;
<<"failed_to_get_container"/utf8>> ->
failed_to_get_container;
<<"log_wait_strategy"/utf8>> ->
wait_strategy_failed;
<<"command_wait_strategy"/utf8>> ->
wait_strategy_failed;
<<"port_wait_strategy"/utf8>> ->
wait_strategy_failed;
_ ->
unknown
end;
{error, _} ->
unknown
end.
-file("src/testcontainers_gleam.gleam", 59).
?DOC(
" Start the Testcontainers GenServer.\n"
"\n"
" This is called automatically by `start_container`, so you only\n"
" need to call it directly if you want to manage the lifecycle yourself.\n"
" Returns `Ok(Nil)` if the GenServer was started or is already running.\n"
).
-spec start_link() -> {ok, nil} | {error, container_error()}.
start_link() ->
case 'Elixir.Testcontainers':start_link() of
{ok, _} ->
{ok, nil};
{error, Raw} ->
Tag_decoder = gleam@dynamic@decode:at(
[0],
gleam@erlang@atom:decoder()
),
case gleam@dynamic@decode:run(Raw, Tag_decoder) of
{ok, Tag} ->
case erlang:atom_to_binary(Tag) of
<<"already_started"/utf8>> ->
{ok, nil};
_ ->
{error, decode_error(Raw)}
end;
{error, _} ->
{error, decode_error(Raw)}
end
end.
-file("src/testcontainers_gleam.gleam", 91).
?DOC(
" Start a container and wait until it is ready.\n"
"\n"
" Automatically starts the Testcontainers GenServer if it is not\n"
" already running. Returns the started container on success, which\n"
" can be queried with `container.container_id` and `container.mapped_port`.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let c =\n"
" container.new(\"redis:7.4-alpine\")\n"
" |> container.with_exposed_port(6379)\n"
"\n"
" let assert Ok(running) = testcontainers_gleam.start_container(c)\n"
" ```\n"
).
-spec start_container(testcontainers_gleam@container:container()) -> {ok,
testcontainers_gleam@container:container()} |
{error, container_error()}.
start_container(Container) ->
_ = 'Elixir.Testcontainers':start_link(),
_pipe = Container,
_pipe@1 = testcontainers_gleam_ffi:start_container(_pipe),
gleam@result:map_error(_pipe@1, fun decode_error/1).
-file("src/testcontainers_gleam.gleam", 106).
?DOC(
" Stop a running container by its container ID.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let assert Ok(Nil) = testcontainers_gleam.stop_container(id)\n"
" ```\n"
).
-spec stop_container(binary()) -> {ok, nil} | {error, container_error()}.
stop_container(Container_id) ->
Raw = 'Elixir.Testcontainers':stop_container(Container_id),
Decoded = begin
_pipe = Raw,
_pipe@1 = gleam@dynamic@decode:run(_pipe, gleam@erlang@atom:decoder()),
gleam@result:'try'(
_pipe@1,
fun(Tag) -> case erlang:atom_to_binary(Tag) of
<<"ok"/utf8>> ->
{ok, nil};
_ ->
{error, []}
end end
)
end,
case Decoded of
{ok, _} ->
{ok, nil};
{error, _} ->
{error, decode_error(Raw)}
end.