-module(dream_test@runner). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream_test/runner.gleam"). -export([max_concurrency/2, default_timeout_ms/2, exit_on_failure/1, progress_reporter/2, results_reporters/2, output/2, filter_tests/2, before_each_test/2, after_each_test/2, before_each_suite/2, after_each_suite/2, before_all_suites/2, after_all_suites/2, silent/1, new/1, add_suites/2, add_suites_with_config/3, has_failures/1, run/1]). -export_type([run_builder/1, suite_run/1, output/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( " Test runner for dream_test.\n" "\n" " This module provides a **pipe-friendly builder API** for running suites and\n" " collecting `dream_test/types.TestResult` values.\n" "\n" " ## When should I use this?\n" "\n" " - Always: the runner is how you execute suites built with `dream_test/unit`,\n" " `dream_test/unit_context`, or `dream_test/gherkin/feature`.\n" "\n" " ## What does the runner do?\n" "\n" " - Runs groups sequentially, tests in parallel (bounded by `max_concurrency`)\n" " - Sandboxes tests and hooks (timeouts + crash isolation)\n" " - Optionally drives an event-based reporter\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/parallel\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" "\n" " pub fn tests() {\n" " describe(\"Example\", [\n" " it(\"works\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"math should work\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " let db_config =\n" " parallel.ParallelConfig(max_concurrency: 1, default_timeout_ms: 60_000)\n" "\n" " runner.new([])\n" " |> runner.add_suites([tests()])\n" " |> runner.add_suites_with_config(db_config, [db_tests()])\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" ). -opaque run_builder(JZP) :: {run_builder, list(suite_run(JZP)), dream_test@parallel:parallel_config(), gleam@option:option(fun((dream_test@types:test_info()) -> boolean())), boolean(), gleam@option:option(dream_test@reporters@progress:progress_reporter()), list(dream_test@reporters@types:results_reporter()), gleam@option:option(output()), list(fun((dream_test@types:test_info(), JZP) -> {ok, JZP} | {error, binary()})), list(fun((dream_test@types:test_info(), JZP) -> {ok, nil} | {error, binary()})), list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), list(fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()})), list(fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()}))}. -type suite_run(JZQ) :: {suite_run, dream_test@types:root(JZQ), gleam@option:option(dream_test@parallel:parallel_config())}. -type output() :: {output, fun((binary()) -> nil), fun((binary()) -> nil)}. -file("src/dream_test/runner.gleam", 320). ?DOC( " Set the maximum number of concurrently running tests.\n" "\n" " - `1` gives fully sequential test execution.\n" " - Higher values increase parallelism.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" " import gleam/io\n" "\n" " pub fn tests() {\n" " describe(\"Sequential tests\", [\n" " it(\"first test\", fn() {\n" " // When tests share external resources, run them sequentially\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"Math works\")\n" " }),\n" " it(\"second test\", fn() {\n" " 2 + 2\n" " |> should\n" " |> be_equal(4)\n" " |> or_fail_with(\"Math still works\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " // Sequential execution for tests with shared state\n" " runner.new([tests()])\n" " |> runner.max_concurrency(1)\n" " |> runner.default_timeout_ms(30_000)\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `builder`: the runner builder you’re configuring\n" " - `max`: maximum number of concurrently running tests (use `1` for fully sequential)\n" "\n" " ## Returns\n" "\n" " The updated `RunBuilder(ctx)`.\n" ). -spec max_concurrency(run_builder(KAF), integer()) -> run_builder(KAF). max_concurrency(Builder, Max) -> {parallel_config, _, Timeout} = erlang:element(3, Builder), {run_builder, erlang:element(2, Builder), {parallel_config, Max, Timeout}, erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 379). ?DOC( " Set the default timeout (milliseconds) applied to tests without an explicit timeout.\n" "\n" " Tests that exceed the timeout are killed and reported as `TimedOut`.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" " import gleam/io\n" "\n" " pub fn tests() {\n" " describe(\"Runner config demo\", [\n" " it(\"runs with custom config\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"Math works\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.max_concurrency(8)\n" " |> runner.default_timeout_ms(10_000)\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `builder`: the runner builder you’re configuring\n" " - `timeout_ms`: timeout in milliseconds applied to tests without an explicit timeout\n" "\n" " ## Returns\n" "\n" " The updated `RunBuilder(ctx)`.\n" ). -spec default_timeout_ms(run_builder(KAI), integer()) -> run_builder(KAI). default_timeout_ms(Builder, Timeout_ms) -> {parallel_config, Max, _} = erlang:element(3, Builder), {run_builder, erlang:element(2, Builder), {parallel_config, Max, Timeout_ms}, erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 435). ?DOC( " Exit the BEAM with a non-zero code if any tests fail.\n" "\n" " Useful for CI pipelines.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" " import gleam/io\n" "\n" " pub fn tests() {\n" " describe(\"Example\", [\n" " it(\"works\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"math should work\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `builder`: the runner builder you’re configuring\n" "\n" " ## Returns\n" "\n" " The updated `RunBuilder(ctx)`.\n" ). -spec exit_on_failure(run_builder(KAL)) -> run_builder(KAL). exit_on_failure(Builder) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), true, erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 443). ?DOC( " Attach a progress reporter (live output during the run).\n" "\n" " This reporter is driven by `TestFinished` events in completion order.\n" " It is intended for a single in-place progress bar UI.\n" ). -spec progress_reporter( run_builder(KAO), dream_test@reporters@progress:progress_reporter() ) -> run_builder(KAO). progress_reporter(Builder, Reporter) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), {some, Reporter}, erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 454). ?DOC( " Attach results reporters (printed at the end, in the order provided).\n" "\n" " Results reporters receive the full traversal-ordered results list from the\n" " `RunFinished` event, so their output is deterministic under parallel execution.\n" ). -spec results_reporters( run_builder(KAR), list(dream_test@reporters@types:results_reporter()) ) -> run_builder(KAR). results_reporters(Builder, Reporters) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), Reporters, erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 478). ?DOC( " Configure output sinks for `runner.run()`.\n" "\n" " This is how you route reporter output (stdout vs stderr, capturing output in\n" " tests, etc).\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/runner\n" " import gleam/io\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.output(runner.Output(out: io.print, error: io.eprint))\n" " |> runner.run()\n" " }\n" " ```\n" ). -spec output(run_builder(KAV), output()) -> run_builder(KAV). output(Builder, Output) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), {some, Output}, erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 545). ?DOC( " Filter which tests are executed.\n" "\n" " The predicate receives `TestInfo` (name, full name, effective tags, kind).\n" " Tags include inherited group tags.\n" "\n" " Groups with no selected tests in their entire subtree are skipped entirely,\n" " including hooks.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should, succeed}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner.{type TestInfo}\n" " import dream_test/unit.{describe, it, with_tags}\n" " import gleam/io\n" " import gleam/list\n" "\n" " pub fn tests() {\n" " describe(\"Filtering tests\", [\n" " it(\"smoke\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"math should work\")\n" " })\n" " |> with_tags([\"smoke\"]),\n" " it(\"slow\", fn() { Ok(succeed()) })\n" " |> with_tags([\"slow\"]),\n" " ])\n" " }\n" "\n" " pub fn only_smoke(info: TestInfo) -> Bool {\n" " list.contains(info.tags, \"smoke\")\n" " }\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.filter_tests(only_smoke)\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `builder`: the runner builder you’re configuring\n" " - `predicate`: function that decides whether a test should run\n" "\n" " ## Returns\n" "\n" " The updated `RunBuilder(ctx)`.\n" ). -spec filter_tests( run_builder(KBB), fun((dream_test@types:test_info()) -> boolean()) ) -> run_builder(KBB). filter_tests(Builder, Predicate) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), {some, Predicate}, erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 572). ?DOC( " Register a runner-level hook that runs before each test.\n" "\n" " The hook receives `types.TestInfo` and the current context value.\n" " If it returns `Error(\"...\")`, the test is marked `SetupFailed`\n" " and the test body does not run.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/runner\n" " import dream_test/types.{type TestInfo}\n" "\n" " fn log_test(info: TestInfo, ctx: Nil) {\n" " io.println(\"starting \" <> string.join(info.full_name, \" > \"))\n" " Ok(ctx)\n" " }\n" "\n" " runner.new([suite])\n" " |> runner.before_each_test(log_test)\n" " ```\n" ). -spec before_each_test( run_builder(KBE), fun((dream_test@types:test_info(), KBE) -> {ok, KBE} | {error, binary()}) ) -> run_builder(KBE). before_each_test(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), lists:append(erlang:element(9, Builder), [Hook]), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 586). ?DOC( " Register a runner-level hook that runs after each test.\n" "\n" " The hook receives `types.TestInfo` and the current context value.\n" " If it returns `Error(\"...\")`, the test is marked `Failed`.\n" ). -spec after_each_test( run_builder(KBJ), fun((dream_test@types:test_info(), KBJ) -> {ok, nil} | {error, binary()}) ) -> run_builder(KBJ). after_each_test(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), lists:append(erlang:element(10, Builder), [Hook]), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 601). ?DOC( " Register a runner-level hook that runs before each suite.\n" "\n" " The hook receives `types.SuiteInfo` for the suite about to run.\n" " If it returns `Error(\"...\")`, all tests in that suite are marked `Failed`\n" " and the suite is skipped.\n" ). -spec before_each_suite( run_builder(KBO), fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()}) ) -> run_builder(KBO). before_each_suite(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), lists:append(erlang:element(11, Builder), [Hook]), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 617). ?DOC( " Register a runner-level hook that runs after each suite.\n" "\n" " The hook receives `types.SuiteInfo` for the suite that just ran.\n" " If it returns `Error(\"...\")`, a synthetic failure result is appended.\n" ). -spec after_each_suite( run_builder(KBT), fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()}) ) -> run_builder(KBT). after_each_suite(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), lists:append(erlang:element(12, Builder), [Hook]), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 632). ?DOC( " Register a runner-level hook that runs before all suites.\n" "\n" " The hook receives the full list of `SuiteInfo` after filtering.\n" " If it returns `Error(\"...\")`, all selected tests are marked `Failed`\n" " and the run short-circuits.\n" ). -spec before_all_suites( run_builder(KBY), fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()}) ) -> run_builder(KBY). before_all_suites(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), lists:append(erlang:element(13, Builder), [Hook]), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 648). ?DOC( " Register a runner-level hook that runs after all suites.\n" "\n" " The hook receives the full list of `SuiteInfo` after filtering.\n" " If it returns `Error(\"...\")`, a synthetic failure result is appended.\n" ). -spec after_all_suites( run_builder(KCE), fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()}) ) -> run_builder(KCE). after_all_suites(Builder, Hook) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), lists:append(erlang:element(14, Builder), [Hook])}. -file("src/dream_test/runner.gleam", 821). -spec suite_name_from_tree(dream_test@types:node_(any())) -> binary(). suite_name_from_tree(Tree) -> case Tree of {group, Name, _, _} -> Name; _ -> <<""/utf8>> end. -file("src/dream_test/runner.gleam", 912). -spec all_sources_match(binary(), list(dream_test@types:test_info())) -> boolean(). all_sources_match(Value, Rest) -> case Rest of [] -> true; [{test_info, _, _, _, _, Source} | Next] -> case Source of {some, S} -> case S =:= Value of true -> all_sources_match(Value, Next); false -> false end; none -> false end end. -file("src/dream_test/runner.gleam", 898). -spec suite_source_from_tests_with_first( gleam@option:option(binary()), list(dream_test@types:test_info()) ) -> gleam@option:option(binary()). suite_source_from_tests_with_first(First, Rest) -> case First of none -> none; {some, Value} -> case all_sources_match(Value, Rest) of true -> {some, Value}; false -> none end end. -file("src/dream_test/runner.gleam", 882). -spec suite_source_from_tests(list(dream_test@types:test_info())) -> gleam@option:option(binary()). suite_source_from_tests(Tests) -> case Tests of [] -> none; [{test_info, _, _, _, _, Source} | Rest] -> suite_source_from_tests_with_first(Source, Rest) end. -file("src/dream_test/runner.gleam", 936). -spec run_before_all_suites_hooks( list(fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()})), list(dream_test@types:suite_info()) ) -> {ok, nil} | {error, binary()}. run_before_all_suites_hooks(Hooks, Suites) -> case Hooks of [] -> {ok, nil}; [Hook | Rest] -> case Hook(Suites) of {ok, _} -> run_before_all_suites_hooks(Rest, Suites); {error, Message} -> {error, Message} end end. -file("src/dream_test/runner.gleam", 950). -spec run_before_each_suite_hooks( list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), dream_test@types:suite_info() ) -> {ok, nil} | {error, binary()}. run_before_each_suite_hooks(Hooks, Suite) -> case Hooks of [] -> {ok, nil}; [Hook | Rest] -> case Hook(Suite) of {ok, _} -> run_before_each_suite_hooks(Rest, Suite); {error, Message} -> {error, Message} end end. -file("src/dream_test/runner.gleam", 964). -spec run_after_each_suite_hooks( list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), dream_test@types:suite_info() ) -> {ok, nil} | {error, binary()}. run_after_each_suite_hooks(Hooks, Suite) -> case Hooks of [] -> {ok, nil}; [Hook | Rest] -> case Hook(Suite) of {ok, _} -> run_after_each_suite_hooks(Rest, Suite); {error, Message} -> {error, Message} end end. -file("src/dream_test/runner.gleam", 978). -spec run_after_all_suites_hooks( list(fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()})), list(dream_test@types:suite_info()) ) -> {ok, nil} | {error, binary()}. run_after_all_suites_hooks(Hooks, Suites) -> case Hooks of [] -> {ok, nil}; [Hook | Rest] -> case Hook(Suites) of {ok, _} -> run_after_all_suites_hooks(Rest, Suites); {error, Message} -> {error, Message} end end. -file("src/dream_test/runner.gleam", 1233). -spec hook_failure(binary(), binary()) -> dream_test@types:assertion_failure(). hook_failure(Operator, Message) -> {assertion_failure, Operator, Message, none}. -file("src/dream_test/runner.gleam", 1182). -spec failed_result_for_test_info( dream_test@types:test_info(), binary(), binary() ) -> dream_test@types:test_result(). failed_result_for_test_info(Info, Operator, Message) -> {test_info, Name, Full_name, Tags, Kind, _} = Info, {test_result, Name, Full_name, failed, 0, Tags, [hook_failure(Operator, Message)], Kind}. -file("src/dream_test/runner.gleam", 1166). -spec build_failed_results_from_tests_rev( list(dream_test@types:test_info()), binary(), binary(), list(dream_test@types:test_result()) ) -> list(dream_test@types:test_result()). build_failed_results_from_tests_rev(Tests, Operator, Message, Acc_rev) -> case Tests of [] -> Acc_rev; [Test_info | Rest] -> build_failed_results_from_tests_rev( Rest, Operator, Message, [failed_result_for_test_info(Test_info, Operator, Message) | Acc_rev] ) end. -file("src/dream_test/runner.gleam", 1134). -spec build_failed_results_from_suites_rev( list(dream_test@types:suite_info()), binary(), binary(), list(dream_test@types:test_result()) ) -> list(dream_test@types:test_result()). build_failed_results_from_suites_rev(Suites, Operator, Message, Acc_rev) -> case Suites of [] -> Acc_rev; [Suite | Rest] -> build_failed_results_from_suites_rev( Rest, Operator, Message, build_failed_results_from_tests_rev( erlang:element(3, Suite), Operator, Message, Acc_rev ) ) end. -file("src/dream_test/runner.gleam", 1125). -spec build_failed_results_from_suites( list(dream_test@types:suite_info()), binary(), binary() ) -> list(dream_test@types:test_result()). build_failed_results_from_suites(Suites, Operator, Message) -> _pipe = build_failed_results_from_suites_rev(Suites, Operator, Message, []), lists:reverse(_pipe). -file("src/dream_test/runner.gleam", 1157). -spec build_failed_results_from_tests( list(dream_test@types:test_info()), binary(), binary() ) -> list(dream_test@types:test_result()). build_failed_results_from_tests(Tests, Operator, Message) -> _pipe = build_failed_results_from_tests_rev(Tests, Operator, Message, []), lists:reverse(_pipe). -file("src/dream_test/runner.gleam", 1205). -spec after_all_suites_failure_result(binary()) -> dream_test@types:test_result(). after_all_suites_failure_result(Message) -> {test_result, <<""/utf8>>, [<<""/utf8>>], failed, 0, [], [hook_failure(<<"after_all_suites"/utf8>>, Message)], unit}. -file("src/dream_test/runner.gleam", 1113). -spec apply_after_all_suites_hooks( list(fun((list(dream_test@types:suite_info())) -> {ok, nil} | {error, binary()})), list(dream_test@types:suite_info()), list(dream_test@types:test_result()) ) -> list(dream_test@types:test_result()). apply_after_all_suites_hooks(Hooks, Suites, Results) -> case run_after_all_suites_hooks(Hooks, Suites) of {ok, _} -> Results; {error, Message} -> lists:append(Results, [after_all_suites_failure_result(Message)]) end. -file("src/dream_test/runner.gleam", 1217). -spec after_each_suite_failure_result(dream_test@types:suite_info(), binary()) -> dream_test@types:test_result(). after_each_suite_failure_result(Suite_info, Message) -> {suite_info, Name, _, _} = Suite_info, {test_result, <<""/utf8>>, [Name, <<""/utf8>>], failed, 0, [], [hook_failure(<<"after_each_suite"/utf8>>, Message)], unit}. -file("src/dream_test/runner.gleam", 1099). -spec apply_after_each_suite_hooks( list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), dream_test@types:suite_info(), list(dream_test@types:test_result()) ) -> list(dream_test@types:test_result()). apply_after_each_suite_hooks(Hooks, Suite_info, Results) -> case run_after_each_suite_hooks(Hooks, Suite_info) of {ok, _} -> Results; {error, Message} -> lists:append( Results, [after_each_suite_failure_result(Suite_info, Message)] ) end. -file("src/dream_test/runner.gleam", 1288). -spec default_output() -> output(). default_output() -> {output, fun gleam_stdlib:print/1, fun gleam_stdlib:print_error/1}. -file("src/dream_test/runner.gleam", 1296). -spec discard_output(binary()) -> nil. discard_output(_) -> nil. -file("src/dream_test/runner.gleam", 1292). -spec silent_output() -> output(). silent_output() -> {output, fun discard_output/1, fun discard_output/1}. -file("src/dream_test/runner.gleam", 486). ?DOC(" Disable all reporter output (still returns results from `runner.run()`).\n"). -spec silent(run_builder(KAY)) -> run_builder(KAY). silent(Builder) -> {run_builder, erlang:element(2, Builder), erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), {some, silent_output()}, erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 1451). -spec suite_run_config( dream_test@parallel:parallel_config(), gleam@option:option(dream_test@parallel:parallel_config()) ) -> dream_test@parallel:parallel_config(). suite_run_config(Default_config, Override) -> case Override of none -> Default_config; {some, Config} -> Config end. -file("src/dream_test/runner.gleam", 1494). -spec render_results_reporter( dream_test@reporters@types:results_reporter(), list(dream_test@types:test_result()) ) -> binary(). render_results_reporter(Reporter, Results) -> case Reporter of {bdd, Config} -> dream_test@reporters@bdd:render(Config, Results); {json, Config@1} -> dream_test@reporters@json:render(Config@1, Results) end. -file("src/dream_test/runner.gleam", 1480). -spec write_results_reporters_loop( list(dream_test@reporters@types:results_reporter()), list(dream_test@types:test_result()), fun((binary()) -> nil) ) -> nil. write_results_reporters_loop(Reporters, Results, Write) -> case Reporters of [] -> nil; [Reporter | Rest] -> Write(render_results_reporter(Reporter, Results)), write_results_reporters_loop(Rest, Results, Write) end. -file("src/dream_test/runner.gleam", 1504). -spec output_out(output()) -> fun((binary()) -> nil). output_out(Output) -> {output, Out, _} = Output, Out. -file("src/dream_test/runner.gleam", 1461). -spec write_progress_event( dream_test@reporters@progress:progress_reporter(), dream_test@reporters@types:reporter_event(), output() ) -> nil. write_progress_event(Reporter, Event, Output) -> case dream_test@reporters@progress:handle_event(Reporter, Event) of none -> nil; {some, Text} -> (output_out(Output))(Text) end. -file("src/dream_test/runner.gleam", 1237). -spec emit_test_finished_progress( gleam@option:option(dream_test@reporters@progress:progress_reporter()), output(), integer(), integer(), dream_test@types:test_result() ) -> integer(). emit_test_finished_progress(Progress_reporter, Output, Completed, Total, Result) -> Next_completed = Completed + 1, case Progress_reporter of none -> Next_completed; {some, Reporter} -> write_progress_event( Reporter, {test_finished, Next_completed, Total, Result}, Output ), Next_completed end. -file("src/dream_test/runner.gleam", 1262). -spec emit_test_finished_progress_results( gleam@option:option(dream_test@reporters@progress:progress_reporter()), output(), integer(), integer(), list(dream_test@types:test_result()) ) -> integer(). emit_test_finished_progress_results( Progress_reporter, Output, Completed, Total, Results ) -> case Results of [] -> Completed; [Result | Rest] -> emit_test_finished_progress_results( Progress_reporter, Output, emit_test_finished_progress( Progress_reporter, Output, Completed, Total, Result ), Total, Rest ) end. -file("src/dream_test/runner.gleam", 992). -spec run_suites_with_hooks( list(suite_run(KEN)), list(dream_test@types:suite_info()), dream_test@parallel:parallel_config(), gleam@option:option(dream_test@reporters@progress:progress_reporter()), output(), integer(), integer(), list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), list(fun((dream_test@types:suite_info()) -> {ok, nil} | {error, binary()})), list(fun((dream_test@types:test_info(), KEN) -> {ok, KEN} | {error, binary()})), list(fun((dream_test@types:test_info(), KEN) -> {ok, nil} | {error, binary()})), list(dream_test@types:test_result()) ) -> {list(dream_test@types:test_result()), integer(), gleam@option:option(dream_test@reporters@progress:progress_reporter())}. run_suites_with_hooks( Suite_runs, Suite_infos, Default_config, Progress_reporter, Output, Total, Completed, Before_each_suite_hooks, After_each_suite_hooks, Runner_before_each_test, Runner_after_each_test, Acc ) -> case {Suite_runs, Suite_infos} of {[], []} -> {Acc, Completed, Progress_reporter}; {[{suite_run, Suite, Override} | Rest], [Suite_info | Rest_infos]} -> Before_result = run_before_each_suite_hooks( Before_each_suite_hooks, Suite_info ), case Before_result of {error, Message} -> Failures = build_failed_results_from_tests( erlang:element(3, Suite_info), <<"before_each_suite"/utf8>>, Message ), Completed_after_failures = emit_test_finished_progress_results( Progress_reporter, Output, Completed, Total, Failures ), Acc_with_failures = lists:append(Acc, Failures), Acc_after_after_each = apply_after_each_suite_hooks( After_each_suite_hooks, Suite_info, Acc_with_failures ), run_suites_with_hooks( Rest, Rest_infos, Default_config, Progress_reporter, Output, Total, Completed_after_failures, Before_each_suite_hooks, After_each_suite_hooks, Runner_before_each_test, Runner_after_each_test, Acc_after_after_each ); {ok, _} -> Suite_config = suite_run_config(Default_config, Override), Parallel_result = dream_test@parallel:run_root_parallel_with_reporter( {run_root_parallel_with_reporter_config, Suite_config, Suite, Progress_reporter, output_out(Output), Total, Completed, Runner_before_each_test, Runner_after_each_test} ), {run_root_parallel_with_reporter_result, Results, Completed_after_suite, Next_progress_reporter} = Parallel_result, Acc_with_results = lists:append(Acc, Results), Acc_after_after_each@1 = apply_after_each_suite_hooks( After_each_suite_hooks, Suite_info, Acc_with_results ), run_suites_with_hooks( Rest, Rest_infos, Default_config, Next_progress_reporter, Output, Total, Completed_after_suite, Before_each_suite_hooks, After_each_suite_hooks, Runner_before_each_test, Runner_after_each_test, Acc_after_after_each@1 ) end; {_, _} -> {Acc, Completed, Progress_reporter} end. -file("src/dream_test/runner.gleam", 1472). -spec write_results_reporters( list(dream_test@reporters@types:results_reporter()), list(dream_test@types:test_result()), output() ) -> nil. write_results_reporters(Reporters, Results, Output) -> write_results_reporters_loop(Reporters, Results, output_out(Output)). -file("src/dream_test/runner.gleam", 1541). -spec suites_to_suite_runs_default( list(dream_test@types:root(KIE)), list(suite_run(KIE)) ) -> list(suite_run(KIE)). suites_to_suite_runs_default(Suites, Acc_rev) -> case Suites of [] -> lists:reverse(Acc_rev); [Suite | Rest] -> suites_to_suite_runs_default( Rest, [{suite_run, Suite, none} | Acc_rev] ) end. -file("src/dream_test/runner.gleam", 190). ?DOC( " Create a new runner builder for a list of suites.\n" "\n" " The type parameter `ctx` is the suite context type. For `dream_test/unit`\n" " suites this is `Nil`. For `dream_test/unit_context` suites it is your custom\n" " context type.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" " import gleam/io\n" "\n" " pub fn tests() {\n" " describe(\"Example\", [\n" " it(\"works\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"math should work\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `suites`: the test suites you want to run (often just `[tests()]`)\n" "\n" " ## Returns\n" "\n" " A `RunBuilder(ctx)` you can pipe through configuration helpers and finally\n" " `runner.run()`.\n" ). -spec new(list(dream_test@types:root(JZR))) -> run_builder(JZR). new(Suites) -> Config = dream_test@parallel:default_config(), {run_builder, suites_to_suite_runs_default(Suites, []), Config, none, false, none, [], none, [], [], [], [], [], []}. -file("src/dream_test/runner.gleam", 1555). -spec suites_to_suite_runs_with_override( dream_test@parallel:parallel_config(), list(dream_test@types:root(KIL)), list(suite_run(KIL)) ) -> list(suite_run(KIL)). suites_to_suite_runs_with_override(Config, Suites, Acc_rev) -> case Suites of [] -> lists:reverse(Acc_rev); [Suite | Rest] -> suites_to_suite_runs_with_override( Config, Rest, [{suite_run, Suite, {some, Config}} | Acc_rev] ) end. -file("src/dream_test/runner.gleam", 1570). -spec append_suite_runs_default( list(suite_run(KIS)), list(dream_test@types:root(KIS)) ) -> list(suite_run(KIS)). append_suite_runs_default(Existing, Suites) -> lists:append(Existing, suites_to_suite_runs_default(Suites, [])). -file("src/dream_test/runner.gleam", 225). ?DOC( " Append suites to the run, using the builder’s current execution config.\n" "\n" " This is useful when you want to build up your suite list incrementally\n" " (especially when some suites need a different execution config).\n" "\n" " Suites added with `add_suites` will run using the runner’s current execution\n" " config (configured via `max_concurrency` / `default_timeout_ms`).\n" "\n" " ## Example\n" "\n" " ```gleam\n" " runner.new([])\n" " |> runner.add_suites([unit_suite()])\n" " |> runner.add_suites([integration_suite()])\n" " |> runner.run()\n" " ```\n" ). -spec add_suites(run_builder(JZV), list(dream_test@types:root(JZV))) -> run_builder(JZV). add_suites(Builder, Suites) -> Appended = append_suite_runs_default(erlang:element(2, Builder), Suites), {run_builder, Appended, erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 1577). -spec append_suite_runs_with_override( list(suite_run(KIZ)), dream_test@parallel:parallel_config(), list(dream_test@types:root(KIZ)) ) -> list(suite_run(KIZ)). append_suite_runs_with_override(Existing, Config, Suites) -> lists:append( Existing, suites_to_suite_runs_with_override(Config, Suites, []) ). -file("src/dream_test/runner.gleam", 257). ?DOC( " Append suites to the run, using an explicit execution config override.\n" "\n" " This lets you run suites with different concurrency/timeout policies in a\n" " single runner invocation (for example: DB suites sequential, unit suites\n" " parallel).\n" "\n" " The override applies only to the suites added by this call. Reporting, output,\n" " filtering, and exit behavior remain global runner settings.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/parallel\n" "\n" " let db_config =\n" " parallel.ParallelConfig(max_concurrency: 1, default_timeout_ms: 60_000)\n" "\n" " runner.new([])\n" " |> runner.add_suites([unit_suite()])\n" " |> runner.add_suites_with_config(db_config, [db_suite()])\n" " |> runner.max_concurrency(50)\n" " |> runner.default_timeout_ms(5_000)\n" " |> runner.run()\n" " ```\n" ). -spec add_suites_with_config( run_builder(KAA), dream_test@parallel:parallel_config(), list(dream_test@types:root(KAA)) ) -> run_builder(KAA). add_suites_with_config(Builder, Config, Suites) -> Appended = append_suite_runs_with_override( erlang:element(2, Builder), Config, Suites ), {run_builder, Appended, erlang:element(3, Builder), erlang:element(4, Builder), erlang:element(5, Builder), erlang:element(6, Builder), erlang:element(7, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(13, Builder), erlang:element(14, Builder)}. -file("src/dream_test/runner.gleam", 1631). ?DOC( " Return `True` if the list contains any failing statuses.\n" "\n" " This treats `Failed`, `SetupFailed`, and `TimedOut` as failures.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should, succeed}\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" "\n" " pub fn tests() {\n" " describe(\"has_failures\", [\n" " it(\"passes\", fn() { Ok(succeed()) }),\n" " ])\n" " }\n" "\n" " fn failing_suite() {\n" " describe(\"failing suite\", [\n" " it(\"fails\", fn() {\n" " 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"intentional failure for has_failures example\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " let results = runner.new([failing_suite()]) |> runner.run()\n" "\n" " results\n" " |> runner.has_failures()\n" " |> should\n" " |> be_equal(True)\n" " |> or_fail_with(\"expected failures to be present\")\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `results`: list of `TestResult` values returned by `runner.run`\n" "\n" " ## Returns\n" "\n" " `True` when any result has status `Failed`, `SetupFailed`, or `TimedOut`.\n" ). -spec has_failures(list(dream_test@types:test_result())) -> boolean(). has_failures(Results) -> case Results of [] -> false; [R | Rest] -> case erlang:element(4, R) of failed -> true; setup_failed -> true; timed_out -> true; _ -> has_failures(Rest) end end. -file("src/dream_test/runner.gleam", 1300). -spec maybe_exit_on_failure(boolean(), list(dream_test@types:test_result())) -> nil. maybe_exit_on_failure(Should_exit, Results) -> Should_halt = Should_exit andalso has_failures(Results), case Should_halt of true -> erlang:halt(1); false -> nil end. -file("src/dream_test/runner.gleam", 864). -spec collect_test_infos_children( list(dream_test@types:node_(any())), list(binary()), list(binary()), list(dream_test@types:test_info()) ) -> list(dream_test@types:test_info()). collect_test_infos_children(Children, Scope, Inherited_tags, Acc_rev) -> case Children of [] -> Acc_rev; [Child | Rest] -> collect_test_infos_children( Rest, Scope, Inherited_tags, collect_test_infos(Child, Scope, Inherited_tags, Acc_rev) ) end. -file("src/dream_test/runner.gleam", 828). -spec collect_test_infos( dream_test@types:node_(any()), list(binary()), list(binary()), list(dream_test@types:test_info()) ) -> list(dream_test@types:test_info()). collect_test_infos(Node, Scope, Inherited_tags, Acc_rev) -> case Node of {test, Name, Tags, Kind, _, _, Source} -> Full_name = lists:append(Scope, [Name]), Effective_tags = lists:append(Inherited_tags, Tags), Info = {test_info, Name, Full_name, Effective_tags, Kind, Source}, [Info | Acc_rev]; {group, Name@1, Tags@1, Children} -> Next_scope = lists:append(Scope, [Name@1]), Next_tags = lists:append(Inherited_tags, Tags@1), collect_test_infos_children( Children, Next_scope, Next_tags, Acc_rev ); _ -> Acc_rev end. -file("src/dream_test/runner.gleam", 809). -spec suite_info_from_suite(dream_test@types:root(any())) -> dream_test@types:suite_info(). suite_info_from_suite(Suite) -> {root, _, Tree} = Suite, Tests_rev = collect_test_infos(Tree, [], [], []), Tests = lists:reverse(Tests_rev), Source = suite_source_from_tests(Tests), {suite_info, suite_name_from_tree(Tree), Tests, Source}. -file("src/dream_test/runner.gleam", 798). -spec suite_infos_from_runs( list(suite_run(any())), list(dream_test@types:suite_info()) ) -> list(dream_test@types:suite_info()). suite_infos_from_runs(Suite_runs, Acc_rev) -> case Suite_runs of [] -> lists:reverse(Acc_rev); [{suite_run, Suite, _} | Rest] -> suite_infos_from_runs( Rest, [suite_info_from_suite(Suite) | Acc_rev] ) end. -file("src/dream_test/runner.gleam", 1529). -spec count_tests_in_children(list(dream_test@types:node_(any())), integer()) -> integer(). count_tests_in_children(Children, Acc) -> case Children of [] -> Acc; [Child | Rest] -> count_tests_in_children(Rest, Acc + count_tests_in_suite(Child)) end. -file("src/dream_test/runner.gleam", 1521). -spec count_tests_in_suite(dream_test@types:node_(any())) -> integer(). count_tests_in_suite(Node) -> case Node of {test, _, _, _, _, _, _} -> 1; {group, _, _, Children} -> count_tests_in_children(Children, 0); _ -> 0 end. -file("src/dream_test/runner.gleam", 1513). -spec count_total_tests_from_list(list(suite_run(any())), integer()) -> integer(). count_total_tests_from_list(Suite_runs, Acc) -> case Suite_runs of [] -> Acc; [{suite_run, Suite, _} | Rest] -> count_total_tests_from_list( Rest, Acc + count_tests_in_suite(erlang:element(3, Suite)) ) end. -file("src/dream_test/runner.gleam", 1509). -spec count_total_tests(list(suite_run(any()))) -> integer(). count_total_tests(Suite_runs) -> count_total_tests_from_list(Suite_runs, 0). -file("src/dream_test/runner.gleam", 1413). -spec filter_children( list(dream_test@types:node_(KHE)), list(binary()), list(binary()), fun((dream_test@types:test_info()) -> boolean()), list(dream_test@types:node_(KHE)), boolean() ) -> {list(dream_test@types:node_(KHE)), boolean()}. filter_children(Children, Scope, Inherited_tags, Predicate, Acc_rev, Has_tests) -> case Children of [] -> {lists:reverse(Acc_rev), Has_tests}; [Child | Rest] -> {Maybe_child, Child_has_tests} = filter_node( Child, Scope, Inherited_tags, Predicate ), Next_has_tests = Has_tests orelse Child_has_tests, case Maybe_child of none -> filter_children( Rest, Scope, Inherited_tags, Predicate, Acc_rev, Next_has_tests ); {some, Kept} -> filter_children( Rest, Scope, Inherited_tags, Predicate, [Kept | Acc_rev], Next_has_tests ) end end. -file("src/dream_test/runner.gleam", 1351). -spec filter_node( dream_test@types:node_(KGY), list(binary()), list(binary()), fun((dream_test@types:test_info()) -> boolean()) ) -> {gleam@option:option(dream_test@types:node_(KGY)), boolean()}. filter_node(Node, Scope, Inherited_tags, Predicate) -> case Node of {test, Name, Tags, Kind, Run, Timeout_ms, Source} -> Full_name = lists:append(Scope, [Name]), Effective_tags = lists:append(Inherited_tags, Tags), Info = {test_info, Name, Full_name, Effective_tags, Kind, Source}, case Predicate(Info) of true -> {{some, {test, Name, Tags, Kind, Run, Timeout_ms, Source}}, true}; false -> {none, false} end; {group, Name@1, Tags@1, Children} -> Next_scope = lists:append(Scope, [Name@1]), Next_tags = lists:append(Inherited_tags, Tags@1), {Filtered_children, Has_tests} = filter_children( Children, Next_scope, Next_tags, Predicate, [], false ), case Has_tests of true -> {{some, {group, Name@1, Tags@1, Filtered_children}}, true}; false -> {none, false} end; {before_all, _} -> {{some, Node}, false}; {before_each, _} -> {{some, Node}, false}; {after_each, _} -> {{some, Node}, false}; {after_all, _} -> {{some, Node}, false} end. -file("src/dream_test/runner.gleam", 1339). -spec filter_root( dream_test@types:root(KGU), fun((dream_test@types:test_info()) -> boolean()) ) -> {gleam@option:option(dream_test@types:root(KGU)), boolean()}. filter_root(Suite, Predicate) -> {root, Seed, Tree} = Suite, {Maybe_tree, Has_tests} = filter_node(Tree, [], [], Predicate), case Maybe_tree of none -> {none, Has_tests}; {some, Next_tree} -> {{some, {root, Seed, Next_tree}}, Has_tests} end. -file("src/dream_test/runner.gleam", 1318). -spec filter_suite_runs( list(suite_run(KGN)), fun((dream_test@types:test_info()) -> boolean()), list(suite_run(KGN)) ) -> list(suite_run(KGN)). filter_suite_runs(Suite_runs, Predicate, Acc_rev) -> case Suite_runs of [] -> lists:reverse(Acc_rev); [{suite_run, Suite, Override} | Rest] -> {Maybe, _} = filter_root(Suite, Predicate), case Maybe of none -> filter_suite_runs(Rest, Predicate, Acc_rev); {some, Filtered} -> filter_suite_runs( Rest, Predicate, [{suite_run, Filtered, Override} | Acc_rev] ) end end. -file("src/dream_test/runner.gleam", 1308). -spec apply_test_filter( list(suite_run(KGH)), gleam@option:option(fun((dream_test@types:test_info()) -> boolean())) ) -> list(suite_run(KGH)). apply_test_filter(Suite_runs, Predicate) -> case Predicate of none -> Suite_runs; {some, P} -> filter_suite_runs(Suite_runs, P, []) end. -file("src/dream_test/runner.gleam", 699). ?DOC( " Run all suites and return a list of `TestResult`.\n" "\n" " If a progress reporter is attached, the runner will emit progress output during\n" " the run. Results reporters print at the end of the run.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_test/matchers.{be_equal, or_fail_with, should}\n" " import dream_test/reporters/bdd\n" " import dream_test/reporters/progress\n" " import dream_test/runner\n" " import dream_test/unit.{describe, it}\n" "\n" " pub fn tests() {\n" " describe(\"Example\", [\n" " it(\"works\", fn() {\n" " 1 + 1\n" " |> should\n" " |> be_equal(2)\n" " |> or_fail_with(\"math should work\")\n" " }),\n" " ])\n" " }\n" "\n" " pub fn main() {\n" " runner.new([tests()])\n" " |> runner.progress_reporter(progress.new())\n" " |> runner.results_reporters([bdd.new()])\n" " |> runner.exit_on_failure()\n" " |> runner.run()\n" " }\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `builder`: the fully configured runner builder\n" "\n" " ## Returns\n" "\n" " A list of `TestResult` values, in deterministic order.\n" ). -spec run(run_builder(any())) -> list(dream_test@types:test_result()). run(Builder) -> Selected_runs = apply_test_filter( erlang:element(2, Builder), erlang:element(4, Builder) ), Total = count_total_tests(Selected_runs), Suite_infos = suite_infos_from_runs(Selected_runs, []), Output@1 = case erlang:element(8, Builder) of {some, Output} -> Output; none -> default_output() end, Completed0 = 0, Progress_reporter0 = erlang:element(6, Builder), Completed1 = case Progress_reporter0 of none -> Completed0; {some, Progress_reporter} -> write_progress_event( Progress_reporter, {run_started, Total}, Output@1 ), Completed0 end, Before_all_result = run_before_all_suites_hooks( erlang:element(13, Builder), Suite_infos ), {Results, Completed2, Progress_reporter1} = case Before_all_result of {ok, _} -> run_suites_with_hooks( Selected_runs, Suite_infos, erlang:element(3, Builder), Progress_reporter0, Output@1, Total, Completed1, erlang:element(11, Builder), erlang:element(12, Builder), erlang:element(9, Builder), erlang:element(10, Builder), [] ); {error, Message} -> Failures = build_failed_results_from_suites( Suite_infos, <<"before_all_suites"/utf8>>, Message ), Completed_after_failures = emit_test_finished_progress_results( Progress_reporter0, Output@1, Completed1, Total, Failures ), Results_with_after_all = apply_after_all_suites_hooks( erlang:element(14, Builder), Suite_infos, Failures ), {Results_with_after_all, Completed_after_failures, Progress_reporter0} end, Final_results = case Before_all_result of {ok, _} -> apply_after_all_suites_hooks( erlang:element(14, Builder), Suite_infos, Results ); {error, _} -> Results end, case Progress_reporter1 of none -> nil; {some, Progress_reporter@1} -> write_progress_event( Progress_reporter@1, {run_finished, Completed2, Total, Final_results}, Output@1 ) end, write_results_reporters(erlang:element(7, Builder), Final_results, Output@1), maybe_exit_on_failure(erlang:element(5, Builder), Final_results), Final_results.