# Testing apps that use Refine

Refine keeps facet data up to date using database triggers. Because database 
triggers behave differently in the Ecto test sandbox, some adjustments to your test setup are required.

## Use the sandbox in :auto mode

Most Ecto test suites run the SQL sandbox in `:manual` mode, where each test runs inside a transaction
that is rolled back when the test finishes. That gives you clean isolation, but it doesn't
work for testing Refine's incremental updates.

The reason is that Refine's triggers and `Refine.merge_deltas/2` need to see committed data. Inside a rolled-back
transaction, the data your test writes is never committed, so the triggers don't behave the way they
would in production, and your assertions won't match.

So for tests that exercise facet updates, switch the sandbox to `:auto` mode:

```elixir
Ecto.Adapters.SQL.Sandbox.mode(YourApp.Repo, :auto)
```

This way your writes are committed, and the triggers function similar to production.

## Clean up between tests

The trade-off with `:auto` mode is that nothing is rolled back, so anything a test creates sticks around.
For Refine, that includes the triggers it installs on your tables. If one test creates a facets table
and the next runs without clearing it, those leftover triggers can fire during the second test and
quietly throw off its results - and because it depends on test order, the failures are intermittent and hard to track down.

### Clean up artifacts

Running a reset in a setup block guarantees that every test starts clean, regardless of how the previous
one ended - including tests that failed partway through.

You can drop every facets table you know your tests create, calling `drop_facets_table/2` for each:

```elixir
setup do
  for config <- my_test_configs() do
    Refine.drop_facets_table(config, repo: Repo)
  end

  :ok
end
```

If your tests create many facets tables, or you'd rather not maintain a list, you can instead discover and drop
Refine's artifacts using an included test helper function `Refine.TestHelpers.reset_facets_artifacts/1` that cleans up anything any test created:

```elixir
setup do
  Refine.TestHelpers.reset_facets_artifacts(repo: Repo) 
  :ok
end
```

### Clean up data

`Refine.TestHelpers.reset_facets_artifacts/1` removes the tables and triggers Refine created - but it deliberately
leaves your own data tables alone. 

Under `:auto` mode, every change a test makes is committed, so you also need to reset your data 
between tests, or changes from one test (a deleted row, an inserted record) will carry into the next.

Reset your data with `TRUNCATE ... RESTART IDENTITY CASCADE` to reset the auto-incrementing identity sequence:

```elixir
setup do
  Refine.TestHelpers.reset_facets_artifacts(repo: Repo)

  Repo.query!("""
    TRUNCATE articles, categories, article_categories
    RESTART IDENTITY CASCADE
  """)
  
  # ... insert fresh fixtures
  
  :ok
end
```