Initial commit: there's still tons of base Phoenix boilerplate to remove, but the...
[tech-radar-editor.git] / test / support / model_case.ex
1 defmodule TechRadarEditor.ModelCase do
2 @moduledoc """
3 This module defines the test case to be used by
4 model tests.
5
6 You may define functions here to be used as helpers in
7 your model tests. See `errors_on/2`'s definition as reference.
8
9 Finally, if the test case interacts with the database,
10 it cannot be async. For this reason, every test runs
11 inside a transaction which is reset at the beginning
12 of the test unless the test case is marked as async.
13 """
14
15 use ExUnit.CaseTemplate
16
17 using do
18 quote do
19 alias TechRadarEditor.Repo
20
21 import Ecto
22 import Ecto.Changeset
23 import Ecto.Query
24 import TechRadarEditor.ModelCase
25 end
26 end
27
28 setup tags do
29 :ok = Ecto.Adapters.SQL.Sandbox.checkout(TechRadarEditor.Repo)
30
31 unless tags[:async] do
32 Ecto.Adapters.SQL.Sandbox.mode(TechRadarEditor.Repo, {:shared, self()})
33 end
34
35 :ok
36 end
37
38 @doc """
39 Helper for returning list of errors in a struct when given certain data.
40
41 ## Examples
42
43 Given a User schema that lists `:name` as a required field and validates
44 `:password` to be safe, it would return:
45
46 iex> errors_on(%User{}, %{password: "password"})
47 [password: "is unsafe", name: "is blank"]
48
49 You could then write your assertion like:
50
51 assert {:password, "is unsafe"} in errors_on(%User{}, %{password: "password"})
52
53 You can also create the changeset manually and retrieve the errors
54 field directly:
55
56 iex> changeset = User.changeset(%User{}, password: "password")
57 iex> {:password, "is unsafe"} in changeset.errors
58 true
59 """
60 def errors_on(struct, data) do
61 struct.__struct__.changeset(struct, data)
62 |> Ecto.Changeset.traverse_errors(&TechRadarEditor.ErrorHelpers.translate_error/1)
63 |> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)
64 end
65 end