diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e47e9788..80e245a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: Kaffy CI (Elixir) on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] jobs: test: @@ -12,20 +12,20 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - otp: ['22', '23', '24', '25'] - elixir: ['1.12.3', '1.13.4', '1.14.5', '1.15.5'] + otp: ["22", "23", "24", "25"] + elixir: ["1.12.3", "1.13.4", "1.14.5", "1.15.5"] # Exclude invalid combinations of Elixir and OTP exclude: - - otp: '22' - elixir: '1.14.5' - - otp: '22' - elixir: '1.15.5' - - otp: '23' - elixir: '1.15.5' - - otp: '25' - elixir: '1.12.3' - - otp: '25' - elixir: '1.13.4' + - otp: "22" + elixir: "1.14.5" + - otp: "22" + elixir: "1.15.5" + - otp: "23" + elixir: "1.15.5" + - otp: "25" + elixir: "1.12.3" + - otp: "25" + elixir: "1.13.4" # Include the release candidate for the next Elixir, but don't # fail CI. # include: @@ -34,19 +34,23 @@ jobs: # experimental: true steps: - - uses: actions/checkout@v3 - - name: Set up Elixir - uses: erlef/setup-beam@v1 - with: - elixir-version: ${{matrix.elixir}} # Define the elixir version [required] - otp-version: ${{matrix.otp}} # Define the OTP version [required] - - name: Restore dependencies cache - uses: actions/cache@v2 - with: - path: deps - key: ${{ runner.os }}-${{ matrix.elixir }}-${{ matrix.otp }}-mix-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-${{ matrix.elixir }}-${{ matrix.otp }}-mix- - - name: Install dependencies - run: mix deps.get - - name: Run tests - run: mix test + - uses: actions/checkout@v3 + - name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + elixir-version: ${{matrix.elixir}} # Define the elixir version [required] + otp-version: ${{matrix.otp}} # Define the OTP version [required] + - name: Restore dependencies cache + uses: actions/cache@v2 + with: + path: deps + key: ${{ runner.os }}-${{ matrix.elixir }}-${{ matrix.otp }}-mix-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-${{ matrix.elixir }}-${{ matrix.otp }}-mix- + - name: Setup Postgres Database + run: docker compose up -d + - name: Install dependencies + run: mix deps.get + - name: Run tests + env: + MIX_ENV: test + run: mix do test.setup, test diff --git a/config/config.exs b/config/config.exs index 76bc7561..4c8be053 100644 --- a/config/config.exs +++ b/config/config.exs @@ -2,3 +2,15 @@ import Config # Use Jason for JSON parsing in Phoenix # config :phoenix, :json_library, Jason + +config :kaffy, ecto_repos: [KaffyTest.Repo] + +config :logger, level: :warning + +config :kaffy, KaffyTest.Repo, + name: KaffyTest.Repo, + pool: Ecto.Adapters.SQL.Sandbox, + pool_size: System.schedulers_online() * 2, + priv: "test/support/postgres", + stacktrace: true, + url: "postgres://postgres:postgres@localhost:5432/kaffy_test" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..fcc40fa3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +name: "kaffy" + +services: + postgres: + image: postgres:16.2 + ports: + - "5432:5432" + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: kaffy_test diff --git a/mix.exs b/mix.exs index 099ffa85..7975d8d0 100644 --- a/mix.exs +++ b/mix.exs @@ -7,10 +7,16 @@ defmodule Kaffy.MixProject do def project do [ app: :kaffy, + aliases: aliases(), version: @version, elixir: "~> 1.12", compilers: Mix.compilers(), elixirc_paths: elixirc_paths(Mix.env()), + preferred_cli_env: [ + "test.reset": :test, + "test.setup": :test, + "ecto.gen.migration": :test + ], start_permanent: Mix.env() == :prod, description: description(), package: package(), @@ -29,20 +35,23 @@ defmodule Kaffy.MixProject do end # Specifies which paths to compile per environment. - defp elixirc_paths(:test), do: ["lib", "test/fixtures"] + defp elixirc_paths(:test), do: ["lib", "test/fixtures", "test/support"] defp elixirc_paths(_), do: ["lib"] # Run "mix help deps" to learn about dependencies. defp deps do [ + {:ex_machina, "~> 2.7.0", only: :test}, {:phoenix, "~> 1.7.10"}, {:phoenix_html, "~> 4.0"}, {:phoenix_html_helpers, "~> 1.0"}, {:phoenix_view, "~> 2.0.2"}, {:mock, "~> 0.3.3", only: :test}, {:ecto, "~> 3.0"}, + {:ecto_sql, "~> 3.10"}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, - {:jason, "~> 1.3", only: :test} + {:jason, "~> 1.3", only: :test}, + {:postgrex, "~> 0.16", optional: true} ] end @@ -77,4 +86,11 @@ defmodule Kaffy.MixProject do formatters: ["html"] ] end + + defp aliases do + [ + "test.reset": ["ecto.drop", "test.setup"], + "test.setup": ["ecto.create", "ecto.migrate"] + ] + end end diff --git a/mix.lock b/mix.lock index f8260d0b..7dae37bb 100644 --- a/mix.lock +++ b/mix.lock @@ -1,9 +1,12 @@ %{ "castore": {:hex, :castore, "1.0.5", "9eeebb394cc9a0f3ae56b813459f990abb0a3dedee1be6b27fdb50301930502f", [:mix], [], "hexpm", "8d7c597c3e4a64c395980882d4bca3cebb8d74197c590dc272cfd3b6a6310578"}, + "db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"}, "ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"}, + "ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"}, "ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"}, + "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, @@ -20,6 +23,7 @@ "phoenix_view": {:hex, :phoenix_view, "2.0.3", "4d32c4817fce933693741deeb99ef1392619f942633dde834a5163124813aad3", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "cd34049af41be2c627df99cd4eaa71fc52a328c0c3d8e7d4aa28f880c30e7f64"}, "plug": {:hex, :plug, "1.15.3", "712976f504418f6dff0a3e554c40d705a9bcf89a7ccef92fc6a5ef8f16a30a97", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2"}, "plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, + "postgrex": {:hex, :postgrex, "0.17.5", "0483d054938a8dc069b21bdd636bf56c487404c241ce6c319c1f43588246b281", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "50b8b11afbb2c4095a3ba675b4f055c416d0f3d7de6633a595fc131a828a67eb"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, diff --git a/test/fixtures/travel_schema.ex b/test/fixtures/travel_schema.ex index 60dd6cb3..f03b8f0f 100644 --- a/test/fixtures/travel_schema.ex +++ b/test/fixtures/travel_schema.ex @@ -25,7 +25,11 @@ defmodule Fixtures.TravelSchema do field(:description, :string) field(:number_of_people, :integer) field(:requires_passport, :boolean) - field(:travel_type, Ecto.Enum, values: [business: "business", leisure: "leisure", other: "undisclosed"]) + + field(:travel_type, Ecto.Enum, + values: [business: "business", leisure: "leisure", other: "undisclosed"] + ) + field(:start_time, :utc_datetime) field(:local_start_time, :naive_datetime) field(:end_date, :date) diff --git a/test/kaffy/resource_query_test.exs b/test/kaffy/resource_query_test.exs new file mode 100644 index 00000000..fbdecd5c --- /dev/null +++ b/test/kaffy/resource_query_test.exs @@ -0,0 +1,133 @@ +defmodule Kaffy.ResourceQueryTest do + use Kaffy.DataCase, async: false + + alias Kaffy.ResourceQuery + alias KaffyTest.Schemas.Pet + + defmodule PetAdmin do + end + + setup_all do + Application.put_env(:kaffy, :ecto_repo, KaffyTest.Repo) + + Application.put_env(:kaffy, :resources, fn _ -> + [ + admin: [ + name: "Pets", + resources: [ + pets: [ + schema: KaffyTest.Schemas.Pet, + admin: PetAdmin + ] + ] + ] + ] + end) + end + + setup do + conn = + build_conn() + |> Plug.Test.init_test_session(%{}) + |> Phoenix.Controller.fetch_flash([]) + |> Map.put(:query_params, %{}) + + [conn: conn] + end + + describe "list_resource/3" do + test "returns all resources", %{conn: conn} do + [pet1 | _pets] = insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + assert {3, pets} = ResourceQuery.list_resource(conn, resource, %{}) + assert Enum.any?(pets, fn %Pet{} = pet -> pet.id == pet1.id end) + end + + test "returns per_page limit", %{conn: conn} do + pets = insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + assert {3, [returned_pet]} = ResourceQuery.list_resource(conn, resource, %{"limit" => "1"}) + + pet_ids = Enum.map(pets, & &1.id) + assert Enum.member?(pet_ids, returned_pet.id) + end + + test "returns pages", %{conn: conn} do + pets = insert_list(3, :pet) + + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + + assert {3, [returned_pet1]} = + ResourceQuery.list_resource(conn, resource, %{"limit" => "1", "page" => "1"}) + + assert {3, [returned_pet2]} = + ResourceQuery.list_resource(conn, resource, %{"limit" => "1", "page" => "2"}) + + assert {3, [returned_pet3]} = + ResourceQuery.list_resource(conn, resource, %{"limit" => "1", "page" => "3"}) + + pet_ids = + Enum.map(pets, & &1.id) + |> Enum.sort() + + returned_pet_ids = + [returned_pet1.id, returned_pet2.id, returned_pet3.id] + |> Enum.sort() + + assert returned_pet_ids == pet_ids + end + + test "returns search results", %{conn: conn} do + insert_list(3, :pet) + pet = insert(:pet, name: "Fido") + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + + assert {1, [returned_pet]} = + ResourceQuery.list_resource(conn, resource, %{"search" => "Fido"}) + + assert returned_pet.id == pet.id + end + + test "returns no results when search does not match", %{conn: conn} do + insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + assert {0, []} = ResourceQuery.list_resource(conn, resource, %{"search" => "Fido"}) + end + + test "returns filter results", %{conn: conn} do + insert_list(3, :pet) + pet = insert(:pet, name: "Fido") + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + conn = Map.put(conn, :query_params, %{"person_id" => pet.person.id}) + assert {1, [returned_pet]} = ResourceQuery.list_resource(conn, resource, %{}) + assert returned_pet.id == pet.id + end + + test "returns no results when filter does not match", %{conn: conn} do + insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + conn = Map.put(conn, :query_params, %{"person_id" => "0"}) + assert {0, []} = ResourceQuery.list_resource(conn, resource, %{}) + end + + test "returns ordered results", %{conn: conn} do + pets = insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + conn = Map.put(conn, :query_params, %{"_of" => "id", "_ow" => "asc"}) + assert {3, returned_pets} = ResourceQuery.list_resource(conn, resource, %{}) + returned_pet_ids = Enum.map(returned_pets, & &1.id) + sorted_pet_ids = Enum.sort(Enum.map(pets, & &1.id)) + assert returned_pet_ids == sorted_pet_ids + end + + test "returns ordered results descending", %{conn: conn} do + pets = insert_list(3, :pet) + resource = Kaffy.Utils.get_resource(conn, "admin", "pets") + conn = Map.put(conn, :query_params, %{"_of" => "id", "_ow" => "desc"}) + assert {3, returned_pets} = ResourceQuery.list_resource(conn, resource, %{}) + returned_pet_ids = Enum.map(returned_pets, & &1.id) + sorted_pet_ids = Enum.reverse(Enum.sort(Enum.map(pets, & &1.id))) + assert returned_pet_ids == sorted_pet_ids + end + end +end diff --git a/test/resource_admin_test.exs b/test/resource_admin_test.exs index f17f3cfc..0314f4f5 100644 --- a/test/resource_admin_test.exs +++ b/test/resource_admin_test.exs @@ -32,9 +32,10 @@ defmodule Kaffy.ResourceAdminTest do end def deserialize_id(_schema, serialized_id) do - {person_id, pet_id} = serialized_id - |> Base.url_decode64!(padding: false) - |> :erlang.binary_to_term() + {person_id, pet_id} = + serialized_id + |> Base.url_decode64!(padding: false) + |> :erlang.binary_to_term() [person_id: person_id, pet_id: pet_id] end @@ -75,11 +76,17 @@ defmodule Kaffy.ResourceAdminTest do end test "serialize composite id" do - assert ResourceAdmin.serialize_id([schema: Owner, admin: OwnerAdmin], %{person_id: 1, pet_id: 2}) == "1:2" + assert ResourceAdmin.serialize_id([schema: Owner, admin: OwnerAdmin], %{ + person_id: 1, + pet_id: 2 + }) == "1:2" end test "custom serialization of composite key" do - assert ResourceAdmin.serialize_id([schema: Owner, admin: OwnerETFAdmin], %{person_id: 1, pet_id: 2}) == "g2gCYQFhAg" + assert ResourceAdmin.serialize_id([schema: Owner, admin: OwnerETFAdmin], %{ + person_id: 1, + pet_id: 2 + }) == "g2gCYQFhAg" end end @@ -89,14 +96,18 @@ defmodule Kaffy.ResourceAdminTest do end test "deserialize composite id" do - assert ResourceAdmin.deserialize_id([schema: Owner, admin: OwnerAdmin], "1:2") == [person_id: "1", pet_id: "2"] + assert ResourceAdmin.deserialize_id([schema: Owner, admin: OwnerAdmin], "1:2") == [ + person_id: "1", + pet_id: "2" + ] end test "custom deserialization of composite key" do - assert ResourceAdmin.deserialize_id([schema: Owner, admin: OwnerETFAdmin], "g2gCYQFhAg") == [person_id: 1, pet_id: 2] + assert ResourceAdmin.deserialize_id([schema: Owner, admin: OwnerETFAdmin], "g2gCYQFhAg") == + [person_id: 1, pet_id: 2] end end - + describe "index_description/1" do test "nil if index_description is not defined as function in admin" do refute ResourceAdmin.index_description(schema: Nested.Node, admin: NestedNodeAdmin) diff --git a/test/support/data_case.ex b/test/support/data_case.ex new file mode 100644 index 00000000..aa0ce152 --- /dev/null +++ b/test/support/data_case.ex @@ -0,0 +1,27 @@ +defmodule Kaffy.DataCase do + use ExUnit.CaseTemplate + + using do + quote do + import Ecto + import Ecto.Changeset + import Ecto.Query + import KaffyTest.Factory + import Phoenix.ConnTest + + alias KaffyTest.Repo + end + end + + setup tags do + start_supervised(KaffyTest.Repo) + + :ok = Ecto.Adapters.SQL.Sandbox.checkout(KaffyTest.Repo) + + unless tags[:async] do + Ecto.Adapters.SQL.Sandbox.mode(KaffyTest.Repo, {:shared, self()}) + end + + :ok + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex new file mode 100644 index 00000000..c8b85a1c --- /dev/null +++ b/test/support/factory.ex @@ -0,0 +1,39 @@ +defmodule KaffyTest.Factory do + use ExMachina.Ecto, repo: KaffyTest.Repo + + alias KaffyTest.Schemas.Company + alias KaffyTest.Schemas.Owner + alias KaffyTest.Schemas.Person + alias KaffyTest.Schemas.Pet + + def company_factory do + %Company{name: sequence(:company, &"Company #{&1}")} + end + + def person_factory do + age = Enum.random(21..100) + dob = Date.utc_today() |> Date.add(-age) + + %Person{ + name: sequence(:person, &"Person #{&1}"), + age: age, + married: Enum.random([true, false]), + birth_date: dob, + address: sequence(:address, &"Address #{&1}"), + company: build(:company) + } + end + + def pet_factory do + %Pet{ + name: sequence(:pet, &"Pet #{&1}"), + type: Enum.random(["feline", "canine", "avian"]), + weight: Decimal.new(Enum.random(1..100)), + person: build(:person) + } + end + + def owner_factory do + %Owner{} + end +end diff --git a/test/support/postgres/migrations/20240502162110_create_test_schemas.exs b/test/support/postgres/migrations/20240502162110_create_test_schemas.exs new file mode 100644 index 00000000..1535d2e6 --- /dev/null +++ b/test/support/postgres/migrations/20240502162110_create_test_schemas.exs @@ -0,0 +1,30 @@ +defmodule KaffyTest.Repo.Migrations.CreateTestSchemas do + use Ecto.Migration + + def change do + create table(:companies) do + add(:name, :string) + end + + create table(:people) do + add(:name, :string) + add(:age, :integer) + add(:married, :boolean, default: false) + add(:birth_date, :date) + add(:address, :string) + add(:company_id, references(:companies, on_delete: :nothing)) + end + + create table(:pets) do + add(:name, :string) + add(:type, :string, default: "feline") + add(:weight, :decimal) + add(:person_id, references(:people, on_delete: :nothing)) + end + + create table(:owner, primary_key: false) do + add(:person_id, references(:people, on_delete: :nothing)) + add(:pet_id, references(:pets, on_delete: :nothing)) + end + end +end diff --git a/test/support/repo.ex b/test/support/repo.ex new file mode 100644 index 00000000..54c94b69 --- /dev/null +++ b/test/support/repo.ex @@ -0,0 +1,3 @@ +defmodule KaffyTest.Repo do + use Ecto.Repo, otp_app: :kaffy, adapter: Ecto.Adapters.Postgres +end diff --git a/test/support/schemas.ex b/test/support/schemas.ex new file mode 100644 index 00000000..c810fbc8 --- /dev/null +++ b/test/support/schemas.ex @@ -0,0 +1,43 @@ +defmodule KaffyTest.Schemas.Person do + use Ecto.Schema + + schema "people" do + field(:name, :string) + field(:age, :integer) + field(:married, :boolean, default: false) + field(:birth_date, :date) + field(:address, :string) + has_many(:pets, KaffyTest.Schemas.Pet) + belongs_to(:company, KaffyTest.Schemas.Company) + end +end + +defmodule KaffyTest.Schemas.Pet do + use Ecto.Schema + + schema "pets" do + field(:name, :string) + field(:type, :string, default: "feline") + field(:weight, :decimal) + belongs_to(:person, KaffyTest.Schemas.Person) + end +end + +defmodule KaffyTest.Schemas.Company do + use Ecto.Schema + + schema "companies" do + field(:name, :string) + has_many(:people, KaffyTest.Schemas.Person) + end +end + +defmodule KaffyTest.Schemas.Owner do + use Ecto.Schema + + @primary_key false + schema "owner" do + field(:person_id, :id, primary_key: true) + field(:pet_id, :id, primary_key: true) + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs index 76ac6a04..276f683d 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,19 +1,6 @@ ExUnit.start() Application.put_env(:phoenix, :json_library, Jason) - -defmodule KaffyTest.Schemas.Person do - use Ecto.Schema - - schema "people" do - field(:name, :string) - field(:age, :integer) - field(:married, :boolean, default: false) - field(:birth_date, :date) - field(:address, :string) - has_many(:pets, KaffyTest.Schemas.Pet) - belongs_to(:company, KaffyTest.Schemas.Company) - end -end +{:ok, _} = Application.ensure_all_started(:ex_machina) defmodule KaffyTest.Admin.PersonAdmin do def index(_) do @@ -23,33 +10,3 @@ defmodule KaffyTest.Admin.PersonAdmin do ] end end - -defmodule KaffyTest.Schemas.Pet do - use Ecto.Schema - - schema "pets" do - field(:name, :string) - field(:type, :string, default: "feline") - field(:weight, :decimal) - belongs_to(:person, KaffyTest.Schemas.Person) - end -end - -defmodule KaffyTest.Schemas.Company do - use Ecto.Schema - - schema "companies" do - field(:name, :string) - has_many(:people, KaffyTest.Schemas.Person) - end -end - -defmodule KaffyTest.Schemas.Owner do - use Ecto.Schema - - @primary_key false - schema "owner" do - field :person_id, :id, primary_key: true - field :pet_id, :id, primary_key: true - end -end