From 0259a7451d7867ac7fb317ef668508fe323a3f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wo=CC=88ginger?= Date: Mon, 25 Dec 2023 14:11:10 +0100 Subject: [PATCH] make episode a required attribute for nodes --- lib/radiator/outline/node.ex | 6 +-- lib/radiator/podcast.ex | 3 +- lib/radiator/podcast/episode.ex | 2 +- .../controllers/api/outline_controller.ex | 19 ++++----- test/radiator/outline_test.exs | 10 +++-- .../api/outline_controller_test.exs | 40 +++++++++++++++---- test/support/fixtures/outline_fixtures.ex | 2 + 7 files changed, 57 insertions(+), 25 deletions(-) diff --git a/lib/radiator/outline/node.ex b/lib/radiator/outline/node.ex index 629f3a3b..a078b009 100644 --- a/lib/radiator/outline/node.ex +++ b/lib/radiator/outline/node.ex @@ -22,14 +22,14 @@ defmodule Radiator.Outline.Node do end @required_fields [ - :content + :content, + :episode_id ] @optional_fields [ :creator_id, :parent_id, - :prev_id, - :episode_id # FIXME: should be required + :prev_id ] @all_fields @optional_fields ++ @required_fields diff --git a/lib/radiator/podcast.ex b/lib/radiator/podcast.ex index 086c1f13..eaf8764e 100644 --- a/lib/radiator/podcast.ex +++ b/lib/radiator/podcast.ex @@ -227,7 +227,8 @@ defmodule Radiator.Podcast do def get_episode!(id), do: Repo.get!(Episode, id) @doc """ - Returns the newest (TODO: not published ) episode for a show. + Finds the newest (TODO: not published ) episode for a show. + Returns %Episode{} or `nil` and expects an id of the show. ## Examples diff --git a/lib/radiator/podcast/episode.ex b/lib/radiator/podcast/episode.ex index b96b6654..ced456a4 100644 --- a/lib/radiator/podcast/episode.ex +++ b/lib/radiator/podcast/episode.ex @@ -1,7 +1,7 @@ defmodule Radiator.Podcast.Episode do @moduledoc """ Represents the Episode model. - TODO: Episodes should be numbered and ordered inside a show. + Episodes are numbered inside a show. """ use Ecto.Schema import Ecto.Changeset diff --git a/lib/radiator_web/controllers/api/outline_controller.ex b/lib/radiator_web/controllers/api/outline_controller.ex index c132055a..795d2d75 100644 --- a/lib/radiator_web/controllers/api/outline_controller.ex +++ b/lib/radiator_web/controllers/api/outline_controller.ex @@ -1,18 +1,16 @@ defmodule RadiatorWeb.Api.OutlineController do use RadiatorWeb, :controller - alias Radiator.Accounts - alias Radiator.Outline + alias Radiator.{Accounts, Outline, Podcast} + + def create(conn, %{"content" => content, "show_id" => show_id, "token" => token}) do + episode = Podcast.get_current_episode_for_show(show_id) - def create(conn, %{"content" => content, "token" => token}) do {status_code, body} = token |> decode_token() |> get_user_by_token() - # show will be send in request from frontend (show_id) - # fetch wanted/current episode for show - - |> create_node(content) + |> create_node(content, episode.id) |> get_response() conn @@ -31,8 +29,11 @@ defmodule RadiatorWeb.Api.OutlineController do defp get_user_by_token({:ok, token}), do: Accounts.get_user_by_api_token(token) defp get_user_by_token(:error), do: {:error, :token} - defp create_node(nil, _), do: {:error, :user} - defp create_node(user, content), do: Outline.create_node(%{"content" => content}, user) + defp create_node(nil, _, _), do: {:error, :user} + defp create_node(_, _, nil), do: {:error, :episode} + + defp create_node(user, content, episode_id), + do: Outline.create_node(%{"content" => content, "episode_id" => episode_id}, user) defp get_response({:ok, node}), do: {200, %{uuid: node.uuid}} defp get_response({:error, _}), do: {400, %{error: "params"}} diff --git a/test/radiator/outline_test.exs b/test/radiator/outline_test.exs index 3b09125c..505364ef 100644 --- a/test/radiator/outline_test.exs +++ b/test/radiator/outline_test.exs @@ -7,6 +7,7 @@ defmodule Radiator.OutlineTest do alias Radiator.Outline.Node import Radiator.OutlineFixtures + alias Radiator.PodcastFixtures @invalid_attrs %{content: nil} @@ -21,22 +22,25 @@ defmodule Radiator.OutlineTest do end test "create_node/1 with valid data creates a node" do - valid_attrs = %{content: "some content"} + episode = PodcastFixtures.episode_fixture() + valid_attrs = %{content: "some content", episode_id: episode.id} assert {:ok, %Node{} = node} = Outline.create_node(valid_attrs) assert node.content == "some content" end test "create_node/1 trims whitespace from content" do - valid_attrs = %{content: " some content "} + episode = PodcastFixtures.episode_fixture() + valid_attrs = %{content: " some content ", episode_id: episode.id} assert {:ok, %Node{} = node} = Outline.create_node(valid_attrs) assert node.content == "some content" end test "create_node/1 can have a creator" do + episode = PodcastFixtures.episode_fixture() user = %{id: 2} - valid_attrs = %{content: "some content"} + valid_attrs = %{content: "some content", episode_id: episode.id} assert {:ok, %Node{} = node} = Outline.create_node(valid_attrs, user) assert node.content == "some content" diff --git a/test/radiator_web/controllers/api/outline_controller_test.exs b/test/radiator_web/controllers/api/outline_controller_test.exs index 2203a25d..68b90eb1 100644 --- a/test/radiator_web/controllers/api/outline_controller_test.exs +++ b/test/radiator_web/controllers/api/outline_controller_test.exs @@ -2,29 +2,50 @@ defmodule RadiatorWeb.Api.OutlineControllerTest do use RadiatorWeb.ConnCase, async: true import Radiator.AccountsFixtures + import Radiator.PodcastFixtures - alias Radiator.Accounts - alias Radiator.Outline + alias Radiator.{Accounts, Outline, Podcast} describe "POST /api/v1/outline" do setup %{conn: conn} do user = user_fixture() + show_id = episode_fixture().show_id token = user |> Accounts.generate_user_api_token() |> Base.url_encode64() - %{conn: conn, user: user, token: token} + %{conn: conn, user: user, token: token, show_id: show_id} end - test "creates a node if content is present", %{conn: conn, user: %{id: user_id}, token: token} do - body = %{"content" => "new node content", "token" => token} + test "creates a node if content is present", %{ + conn: conn, + user: %{id: user_id}, + show_id: show_id, + token: token + } do + body = %{"content" => "new node content", "token" => token, show_id: show_id} conn = post(conn, ~p"/api/v1/outline", body) %{"uuid" => uuid} = json_response(conn, 200) - assert %{content: "new node content", creator_id: ^user_id} = Outline.get_node!(uuid) + assert %{content: "new node content", creator_id: ^user_id} = + Outline.get_node!(uuid) + end + + test "created node is connected to episode", %{ + conn: conn, + show_id: show_id, + token: token + } do + body = %{"content" => "new node content", "token" => token, show_id: show_id} + conn = post(conn, ~p"/api/v1/outline", body) + + %{"uuid" => uuid} = json_response(conn, 200) + + episode_id = Podcast.get_current_episode_for_show(show_id).id + assert %{content: "new node content", episode_id: ^episode_id} = Outline.get_node!(uuid) end test "can't create node when content is missing", %{conn: conn} do @@ -33,8 +54,11 @@ defmodule RadiatorWeb.Api.OutlineControllerTest do assert %{"error" => "missing params"} = json_response(conn, 400) end - test "can't create node when token is wrong", %{conn: conn} do - body = %{"content" => "new node content", "token" => "invalid"} + test "can't create node when token is wrong", %{ + conn: conn, + show_id: show_id + } do + body = %{"content" => "new node content", "token" => "invalid", show_id: show_id} conn = post(conn, ~p"/api/v1/outline", body) assert %{"error" => "params"} = json_response(conn, 400) diff --git a/test/support/fixtures/outline_fixtures.ex b/test/support/fixtures/outline_fixtures.ex index bf276e5e..37257fb2 100644 --- a/test/support/fixtures/outline_fixtures.ex +++ b/test/support/fixtures/outline_fixtures.ex @@ -4,6 +4,7 @@ defmodule Radiator.OutlineFixtures do entities via the `Radiator.Outline` context. """ alias Radiator.PodcastFixtures + @doc """ Generate a node. """ @@ -17,6 +18,7 @@ defmodule Radiator.OutlineFixtures do episode_id: episode.id }) |> Radiator.Outline.create_node() + node end end