-module(dream_test@matchers). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream_test/matchers.gleam"). -export([should/1, or_fail_with/2, fail_with/1, succeed/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( " Matcher API for Dream Test.\n" "\n" " Matchers are small functions you pipe values through to produce the value a\n" " Dream Test `it(...)` body returns: `Result(AssertionResult, String)`.\n" "\n" " You’ll typically:\n" "\n" " - Start with `should` (wrap a value for matching)\n" " - Apply one or more matchers (like `be_equal`, `be_some`, `contain_string`)\n" " - Finish with `or_fail_with(\"...\")` to produce the final test result\n" "\n" " ## Available Matchers\n" "\n" " | Category | Matchers |\n" " |----------------|-------------------------------------------------------------|\n" " | **Equality** | `be_equal`, `not_equal` |\n" " | **Boolean** | `be_true`, `be_false` |\n" " | **Option** | `be_some`, `be_none` |\n" " | **Result** | `be_ok`, `be_error` |\n" " | **Collections**| `contain`, `not_contain`, `have_length`, `be_empty` |\n" " | **Comparison** | `be_greater_than`, `be_less_than`, `be_at_least`, `be_at_most`, `be_between`, `be_in_range`, `be_greater_than_float`, `be_less_than_float` |\n" " | **String** | `start_with`, `end_with`, `contain_string`, `match_regex` |\n" " | **Snapshot** | `match_snapshot`, `match_snapshot_inspect` |\n" "\n" " ## Chaining Matchers\n" "\n" " Some matchers “unwrap” values:\n" " - `be_some()` turns `Option(a)` into `a`\n" " - `be_ok()` turns `Result(a, e)` into `a`\n" "\n" " That’s why you can chain checks after them.\n" "\n" " ## Explicit failures\n" "\n" " Sometimes you need to explicitly return “pass” or “fail” from a branch of a\n" " `case` expression. Use `succeed()` / `fail_with(\"...\")` for that.\n" "\n" " ## Imports\n" "\n" " You can import individual matchers, or import the whole module and qualify\n" " with `matchers.`. The examples in these docs assume you imported the matcher\n" " functions you’re using.\n" ). -file("src/dream_test/matchers.gleam", 81). ?DOC( " Start a matcher chain.\n" "\n" " This wraps a value so it can be piped through matchers.\n" " Every matcher chain starts with `should`.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " True\n" " |> should\n" " |> be_true()\n" " |> or_fail_with(\"expected True\")\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `value`: any value you want to make assertions about\n" "\n" " ## Returns\n" "\n" " A `MatchResult(a)` containing `value`. Subsequent matchers will either:\n" " - preserve this value (for “checking” matchers), or\n" " - transform it (for “unwrapping” matchers like `be_some` / `be_ok`).\n" ). -spec should(HZF) -> dream_test@types:match_result(HZF). should(Value) -> {match_ok, Value}. -file("src/dream_test/matchers.gleam", 808). -spec or_fail_with_assertion(dream_test@types:match_result(any()), binary()) -> dream_test@types:assertion_result(). or_fail_with_assertion(Result, Message) -> case Result of {match_ok, _} -> assertion_ok; {match_failed, Failure} -> {assertion_failed, {assertion_failure, erlang:element(2, Failure), Message, erlang:element(4, Failure)}} end. -file("src/dream_test/matchers.gleam", 801). ?DOC( " Complete a matcher chain and provide a failure message.\n" "\n" " This is the **terminal operation** that ends every matcher chain. It\n" " converts the `MatchResult` into an `AssertionResult` that the test runner\n" " understands.\n" "\n" " If the matcher passed, returns `AssertionOk`. If it failed, returns\n" " `AssertionFailed` with the provided message.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " 2 + 3\n" " |> should\n" " |> be_equal(5)\n" " |> or_fail_with(\"2 + 3 should equal 5\")\n" " ```\n" "\n" " ## Parameters\n" "\n" " - `result`: the `MatchResult(a)` produced by `should` and matchers\n" " - `message`: message to show if the chain failed\n" "\n" " ## Returns\n" "\n" " A `Result(AssertionResult, String)` so test bodies can return it directly:\n" "\n" " - `Ok(AssertionOk)` when the chain passed\n" " - `Ok(AssertionFailed(...))` when the chain failed\n" "\n" " (This function currently never returns `Error`, but the `Result` shape keeps\n" " test bodies uniform for `dream_test/unit`: `fn() { ... } -> Result(AssertionResult, String)`.)\n" "\n" " ## Writing Good Messages\n" "\n" " Good failure messages explain **what should have happened**:\n" " - ✓ \"User should be authenticated after login\"\n" " - ✓ \"Cart total should include tax\"\n" " - ✗ \"wrong\"\n" " - ✗ \"failed\"\n" ). -spec or_fail_with(dream_test@types:match_result(any()), binary()) -> {ok, dream_test@types:assertion_result()} | {error, binary()}. or_fail_with(Result, Message) -> {ok, or_fail_with_assertion(Result, Message)}. -file("src/dream_test/matchers.gleam", 846). ?DOC( " Explicitly fail a test with a message.\n" "\n" " Use this when you need to fail a test in a conditional branch where\n" " the normal matcher chain doesn't apply.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " Ok(case 1 + 1 {\n" " 2 -> succeed()\n" " _ -> fail_with(\"expected 1 + 1 to be 2\")\n" " })\n" " ```\n" "\n" " ## When to Use\n" "\n" " - In `case` branches that represent unexpected states\n" " - When testing that something does NOT happen\n" " - As a placeholder for unimplemented test branches\n" "\n" " ## Returns\n" "\n" " An `AssertionResult` you can wrap in `Ok(...)` from a test body.\n" "\n" " If you want to abort a test immediately (rather than “failing a matcher”),\n" " return `Error(\"...\")` from the test body instead.\n" ). -spec fail_with(binary()) -> dream_test@types:assertion_result(). fail_with(Message) -> {assertion_failed, {assertion_failure, <<"fail_with"/utf8>>, Message, none}}. -file("src/dream_test/matchers.gleam", 878). ?DOC( " Explicitly mark a matcher chain as successful.\n" "\n" " Use this when you need to explicitly succeed in a conditional branch,\n" " as the counterpart to `fail_with`.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " Ok(case 1 + 1 {\n" " 2 -> succeed()\n" " _ -> fail_with(\"expected 1 + 1 to be 2\")\n" " })\n" " ```\n" "\n" " ## When to Use\n" "\n" " - In `case` branches where success is the expected outcome\n" " - When all branches of a case must return an `AssertionResult`\n" " - To make intent explicit rather than relying on implicit success\n" "\n" " ## Returns\n" "\n" " `AssertionOk`.\n" ). -spec succeed() -> dream_test@types:assertion_result(). succeed() -> assertion_ok.