# `Cauldron2D.Test`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d/lib/cauldron_2d/test.ex#L1)

Drives a `Cauldron2D.Game` in a test, with no world process and no clock: join
players, hold actions, run ticks, read views and events.

    driver = Cauldron2D.Test.new(MyGame, game_opts: [seed: 1], hz: 50)
    {:ok, driver} = Cauldron2D.Test.join(driver, :alice, %{username: "alice"})
    driver = driver |> Cauldron2D.Test.hold(:alice, [:thrust]) |> Cauldron2D.Test.tick(10)
    Cauldron2D.Test.view(driver, :alice)
    Cauldron2D.Test.events(driver)

A tick is what `Cauldron2D.World` does on one step: the input held since the last tick
is applied, the game steps by `1 / hz`, and its events are drained and kept, oldest
first. `until/3` ticks until a condition holds or a limit is reached.

# `t`

```elixir
@type t() :: %Cauldron2D.Test{
  dt: float(),
  events: [term()],
  game: module(),
  pending: %{required(term()) =&gt; Cauldron2D.Input.state()},
  state: term(),
  ticks: non_neg_integer()
}
```

# `events`

```elixir
@spec events(t()) :: [term()]
```

Every event drained so far, oldest first.

# `hold`

```elixir
@spec hold(t(), term(), [atom()], {number(), number()} | nil, %{
  required(atom()) =&gt; float()
}) :: t()
```

What player `id` holds from the next tick: a list of actions, an aim, and optionally how hard each action is held.

# `join`

```elixir
@spec join(t(), term(), map()) :: {:ok, t()} | {:error, term()}
```

Join player `id` with `props`; the game's refusal is returned as it gave it.

# `leave`

```elixir
@spec leave(t(), term()) :: t()
```

Player `id` leaves.

# `new`

```elixir
@spec new(module(), keyword()) :: t()
```

A driver for `game`; options `:game_opts` (default `[]`) and `:hz` (default `50`).

# `state`

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

The game's state.

# `tick`

```elixir
@spec tick(t(), pos_integer()) :: t()
```

Run `count` ticks.

# `tick_count`

```elixir
@spec tick_count(t()) :: non_neg_integer()
```

How many ticks have run.

# `until`

```elixir
@spec until(t(), (t() -&gt; boolean()), pos_integer()) :: {:ok, t()} | {:timeout, t()}
```

Tick until `condition` holds of the driver, at most `limit` times; `{:timeout, driver}` when it never did.

# `view`

```elixir
@spec view(t(), term()) :: term()
```

The game's view for player `id` now.

---

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