From 04d798aaa7c1ba7d34ab6934d41a2606ad3d4ddf Mon Sep 17 00:00:00 2001 From: shibao Date: Sat, 22 Jan 2022 21:40:29 -0500 Subject: [PATCH] fix dialyzer, credo and format --- lib/cannery/accounts.ex | 87 ++++++++++--------- lib/cannery/accounts/user.ex | 48 +++++----- lib/cannery/accounts/user_notifier.ex | 4 + lib/cannery/accounts/user_token.ex | 48 +++++++--- lib/cannery/ammo/ammo_group.ex | 7 ++ lib/cannery/ammo/ammo_type.ex | 6 ++ lib/cannery/containers.ex | 37 ++++---- lib/cannery/containers/container.ex | 22 +++-- lib/cannery/containers/container_tag.ex | 18 ++-- lib/cannery/invites.ex | 20 ++--- lib/cannery/invites/invite.ex | 24 +++-- lib/cannery/mailer.ex | 4 + lib/cannery/release.ex | 6 ++ lib/cannery/repo/migrator.ex | 4 + lib/cannery/tags/tag.ex | 21 +++-- lib/cannery_web/component/topbar.ex | 8 +- lib/cannery_web/controllers/user_auth.ex | 11 ++- .../live/ammo_group_live/form_component.ex | 4 + lib/cannery_web/live/ammo_group_live/index.ex | 4 + lib/cannery_web/live/ammo_group_live/show.ex | 4 + .../live/ammo_type_live/form_component.ex | 4 + lib/cannery_web/live/ammo_type_live/index.ex | 4 + lib/cannery_web/live/ammo_type_live/show.ex | 4 + .../live/container_live/form_component.ex | 4 + lib/cannery_web/live/container_live/index.ex | 4 + lib/cannery_web/live/container_live/show.ex | 4 + lib/cannery_web/live/home_live.ex | 6 +- .../live/invite_live/form_component.ex | 4 + lib/cannery_web/live/invite_live/index.ex | 8 +- lib/cannery_web/live/live_helpers.ex | 6 +- lib/cannery_web/live/modal_component.ex | 4 + .../live/tag_live/form_component.ex | 6 +- lib/cannery_web/live/tag_live/index.ex | 4 + lib/cannery_web/telemetry.ex | 4 + lib/cannery_web/views/layout_view.ex | 4 +- test/support/channel_case.ex | 5 +- test/support/conn_case.ex | 5 +- test/support/data_case.ex | 5 +- test/support/fixtures/accounts_fixtures.ex | 2 +- 39 files changed, 331 insertions(+), 143 deletions(-) diff --git a/lib/cannery/accounts.ex b/lib/cannery/accounts.ex index d453473..1a1725e 100644 --- a/lib/cannery/accounts.ex +++ b/lib/cannery/accounts.ex @@ -4,8 +4,9 @@ defmodule Cannery.Accounts do """ import Ecto.Query, warn: false - alias Cannery.{Repo} - alias Cannery.Accounts.{User, UserToken, UserNotifier} + alias Cannery.Repo + alias Cannery.Accounts.{User, UserNotifier, UserToken} + alias Ecto.{Changeset, Multi} ## Database getters @@ -89,10 +90,10 @@ defmodule Cannery.Accounts do {:ok, %User{}} iex> register_user(%{field: bad_value}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ - @spec register_user(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} + @spec register_user(map()) :: {:ok, User.t()} | {:error, Changeset.t()} def register_user(attrs) do # if no registered users, make first user an admin attrs = @@ -104,15 +105,16 @@ defmodule Cannery.Accounts do end @doc """ - Returns an `%Ecto.Changeset{}` for tracking user changes. + Returns an `%Changeset{}` for tracking user changes. ## Examples iex> change_user_registration(user) - %Ecto.Changeset{data: %User{}} + %Changeset{data: %User{}} """ - @spec change_user_registration(User.t(), map()) :: Ecto.Changeset.t() + @spec change_user_registration(User.t() | User.new_user()) :: Changeset.t() + @spec change_user_registration(User.t() | User.new_user(), map()) :: Changeset.t() def change_user_registration(user, attrs \\ %{}) do User.registration_changeset(user, attrs, hash_password: false) end @@ -120,29 +122,29 @@ defmodule Cannery.Accounts do ## Settings @doc """ - Returns an `%Ecto.Changeset{}` for changing the user email. + Returns an `%Changeset{}` for changing the user email. ## Examples iex> change_user_email(user) - %Ecto.Changeset{data: %User{}} + %Changeset{data: %User{}} """ - @spec change_user_email(User.t(), map()) :: Ecto.Changeset.t() + @spec change_user_email(User.t(), map()) :: Changeset.t() def change_user_email(user, attrs \\ %{}) do User.email_changeset(user, attrs) end @doc """ - Returns an `%Ecto.Changeset{}` for changing the user role. + Returns an `%Changeset{}` for changing the user role. ## Examples iex> change_user_role(user) - %Ecto.Changeset{data: %User{}} + %Changeset{data: %User{}} """ - @spec change_user_role(User.t(), atom()) :: Ecto.Changeset.t() + @spec change_user_role(User.t(), atom()) :: Changeset.t() def change_user_role(user, role) do User.role_changeset(user, role) end @@ -157,16 +159,16 @@ defmodule Cannery.Accounts do {:ok, %User{}} iex> apply_user_email(user, "invalid password", %{email: ...}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ @spec apply_user_email(User.t(), String.t(), map()) :: - {:ok, User.t()} | {:error, Ecto.Changeset.t()} + {:ok, User.t()} | {:error, Changeset.t()} def apply_user_email(user, password, attrs) do user |> User.email_changeset(attrs) |> User.validate_current_password(password) - |> Ecto.Changeset.apply_action(:update) + |> Changeset.apply_action(:update) end @doc """ @@ -175,7 +177,7 @@ defmodule Cannery.Accounts do If the token matches, the user email is updated and the token is deleted. The confirmed_at date is also updated to the current time. """ - @spec update_user_email(User.t(), UserToken.t()) :: {:ok, any()} | :error + @spec update_user_email(User.t(), String.t()) :: :ok | :error def update_user_email(user, token) do context = "change:#{user.email}" @@ -188,12 +190,13 @@ defmodule Cannery.Accounts do end end + @spec user_email_multi(User.t(), String.t(), String.t()) :: Multi.t() defp user_email_multi(user, email, context) do changeset = user |> User.email_changeset(%{email: email}) |> User.confirm_changeset() - Ecto.Multi.new() - |> Ecto.Multi.update(:user, changeset) - |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, [context])) + Multi.new() + |> Multi.update(:user, changeset) + |> Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, [context])) end @doc """ @@ -216,15 +219,15 @@ defmodule Cannery.Accounts do end @doc """ - Returns an `%Ecto.Changeset{}` for changing the user password. + Returns an `%Changeset{}` for changing the user password. ## Examples iex> change_user_password(user) - %Ecto.Changeset{data: %User{}} + %Changeset{data: %User{}} """ - @spec change_user_password(User.t(), map()) :: Ecto.Changeset.t() + @spec change_user_password(User.t(), map()) :: Changeset.t() def change_user_password(user, attrs \\ %{}) do User.password_changeset(user, attrs, hash_password: false) end @@ -238,20 +241,20 @@ defmodule Cannery.Accounts do {:ok, %User{}} iex> update_user_password(user, "invalid password", %{password: ...}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ @spec update_user_password(User.t(), String.t(), map()) :: - {:ok, User.t()} | {:error, Ecto.Changeset.t()} + {:ok, User.t()} | {:error, Changeset.t()} def update_user_password(user, password, attrs) do changeset = user |> User.password_changeset(attrs) |> User.validate_current_password(password) - Ecto.Multi.new() - |> Ecto.Multi.update(:user, changeset) - |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) + Multi.new() + |> Multi.update(:user, changeset) + |> Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) |> Repo.transaction() |> case do {:ok, %{user: user}} -> {:ok, user} @@ -269,7 +272,7 @@ defmodule Cannery.Accounts do @doc """ Generates a session token. """ - @spec generate_user_session_token(User.t()) :: UserToken.t() + @spec generate_user_session_token(User.t()) :: String.t() def generate_user_session_token(user) do {token, user_token} = UserToken.build_session_token(user) Repo.insert!(user_token) @@ -279,7 +282,7 @@ defmodule Cannery.Accounts do @doc """ Gets the user with the given signed token. """ - @spec get_user_by_session_token(UserToken.t()) :: User.t() + @spec get_user_by_session_token(String.t()) :: User.t() def get_user_by_session_token(token) do {:ok, query} = UserToken.verify_session_token_query(token) Repo.one(query) @@ -288,7 +291,7 @@ defmodule Cannery.Accounts do @doc """ Deletes the signed token with the given context. """ - @spec delete_session_token(UserToken.t()) :: :ok + @spec delete_session_token(String.t()) :: :ok def delete_session_token(token) do Repo.delete_all(UserToken.token_and_context_query(token, "session")) :ok @@ -298,7 +301,7 @@ defmodule Cannery.Accounts do Returns a boolean if registration is allowed or not """ @spec allow_registration?() :: boolean() - def allow_registration?() do + def allow_registration? do Application.get_env(:cannery, CanneryWeb.Endpoint)[:registration] == "public" or list_users_by_role(:admin) |> Enum.empty?() end @@ -336,7 +339,7 @@ defmodule Cannery.Accounts do If the token matches, the user account is marked as confirmed and the token is deleted. """ - @spec confirm_user(UserToken.t()) :: {:ok, User.t()} | atom() + @spec confirm_user(String.t()) :: {:ok, User.t()} | atom() def confirm_user(token) do with {:ok, query} <- UserToken.verify_email_token_query(token, "confirm"), %User{} = user <- Repo.one(query), @@ -348,9 +351,9 @@ defmodule Cannery.Accounts do end defp confirm_user_multi(user) do - Ecto.Multi.new() - |> Ecto.Multi.update(:user, User.confirm_changeset(user)) - |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, ["confirm"])) + Multi.new() + |> Multi.update(:user, User.confirm_changeset(user)) + |> Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, ["confirm"])) end ## Reset password @@ -385,7 +388,7 @@ defmodule Cannery.Accounts do nil """ - @spec get_user_by_reset_password_token(UserToken.t()) :: User.t() | nil + @spec get_user_by_reset_password_token(String.t()) :: User.t() | nil def get_user_by_reset_password_token(token) do with {:ok, query} <- UserToken.verify_email_token_query(token, "reset_password"), %User{} = user <- Repo.one(query) do @@ -404,14 +407,14 @@ defmodule Cannery.Accounts do {:ok, %User{}} iex> reset_user_password(user, %{password: "valid", password_confirmation: "not the same"}) - {:error, %Ecto.Changeset{}} + {:error, %Changeset{}} """ - @spec reset_user_password(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} + @spec reset_user_password(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} def reset_user_password(user, attrs) do - Ecto.Multi.new() - |> Ecto.Multi.update(:user, User.password_changeset(user, attrs)) - |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) + Multi.new() + |> Multi.update(:user, User.password_changeset(user, attrs)) + |> Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) |> Repo.transaction() |> case do {:ok, %{user: user}} -> {:ok, user} diff --git a/lib/cannery/accounts/user.ex b/lib/cannery/accounts/user.ex index 1e8af2d..8ef2253 100644 --- a/lib/cannery/accounts/user.ex +++ b/lib/cannery/accounts/user.ex @@ -1,8 +1,12 @@ defmodule Cannery.Accounts.User do + @moduledoc """ + A cannery user + """ + use Ecto.Schema import Ecto.Changeset - alias Cannery.Accounts.{User} - alias Cannery.Invites.{Invite} + alias Ecto.{Changeset, UUID} + alias Cannery.{Accounts.User, Invites.Invite} @derive {Inspect, except: [:password]} @primary_key {:id, :binary_id, autogenerate: true} @@ -19,8 +23,8 @@ defmodule Cannery.Accounts.User do timestamps() end - @type t :: %{ - id: Ecto.UUID.t(), + @type t :: %User{ + id: UUID.t(), email: String.t(), password: String.t(), hashed_password: String.t(), @@ -31,6 +35,8 @@ defmodule Cannery.Accounts.User do updated_at: NaiveDateTime.t() } + @type new_user :: %User{} + @doc """ A user changeset for registration. @@ -48,8 +54,8 @@ defmodule Cannery.Accounts.User do validations on a LiveView form), this option can be set to `false`. Defaults to `true`. """ - @spec registration_changeset(User.t(), map()) :: Ecto.Changeset.t() - @spec registration_changeset(User.t(), map(), keyword()) :: Ecto.Changeset.t() + @spec registration_changeset(User.t() | User.new_user(), map()) :: Changeset.t() + @spec registration_changeset(User.t() | User.new_user(), map(), keyword()) :: Changeset.t() def registration_changeset(user, attrs, opts \\ []) do user |> cast(attrs, [:email, :password, :role]) @@ -61,12 +67,12 @@ defmodule Cannery.Accounts.User do A user changeset for role. """ - @spec role_changeset(User.t(), atom()) :: Ecto.Changeset.t() + @spec role_changeset(User.t(), atom()) :: Changeset.t() def role_changeset(user, role) do user |> cast(%{"role" => role}, [:role]) end - @spec validate_email(Ecto.Changeset.t()) :: Ecto.Changeset.t() + @spec validate_email(Changeset.t()) :: Changeset.t() defp validate_email(changeset) do changeset |> validate_required([:email]) @@ -76,7 +82,7 @@ defmodule Cannery.Accounts.User do |> unique_constraint(:email) end - @spec validate_password(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t() + @spec validate_password(Changeset.t(), keyword()) :: Changeset.t() defp validate_password(changeset, opts) do changeset |> validate_required([:password]) @@ -87,7 +93,7 @@ defmodule Cannery.Accounts.User do |> maybe_hash_password(opts) end - @spec maybe_hash_password(Ecto.Changeset.t(), keyword()) :: Ecto.Changeset.t() + @spec maybe_hash_password(Changeset.t(), keyword()) :: Changeset.t() defp maybe_hash_password(changeset, opts) do hash_password? = Keyword.get(opts, :hash_password, true) password = get_change(changeset, :password) @@ -106,7 +112,7 @@ defmodule Cannery.Accounts.User do It requires the email to change otherwise an error is added. """ - @spec email_changeset(User.t(), map()) :: Ecto.Changeset.t() + @spec email_changeset(User.t(), map()) :: Changeset.t() def email_changeset(user, attrs) do user |> cast(attrs, [:email]) @@ -129,8 +135,8 @@ defmodule Cannery.Accounts.User do validations on a LiveView form), this option can be set to `false`. Defaults to `true`. """ - @spec password_changeset(User.t(), map()) :: Ecto.Changeset.t() - @spec password_changeset(User.t(), map(), keyword()) :: Ecto.Changeset.t() + @spec password_changeset(User.t(), map()) :: Changeset.t() + @spec password_changeset(User.t(), map(), keyword()) :: Changeset.t() def password_changeset(user, attrs, opts \\ []) do user |> cast(attrs, [:password]) @@ -141,10 +147,10 @@ defmodule Cannery.Accounts.User do @doc """ Confirms the account by setting `confirmed_at`. """ - @spec confirm_changeset(User.t()) :: Ecto.Changeset.t() - def confirm_changeset(user) do + @spec confirm_changeset(User.t() | Changeset.t()) :: Changeset.t() + def confirm_changeset(user_or_changeset) do now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) - change(user, confirmed_at: now) + user_or_changeset |> change(confirmed_at: now) end @doc """ @@ -167,12 +173,10 @@ defmodule Cannery.Accounts.User do @doc """ Validates the current password otherwise adds an error to the changeset. """ - @spec validate_current_password(Ecto.Changeset.t(), String.t()) :: Ecto.UUID.t() + @spec validate_current_password(Changeset.t(), String.t()) :: Changeset.t() def validate_current_password(changeset, password) do - if valid_password?(changeset.data, password) do - changeset - else - add_error(changeset, :current_password, "is not valid") - end + if valid_password?(changeset.data, password), + do: changeset, + else: changeset |> add_error(:current_password, "is not valid") end end diff --git a/lib/cannery/accounts/user_notifier.ex b/lib/cannery/accounts/user_notifier.ex index 6a5b474..f4c5360 100644 --- a/lib/cannery/accounts/user_notifier.ex +++ b/lib/cannery/accounts/user_notifier.ex @@ -1,4 +1,8 @@ defmodule Cannery.Accounts.UserNotifier do + @moduledoc """ + Contains all user emails and notifications + """ + # For simplicity, this module simply logs messages to the terminal. # You should replace it by a proper email or notification tool, such as: # diff --git a/lib/cannery/accounts/user_token.ex b/lib/cannery/accounts/user_token.ex index 5ecdf23..9c359b8 100644 --- a/lib/cannery/accounts/user_token.ex +++ b/lib/cannery/accounts/user_token.ex @@ -1,7 +1,12 @@ defmodule Cannery.Accounts.UserToken do + @moduledoc """ + Schema for serialized user session and authentication tokens + """ + use Ecto.Schema import Ecto.Query - alias Cannery.{Accounts} + alias Ecto.{Query, UUID} + alias Cannery.{Accounts.User, Accounts.UserToken} @hash_algorithm :sha256 @rand_size 32 @@ -19,19 +24,33 @@ defmodule Cannery.Accounts.UserToken do field :token, :binary field :context, :string field :sent_to, :string - belongs_to :user, Accounts.User + + belongs_to :user, User timestamps(updated_at: false) end + @type t :: %UserToken{ + id: UUID.t(), + token: String.t(), + context: String.t(), + sent_to: String.t(), + user: User.t(), + user_id: UUID.t(), + inserted_at: NaiveDateTime.t() + } + + @type new_token :: %UserToken{} + @doc """ Generates a token that will be stored in a signed place, such as session or cookie. As they are signed, those tokens do not need to be hashed. """ - def build_session_token(user) do + @spec build_session_token(User.t()) :: {token :: String.t(), UserToken.new_token()} + def build_session_token(%{id: user_id}) do token = :crypto.strong_rand_bytes(@rand_size) - {token, %Accounts.UserToken{token: token, context: "session", user_id: user.id}} + {token, %UserToken{token: token, context: "session", user_id: user_id}} end @doc """ @@ -39,6 +58,7 @@ defmodule Cannery.Accounts.UserToken do The query returns the user found by the token. """ + @spec verify_session_token_query(String.t()) :: {:ok, Query.t()} def verify_session_token_query(token) do query = from token in token_and_context_query(token, "session"), @@ -57,16 +77,19 @@ defmodule Cannery.Accounts.UserToken do The token is valid for a week as long as users don't change their email. """ + @spec build_email_token(User.t(), String.t()) :: {String.t(), UserToken.new_token()} def build_email_token(user, context) do build_hashed_token(user, context, user.email) end + @spec build_hashed_token(User.t(), String.t(), String.t()) :: + {String.t(), UserToken.new_token()} defp build_hashed_token(user, context, sent_to) do token = :crypto.strong_rand_bytes(@rand_size) hashed_token = :crypto.hash(@hash_algorithm, token) {Base.url_encode64(token, padding: false), - %Accounts.UserToken{ + %UserToken{ token: hashed_token, context: context, sent_to: sent_to, @@ -79,6 +102,7 @@ defmodule Cannery.Accounts.UserToken do The query returns the user found by the token. """ + @spec verify_email_token_query(String.t(), String.t()) :: {:ok, Query.t()} | :error def verify_email_token_query(token, context) do case Base.url_decode64(token, padding: false) do {:ok, decoded_token} -> @@ -98,6 +122,7 @@ defmodule Cannery.Accounts.UserToken do end end + @spec days_for_context(<<_::56>>) :: non_neg_integer() defp days_for_context("confirm"), do: @confirm_validity_in_days defp days_for_context("reset_password"), do: @reset_password_validity_in_days @@ -106,6 +131,7 @@ defmodule Cannery.Accounts.UserToken do The query returns the user token record. """ + @spec verify_change_email_token_query(String.t(), String.t()) :: {:ok, Query.t()} | :error def verify_change_email_token_query(token, context) do case Base.url_decode64(token, padding: false) do {:ok, decoded_token} -> @@ -125,18 +151,20 @@ defmodule Cannery.Accounts.UserToken do @doc """ Returns the given token with the given context. """ + @spec token_and_context_query(String.t(), String.t()) :: Query.t() + @spec token_and_context_query(User.t(), :all | nonempty_maybe_improper_list()) :: Query.t() def token_and_context_query(token, context) do - from Accounts.UserToken, where: [token: ^token, context: ^context] + from UserToken, where: [token: ^token, context: ^context] end @doc """ Gets all tokens for the given user for the given contexts. """ - def user_and_contexts_query(user, :all) do - from t in Accounts.UserToken, where: t.user_id == ^user.id + def user_and_contexts_query(%{id: user_id}, :all) do + from t in UserToken, where: t.user_id == ^user_id end - def user_and_contexts_query(user, [_ | _] = contexts) do - from t in Accounts.UserToken, where: t.user_id == ^user.id and t.context in ^contexts + def user_and_contexts_query(%{id: user_id}, [_ | _] = contexts) do + from t in UserToken, where: t.user_id == ^user_id and t.context in ^contexts end end diff --git a/lib/cannery/ammo/ammo_group.ex b/lib/cannery/ammo/ammo_group.ex index 247ac45..1478e56 100644 --- a/lib/cannery/ammo/ammo_group.ex +++ b/lib/cannery/ammo/ammo_group.ex @@ -1,4 +1,11 @@ defmodule Cannery.Ammo.AmmoGroup do + @moduledoc """ + A group of a certain ammunition type. + + Can be placed in a container, and contains auxiliary information such as the + amount paid for that ammunition, or what condition it is in + """ + use Ecto.Schema import Ecto.Changeset alias Cannery.{Accounts, Ammo, Containers, Tags} diff --git a/lib/cannery/ammo/ammo_type.ex b/lib/cannery/ammo/ammo_type.ex index e2c4ebb..bfe67af 100644 --- a/lib/cannery/ammo/ammo_type.ex +++ b/lib/cannery/ammo/ammo_type.ex @@ -1,4 +1,10 @@ defmodule Cannery.Ammo.AmmoType do + @moduledoc """ + An ammunition type. + + Contains statistical information about the ammunition. + """ + use Ecto.Schema import Ecto.Changeset diff --git a/lib/cannery/containers.ex b/lib/cannery/containers.ex index e47bf10..1d4ea21 100644 --- a/lib/cannery/containers.ex +++ b/lib/cannery/containers.ex @@ -4,9 +4,8 @@ defmodule Cannery.Containers do """ import Ecto.Query, warn: false - alias Cannery.Repo - - alias Cannery.Containers.Container + alias Cannery.{Containers.Container, Repo} + alias Ecto.{Changeset, UUID} @doc """ Returns the list of containers. @@ -17,6 +16,7 @@ defmodule Cannery.Containers do [%Container{}, ...] """ + @spec list_containers() :: [Container.t()] def list_containers do Repo.all(Container) end @@ -35,6 +35,7 @@ defmodule Cannery.Containers do ** (Ecto.NoResultsError) """ + @spec get_container!(container_id :: UUID.t()) :: Container.t() def get_container!(id), do: Repo.get!(Container, id) @doc """ @@ -49,10 +50,9 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - def create_container(attrs \\ %{}) do - %Container{} - |> Container.changeset(attrs) - |> Repo.insert() + @spec create_container(attrs :: map()) :: {:ok, Container.t()} | {:error, Changeset.t()} + def create_container(attrs) do + %Container{} |> Container.changeset(attrs) |> Repo.insert() end @doc """ @@ -67,10 +67,10 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - def update_container(%Container{} = container, attrs) do - container - |> Container.changeset(attrs) - |> Repo.update() + @spec update_container(Container.t() | Ecto.Changeset.t(), map()) :: + {:ok, Container.t()} | {:error, Ecto.Changeset.t()} + def update_container(container, attrs) do + container |> Container.changeset(attrs) |> Repo.update() end @doc """ @@ -85,9 +85,9 @@ defmodule Cannery.Containers do {:error, %Ecto.Changeset{}} """ - def delete_container(%Container{} = container) do - Repo.delete(container) - end + @spec delete_container(Container.t() | Ecto.Changeset.t()) :: + {:ok, Container.t()} | {:error, Ecto.Changeset.t()} + def delete_container(container), do: Repo.delete(container) @doc """ Returns an `%Ecto.Changeset{}` for tracking container changes. @@ -97,8 +97,11 @@ defmodule Cannery.Containers do iex> change_container(container) %Ecto.Changeset{data: %Container{}} + iex> change_container(%Ecto.Changeset{}) + %Ecto.Changeset{data: %Container{}} + """ - def change_container(%Container{} = container, attrs \\ %{}) do - Container.changeset(container, attrs) - end + @spec change_container(Container.t()) :: Changeset.t() + @spec change_container(Container.t(), map()) :: Changeset.t() + def change_container(container, attrs \\ %{}), do: container |> Container.changeset(attrs) end diff --git a/lib/cannery/containers/container.ex b/lib/cannery/containers/container.ex index 019550c..59247a1 100644 --- a/lib/cannery/containers/container.ex +++ b/lib/cannery/containers/container.ex @@ -1,7 +1,12 @@ defmodule Cannery.Containers.Container do + @moduledoc """ + A container that holds ammunition and belongs to a user. + """ + use Ecto.Schema import Ecto.Changeset - alias Cannery.{Accounts} + alias Ecto.{Changeset, UUID} + alias Cannery.{Accounts.User, Containers.Container} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id @@ -11,27 +16,30 @@ defmodule Cannery.Containers.Container do field :location, :string field :type, :string - belongs_to :user, Accounts.User + belongs_to :user, User timestamps() end - @type t :: %{ - id: Ecto.UUID.t(), + @type t :: %Container{ + id: UUID.t(), name: String.t(), desc: String.t(), location: String.t(), type: String.t(), - user: Accounts.User.t(), - user_id: Ecto.UUID.t(), + user: User.t(), + user_id: UUID.t(), inserted_at: NaiveDateTime.t(), updated_at: NaiveDateTime.t() } + @type new_container :: %Container{} + @doc false + @spec changeset(Container.t() | Container.new_container(), map()) :: Changeset.t() def changeset(container, attrs) do container |> cast(attrs, [:name, :desc, :type, :location, :user_id]) - |> validate_required([:name, :desc, :type, :location, :user_id]) + |> validate_required([:name, :type, :user_id]) end end diff --git a/lib/cannery/containers/container_tag.ex b/lib/cannery/containers/container_tag.ex index b88b506..abc58a1 100644 --- a/lib/cannery/containers/container_tag.ex +++ b/lib/cannery/containers/container_tag.ex @@ -1,28 +1,34 @@ defmodule Cannery.Containers.ContainerTag do + @moduledoc """ + Thru-table struct for associating Cannery.Containers.Container and + Cannery.Tags.Tag. + """ + use Ecto.Schema import Ecto.Changeset - alias Cannery.{Containers, Tags} + alias Cannery.{Containers.Container, Containers.ContainerTag, Tags.Tag} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "container_tags" do - belongs_to :container, Containers.Container - belongs_to :tag, Tags.Tag + belongs_to :container, Container + belongs_to :tag, Tag timestamps() end - @type t :: %{ + @type t :: %ContainerTag{ id: Ecto.UUID.t(), - container: Containers.Container.t(), + container: Container.t(), container_id: Ecto.UUID.t(), - tag: Tags.Tag.t(), + tag: Tag.t(), tag_id: Ecto.UUID.t(), inserted_at: NaiveDateTime.t(), updated_at: NaiveDateTime.t() } @doc false + @spec changeset(ContainerTag.t(), map()) :: Ecto.Changeset.t() def changeset(container_tag, attrs) do container_tag |> cast(attrs, [:tag_id, :container_id]) diff --git a/lib/cannery/invites.ex b/lib/cannery/invites.ex index 9e95aae..1399802 100644 --- a/lib/cannery/invites.ex +++ b/lib/cannery/invites.ex @@ -4,8 +4,8 @@ defmodule Cannery.Invites do """ import Ecto.Query, warn: false - alias Cannery.{Accounts, Repo} - alias Cannery.Invites.Invite + alias Ecto.{Changeset, UUID} + alias Cannery.{Accounts.User, Invites.Invite, Repo} @invite_token_length 20 @@ -49,7 +49,7 @@ defmodule Cannery.Invites do iex> get_invite_by_token("invalid_token") nil """ - @spec get_invite_by_token(String.t()) :: Invite.t() | nil + @spec get_invite_by_token(String.t() | nil) :: Invite.t() | nil def get_invite_by_token(nil), do: nil def get_invite_by_token(""), do: nil @@ -86,22 +86,22 @@ defmodule Cannery.Invites do ## Examples - iex> create_invite(%Accounts.User{id: "1"}, %{field: value}) + iex> create_invite(%User{id: "1"}, %{field: value}) {:ok, %Invite{}} iex> create_invite("1", %{field: value}) {:ok, %Invite{}} - iex> create_invite(%Accounts.User{id: "1"}, %{field: bad_value}) + iex> create_invite(%User{id: "1"}, %{field: bad_value}) {:error, %Ecto.Changeset{}} """ - @spec create_invite(user_or_user_id :: Accounts.User.t() | Ecto.UUID.t(), attrs :: map()) :: - Invite.t() - def create_invite(%{id: user_id}, attrs) do - create_invite(user_id, attrs) - end + @spec create_invite(user :: User.t(), attrs :: map()) :: + {:ok, Invite.t()} | {:error, Changeset.t()} + def create_invite(%{id: user_id}, attrs), do: create_invite(user_id, attrs) + @spec create_invite(user_id :: UUID.t(), attrs :: map()) :: + {:ok, Invite.t()} | {:error, Changeset.t()} def create_invite(user_id, attrs) when not (user_id |> is_nil()) do attrs = attrs diff --git a/lib/cannery/invites/invite.ex b/lib/cannery/invites/invite.ex index b9107a4..506abda 100644 --- a/lib/cannery/invites/invite.ex +++ b/lib/cannery/invites/invite.ex @@ -1,7 +1,14 @@ defmodule Cannery.Invites.Invite do + @moduledoc """ + An invite, created by an admin to allow someone to join their instance. An + invite can be enabled or disabled, and can have an optional number of uses if + `:uses_left` is defined. + """ + use Ecto.Schema import Ecto.Changeset - alias Cannery.{Accounts} + alias Ecto.{Changeset, UUID} + alias Cannery.{Accounts.User, Invites.Invite} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id @@ -11,22 +18,27 @@ defmodule Cannery.Invites.Invite do field :uses_left, :integer, default: nil field :disabled_at, :naive_datetime - belongs_to :user, Accounts.User + belongs_to :user, User timestamps() end - @type t :: %{ - id: Ecto.UUID.t(), + @type t :: %Invite{ + id: UUID.t(), name: String.t(), token: String.t(), uses_left: integer() | nil, disabled_at: NaiveDateTime.t(), - user: Accounts.User.t(), - user_id: Ecto.UUID.t() + user: User.t(), + user_id: UUID.t(), + inserted_at: NaiveDateTime.t(), + updated_at: NaiveDateTime.t() } + @type new_invite :: %Invite{} + @doc false + @spec changeset(Invite.t() | Invite.new_invite(), map()) :: Changeset.t() def changeset(invite, attrs) do invite |> cast(attrs, [:name, :token, :uses_left, :disabled_at, :user_id]) diff --git a/lib/cannery/mailer.ex b/lib/cannery/mailer.ex index b1cad17..ee9a784 100644 --- a/lib/cannery/mailer.ex +++ b/lib/cannery/mailer.ex @@ -1,3 +1,7 @@ defmodule Cannery.Mailer do + @moduledoc """ + Mailer adapter for emails + """ + use Swoosh.Mailer, otp_app: :cannery end diff --git a/lib/cannery/release.ex b/lib/cannery/release.ex index 1ddcbc2..c86ede1 100644 --- a/lib/cannery/release.ex +++ b/lib/cannery/release.ex @@ -1,4 +1,10 @@ defmodule Cannery.Release do + @moduledoc """ + Contains tasks that will be included in the Mix release + + Ex. `load_app/0` can be invoked with `mix load_app`. + """ + @app :cannery def rollback(repo, version) do diff --git a/lib/cannery/repo/migrator.ex b/lib/cannery/repo/migrator.ex index 42aa8e5..324d333 100644 --- a/lib/cannery/repo/migrator.ex +++ b/lib/cannery/repo/migrator.ex @@ -1,4 +1,8 @@ defmodule Cannery.Repo.Migrator do + @moduledoc """ + Genserver to automatically run migrations in prod env + """ + use GenServer require Logger diff --git a/lib/cannery/tags/tag.ex b/lib/cannery/tags/tag.ex index b9beb2c..1c37475 100644 --- a/lib/cannery/tags/tag.ex +++ b/lib/cannery/tags/tag.ex @@ -1,7 +1,13 @@ defmodule Cannery.Tags.Tag do + @moduledoc """ + Tags are added to containers to help organize, and can include custom-defined + text and bg colors. + """ + use Ecto.Schema import Ecto.Changeset - alias Cannery.{Accounts} + alias Ecto.{Changeset, UUID} + alias Cannery.{Accounts.User, Tags.Tag} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id @@ -10,23 +16,26 @@ defmodule Cannery.Tags.Tag do field :bg_color, :string field :text_color, :string - belongs_to :user, Accounts.User + belongs_to :user, User timestamps() end - @type t :: %{ - id: Ecto.UUID.t(), + @type t :: %Tag{ + id: UUID.t(), name: String.t(), bg_color: String.t(), text_color: String.t(), - user: Accounts.User.t(), - user_id: Ecto.UUID.t(), + user: User.t(), + user_id: UUID.t(), inserted_at: NaiveDateTime.t(), updated_at: NaiveDateTime.t() } + @type new_tag() :: %Tag{} + @doc false + @spec changeset(Tag.t() | Tag.new_tag(), map()) :: Changeset.t() def changeset(tag, attrs) do tag |> cast(attrs, [:name, :bg_color, :text_color, :user_id]) diff --git a/lib/cannery_web/component/topbar.ex b/lib/cannery_web/component/topbar.ex index ad4c606..9581514 100644 --- a/lib/cannery_web/component/topbar.ex +++ b/lib/cannery_web/component/topbar.ex @@ -1,8 +1,12 @@ defmodule CanneryWeb.Component.Topbar do + @moduledoc """ + Component that renders a topbar with user functions/links + """ + use CanneryWeb, :component - alias Cannery.{Accounts} - alias CanneryWeb.{HomeLive} + alias Cannery.Accounts + alias CanneryWeb.HomeLive def topbar(assigns) do assigns = diff --git a/lib/cannery_web/controllers/user_auth.ex b/lib/cannery_web/controllers/user_auth.ex index 743fc1c..ed08be4 100644 --- a/lib/cannery_web/controllers/user_auth.ex +++ b/lib/cannery_web/controllers/user_auth.ex @@ -1,9 +1,13 @@ defmodule CanneryWeb.UserAuth do + @moduledoc """ + Functions for user session and authentication + """ + import Plug.Conn import Phoenix.Controller alias Cannery.Accounts - alias CanneryWeb.{HomeLive} + alias CanneryWeb.HomeLive alias CanneryWeb.Router.Helpers, as: Routes # Make the remember me cookie valid for 60 days. @@ -37,6 +41,11 @@ defmodule CanneryWeb.UserAuth do |> redirect(to: user_return_to || signed_in_path(conn)) end + @spec maybe_write_remember_me_cookie( + Plug.Conn.t(), + String.t() | any(), + %{required(String.t()) => String.t()} | any() + ) :: Plug.Conn.t() defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do put_resp_cookie(conn, @remember_me_cookie, token, @remember_me_options) end diff --git a/lib/cannery_web/live/ammo_group_live/form_component.ex b/lib/cannery_web/live/ammo_group_live/form_component.ex index 1c89f3b..31403b4 100644 --- a/lib/cannery_web/live/ammo_group_live/form_component.ex +++ b/lib/cannery_web/live/ammo_group_live/form_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do + @moduledoc """ + Livecomponent that can update or create an Cannery.Ammo.AmmoGroup + """ + use CanneryWeb, :live_component alias Cannery.Ammo diff --git a/lib/cannery_web/live/ammo_group_live/index.ex b/lib/cannery_web/live/ammo_group_live/index.ex index f7ab770..33952f0 100644 --- a/lib/cannery_web/live/ammo_group_live/index.ex +++ b/lib/cannery_web/live/ammo_group_live/index.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoGroupLive.Index do + @moduledoc """ + Liveview to show a Cannery.Ammo.AmmoGroup index + """ + use CanneryWeb, :live_view alias Cannery.Ammo diff --git a/lib/cannery_web/live/ammo_group_live/show.ex b/lib/cannery_web/live/ammo_group_live/show.ex index 2e32442..658377c 100644 --- a/lib/cannery_web/live/ammo_group_live/show.ex +++ b/lib/cannery_web/live/ammo_group_live/show.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoGroupLive.Show do + @moduledoc """ + Liveview for showing and editing an Cannery.Ammo.AmmoGroup + """ + use CanneryWeb, :live_view alias Cannery.Ammo diff --git a/lib/cannery_web/live/ammo_type_live/form_component.ex b/lib/cannery_web/live/ammo_type_live/form_component.ex index 2cd5cbf..965bd0c 100644 --- a/lib/cannery_web/live/ammo_type_live/form_component.ex +++ b/lib/cannery_web/live/ammo_type_live/form_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoTypeLive.FormComponent do + @moduledoc """ + Livecomponent that can update or create an Cannery.Ammo.AmmoType + """ + use CanneryWeb, :live_component alias Cannery.Ammo diff --git a/lib/cannery_web/live/ammo_type_live/index.ex b/lib/cannery_web/live/ammo_type_live/index.ex index 6509ed0..8a7cab8 100644 --- a/lib/cannery_web/live/ammo_type_live/index.ex +++ b/lib/cannery_web/live/ammo_type_live/index.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoTypeLive.Index do + @moduledoc """ + Liveview for showing a Cannery.Ammo.AmmoType index + """ + use CanneryWeb, :live_view alias Cannery.Ammo diff --git a/lib/cannery_web/live/ammo_type_live/show.ex b/lib/cannery_web/live/ammo_type_live/show.ex index 5bd3b24..1303522 100644 --- a/lib/cannery_web/live/ammo_type_live/show.ex +++ b/lib/cannery_web/live/ammo_type_live/show.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.AmmoTypeLive.Show do + @moduledoc """ + Liveview for showing and editing an Cannery.Ammo.AmmoType + """ + use CanneryWeb, :live_view alias Cannery.Ammo diff --git a/lib/cannery_web/live/container_live/form_component.ex b/lib/cannery_web/live/container_live/form_component.ex index 9e0ea90..51e6331 100644 --- a/lib/cannery_web/live/container_live/form_component.ex +++ b/lib/cannery_web/live/container_live/form_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.ContainerLive.FormComponent do + @moduledoc """ + Livecomponent that can update or create an Cannery.Containers.Container + """ + use CanneryWeb, :live_component alias Cannery.Containers diff --git a/lib/cannery_web/live/container_live/index.ex b/lib/cannery_web/live/container_live/index.ex index 7ef07fa..8619c79 100644 --- a/lib/cannery_web/live/container_live/index.ex +++ b/lib/cannery_web/live/container_live/index.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.ContainerLive.Index do + @moduledoc """ + Liveview for showing Cannery.Containers.Container index + """ + use CanneryWeb, :live_view alias Cannery.Containers diff --git a/lib/cannery_web/live/container_live/show.ex b/lib/cannery_web/live/container_live/show.ex index b81e6a9..b7c6aed 100644 --- a/lib/cannery_web/live/container_live/show.ex +++ b/lib/cannery_web/live/container_live/show.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.ContainerLive.Show do + @moduledoc """ + Liveview for showing and editing a Cannery.Containers.Container + """ + use CanneryWeb, :live_view alias Cannery.Containers diff --git a/lib/cannery_web/live/home_live.ex b/lib/cannery_web/live/home_live.ex index 8c45d27..87d0630 100644 --- a/lib/cannery_web/live/home_live.ex +++ b/lib/cannery_web/live/home_live.ex @@ -1,6 +1,10 @@ defmodule CanneryWeb.HomeLive do + @moduledoc """ + Liveview for the home page + """ + use CanneryWeb, :live_view - alias Cannery.{Accounts} + alias Cannery.Accounts @impl true def mount(_params, session, socket) do diff --git a/lib/cannery_web/live/invite_live/form_component.ex b/lib/cannery_web/live/invite_live/form_component.ex index b5f8a67..ae93b80 100644 --- a/lib/cannery_web/live/invite_live/form_component.ex +++ b/lib/cannery_web/live/invite_live/form_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.InviteLive.FormComponent do + @moduledoc """ + Livecomponent that can update or create an Cannery.Invites.Invite + """ + use CanneryWeb, :live_component alias Cannery.Invites diff --git a/lib/cannery_web/live/invite_live/index.ex b/lib/cannery_web/live/invite_live/index.ex index 93f1bb0..f13f5d5 100644 --- a/lib/cannery_web/live/invite_live/index.ex +++ b/lib/cannery_web/live/invite_live/index.ex @@ -1,8 +1,12 @@ defmodule CanneryWeb.InviteLive.Index do + @moduledoc """ + Liveview to show a Cannery.Invites.Invite index + """ + use CanneryWeb, :live_view - alias Cannery.{Invites} - alias Cannery.Invites.{Invite} + alias Cannery.Invites + alias Cannery.Invites.Invite @impl true def mount(_params, session, socket) do diff --git a/lib/cannery_web/live/live_helpers.ex b/lib/cannery_web/live/live_helpers.ex index 6c6167a..ba05d0f 100644 --- a/lib/cannery_web/live/live_helpers.ex +++ b/lib/cannery_web/live/live_helpers.ex @@ -1,7 +1,11 @@ defmodule CanneryWeb.LiveHelpers do + @moduledoc """ + Contains common helper functions for liveviews + """ + import Phoenix.LiveView.Helpers import Phoenix.LiveView, only: [assign_new: 3] - alias Cannery.{Accounts} + alias Cannery.Accounts @doc """ Renders a component inside the `CanneryWeb.ModalComponent` component. diff --git a/lib/cannery_web/live/modal_component.ex b/lib/cannery_web/live/modal_component.ex index 2000bd5..007b9dc 100644 --- a/lib/cannery_web/live/modal_component.ex +++ b/lib/cannery_web/live/modal_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.ModalComponent do + @moduledoc """ + Livecomponent that displays a floating modal window + """ + use CanneryWeb, :live_component @impl true diff --git a/lib/cannery_web/live/tag_live/form_component.ex b/lib/cannery_web/live/tag_live/form_component.ex index 51d2162..b5128b1 100644 --- a/lib/cannery_web/live/tag_live/form_component.ex +++ b/lib/cannery_web/live/tag_live/form_component.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.TagLive.FormComponent do + @moduledoc """ + Livecomponent that can update or create an Cannery.Tags.Tag + """ + use CanneryWeb, :live_component alias Cannery.Tags @@ -103,7 +107,7 @@ defmodule CanneryWeb.TagLive.FormComponent do Returns a random tag color in `#ffffff` hex format """ @spec random_color() :: String.t() - def random_color() do + def random_color do ["#cc0066", "#ff6699", "#6666ff", "#0066cc", "#00cc66", "#669900", "#ff9900", "#996633"] |> Enum.random() end diff --git a/lib/cannery_web/live/tag_live/index.ex b/lib/cannery_web/live/tag_live/index.ex index b5dbe37..61afe1d 100644 --- a/lib/cannery_web/live/tag_live/index.ex +++ b/lib/cannery_web/live/tag_live/index.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.TagLive.Index do + @moduledoc """ + Liveview to show a Cannery.Tags.Tag index + """ + use CanneryWeb, :live_view alias Cannery.Tags diff --git a/lib/cannery_web/telemetry.ex b/lib/cannery_web/telemetry.ex index d38ec23..021f6c0 100644 --- a/lib/cannery_web/telemetry.ex +++ b/lib/cannery_web/telemetry.ex @@ -1,4 +1,8 @@ defmodule CanneryWeb.Telemetry do + @moduledoc """ + Collects telemetry + """ + use Supervisor import Telemetry.Metrics diff --git a/lib/cannery_web/views/layout_view.ex b/lib/cannery_web/views/layout_view.ex index c55c1a9..bb47d2a 100644 --- a/lib/cannery_web/views/layout_view.ex +++ b/lib/cannery_web/views/layout_view.ex @@ -1,7 +1,7 @@ defmodule CanneryWeb.LayoutView do use CanneryWeb, :view - alias Cannery.{Accounts} - alias CanneryWeb.{HomeLive} + alias Cannery.Accounts + alias CanneryWeb.HomeLive # Phoenix LiveDashboard is available only in development by default, # so we instruct Elixir to not warn if the dashboard route is missing. diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex index 018f090..dbe33e9 100644 --- a/test/support/channel_case.ex +++ b/test/support/channel_case.ex @@ -16,6 +16,7 @@ defmodule CanneryWeb.ChannelCase do """ use ExUnit.CaseTemplate + alias Ecto.Adapters.SQL.Sandbox using do quote do @@ -29,8 +30,8 @@ defmodule CanneryWeb.ChannelCase do end setup tags do - pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) - on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + pid = Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) + on_exit(fn -> Sandbox.stop_owner(pid) end) :ok end end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 5031433..3c8d17e 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -16,6 +16,7 @@ defmodule CanneryWeb.ConnCase do """ use ExUnit.CaseTemplate + alias Ecto.Adapters.SQL.Sandbox using do quote do @@ -32,8 +33,8 @@ defmodule CanneryWeb.ConnCase do end setup tags do - pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) - on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + pid = Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) + on_exit(fn -> Sandbox.stop_owner(pid) end) {:ok, conn: Phoenix.ConnTest.build_conn()} end diff --git a/test/support/data_case.ex b/test/support/data_case.ex index 403d8ee..d336fc5 100644 --- a/test/support/data_case.ex +++ b/test/support/data_case.ex @@ -15,6 +15,7 @@ defmodule Cannery.DataCase do """ use ExUnit.CaseTemplate + alias Ecto.Adapters.SQL.Sandbox using do quote do @@ -28,8 +29,8 @@ defmodule Cannery.DataCase do end setup tags do - pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) - on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + pid = Sandbox.start_owner!(Cannery.Repo, shared: not tags[:async]) + on_exit(fn -> Sandbox.stop_owner(pid) end) :ok end diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex index b0135eb..bef7855 100644 --- a/test/support/fixtures/accounts_fixtures.ex +++ b/test/support/fixtures/accounts_fixtures.ex @@ -4,7 +4,7 @@ defmodule Cannery.AccountsFixtures do entities via the `Cannery.Accounts` context. """ - alias Cannery.{Accounts} + alias Cannery.Accounts def unique_user_email, do: "user#{System.unique_integer()}@example.com" def valid_user_password, do: "hello world!"