# `PactEx.Matchers`
[🔗](https://github.com/arctarus/pact_ex/blob/v0.1.0/lib/pact_ex/matchers.ex#L1)

Pact matchers.

Each function returns a map in the pact_ffi "integration JSON" format. Put
the map where you would put a plain value, in a body, header, query value or
path. The mock server matches by rule instead of by equality, and the
example value is what it returns to the consumer.

    import PactEx.Matchers

    %{
      "id" => integer(1),
      "name" => like("Ada"),
      "email" => regex("ada@example.com", ".+@.+"),
      "tags" => each_like(like("admin"), min: 1)
    }

Matchers nest, and the results are plain maps that encode to JSON.

# `t`

```elixir
@type t() :: %{required(String.t()) =&gt; term()}
```

# `boolean`

```elixir
@spec boolean(boolean()) :: t()
```

Matches any boolean. `value` is the example.

    iex> PactEx.Matchers.boolean(true)
    %{"pact:matcher:type" => "boolean", "value" => true}

# `datetime`

```elixir
@spec datetime(String.t(), String.t()) :: t()
```

Matches a date or time string in the given Java `DateTimeFormatter` `format`.

`value` is the example string. It should follow `format`.

    iex> PactEx.Matchers.datetime("2026-10-22", "yyyy-MM-dd")
    %{"pact:matcher:type" => "datetime", "value" => "2026-10-22", "format" => "yyyy-MM-dd"}

# `decimal`

```elixir
@spec decimal(float()) :: t()
```

Matches any decimal number. `value` is the example and must be a float.

Integers are rejected: pact_matching checks decimals with a float test, and
an integer such as `2` encodes as `2`, which fails its own rule. Use
`2.0`.

    iex> PactEx.Matchers.decimal(1.5)
    %{"pact:matcher:type" => "decimal", "value" => 1.5}

# `each_key`

```elixir
@spec each_key(map(), String.t()) :: t()
```

Matches a map whose keys all match the regular expression `pattern`.

`value` is the example map. Raises `FunctionClauseError` if it is not a map.

    iex> PactEx.Matchers.each_key(%{"happy" => true}, "(happy|ferocious)")
    %{
      "pact:matcher:type" => "eachKey",
      "value" => %{"happy" => true},
      "rules" => [%{"pact:matcher:type" => "regex", "regex" => "(happy|ferocious)"}]
    }

# `each_like`

```elixir
@spec each_like(term(), [{:min, pos_integer()}]) :: t()
```

Matches a list in which every element looks like `value`.

`value` is the example element. The list needs at least `:min` elements
(default `1`). The example list repeats `value` `:min` times, because the
mock server does not pad it and would reject a shorter example.

Raises `ArgumentError` if `:min` is not a positive integer, or if `opts`
has any key other than `:min`. Raises `FunctionClauseError` if `opts` is
not a list.

    iex> PactEx.Matchers.each_like("x", min: 2)
    %{"pact:matcher:type" => "type", "value" => ["x", "x"], "min" => 2}

# `include`

```elixir
@spec include(String.t()) :: t()
```

Matches any string that contains `substring`. `substring` is also the example.

    iex> PactEx.Matchers.include("ell")
    %{"pact:matcher:type" => "include", "value" => "ell"}

# `integer`

```elixir
@spec integer(integer()) :: t()
```

Matches any integer. `value` is the example.

    iex> PactEx.Matchers.integer(1)
    %{"pact:matcher:type" => "integer", "value" => 1}

# `like`

```elixir
@spec like(term()) :: t()
```

Matches any value of the same type as `value`.

    iex> PactEx.Matchers.like(1)
    %{"pact:matcher:type" => "type", "value" => 1}

# `regex`

```elixir
@spec regex(term(), String.t()) :: t()
```

Matches a value against the regular expression `pattern`. The value is
usually a string.

`value` is the example value. It should match `pattern`.

`value` is typed `term()` and not guarded, because a regex rule also applies
to values that are not strings. In a JSON body, `pact_matching` matches the
pattern against the string form of a number, a boolean or `null` (the text it
has in JSON: `42`, `1.5`, `true`, `null`), so `regex(42, "\d+")` is valid.
For a list or a map example, the pattern applies to each scalar inside it,
not to the JSON text of the whole list or map. Path and query values are
matched as strings.

    iex> PactEx.Matchers.regex("male", "(male|female)")
    %{"pact:matcher:type" => "regex", "value" => "male", "regex" => "(male|female)"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
