# `Arc.Test`
[🔗](https://github.com/Cratis/Arc.Elixir/blob/main/lib/arc/test.ex#L4)

ExUnit support that runs the real Arc pipelines against Chronicle's in-memory kernel.

    defmodule MyApp.RegisterAuthorTest do
      use Arc.Test.Case,
        application: MyApp.Arc,
        event_types: [MyApp.Authors.AuthorRegistered]

      test "registers an author", %{arc: arc} do
        result = Arc.Test.execute(arc, %MyApp.Authors.RegisterAuthor{id: "...", name: "Ada"})

        Arc.Test.assert_success(result)
        Arc.Test.assert_appended(arc, MyApp.Authors.AuthorRegistered, event_source_id: "...")
      end
    end

Validation, authorization, binding and the Chronicle append all run for real; nothing is
mocked. Reactors and reducers run synchronously after each append, as in `Chronicle.Testing`.
Each test gets its own kernel, so `async: true` is safe.

# `assert_appended`

```elixir
@spec assert_appended(
  Arc.Test.Scenario.t(),
  struct() | module() | (struct() -&gt; boolean()),
  keyword()
) ::
  true
```

Asserts an event was appended. See `Chronicle.Testing.Assertions.assert_appended/3`.

# `assert_forbidden`

```elixir
@spec assert_forbidden(Arc.CommandResult.t() | Arc.QueryResult.t()) :: true
```

Asserts the caller was not authorized.

# `assert_invalid`

```elixir
@spec assert_invalid(Arc.CommandResult.t() | Arc.QueryResult.t(), atom() | nil) ::
  true
```

Asserts the result was rejected by validation, optionally for a member.

# `assert_success`

```elixir
@spec assert_success(Arc.CommandResult.t() | Arc.QueryResult.t()) :: true
```

Asserts the command succeeded: authorized, valid and without exceptions.

# `configure`

```elixir
@spec configure(module(), atom()) :: :ok
```

Points `application` at a Chronicle test client for the duration of the test, so code that reaches
the application's own configuration (the HTTP host, LiveView) uses it. Restores the previous
configuration when the test exits. Not safe with `async: true`: configuration is global.

# `execute`

```elixir
@spec execute(Arc.Test.Scenario.t(), struct() | {module(), map()}, keyword()) ::
  Arc.CommandResult.t()
```

Executes a command. Accepts the options of `Arc.execute/3`.

# `principal`

```elixir
@spec principal(String.t(), [String.t()]) :: Arc.Principal.t()
```

An authenticated principal.

# `query`

```elixir
@spec query(Arc.Test.Scenario.t(), module(), atom(), map(), keyword()) ::
  Arc.QueryResult.t()
```

Executes a query. Accepts the options of `Arc.query/5`.

# `refute_appended`

```elixir
@spec refute_appended(
  Arc.Test.Scenario.t(),
  struct() | module() | (struct() -&gt; boolean()),
  keyword()
) ::
  false
```

Asserts no matching event was appended.

# `scenario`

```elixir
@spec scenario(module(), atom()) :: Arc.Test.Scenario.t()
```

Builds a scenario for `application` using a Chronicle test client.

# `wait_for_observers`

```elixir
@spec wait_for_observers(Arc.Test.Scenario.t()) :: :ok
```

Waits until Chronicle's in-memory observers have processed every appended event.

---

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