-module(dream_test@matchers@snapshot). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream_test/matchers/snapshot.gleam"). -export([clear_snapshot/1, clear_snapshots_in_directory/1, match_snapshot/2, match_snapshot_inspect/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( " Snapshot matchers for dream_test.\n" "\n" " Snapshot testing compares output against a stored “golden” file.\n" "\n" " - On first run (missing snapshot), the snapshot is created and the test passes.\n" " - On later runs, the output is compared against the file; differences fail.\n" "\n" " Snapshot tests are useful when the output is large or awkward to specify by\n" " hand (rendered HTML, JSON, error messages, logs, etc.).\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let path = \"./test/tmp/match_snapshot_example.snap\"\n" " \"hello\"\n" " |> should\n" " |> match_snapshot(path)\n" " |> or_fail_with(\"expected snapshot match\")\n" " ```\n" ). -file("src/dream_test/matchers/snapshot.gleam", 152). ?DOC( " Delete a snapshot file to force regeneration.\n" "\n" " Use this to programmatically clear a snapshot. The next test run will\n" " create a fresh snapshot with the current output.\n" "\n" " ## Parameters\n" "\n" " - `snapshot_path` - Path to the snapshot file to delete\n" "\n" " ## Returns\n" "\n" " - `Ok(Nil)` - Snapshot was deleted (or didn't exist)\n" " - `Error(String)` - Human-readable error message\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let path = \"./test/tmp/clear_snapshot_example.snap\"\n" "\n" " // Setup: create a snapshot file (no assertions during setup)\n" " use _ <- result.try(\n" " file.write(path, \"hello\") |> result.map_error(file.error_to_string),\n" " )\n" "\n" " clear_snapshot(path)\n" " |> should\n" " |> be_equal(Ok(Nil))\n" " |> or_fail_with(\"expected clear_snapshot to succeed\")\n" " ```\n" ). -spec clear_snapshot(binary()) -> {ok, nil} | {error, binary()}. clear_snapshot(Snapshot_path) -> case dream_test_file_ffi:delete_file(Snapshot_path) of {ok, nil} -> {ok, nil}; {error, Error} -> {error, dream_test@file:error_to_string(Error)} end. -file("src/dream_test/matchers/snapshot.gleam", 194). ?DOC( " Delete all `.snap` files in a directory.\n" "\n" " Clears all snapshot files in the given directory (non-recursively).\n" " Useful for resetting all snapshots before a major refactor.\n" "\n" " ## Parameters\n" "\n" " - `directory` - Path to the directory containing snapshots\n" "\n" " ## Returns\n" "\n" " - `Ok(Int)` - Number of snapshot files deleted\n" " - `Error(String)` - Human-readable error message\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let directory = \"./test/tmp/clear_snapshots_in_directory_example\"\n" " let a = directory <> \"/a.snap\"\n" " let b = directory <> \"/b.snap\"\n" "\n" " // Setup: create two snapshot files (no assertions during setup)\n" " use _ <- result.try(\n" " file.write(a, \"a\") |> result.map_error(file.error_to_string),\n" " )\n" " use _ <- result.try(\n" " file.write(b, \"b\") |> result.map_error(file.error_to_string),\n" " )\n" "\n" " clear_snapshots_in_directory(directory)\n" " |> should\n" " |> be_equal(Ok(2))\n" " |> or_fail_with(\"expected two deleted snapshots\")\n" " ```\n" ). -spec clear_snapshots_in_directory(binary()) -> {ok, integer()} | {error, binary()}. clear_snapshots_in_directory(Directory) -> case dream_test_file_ffi:delete_files_matching(Directory, <<".snap"/utf8>>) of {ok, Count} -> {ok, Count}; {error, Error} -> {error, dream_test@file:error_to_string(Error)} end. -file("src/dream_test/matchers/snapshot.gleam", 227). -spec drop_trailing_newlines(list(binary())) -> list(binary()). drop_trailing_newlines(Graphemes_reversed) -> case Graphemes_reversed of [<<"\n"/utf8>> | Rest] -> drop_trailing_newlines(Rest); [<<"\r"/utf8>> | Rest@1] -> drop_trailing_newlines(Rest@1); Other -> Other end. -file("src/dream_test/matchers/snapshot.gleam", 218). -spec normalize_snapshot_expected(binary()) -> binary(). normalize_snapshot_expected(Expected) -> _pipe = Expected, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = lists:reverse(_pipe@1), _pipe@3 = drop_trailing_newlines(_pipe@2), _pipe@4 = lists:reverse(_pipe@3), gleam@string:join(_pipe@4, <<""/utf8>>). -file("src/dream_test/matchers/snapshot.gleam", 249). -spec make_mismatch_failure(binary(), binary(), binary()) -> dream_test@types:match_result(binary()). make_mismatch_failure(Actual, Expected, Snapshot_path) -> Payload = {snapshot_failure, Actual, Expected, Snapshot_path, false}, {match_failed, {assertion_failure, <<"match_snapshot"/utf8>>, <<""/utf8>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 235). -spec compare_snapshot(binary(), binary(), binary()) -> dream_test@types:match_result(binary()). compare_snapshot(Actual, Expected, Snapshot_path) -> Normalized_actual = normalize_snapshot_expected(Actual), case Normalized_actual =:= Expected of true -> {match_ok, Actual}; false -> make_mismatch_failure(Actual, Expected, Snapshot_path) end. -file("src/dream_test/matchers/snapshot.gleam", 268). -spec make_read_error_failure(binary(), dream_test@file:file_error()) -> dream_test@types:match_result(binary()). make_read_error_failure(Snapshot_path, Error) -> Payload = {snapshot_failure, <<""/utf8>>, <<""/utf8>>, Snapshot_path, true}, {match_failed, {assertion_failure, <<"match_snapshot"/utf8>>, <<"Failed to read snapshot: "/utf8, (dream_test@file:error_to_string(Error))/binary>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 293). -spec make_write_failure(binary(), dream_test@file:file_error()) -> dream_test@types:match_result(binary()). make_write_failure(Snapshot_path, Error) -> Payload = {snapshot_failure, <<""/utf8>>, <<""/utf8>>, Snapshot_path, true}, {match_failed, {assertion_failure, <<"match_snapshot"/utf8>>, <<"Failed to write snapshot: "/utf8, (dream_test@file:error_to_string(Error))/binary>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 286). -spec create_snapshot(binary(), binary()) -> dream_test@types:match_result(binary()). create_snapshot(Actual, Snapshot_path) -> case dream_test_file_ffi:write_file(Snapshot_path, Actual) of {ok, nil} -> {match_ok, Actual}; {error, Error} -> make_write_failure(Snapshot_path, Error) end. -file("src/dream_test/matchers/snapshot.gleam", 205). -spec check_snapshot(binary(), binary()) -> dream_test@types:match_result(binary()). check_snapshot(Actual, Snapshot_path) -> case dream_test_file_ffi:read_file(Snapshot_path) of {ok, Expected} -> compare_snapshot( Actual, normalize_snapshot_expected(Expected), Snapshot_path ); {error, {not_found, _}} -> create_snapshot(Actual, Snapshot_path); {error, Error} -> make_read_error_failure(Snapshot_path, Error) end. -file("src/dream_test/matchers/snapshot.gleam", 65). ?DOC( " Assert that a string value matches the content of a snapshot file.\n" "\n" " This is the primary snapshot matcher. Use it when you have string output\n" " (JSON, HTML, plain text, etc.) that you want to compare against a snapshot.\n" "\n" " ## Behavior\n" "\n" " - **Snapshot doesn't exist**: Creates it and the test **passes**\n" " - **Snapshot exists and matches**: Test **passes**\n" " - **Snapshot exists but differs**: Test **fails** with detailed diff\n" "\n" " ## Parameters\n" "\n" " - `value_or_result` - The `MatchResult(String)` from the assertion chain\n" " - `snapshot_path` - Path to the snapshot file (will be created if missing)\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let path = \"./test/tmp/match_snapshot_example.snap\"\n" " \"hello\"\n" " |> should\n" " |> match_snapshot(path)\n" " |> or_fail_with(\"expected snapshot match\")\n" " ```\n" "\n" " ## Returns\n" "\n" " A `MatchResult(String)`:\n" " - On success, preserves the original string for further chaining.\n" " - On failure, the chain becomes failed and later matchers are skipped.\n" ). -spec match_snapshot(dream_test@types:match_result(binary()), binary()) -> dream_test@types:match_result(binary()). match_snapshot(Value_or_result, Snapshot_path) -> case Value_or_result of {match_failed, Failure} -> {match_failed, Failure}; {match_ok, Actual} -> check_snapshot(Actual, Snapshot_path) end. -file("src/dream_test/matchers/snapshot.gleam", 342). -spec make_mismatch_failure_inspect(binary(), binary(), binary()) -> dream_test@types:match_result(any()). make_mismatch_failure_inspect(Actual, Expected, Snapshot_path) -> Payload = {snapshot_failure, Actual, Expected, Snapshot_path, false}, {match_failed, {assertion_failure, <<"match_snapshot_inspect"/utf8>>, <<""/utf8>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 330). -spec compare_snapshot_inspect(HTH, binary(), binary(), binary()) -> dream_test@types:match_result(HTH). compare_snapshot_inspect(Value, Serialized, Expected, Snapshot_path) -> case Serialized =:= Expected of true -> {match_ok, Value}; false -> make_mismatch_failure_inspect(Serialized, Expected, Snapshot_path) end. -file("src/dream_test/matchers/snapshot.gleam", 361). -spec make_read_error_failure_inspect(binary(), dream_test@file:file_error()) -> dream_test@types:match_result(any()). make_read_error_failure_inspect(Snapshot_path, Error) -> Payload = {snapshot_failure, <<""/utf8>>, <<""/utf8>>, Snapshot_path, true}, {match_failed, {assertion_failure, <<"match_snapshot_inspect"/utf8>>, <<"Failed to read snapshot: "/utf8, (dream_test@file:error_to_string(Error))/binary>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 390). -spec make_write_failure_inspect(binary(), dream_test@file:file_error()) -> dream_test@types:match_result(any()). make_write_failure_inspect(Snapshot_path, Error) -> Payload = {snapshot_failure, <<""/utf8>>, <<""/utf8>>, Snapshot_path, true}, {match_failed, {assertion_failure, <<"match_snapshot_inspect"/utf8>>, <<"Failed to write snapshot: "/utf8, (dream_test@file:error_to_string(Error))/binary>>, {some, Payload}}}. -file("src/dream_test/matchers/snapshot.gleam", 379). -spec create_snapshot_inspect(HTN, binary(), binary()) -> dream_test@types:match_result(HTN). create_snapshot_inspect(Value, Serialized, Snapshot_path) -> case dream_test_file_ffi:write_file(Snapshot_path, Serialized) of {ok, nil} -> {match_ok, Value}; {error, Error} -> make_write_failure_inspect(Snapshot_path, Error) end. -file("src/dream_test/matchers/snapshot.gleam", 311). -spec check_snapshot_inspect(HTF, binary()) -> dream_test@types:match_result(HTF). check_snapshot_inspect(Value, Snapshot_path) -> Serialized = gleam@string:inspect(Value), case dream_test_file_ffi:read_file(Snapshot_path) of {ok, Expected} -> compare_snapshot_inspect( Value, Serialized, normalize_snapshot_expected(Expected), Snapshot_path ); {error, {not_found, _}} -> create_snapshot_inspect(Value, Serialized, Snapshot_path); {error, Error} -> make_read_error_failure_inspect(Snapshot_path, Error) end. -file("src/dream_test/matchers/snapshot.gleam", 108). ?DOC( " Assert that any value matches a snapshot when serialized.\n" "\n" " Use this when testing complex data structures that aren't strings.\n" " The value is converted to a string using `string.inspect`, which\n" " produces Gleam's debug representation.\n" "\n" " ## When to Use This\n" "\n" " - Testing return values of functions (records, tuples, lists)\n" " - Comparing parsed AST structures\n" " - Verifying complex state after operations\n" "\n" " ## Parameters\n" "\n" " - `value_or_result` - The `MatchResult(value)` from the assertion chain\n" " - `snapshot_path` - Path to the snapshot file\n" "\n" " ## Example\n" "\n" " ```gleam\n" " let path = \"./test/tmp/match_snapshot_inspect_example.snap\"\n" " Some(1)\n" " |> should\n" " |> match_snapshot_inspect(path)\n" " |> or_fail_with(\"expected inspect snapshot match\")\n" " ```\n" "\n" " ## Returns\n" "\n" " A `MatchResult(value)`:\n" " - On success, preserves the original value for further chaining.\n" " - On failure, the chain becomes failed and later matchers are skipped.\n" ). -spec match_snapshot_inspect(dream_test@types:match_result(HSQ), binary()) -> dream_test@types:match_result(HSQ). match_snapshot_inspect(Value_or_result, Snapshot_path) -> case Value_or_result of {match_failed, Failure} -> {match_failed, Failure}; {match_ok, Value} -> check_snapshot_inspect(Value, Snapshot_path) end.