Testing apps that use Refine
Copy MarkdownRefine 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:
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:
setup do
for config <- my_test_configs() do
Refine.drop_facets_table(config, repo: Repo)
end
:ok
endIf 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:
setup do
Refine.TestHelpers.reset_facets_artifacts(repo: Repo)
:ok
endClean 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:
setup do
Refine.TestHelpers.reset_facets_artifacts(repo: Repo)
Repo.query!("""
TRUNCATE articles, categories, article_categories
RESTART IDENTITY CASCADE
""")
# ... insert fresh fixtures
:ok
end