Current section

Files

Jump to
dream_test src dream_test@reporter@gherkin.erl
Raw

src/dream_test@reporter@gherkin.erl

-module(dream_test@reporter@gherkin).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/dream_test/reporter/gherkin.gleam").
-export([is_gherkin_result/1, format/1, report/2]).
-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(
" Gherkin-style test reporter for dream_test.\n"
"\n"
" This reporter formats Gherkin test results in a Cucumber-like format\n"
" that mirrors the Given/When/Then structure of your scenarios.\n"
"\n"
" ## Example Output\n"
"\n"
" ```text\n"
" Feature: Shopping Cart\n"
" Scenario: Adding items ✓ (2ms)\n"
" Scenario: Removing items ✗ (3ms)\n"
" ✗ equal\n"
" Message: Item count mismatch\n"
" Expected: 7\n"
" Actual: 10\n"
"\n"
" Summary: 2 run, 1 failed, 1 passed in 5ms\n"
" ```\n"
"\n"
" ## Usage\n"
"\n"
" ```gleam\n"
" import dream_test/gherkin/feature\n"
" import dream_test/runner\n"
" import dream_test/reporter/gherkin as gherkin_reporter\n"
" import gleam/io\n"
"\n"
" pub fn main() {\n"
" my_feature_suite()\n"
" |> runner.run_suite()\n"
" |> gherkin_reporter.report(io.print)\n"
" }\n"
" ```\n"
"\n"
" ## Status Markers\n"
"\n"
" | Status | Marker | Meaning |\n"
" |-------------|--------|--------------------------------|\n"
" | Passed | ✓ | All steps succeeded |\n"
" | Failed | ✗ | One or more steps failed |\n"
" | Skipped | - | Scenario was skipped |\n"
" | Pending | ~ | Scenario is a placeholder |\n"
" | TimedOut | ! | Scenario exceeded timeout |\n"
" | SetupFailed | âš  | A setup hook failed |\n"
).
-file("src/dream_test/reporter/gherkin.gleam", 120).
?DOC(
" Check if a TestResult is from a Gherkin test.\n"
"\n"
" Useful for filtering or routing results to the appropriate reporter.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let gherkin_results = list.filter(results, is_gherkin_result)\n"
" let unit_results = list.filter(results, fn(r) { !is_gherkin_result(r) })\n"
" ```\n"
).
-spec is_gherkin_result(dream_test@types:test_result()) -> boolean().
is_gherkin_result(Result) ->
case erlang:element(8, Result) of
{gherkin_scenario, _} ->
true;
_ ->
false
end.
-file("src/dream_test/reporter/gherkin.gleam", 149).
-spec extract_feature_name(list(binary())) -> binary().
extract_feature_name(Full_name) ->
case Full_name of
[] ->
<<"Unknown Feature"/utf8>>;
[Feature | _] ->
Feature
end.
-file("src/dream_test/reporter/gherkin.gleam", 156).
-spec format_feature_header_if_new(binary(), binary()) -> binary().
format_feature_header_if_new(Current, Previous) ->
case Current =:= Previous of
true ->
<<""/utf8>>;
false ->
erlang:list_to_binary(
[<<"Feature: "/utf8>>, Current, <<"\n"/utf8>>]
)
end.
-file("src/dream_test/reporter/gherkin.gleam", 173).
-spec format_duration(integer()) -> binary().
format_duration(Duration_ms) ->
case Duration_ms of
Ms when Ms =< 0 ->
<<""/utf8>>;
Ms@1 ->
<<<<" ("/utf8, (dream_test@timing:format_duration_ms(Ms@1))/binary>>/binary,
")"/utf8>>
end.
-file("src/dream_test/reporter/gherkin.gleam", 181).
-spec extract_scenario_name(list(binary())) -> binary().
extract_scenario_name(Full_name) ->
case lists:reverse(Full_name) of
[] ->
<<"Unknown Scenario"/utf8>>;
[Name | _] ->
Name
end.
-file("src/dream_test/reporter/gherkin.gleam", 188).
-spec status_marker(dream_test@types:status()) -> binary().
status_marker(Status) ->
case Status of
passed ->
<<"✓"/utf8>>;
failed ->
<<"✗"/utf8>>;
skipped ->
<<"-"/utf8>>;
pending ->
<<"~"/utf8>>;
timed_out ->
<<"!"/utf8>>;
setup_failed ->
<<"âš "/utf8>>
end.
-file("src/dream_test/reporter/gherkin.gleam", 232).
-spec format_failure_message(binary()) -> binary().
format_failure_message(Message) ->
case Message of
<<""/utf8>> ->
<<""/utf8>>;
_ ->
erlang:list_to_binary(
[<<" Message: "/utf8>>, Message, <<"\n"/utf8>>]
)
end.
-file("src/dream_test/reporter/gherkin.gleam", 239).
-spec format_failure_payload(
gleam@option:option(dream_test@types:failure_payload())
) -> binary().
format_failure_payload(Payload) ->
case Payload of
{some, {equality_failure, Actual, Expected}} ->
erlang:list_to_binary(
[<<" Expected: "/utf8>>,
Expected,
<<"\n"/utf8>>,
<<" Actual: "/utf8>>,
Actual,
<<"\n"/utf8>>]
);
_ ->
<<""/utf8>>
end.
-file("src/dream_test/reporter/gherkin.gleam", 225).
-spec format_one_failure(dream_test@types:assertion_failure()) -> binary().
format_one_failure(Failure) ->
Header = erlang:list_to_binary(
[<<" ✗ "/utf8>>, erlang:element(2, Failure), <<"\n"/utf8>>]
),
Message_text = format_failure_message(erlang:element(3, Failure)),
Payload_text = format_failure_payload(erlang:element(4, Failure)),
erlang:list_to_binary([Header, Message_text, Payload_text]).
-file("src/dream_test/reporter/gherkin.gleam", 211).
-spec format_all_failures(list(dream_test@types:assertion_failure()), binary()) -> binary().
format_all_failures(Failures, Accumulated) ->
case Failures of
[] ->
Accumulated;
[Failure | Rest] ->
Formatted = format_one_failure(Failure),
Updated = erlang:list_to_binary([Accumulated, Formatted]),
format_all_failures(Rest, Updated)
end.
-file("src/dream_test/reporter/gherkin.gleam", 203).
-spec format_failure_details(dream_test@types:test_result()) -> binary().
format_failure_details(Result) ->
case erlang:element(4, Result) of
failed ->
format_all_failures(erlang:element(7, Result), <<""/utf8>>);
setup_failed ->
format_all_failures(erlang:element(7, Result), <<""/utf8>>);
_ ->
<<""/utf8>>
end.
-file("src/dream_test/reporter/gherkin.gleam", 163).
-spec format_scenario(dream_test@types:test_result()) -> binary().
format_scenario(Result) ->
Scenario_name = extract_scenario_name(erlang:element(3, Result)),
Marker = status_marker(erlang:element(4, Result)),
Duration = format_duration(erlang:element(5, Result)),
Scenario_line = erlang:list_to_binary(
[<<" Scenario: "/utf8>>,
Scenario_name,
<<" "/utf8>>,
Marker,
Duration,
<<"\n"/utf8>>]
),
Failure_text = format_failure_details(Result),
erlang:list_to_binary([Scenario_line, Failure_text]).
-file("src/dream_test/reporter/gherkin.gleam", 131).
-spec format_all_results(
list(dream_test@types:test_result()),
binary(),
binary()
) -> binary().
format_all_results(Results, Previous_feature, Accumulated) ->
case Results of
[] ->
Accumulated;
[Result | Rest] ->
Feature_name = extract_feature_name(erlang:element(3, Result)),
Feature_header = format_feature_header_if_new(
Feature_name,
Previous_feature
),
Scenario_text = format_scenario(Result),
Updated = erlang:list_to_binary(
[Accumulated, Feature_header, Scenario_text]
),
format_all_results(Rest, Feature_name, Updated)
end.
-file("src/dream_test/reporter/gherkin.gleam", 285).
-spec sum_durations(list(dream_test@types:test_result()), integer()) -> integer().
sum_durations(Results, Total) ->
case Results of
[] ->
Total;
[Result | Rest] ->
sum_durations(Rest, Total + erlang:element(5, Result))
end.
-file("src/dream_test/reporter/gherkin.gleam", 308).
-spec format_summary_parts(list(binary())) -> binary().
format_summary_parts(Parts) ->
case Parts of
[] ->
<<""/utf8>>;
_ ->
erlang:list_to_binary(
[<<", "/utf8>>, gleam@string:join(Parts, <<", "/utf8>>)]
)
end.
-file("src/dream_test/reporter/gherkin.gleam", 315).
-spec add_summary_part_if_nonzero(list(binary()), integer(), binary()) -> list(binary()).
add_summary_part_if_nonzero(Parts, Count, Label) ->
case Count of
0 ->
Parts;
_ ->
[erlang:list_to_binary([erlang:integer_to_binary(Count), Label]) |
Parts]
end.
-file("src/dream_test/reporter/gherkin.gleam", 292).
-spec build_summary_suffix(integer(), integer(), integer(), integer()) -> binary().
build_summary_suffix(Skipped, Pending, Timed_out, Setup_failed) ->
Parts = begin
_pipe = [],
_pipe@1 = add_summary_part_if_nonzero(
_pipe,
Skipped,
<<" skipped"/utf8>>
),
_pipe@2 = add_summary_part_if_nonzero(
_pipe@1,
Pending,
<<" pending"/utf8>>
),
_pipe@3 = add_summary_part_if_nonzero(
_pipe@2,
Timed_out,
<<" timed out"/utf8>>
),
add_summary_part_if_nonzero(
_pipe@3,
Setup_failed,
<<" setup failed"/utf8>>
)
end,
format_summary_parts(Parts).
-file("src/dream_test/reporter/gherkin.gleam", 326).
-spec count_by_status(
list(dream_test@types:test_result()),
dream_test@types:status()
) -> integer().
count_by_status(Results, Wanted) ->
gleam@list:fold(
Results,
0,
fun(Count, Result) -> case erlang:element(4, Result) =:= Wanted of
true ->
Count + 1;
false ->
Count
end end
).
-file("src/dream_test/reporter/gherkin.gleam", 260).
-spec format_summary(list(dream_test@types:test_result())) -> binary().
format_summary(Results) ->
Total = erlang:length(Results),
Failed = count_by_status(Results, failed),
Skipped = count_by_status(Results, skipped),
Pending = count_by_status(Results, pending),
Timed_out = count_by_status(Results, timed_out),
Setup_failed = count_by_status(Results, setup_failed),
Passed = ((((Total - Failed) - Skipped) - Pending) - Timed_out) - Setup_failed,
Total_duration = sum_durations(Results, 0),
erlang:list_to_binary(
[<<"Summary: "/utf8>>,
erlang:integer_to_binary(Total),
<<" run, "/utf8>>,
erlang:integer_to_binary(Failed),
<<" failed, "/utf8>>,
erlang:integer_to_binary(Passed),
<<" passed"/utf8>>,
build_summary_suffix(Skipped, Pending, Timed_out, Setup_failed),
<<" in "/utf8>>,
dream_test@timing:format_duration_ms(Total_duration),
<<"\n"/utf8>>]
).
-file("src/dream_test/reporter/gherkin.gleam", 76).
?DOC(
" Format test results as a Gherkin-style report string.\n"
"\n"
" Returns the complete report including:\n"
" - Feature name as header\n"
" - Scenario names with status markers\n"
" - Summary with scenario counts\n"
"\n"
" Use this when you need the report as a string.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let report_string = format(results)\n"
" file.write(\"cucumber-results.txt\", report_string)\n"
" ```\n"
).
-spec format(list(dream_test@types:test_result())) -> binary().
format(Results) ->
Formatted_results = format_all_results(Results, <<""/utf8>>, <<""/utf8>>),
Summary_text = format_summary(Results),
erlang:list_to_binary([Formatted_results, <<"\n"/utf8>>, Summary_text]).
-file("src/dream_test/reporter/gherkin.gleam", 101).
?DOC(
" Print test results using a provided writer function.\n"
"\n"
" This is the main entry point for Gherkin test runs.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" results |> report(io.print)\n"
" ```\n"
"\n"
" ## Parameters\n"
"\n"
" - `results` - List of test results from the runner\n"
" - `write` - Function that handles the formatted output string\n"
"\n"
" ## Returns\n"
"\n"
" Returns the input results unchanged, enabling pipeline composition.\n"
).
-spec report(list(dream_test@types:test_result()), fun((binary()) -> nil)) -> list(dream_test@types:test_result()).
report(Results, Write) ->
Write(format(Results)),
Results.