-module(dream_test@assertions@should). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream_test/assertions/should.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( " Assertion API for dream_test.\n" "\n" " This module provides a fluent, pipe-friendly assertion API. Every assertion\n" " chain starts with `should()` and ends with `or_fail_with()`.\n" "\n" " ## Basic Pattern\n" "\n" " ```gleam\n" " value\n" " |> should()\n" " |> equal(expected)\n" " |> or_fail_with(\"Helpful error message\")\n" " ```\n" "\n" " ## Available Matchers\n" "\n" " | Category | Matchers |\n" " |----------------|-------------------------------------------------------------|\n" " | **Equality** | `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` |\n" " | **String** | `start_with`, `end_with`, `contain_string` |\n" " | **Snapshot** | `match_snapshot`, `match_snapshot_inspect` |\n" "\n" " ## Chaining Matchers\n" "\n" " Matchers can be chained. Each matcher passes its unwrapped value to the next:\n" "\n" " ```gleam\n" " // Unwrap Some, then check the inner value\n" " Some(42)\n" " |> should()\n" " |> be_some()\n" " |> equal(42)\n" " |> or_fail_with(\"Should be Some(42)\")\n" "\n" " // Unwrap Ok, then check the inner value\n" " Ok(\"hello\")\n" " |> should()\n" " |> be_ok()\n" " |> equal(\"hello\")\n" " |> or_fail_with(\"Should be Ok with 'hello'\")\n" "\n" " // Unwrap Ok, then check the inner Option\n" " Ok(Some(42))\n" " |> should()\n" " |> be_ok()\n" " |> be_some()\n" " |> be_greater_than(40)\n" " |> or_fail_with(\"Should be Ok(Some(n)) where n > 40\")\n" " ```\n" "\n" " ## Explicit Failures\n" "\n" " Sometimes you need to fail a test explicitly in a conditional branch:\n" "\n" " ```gleam\n" " case result {\n" " Ok(user) -> {\n" " user.name\n" " |> should()\n" " |> equal(\"Alice\")\n" " |> or_fail_with(\"User should be Alice\")\n" " }\n" " Error(_) -> fail_with(\"Should have returned a user\")\n" " }\n" " ```\n" "\n" " ## Import Style\n" "\n" " For best readability, import the commonly used functions unqualified:\n" "\n" " ```gleam\n" " import dream_test/assertions/should.{\n" " should, equal, be_ok, be_some, or_fail_with, fail_with, succeed,\n" " }\n" " ```\n" ). -file("src/dream_test/assertions/should.gleam", 110). ?DOC( " Start an assertion chain.\n" "\n" " This wraps any value in a `MatchResult` so it can be piped into matchers.\n" " Every assertion chain should start with this function.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " 42\n" " |> should()\n" " |> equal(42)\n" " |> or_fail_with(\"Should be 42\")\n" " ```\n" ). -spec should(GHW) -> dream_test@types:match_result(GHW). should(Value) -> {match_ok, Value}. -file("src/dream_test/assertions/should.gleam", 569). ?DOC( " Complete an assertion chain and provide a failure message.\n" "\n" " This is the **terminal operation** that ends every assertion chain. It\n" " converts the `MatchResult` into an `AssertionResult` that the test runner\n" " understands.\n" "\n" " If the assertion passed, returns `AssertionOk`. If it failed, returns\n" " `AssertionFailed` with the provided message.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " result\n" " |> should()\n" " |> equal(42)\n" " |> or_fail_with(\"Result should be 42\")\n" " ```\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()) -> dream_test@types:assertion_result(). or_fail_with(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/assertions/should.gleam", 603). ?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 assertion chain doesn't apply.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " case result {\n" " Ok(value) -> {\n" " value\n" " |> should()\n" " |> equal(expected)\n" " |> or_fail_with(\"Value should match\")\n" " }\n" " Error(_) -> fail_with(\"Should have succeeded but got an error\")\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" ). -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/assertions/should.gleam", 631). ?DOC( " Explicitly mark an assertion 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" " case result {\n" " Ok(_) -> succeed()\n" " Error(_) -> fail_with(\"Should have succeeded\")\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" ). -spec succeed() -> dream_test@types:assertion_result(). succeed() -> assertion_ok.