diff --git a/lib/aggiedit/rooms.ex b/lib/aggiedit/rooms.ex index eac2b65..fb10c4b 100644 --- a/lib/aggiedit/rooms.ex +++ b/lib/aggiedit/rooms.ex @@ -108,4 +108,100 @@ defmodule Aggiedit.Rooms do nil -> create_room(%{domain: domain}) end end + + alias Aggiedit.Rooms.Post + + @doc """ + Returns the list of posts. + + ## Examples + + iex> list_posts() + [%Post{}, ...] + + """ + def list_posts do + Repo.all(Post) + end + + @doc """ + Gets a single post. + + Raises `Ecto.NoResultsError` if the Post does not exist. + + ## Examples + + iex> get_post!(123) + %Post{} + + iex> get_post!(456) + ** (Ecto.NoResultsError) + + """ + def get_post!(id), do: Repo.get!(Post, id) + + @doc """ + Creates a post. + + ## Examples + + iex> create_post(%{field: value}) + {:ok, %Post{}} + + iex> create_post(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_post(attrs \\ %{}) do + %Post{} + |> Post.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a post. + + ## Examples + + iex> update_post(post, %{field: new_value}) + {:ok, %Post{}} + + iex> update_post(post, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_post(%Post{} = post, attrs) do + post + |> Post.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a post. + + ## Examples + + iex> delete_post(post) + {:ok, %Post{}} + + iex> delete_post(post) + {:error, %Ecto.Changeset{}} + + """ + def delete_post(%Post{} = post) do + Repo.delete(post) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking post changes. + + ## Examples + + iex> change_post(post) + %Ecto.Changeset{data: %Post{}} + + """ + def change_post(%Post{} = post, attrs \\ %{}) do + Post.changeset(post, attrs) + end end diff --git a/lib/aggiedit/rooms/post.ex b/lib/aggiedit/rooms/post.ex new file mode 100644 index 0000000..c6ca24a --- /dev/null +++ b/lib/aggiedit/rooms/post.ex @@ -0,0 +1,21 @@ +defmodule Aggiedit.Rooms.Post do + use Ecto.Schema + import Ecto.Changeset + + schema "posts" do + field :body, :string + field :title, :string + field :user_id, :id + field :upload_id, :id + field :room_id, :id + + timestamps() + end + + @doc false + def changeset(post, attrs) do + post + |> cast(attrs, [:title, :body]) + |> validate_required([:title, :body]) + end +end diff --git a/lib/aggiedit/uploads.ex b/lib/aggiedit/uploads.ex new file mode 100644 index 0000000..2dcdcc3 --- /dev/null +++ b/lib/aggiedit/uploads.ex @@ -0,0 +1,104 @@ +defmodule Aggiedit.Uploads do + @moduledoc """ + The Uploads context. + """ + + import Ecto.Query, warn: false + alias Aggiedit.Repo + + alias Aggiedit.Uploads.Upload + + @doc """ + Returns the list of uploads. + + ## Examples + + iex> list_uploads() + [%Upload{}, ...] + + """ + def list_uploads do + Repo.all(Upload) + end + + @doc """ + Gets a single upload. + + Raises `Ecto.NoResultsError` if the Upload does not exist. + + ## Examples + + iex> get_upload!(123) + %Upload{} + + iex> get_upload!(456) + ** (Ecto.NoResultsError) + + """ + def get_upload!(id), do: Repo.get!(Upload, id) + + @doc """ + Creates a upload. + + ## Examples + + iex> create_upload(%{field: value}) + {:ok, %Upload{}} + + iex> create_upload(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_upload(attrs \\ %{}) do + %Upload{} + |> Upload.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a upload. + + ## Examples + + iex> update_upload(upload, %{field: new_value}) + {:ok, %Upload{}} + + iex> update_upload(upload, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_upload(%Upload{} = upload, attrs) do + upload + |> Upload.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a upload. + + ## Examples + + iex> delete_upload(upload) + {:ok, %Upload{}} + + iex> delete_upload(upload) + {:error, %Ecto.Changeset{}} + + """ + def delete_upload(%Upload{} = upload) do + Repo.delete(upload) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking upload changes. + + ## Examples + + iex> change_upload(upload) + %Ecto.Changeset{data: %Upload{}} + + """ + def change_upload(%Upload{} = upload, attrs \\ %{}) do + Upload.changeset(upload, attrs) + end +end diff --git a/lib/aggiedit/uploads/upload.ex b/lib/aggiedit/uploads/upload.ex new file mode 100644 index 0000000..f5f028d --- /dev/null +++ b/lib/aggiedit/uploads/upload.ex @@ -0,0 +1,21 @@ +defmodule Aggiedit.Uploads.Upload do + use Ecto.Schema + import Ecto.Changeset + + schema "uploads" do + field :file, :string + field :mime, :string + field :size, :integer + + belongs_to :user, Aggiedit.Accounts.User + + timestamps() + end + + @doc false + def changeset(upload, attrs) do + upload + |> cast(attrs, [:file, :mime, :size]) + |> validate_required([:file, :mime, :size]) + end +end diff --git a/lib/aggiedit_web.ex b/lib/aggiedit_web.ex index 0b7717c..c6b6841 100644 --- a/lib/aggiedit_web.ex +++ b/lib/aggiedit_web.ex @@ -91,6 +91,7 @@ defmodule AggieditWeb do # Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc) import Phoenix.LiveView.Helpers + import AggieditWeb.LiveHelpers # Import basic rendering functionality (render, render_layout, etc) import Phoenix.View diff --git a/lib/aggiedit_web/live/live_helpers.ex b/lib/aggiedit_web/live/live_helpers.ex new file mode 100644 index 0000000..aa6b28a --- /dev/null +++ b/lib/aggiedit_web/live/live_helpers.ex @@ -0,0 +1,60 @@ +defmodule AggieditWeb.LiveHelpers do + import Phoenix.LiveView + import Phoenix.LiveView.Helpers + + alias Phoenix.LiveView.JS + + @doc """ + Renders a live component inside a modal. + + The rendered modal receives a `:return_to` option to properly update + the URL when the modal is closed. + + ## Examples + + <.modal return_to={Routes.post_index_path(@socket, :index)}> + <.live_component + module={AggieditWeb.PostLive.FormComponent} + id={@post.id || :new} + title={@page_title} + action={@live_action} + return_to={Routes.post_index_path(@socket, :index)} + post: @post + /> + + """ + def modal(assigns) do + assigns = assign_new(assigns, :return_to, fn -> nil end) + + ~H""" + + """ + end + + defp hide_modal(js \\ %JS{}) do + js + |> JS.hide(to: "#modal", transition: "fade-out") + |> JS.hide(to: "#modal-content", transition: "fade-out-scale") + end +end diff --git a/lib/aggiedit_web/live/post_live/form_component.ex b/lib/aggiedit_web/live/post_live/form_component.ex new file mode 100644 index 0000000..11ad4a1 --- /dev/null +++ b/lib/aggiedit_web/live/post_live/form_component.ex @@ -0,0 +1,55 @@ +defmodule AggieditWeb.PostLive.FormComponent do + use AggieditWeb, :live_component + + alias Aggiedit.Rooms + + @impl true + def update(%{post: post} = assigns, socket) do + changeset = Rooms.change_post(post) + + {:ok, + socket + |> assign(assigns) + |> assign(:changeset, changeset)} + end + + @impl true + def handle_event("validate", %{"post" => post_params}, socket) do + changeset = + socket.assigns.post + |> Rooms.change_post(post_params) + |> Map.put(:action, :validate) + + {:noreply, assign(socket, :changeset, changeset)} + end + + def handle_event("save", %{"post" => post_params}, socket) do + save_post(socket, socket.assigns.action, post_params) + end + + defp save_post(socket, :edit, post_params) do + case Rooms.update_post(socket.assigns.post, post_params) do + {:ok, _post} -> + {:noreply, + socket + |> put_flash(:info, "Post updated successfully") + |> push_redirect(to: socket.assigns.return_to)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, :changeset, changeset)} + end + end + + defp save_post(socket, :new, post_params) do + case Rooms.create_post(post_params) do + {:ok, _post} -> + {:noreply, + socket + |> put_flash(:info, "Post created successfully") + |> push_redirect(to: socket.assigns.return_to)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, changeset: changeset)} + end + end +end diff --git a/lib/aggiedit_web/live/post_live/form_component.html.heex b/lib/aggiedit_web/live/post_live/form_component.html.heex new file mode 100644 index 0000000..682ec78 --- /dev/null +++ b/lib/aggiedit_web/live/post_live/form_component.html.heex @@ -0,0 +1,24 @@ +
+

<%= @title %>

+ + <.form + let={f} + for={@changeset} + id="post-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save"> + + <%= label f, :title %> + <%= textarea f, :title %> + <%= error_tag f, :title %> + + <%= label f, :body %> + <%= textarea f, :body %> + <%= error_tag f, :body %> + +
+ <%= submit "Save", phx_disable_with: "Saving..." %> +
+ +
diff --git a/lib/aggiedit_web/live/post_live/index.ex b/lib/aggiedit_web/live/post_live/index.ex new file mode 100644 index 0000000..0b12ed0 --- /dev/null +++ b/lib/aggiedit_web/live/post_live/index.ex @@ -0,0 +1,46 @@ +defmodule AggieditWeb.PostLive.Index do + use AggieditWeb, :live_view + + alias Aggiedit.Rooms + alias Aggiedit.Rooms.Post + + @impl true + def mount(_params, _session, socket) do + {:ok, assign(socket, :posts, list_posts())} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :edit, %{"id" => id}) do + socket + |> assign(:page_title, "Edit Post") + |> assign(:post, Rooms.get_post!(id)) + end + + defp apply_action(socket, :new, _params) do + socket + |> assign(:page_title, "New Post") + |> assign(:post, %Post{}) + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing Posts") + |> assign(:post, nil) + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + post = Rooms.get_post!(id) + {:ok, _} = Rooms.delete_post(post) + + {:noreply, assign(socket, :posts, list_posts())} + end + + defp list_posts do + Rooms.list_posts() + end +end diff --git a/lib/aggiedit_web/live/post_live/index.html.heex b/lib/aggiedit_web/live/post_live/index.html.heex new file mode 100644 index 0000000..4297d5a --- /dev/null +++ b/lib/aggiedit_web/live/post_live/index.html.heex @@ -0,0 +1,41 @@ +

Listing Posts

+ +<%= if @live_action in [:new, :edit] do %> + <.modal return_to={Routes.post_index_path(@socket, :index)}> + <.live_component + module={AggieditWeb.PostLive.FormComponent} + id={@post.id || :new} + title={@page_title} + action={@live_action} + post={@post} + return_to={Routes.post_index_path(@socket, :index)} + /> + +<% end %> + + + + + + + + + + + + <%= for post <- @posts do %> + + + + + + + <% end %> + +
TitleBody
<%= post.title %><%= post.body %> + <%= live_redirect "Show", to: Routes.post_show_path(@socket, :show, post) %> + <%= live_patch "Edit", to: Routes.post_index_path(@socket, :edit, post) %> + <%= link "Delete", to: "#", phx_click: "delete", phx_value_id: post.id, data: [confirm: "Are you sure?"] %> +
+ +<%= live_patch "New Post", to: Routes.post_index_path(@socket, :new) %> diff --git a/lib/aggiedit_web/live/post_live/show.ex b/lib/aggiedit_web/live/post_live/show.ex new file mode 100644 index 0000000..2416156 --- /dev/null +++ b/lib/aggiedit_web/live/post_live/show.ex @@ -0,0 +1,21 @@ +defmodule AggieditWeb.PostLive.Show do + use AggieditWeb, :live_view + + alias Aggiedit.Rooms + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:post, Rooms.get_post!(id))} + end + + defp page_title(:show), do: "Show Post" + defp page_title(:edit), do: "Edit Post" +end diff --git a/lib/aggiedit_web/live/post_live/show.html.heex b/lib/aggiedit_web/live/post_live/show.html.heex new file mode 100644 index 0000000..e6eaebe --- /dev/null +++ b/lib/aggiedit_web/live/post_live/show.html.heex @@ -0,0 +1,31 @@ +

Show Post

+ +<%= if @live_action in [:edit] do %> + <.modal return_to={Routes.post_show_path(@socket, :show, @post)}> + <.live_component + module={AggieditWeb.PostLive.FormComponent} + id={@post.id} + title={@page_title} + action={@live_action} + post={@post} + return_to={Routes.post_show_path(@socket, :show, @post)} + /> + +<% end %> + + + +<%= live_patch "Edit", to: Routes.post_show_path(@socket, :edit, @post), class: "button" %> | +<%= live_redirect "Back", to: Routes.post_index_path(@socket, :index) %> diff --git a/lib/aggiedit_web/router.ex b/lib/aggiedit_web/router.ex index e400391..dec730a 100644 --- a/lib/aggiedit_web/router.ex +++ b/lib/aggiedit_web/router.ex @@ -21,6 +21,13 @@ defmodule AggieditWeb.Router do pipe_through :browser get "/", PageController, :index + + live "/posts", PostLive.Index, :index + live "/posts/new", PostLive.Index, :new + live "/posts/:id/edit", PostLive.Index, :edit + + live "/posts/:id", PostLive.Show, :show + live "/posts/:id/show/edit", PostLive.Show, :edit end # Other scopes may use custom stacks. diff --git a/priv/repo/migrations/20220406184635_create_uploads.exs b/priv/repo/migrations/20220406184635_create_uploads.exs new file mode 100644 index 0000000..4b28397 --- /dev/null +++ b/priv/repo/migrations/20220406184635_create_uploads.exs @@ -0,0 +1,16 @@ +defmodule Aggiedit.Repo.Migrations.CreateUploads do + use Ecto.Migration + + def change do + create table(:uploads) do + add :file, :text + add :mime, :text + add :size, :integer + add :user_id, references(:users, on_delete: :nothing) + + timestamps() + end + + create index(:uploads, [:user_id]) + end +end diff --git a/priv/repo/migrations/20220406185124_create_posts.exs b/priv/repo/migrations/20220406185124_create_posts.exs new file mode 100644 index 0000000..223265c --- /dev/null +++ b/priv/repo/migrations/20220406185124_create_posts.exs @@ -0,0 +1,19 @@ +defmodule Aggiedit.Repo.Migrations.CreatePosts do + use Ecto.Migration + + def change do + create table(:posts) do + add :title, :text + add :body, :text + add :user_id, references(:users, on_delete: :nothing) + add :upload_id, references(:uploads, on_delete: :nothing) + add :room_id, references(:rooms, on_delete: :nothing) + + timestamps() + end + + create index(:posts, [:user_id]) + create index(:posts, [:upload_id]) + create index(:posts, [:room_id]) + end +end diff --git a/test/aggiedit/rooms_test.exs b/test/aggiedit/rooms_test.exs index 2a270e6..7c48e0c 100644 --- a/test/aggiedit/rooms_test.exs +++ b/test/aggiedit/rooms_test.exs @@ -56,4 +56,60 @@ defmodule Aggiedit.RoomsTest do assert %Ecto.Changeset{} = Rooms.change_room(room) end end + + describe "posts" do + alias Aggiedit.Rooms.Post + + import Aggiedit.RoomsFixtures + + @invalid_attrs %{body: nil, title: nil} + + test "list_posts/0 returns all posts" do + post = post_fixture() + assert Rooms.list_posts() == [post] + end + + test "get_post!/1 returns the post with given id" do + post = post_fixture() + assert Rooms.get_post!(post.id) == post + end + + test "create_post/1 with valid data creates a post" do + valid_attrs = %{body: "some body", title: "some title"} + + assert {:ok, %Post{} = post} = Rooms.create_post(valid_attrs) + assert post.body == "some body" + assert post.title == "some title" + end + + test "create_post/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Rooms.create_post(@invalid_attrs) + end + + test "update_post/2 with valid data updates the post" do + post = post_fixture() + update_attrs = %{body: "some updated body", title: "some updated title"} + + assert {:ok, %Post{} = post} = Rooms.update_post(post, update_attrs) + assert post.body == "some updated body" + assert post.title == "some updated title" + end + + test "update_post/2 with invalid data returns error changeset" do + post = post_fixture() + assert {:error, %Ecto.Changeset{}} = Rooms.update_post(post, @invalid_attrs) + assert post == Rooms.get_post!(post.id) + end + + test "delete_post/1 deletes the post" do + post = post_fixture() + assert {:ok, %Post{}} = Rooms.delete_post(post) + assert_raise Ecto.NoResultsError, fn -> Rooms.get_post!(post.id) end + end + + test "change_post/1 returns a post changeset" do + post = post_fixture() + assert %Ecto.Changeset{} = Rooms.change_post(post) + end + end end diff --git a/test/aggiedit/uploads_test.exs b/test/aggiedit/uploads_test.exs new file mode 100644 index 0000000..270f226 --- /dev/null +++ b/test/aggiedit/uploads_test.exs @@ -0,0 +1,63 @@ +defmodule Aggiedit.UploadsTest do + use Aggiedit.DataCase + + alias Aggiedit.Uploads + + describe "uploads" do + alias Aggiedit.Uploads.Upload + + import Aggiedit.UploadsFixtures + + @invalid_attrs %{file: nil, mime: nil, size: nil} + + test "list_uploads/0 returns all uploads" do + upload = upload_fixture() + assert Uploads.list_uploads() == [upload] + end + + test "get_upload!/1 returns the upload with given id" do + upload = upload_fixture() + assert Uploads.get_upload!(upload.id) == upload + end + + test "create_upload/1 with valid data creates a upload" do + valid_attrs = %{file: "some file", mime: "some mime", size: 42} + + assert {:ok, %Upload{} = upload} = Uploads.create_upload(valid_attrs) + assert upload.file == "some file" + assert upload.mime == "some mime" + assert upload.size == 42 + end + + test "create_upload/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Uploads.create_upload(@invalid_attrs) + end + + test "update_upload/2 with valid data updates the upload" do + upload = upload_fixture() + update_attrs = %{file: "some updated file", mime: "some updated mime", size: 43} + + assert {:ok, %Upload{} = upload} = Uploads.update_upload(upload, update_attrs) + assert upload.file == "some updated file" + assert upload.mime == "some updated mime" + assert upload.size == 43 + end + + test "update_upload/2 with invalid data returns error changeset" do + upload = upload_fixture() + assert {:error, %Ecto.Changeset{}} = Uploads.update_upload(upload, @invalid_attrs) + assert upload == Uploads.get_upload!(upload.id) + end + + test "delete_upload/1 deletes the upload" do + upload = upload_fixture() + assert {:ok, %Upload{}} = Uploads.delete_upload(upload) + assert_raise Ecto.NoResultsError, fn -> Uploads.get_upload!(upload.id) end + end + + test "change_upload/1 returns a upload changeset" do + upload = upload_fixture() + assert %Ecto.Changeset{} = Uploads.change_upload(upload) + end + end +end diff --git a/test/aggiedit_web/live/post_live_test.exs b/test/aggiedit_web/live/post_live_test.exs new file mode 100644 index 0000000..0e5a6f0 --- /dev/null +++ b/test/aggiedit_web/live/post_live_test.exs @@ -0,0 +1,110 @@ +defmodule AggieditWeb.PostLiveTest do + use AggieditWeb.ConnCase + + import Phoenix.LiveViewTest + import Aggiedit.RoomsFixtures + + @create_attrs %{body: "some body", title: "some title"} + @update_attrs %{body: "some updated body", title: "some updated title"} + @invalid_attrs %{body: nil, title: nil} + + defp create_post(_) do + post = post_fixture() + %{post: post} + end + + describe "Index" do + setup [:create_post] + + test "lists all posts", %{conn: conn, post: post} do + {:ok, _index_live, html} = live(conn, Routes.post_index_path(conn, :index)) + + assert html =~ "Listing Posts" + assert html =~ post.body + end + + test "saves new post", %{conn: conn} do + {:ok, index_live, _html} = live(conn, Routes.post_index_path(conn, :index)) + + assert index_live |> element("a", "New Post") |> render_click() =~ + "New Post" + + assert_patch(index_live, Routes.post_index_path(conn, :new)) + + assert index_live + |> form("#post-form", post: @invalid_attrs) + |> render_change() =~ "can't be blank" + + {:ok, _, html} = + index_live + |> form("#post-form", post: @create_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.post_index_path(conn, :index)) + + assert html =~ "Post created successfully" + assert html =~ "some body" + end + + test "updates post in listing", %{conn: conn, post: post} do + {:ok, index_live, _html} = live(conn, Routes.post_index_path(conn, :index)) + + assert index_live |> element("#post-#{post.id} a", "Edit") |> render_click() =~ + "Edit Post" + + assert_patch(index_live, Routes.post_index_path(conn, :edit, post)) + + assert index_live + |> form("#post-form", post: @invalid_attrs) + |> render_change() =~ "can't be blank" + + {:ok, _, html} = + index_live + |> form("#post-form", post: @update_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.post_index_path(conn, :index)) + + assert html =~ "Post updated successfully" + assert html =~ "some updated body" + end + + test "deletes post in listing", %{conn: conn, post: post} do + {:ok, index_live, _html} = live(conn, Routes.post_index_path(conn, :index)) + + assert index_live |> element("#post-#{post.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#post-#{post.id}") + end + end + + describe "Show" do + setup [:create_post] + + test "displays post", %{conn: conn, post: post} do + {:ok, _show_live, html} = live(conn, Routes.post_show_path(conn, :show, post)) + + assert html =~ "Show Post" + assert html =~ post.body + end + + test "updates post within modal", %{conn: conn, post: post} do + {:ok, show_live, _html} = live(conn, Routes.post_show_path(conn, :show, post)) + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Post" + + assert_patch(show_live, Routes.post_show_path(conn, :edit, post)) + + assert show_live + |> form("#post-form", post: @invalid_attrs) + |> render_change() =~ "can't be blank" + + {:ok, _, html} = + show_live + |> form("#post-form", post: @update_attrs) + |> render_submit() + |> follow_redirect(conn, Routes.post_show_path(conn, :show, post)) + + assert html =~ "Post updated successfully" + assert html =~ "some updated body" + end + end +end diff --git a/test/support/fixtures/rooms_fixtures.ex b/test/support/fixtures/rooms_fixtures.ex index fd5671e..fe3200e 100644 --- a/test/support/fixtures/rooms_fixtures.ex +++ b/test/support/fixtures/rooms_fixtures.ex @@ -17,4 +17,19 @@ defmodule Aggiedit.RoomsFixtures do room end + + @doc """ + Generate a post. + """ + def post_fixture(attrs \\ %{}) do + {:ok, post} = + attrs + |> Enum.into(%{ + body: "some body", + title: "some title" + }) + |> Aggiedit.Rooms.create_post() + + post + end end diff --git a/test/support/fixtures/uploads_fixtures.ex b/test/support/fixtures/uploads_fixtures.ex new file mode 100644 index 0000000..b590280 --- /dev/null +++ b/test/support/fixtures/uploads_fixtures.ex @@ -0,0 +1,22 @@ +defmodule Aggiedit.UploadsFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `Aggiedit.Uploads` context. + """ + + @doc """ + Generate a upload. + """ + def upload_fixture(attrs \\ %{}) do + {:ok, upload} = + attrs + |> Enum.into(%{ + file: "some file", + mime: "some mime", + size: 42 + }) + |> Aggiedit.Uploads.create_upload() + + upload + end +end