From cf7a7ad1fdad2d2f10e151320e9ed3191014892a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wo=CC=88ginger?= Date: Fri, 29 Mar 2024 20:20:15 +0100 Subject: [PATCH] split outline module into node_repository and outline in outline all tree aware functions --- lib/radiator/outline.ex | 282 +++++------------- lib/radiator/outline/event_consumer.ex | 2 +- lib/radiator/outline/node_repository.ex | 148 +++++++++ .../controllers/api/outline_controller.ex | 2 +- lib/radiator_web/live/episode_live/index.ex | 11 +- .../radiator/outline/node_repository_test.exs | 78 +++++ test/radiator/outline_test.exs | 127 +++----- .../api/outline_controller_test.exs | 9 +- test/radiator_web/live/episode_live_test.exs | 14 +- test/support/fixtures/outline_fixtures.ex | 2 +- 10 files changed, 356 insertions(+), 319 deletions(-) create mode 100644 lib/radiator/outline/node_repository.ex create mode 100644 test/radiator/outline/node_repository_test.exs diff --git a/lib/radiator/outline.ex b/lib/radiator/outline.ex index 64d0ba16..bc2c83b5 100644 --- a/lib/radiator/outline.ex +++ b/lib/radiator/outline.ex @@ -6,80 +6,109 @@ defmodule Radiator.Outline do import Ecto.Query, warn: false alias Radiator.Outline.Node + alias Radiator.Outline.NodeRepository alias Radiator.Repo - def create(attrs \\ %{}, _socket_id \\ nil) do - attrs - |> create_node() - end - - def delete(%Node{} = node, _socket_id \\ nil) do - node - |> delete_node() - end - @doc """ - Returns the list of nodes. + Inserts a node. ## Examples - iex> list_nodes() - [%Node{}, ...] + iex> insert_node(%{content: 'foo'}) + {:ok, %Node{}} + + iex> insert_node(%{content: value}) + {:error, :parent_and_prev_not_consistent} """ - def list_nodes do - Node - |> Repo.all() + # creates a node and inserts it into the outline tree + # if a parent node is given, the new node will be inserted as a child of the parent node + # if a previous node is given, the new node will be inserted after the previous node + # if no parent is given, the new node will be inserted as a root node + # if no previous node is given, the new node will be inserted as the first child of the parent node + def insert_node(attrs) do + Repo.transaction(fn -> + prev_node_id = attrs["prev_node"] + parent_node_id = attrs["parent_node"] + episode_id = attrs["episode_id"] + # find Node which has been previously connected to prev_node + node_to_move = + Node + |> where(episode_id: ^episode_id) + |> where_prev_node_equals(prev_node_id) + |> where_parent_node_equals(parent_node_id) + |> Repo.one() + + with parent_node <- NodeRepository.get_node_if(parent_node_id), + prev_node <- NodeRepository.get_node_if(prev_node_id), + true <- parent_and_prev_consistent?(parent_node, prev_node), + {:ok, node} <- NodeRepository.create_node(attrs), + {:ok, _node_to_move} <- move_node_(node_to_move, nil, node.uuid), + {:ok, node} <- move_node_(node, parent_node_id, prev_node_id) do + node + else + false -> + Repo.rollback("Insert node failed. Parent and prev node are not consistent.") + + {:error, _} -> + Repo.rollback("Insert node failed. Unkown error") + end + end) end @doc """ - Returns the list of nodes for an episode. + Updates a nodes content. ## Examples - iex> list_nodes(123) - [%Node{}, ...] + iex> update_node_content(node, %{content: new_value}) + {:ok, %Node{}} - """ + iex> update_node_content(node, %{content: nil}) + {:error, %Ecto.Changeset{}} - def list_nodes_by_episode(episode_id) do - Node - |> where([p], p.episode_id == ^episode_id) - |> Repo.all() + """ + def update_node_content(%Node{} = node, attrs, _socket_id \\ nil) do + node + |> Node.update_content_changeset(attrs) + |> Repo.update() end @doc """ - Returns the the number of nodes for an episode - + Removes a node from the tree and deletes it from the repository. + Recursivly deletes all children if there are some. ## Examples - iex> count_nodes_by_episode(123) - 3 - - """ - def count_nodes_by_episode(episode_id) do - episode_id - |> list_nodes_by_episode() - |> Enum.count() - end + iex> remove_node(node) + {:ok, %Node{}} - @doc """ - Gets a single node. + iex> remove_node(node) + {:error, %Ecto.Changeset{}} - Raises `Ecto.NoResultsError` if the Node does not exist. + """ + def remove_node(%Node{} = node, _socket_id \\ nil) do + next_node = + Node + |> where([n], n.prev_id == ^node.uuid) + |> Repo.one() - ## Examples + prev_node = get_prev_node(node) - iex> get_node!(123) - %Node{} + if next_node do + next_node + |> Node.move_node_changeset(%{prev_id: get_node_id(prev_node)}) + |> Repo.update() + end - iex> get_node!(456) - ** (Ecto.NoResultsError) + # no tail recursion but we dont have too much levels in a tree + node + |> get_all_child_nodes() + |> Enum.each(fn child_node -> + remove_node(child_node) + end) - """ - def get_node!(id) do - Node - |> Repo.get!(id) + # finally delete the node itself from the database + NodeRepository.delete_node(node) end @doc """ @@ -115,45 +144,6 @@ defmodule Radiator.Outline do |> Repo.all() end - @doc """ - Gets a single node. - - Returns `nil` if the Node does not exist. - - ## Examples - - iex> get_node(123) - %Node{} - - iex> get_node(456) - nil - - """ - def get_node(id) do - Node - |> Repo.get(id) - end - - @doc """ - Gets a single node where id can be nil. - - Returns `nil` if the Node does not exist. - - ## Examples - - iex> get_node_if(123) - %Node{} - - iex> get_node_if(456) - nil - - iex> get_node_if(nil) - nil - - """ - def get_node_if(nil), do: nil - def get_node_if(node), do: get_node(node) - @doc """ Gets all nodes of an episode as a tree. Uses a Common Table Expression (CTE) to recursively query the database. @@ -237,71 +227,6 @@ defmodule Radiator.Outline do {:ok, tree} end - @doc """ - Creates a node. - - ## Examples - - iex> create_node(%{field: value}) - {:ok, %Node{}} - - iex> create_node(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_node(attrs \\ %{}, _socket_id \\ nil) do - %Node{} - |> Node.insert_changeset(attrs) - |> Repo.insert() - end - - @doc """ - Inserts a node. - - ## Examples - - iex> insert_node(%{content: 'foo'}) - {:ok, %Node{}} - - iex> insert_node(%{content: value}) - {:error, :parent_and_prev_not_consistent} - - """ - # creates a node and inserts it into the outline tree - # if a parent node is given, the new node will be inserted as a child of the parent node - # if a previous node is given, the new node will be inserted after the previous node - # if no parent is given, the new node will be inserted as a root node - # if no previous node is given, the new node will be inserted as the first child of the parent node - def insert_node(attrs) do - Repo.transaction(fn -> - prev_node_id = attrs["prev_node"] - parent_node_id = attrs["parent_node"] - episode_id = attrs["episode_id"] - # find Node which has been previously connected to prev_node - node_to_move = - Node - |> where(episode_id: ^episode_id) - |> where_prev_node_equals(prev_node_id) - |> where_parent_node_equals(parent_node_id) - |> Repo.one() - - with parent_node <- get_node_if(parent_node_id), - prev_node <- get_node_if(prev_node_id), - true <- parent_and_prev_consistent?(parent_node, prev_node), - {:ok, node} <- create_node(attrs), - {:ok, _node_to_move} <- move_node_(node_to_move, nil, node.uuid), - {:ok, node} <- move_node_(node, parent_node_id, prev_node_id) do - node - else - false -> - Repo.rollback("Insert node failed. Parent and prev node are not consistent.") - - {:error, _} -> - Repo.rollback("Insert node failed. Unkown error") - end - end) - end - defp move_node_(nil, _parent_node_id, _prev_node_id), do: {:ok, nil} defp move_node_(node, parent_node_id, prev_node_id) do @@ -326,61 +251,6 @@ defmodule Radiator.Outline do defp where_parent_node_equals(node, nil), do: where(node, [n], is_nil(n.parent_id)) defp where_parent_node_equals(node, parent_id), do: where(node, [n], n.parent_id == ^parent_id) - @doc """ - Updates a nodes content. - - ## Examples - - iex> update_node_content(node, %{content: new_value}) - {:ok, %Node{}} - - iex> update_node_content(node, %{content: nil}) - {:error, %Ecto.Changeset{}} - - """ - def update_node_content(%Node{} = node, attrs, _socket_id \\ nil) do - node - |> Node.update_content_changeset(attrs) - |> Repo.update() - end - - @doc """ - Deletes a node. - - ## Examples - - iex> delete_node(node) - {:ok, %Node{}} - - iex> delete_node(node) - {:error, %Ecto.Changeset{}} - - """ - def delete_node(%Node{} = node) do - next_node = - Node - |> where([n], n.prev_id == ^node.uuid) - |> Repo.one() - - prev_node = get_prev_node(node) - - if next_node do - next_node - |> Node.move_node_changeset(%{prev_id: get_node_id(prev_node)}) - |> Repo.update() - end - - # no tail recursion but we dont have too much levels in a tree - node - |> get_all_child_nodes() - |> Enum.each(fn child_node -> - delete_node(child_node) - end) - - node - |> Repo.delete() - end - defp get_node_id(nil), do: nil defp get_node_id(%Node{} = node) do diff --git a/lib/radiator/outline/event_consumer.ex b/lib/radiator/outline/event_consumer.ex index 4d7d71a7..da9a5c63 100644 --- a/lib/radiator/outline/event_consumer.ex +++ b/lib/radiator/outline/event_consumer.ex @@ -23,7 +23,7 @@ defmodule Radiator.Outline.EventConsumer do defp process_event(%InsertNodeEvent{payload: payload} = _event) do payload - |> Outline.create_node() + |> Outline.insert_node() |> handle_insert_result() # validate diff --git a/lib/radiator/outline/node_repository.ex b/lib/radiator/outline/node_repository.ex new file mode 100644 index 00000000..2ed58cec --- /dev/null +++ b/lib/radiator/outline/node_repository.ex @@ -0,0 +1,148 @@ +defmodule Radiator.Outline.NodeRepository do + @moduledoc """ + Repository functions for the Node module. + Simple not tree aware node database actions. Mostly used internal and by tests. + """ + import Ecto.Query, warn: false + + alias Radiator.Outline.Node + alias Radiator.Repo + + @doc """ + Creates a node in the repository. + + ## Examples + + iex> create_node(%{field: value}) + {:ok, %Node{}} + + iex> create_node(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_node(attrs \\ %{}) do + %Node{} + |> Node.insert_changeset(attrs) + |> Repo.insert() + end + + @doc """ + Deletes a node from the repository. + + ## Examples + + iex> delete_node(%{field: value}) + {:ok, %Node{}} + + iex> delete_node(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def delete_node(%Node{} = node) do + node + |> Repo.delete() + end + + @doc """ + Returns the list of nodes. + + ## Examples + + iex> list_nodes() + [%Node{}, ...] + + """ + def list_nodes do + Node + |> Repo.all() + end + + @doc """ + Returns the list of nodes for an episode. + + ## Examples + + iex> list_nodes(123) + [%Node{}, ...] + + """ + + def list_nodes_by_episode(episode_id) do + Node + |> where([p], p.episode_id == ^episode_id) + |> Repo.all() + end + + @doc """ + Returns the the number of nodes for an episode + + ## Examples + + iex> count_nodes_by_episode(123) + 3 + + """ + def count_nodes_by_episode(episode_id) do + episode_id + |> list_nodes_by_episode() + |> Enum.count() + end + + @doc """ + Gets a single node. + + Returns `nil` if the Node does not exist. + + ## Examples + + iex> get_node(123) + %Node{} + + iex> get_node(456) + nil + + """ + def get_node(id) do + Node + |> Repo.get(id) + end + + @doc """ + Gets a single node where id can be nil. + + Returns `nil` if the Node does not exist. + + ## Examples + + iex> get_node_if(123) + %Node{} + + iex> get_node_if(456) + nil + + iex> get_node_if(nil) + nil + + """ + def get_node_if(nil), do: nil + def get_node_if(node), do: get_node(node) + + @doc """ + Gets a single node. + + Raises `Ecto.NoResultsError` if the Node does not exist. + + ## Examples + + iex> get_node!(123) + %Node{} + + iex> get_node!(456) + ** (Ecto.NoResultsError) + + """ + def get_node!(id) do + Node + |> Repo.get!(id) + end +end diff --git a/lib/radiator_web/controllers/api/outline_controller.ex b/lib/radiator_web/controllers/api/outline_controller.ex index 91889f72..87d7cde4 100644 --- a/lib/radiator_web/controllers/api/outline_controller.ex +++ b/lib/radiator_web/controllers/api/outline_controller.ex @@ -33,7 +33,7 @@ defmodule RadiatorWeb.Api.OutlineController do defp create_node(_, _, nil), do: {:error, :episode} defp create_node(user, content, episode_id) do - Outline.create(%{ + Outline.insert_node(%{ "content" => content, "creator_id" => user.id, "episode_id" => episode_id diff --git a/lib/radiator_web/live/episode_live/index.ex b/lib/radiator_web/live/episode_live/index.ex index 403837a0..97fce833 100644 --- a/lib/radiator_web/live/episode_live/index.ex +++ b/lib/radiator_web/live/episode_live/index.ex @@ -2,6 +2,7 @@ defmodule RadiatorWeb.EpisodeLive.Index do use RadiatorWeb, :live_view alias Radiator.Outline + alias Radiator.Outline.NodeRepository alias Radiator.Podcast alias RadiatorWeb.Endpoint @@ -50,7 +51,7 @@ defmodule RadiatorWeb.EpisodeLive.Index do episode = socket.assigns.selected_episode attrs = Map.merge(params, %{"creator_id" => user.id, "episode_id" => episode.id}) - case Outline.create(attrs, socket.id) do + case Outline.insert_node(attrs) do {:ok, node} -> socket |> reply(:reply, Map.put(node, :temp_id, temp_id)) _ -> socket |> reply(:noreply) end @@ -59,7 +60,7 @@ defmodule RadiatorWeb.EpisodeLive.Index do def handle_event("update_node", %{"uuid" => uuid} = params, socket) do attrs = Map.merge(%{"parent_id" => nil, "prev_id" => nil}, params) - case Outline.get_node(uuid) do + case NodeRepository.get_node(uuid) do nil -> nil node -> Outline.update_node_content(node, attrs, socket.id) end @@ -69,9 +70,9 @@ defmodule RadiatorWeb.EpisodeLive.Index do end def handle_event("delete_node", %{"uuid" => uuid}, socket) do - case Outline.get_node(uuid) do + case NodeRepository.get_node(uuid) do nil -> nil - node -> Outline.delete(node, socket.id) + node -> Outline.remove_node(node, socket.id) end socket @@ -110,6 +111,6 @@ defmodule RadiatorWeb.EpisodeLive.Index do Podcast.get_current_episode_for_show(show_id) end - defp get_nodes(%{id: id}), do: Outline.list_nodes_by_episode(id) + defp get_nodes(%{id: id}), do: NodeRepository.list_nodes_by_episode(id) defp get_nodes(_), do: [] end diff --git a/test/radiator/outline/node_repository_test.exs b/test/radiator/outline/node_repository_test.exs new file mode 100644 index 00000000..0fc179ce --- /dev/null +++ b/test/radiator/outline/node_repository_test.exs @@ -0,0 +1,78 @@ +defmodule Radiator.Outline.NodeRepositoryTest do + use Radiator.DataCase + + alias Radiator.Outline.Node + alias Radiator.Outline.NodeRepository + alias Radiator.PodcastFixtures + + import Radiator.OutlineFixtures + import Ecto.Query, warn: false + + @invalid_attrs %{episode_id: nil} + + describe "create_node/1" do + test "with valid data creates a node" do + episode = PodcastFixtures.episode_fixture() + valid_attrs = %{content: "some content", episode_id: episode.id} + + assert {:ok, %Node{} = node} = NodeRepository.create_node(valid_attrs) + assert node.content == "some content" + end + + test "trims whitespace from content" do + episode = PodcastFixtures.episode_fixture() + valid_attrs = %{content: " some content ", episode_id: episode.id} + + assert {:ok, %Node{} = node} = NodeRepository.create_node(valid_attrs) + assert node.content == "some content" + end + + test "can have a creator" do + episode = PodcastFixtures.episode_fixture() + user = %{id: 2} + valid_attrs = %{content: "some content", episode_id: episode.id, creator_id: user.id} + + assert {:ok, %Node{} = node} = NodeRepository.create_node(valid_attrs) + assert node.content == "some content" + assert node.creator_id == user.id + end + + test "with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = NodeRepository.create_node(@invalid_attrs) + end + end + + describe "get_node!/1" do + test "returns the node with given id" do + node = node_fixture() + assert NodeRepository.get_node!(node.uuid) == node + end + end + + describe "list_nodes/0" do + test "returns all nodes" do + node1 = node_fixture() + node2 = node_fixture() + + assert NodeRepository.list_nodes() == [node1, node2] + end + end + + describe "list_nodes_by_episode/1" do + test "list_nodes/1 returns only nodes of this episode" do + node1 = node_fixture() + node2 = node_fixture() + + assert NodeRepository.list_nodes_by_episode(node1.episode_id) == [node1] + assert NodeRepository.list_nodes_by_episode(node2.episode_id) == [node2] + end + end + + describe "delete_node/1" do + test "deletes the node" do + node = node_fixture() + assert {:ok, %Node{}} = NodeRepository.delete_node(node) + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(node.uuid) end + end + end +end diff --git a/test/radiator/outline_test.exs b/test/radiator/outline_test.exs index 992898d9..f1cce3a6 100644 --- a/test/radiator/outline_test.exs +++ b/test/radiator/outline_test.exs @@ -3,69 +3,12 @@ defmodule Radiator.OutlineTest do alias Radiator.Outline alias Radiator.Outline.Node + alias Radiator.Outline.NodeRepository alias Radiator.PodcastFixtures import Radiator.OutlineFixtures import Ecto.Query, warn: false - @invalid_attrs %{episode_id: nil} - - describe "list_nodes/0" do - test "returns all nodes" do - node1 = node_fixture() - node2 = node_fixture() - - assert Outline.list_nodes() == [node1, node2] - end - - test "list_nodes/1 returns only nodes of this episode" do - node1 = node_fixture() - node2 = node_fixture() - - assert Outline.list_nodes_by_episode(node1.episode_id) == [node1] - assert Outline.list_nodes_by_episode(node2.episode_id) == [node2] - end - end - - describe "get_node!/1" do - test "returns the node with given id" do - node = node_fixture() - assert Outline.get_node!(node.uuid) == node - end - end - - describe "create_node/1" do - test "with valid data creates a node" do - 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 "trims whitespace from content" do - 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 "can have a creator" do - episode = PodcastFixtures.episode_fixture() - user = %{id: 2} - valid_attrs = %{content: "some content", episode_id: episode.id, creator_id: user.id} - - assert {:ok, %Node{} = node} = Outline.create_node(valid_attrs, user) - assert node.content == "some content" - assert node.creator_id == user.id - end - - test "with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = Outline.create_node(@invalid_attrs) - end - end - describe "update_node_content/2" do test "with valid data updates the node" do node = node_fixture() @@ -78,7 +21,7 @@ defmodule Radiator.OutlineTest do test "with invalid data returns error changeset" do node = node_fixture() assert {:error, %Ecto.Changeset{}} = Outline.update_node_content(node, %{"content" => nil}) - assert node == Outline.get_node!(node.uuid) + assert node == NodeRepository.get_node!(node.uuid) end end @@ -117,7 +60,7 @@ defmodule Radiator.OutlineTest do node_3: node_3, nested_node_1: nested_node_1 } do - count_nodes = Outline.count_nodes_by_episode(node_3.episode_id) + count_nodes = NodeRepository.count_nodes_by_episode(node_3.episode_id) node_attrs = %{ "content" => "new node", @@ -127,7 +70,7 @@ defmodule Radiator.OutlineTest do } Outline.insert_node(node_attrs) - new_count_nodes = Outline.count_nodes_by_episode(node_3.episode_id) + new_count_nodes = NodeRepository.count_nodes_by_episode(node_3.episode_id) assert new_count_nodes == count_nodes + 1 end @@ -175,9 +118,9 @@ defmodule Radiator.OutlineTest do {:ok, new_node} = Outline.insert_node(node_attrs) - assert Outline.get_node!(nested_node_2.uuid).prev_id == new_node.uuid + assert NodeRepository.get_node!(nested_node_2.uuid).prev_id == new_node.uuid assert new_node.prev_id == nested_node_1.uuid - assert Outline.get_node!(nested_node_1.uuid).prev_id == nil + assert NodeRepository.get_node!(nested_node_1.uuid).prev_id == nil end test "inserted node can be inserted at the end", %{ @@ -194,9 +137,9 @@ defmodule Radiator.OutlineTest do {:ok, new_node} = Outline.insert_node(node_attrs) - assert Outline.get_node!(nested_node_2.uuid).prev_id == nested_node_1.uuid + assert NodeRepository.get_node!(nested_node_2.uuid).prev_id == nested_node_1.uuid assert new_node.prev_id == nested_node_2.uuid - assert Outline.get_node!(nested_node_1.uuid).prev_id == nil + assert NodeRepository.get_node!(nested_node_1.uuid).prev_id == nil end test "without a prev node inserted node will be first in list", %{ @@ -213,8 +156,8 @@ defmodule Radiator.OutlineTest do {:ok, new_node} = Outline.insert_node(node_attrs) assert new_node.prev_id == nil - assert Outline.get_node!(nested_node_1.uuid).prev_id == new_node.uuid - assert Outline.get_node!(nested_node_2.uuid).prev_id == nested_node_1.uuid + assert NodeRepository.get_node!(nested_node_1.uuid).prev_id == new_node.uuid + assert NodeRepository.get_node!(nested_node_2.uuid).prev_id == nested_node_1.uuid end test "without a parent node the inserted node will be put at the top", %{ @@ -227,7 +170,7 @@ defmodule Radiator.OutlineTest do assert new_node.prev_id == nil assert new_node.parent_id == nil - assert Outline.get_node!(parent_node.uuid).prev_id == new_node.uuid + assert NodeRepository.get_node!(parent_node.uuid).prev_id == new_node.uuid end test "parent node and prev node need to be consistent", %{ @@ -267,7 +210,7 @@ defmodule Radiator.OutlineTest do parent_node: parent_node, nested_node_1: nested_node_1 } do - count_nodes = Outline.count_nodes_by_episode(parent_node.episode_id) + count_nodes = NodeRepository.count_nodes_by_episode(parent_node.episode_id) node_attrs = %{ "content" => "new node", @@ -277,19 +220,19 @@ defmodule Radiator.OutlineTest do } {:error, _error_message} = Outline.insert_node(node_attrs) - new_count_nodes = Outline.count_nodes_by_episode(parent_node.episode_id) + new_count_nodes = NodeRepository.count_nodes_by_episode(parent_node.episode_id) # count stays the same assert new_count_nodes == count_nodes end end - describe "delete_node/1" do + describe "remove_node/1" do setup :complex_node_fixture test "deletes the node" do node = node_fixture() - assert {:ok, %Node{}} = Outline.delete_node(node) - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(node.uuid) end + assert {:ok, %Node{}} = Outline.remove_node(node) + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(node.uuid) end end test "next node must be updated", %{ @@ -299,10 +242,10 @@ defmodule Radiator.OutlineTest do } do assert node_4.prev_id == node_3.uuid - assert {:ok, %Node{}} = Outline.delete_node(node_3) + assert {:ok, %Node{}} = Outline.remove_node(node_3) # reload nodes - node_4 = Outline.get_node!(node_4.uuid) - node_2 = Outline.get_node!(node_2.uuid) + node_4 = NodeRepository.get_node!(node_4.uuid) + node_2 = NodeRepository.get_node!(node_2.uuid) assert node_4.prev_id == node_2.uuid end @@ -311,9 +254,9 @@ defmodule Radiator.OutlineTest do node_6: node_6 } do episode_id = node_6.episode_id - count_nodes = Outline.count_nodes_by_episode(episode_id) - assert {:ok, %Node{}} = Outline.delete_node(node_6) - new_count_nodes = Outline.count_nodes_by_episode(episode_id) + count_nodes = NodeRepository.count_nodes_by_episode(episode_id) + assert {:ok, %Node{}} = Outline.remove_node(node_6) + new_count_nodes = NodeRepository.count_nodes_by_episode(episode_id) assert new_count_nodes == count_nodes - 1 end @@ -323,12 +266,12 @@ defmodule Radiator.OutlineTest do } do episode_id = node_1.episode_id - count_nodes = Outline.count_nodes_by_episode(episode_id) - assert {:ok, %Node{}} = Outline.delete_node(node_1) - new_count_nodes = Outline.count_nodes_by_episode(episode_id) + count_nodes = NodeRepository.count_nodes_by_episode(episode_id) + assert {:ok, %Node{}} = Outline.remove_node(node_1) + new_count_nodes = NodeRepository.count_nodes_by_episode(episode_id) assert new_count_nodes == count_nodes - 1 - node_2 = Outline.get_node!(node_2.uuid) + node_2 = NodeRepository.get_node!(node_2.uuid) assert node_2.prev_id == nil end @@ -337,10 +280,10 @@ defmodule Radiator.OutlineTest do nested_node_1: nested_node_1, nested_node_2: nested_node_2 } do - assert {:ok, %Node{}} = Outline.delete_node(node_3) + assert {:ok, %Node{}} = Outline.remove_node(node_3) - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(nested_node_1.uuid) end - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(nested_node_2.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(nested_node_1.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(nested_node_2.uuid) end end test "when top parent gets deleted the whole tree will be gone", %{ @@ -350,13 +293,13 @@ defmodule Radiator.OutlineTest do nested_node_2: nested_node_2, parent_node: parent_node } do - assert {:ok, %Node{}} = Outline.delete_node(parent_node) + assert {:ok, %Node{}} = Outline.remove_node(parent_node) # test some of elements in the tree - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(node_1.uuid) end - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(node_4.uuid) end - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(node_6.uuid) end - assert_raise Ecto.NoResultsError, fn -> Outline.get_node!(nested_node_2.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(node_1.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(node_4.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(node_6.uuid) end + assert_raise Ecto.NoResultsError, fn -> NodeRepository.get_node!(nested_node_2.uuid) end end end @@ -367,7 +310,7 @@ defmodule Radiator.OutlineTest do episode_id = parent_node.episode_id assert {:ok, tree} = Outline.get_node_tree(episode_id) - all_nodes = Outline.list_nodes_by_episode(episode_id) + all_nodes = NodeRepository.list_nodes_by_episode(episode_id) assert Enum.count(tree) == Enum.count(all_nodes) diff --git a/test/radiator_web/controllers/api/outline_controller_test.exs b/test/radiator_web/controllers/api/outline_controller_test.exs index 68b90eb1..acacbc08 100644 --- a/test/radiator_web/controllers/api/outline_controller_test.exs +++ b/test/radiator_web/controllers/api/outline_controller_test.exs @@ -4,7 +4,8 @@ defmodule RadiatorWeb.Api.OutlineControllerTest do import Radiator.AccountsFixtures import Radiator.PodcastFixtures - alias Radiator.{Accounts, Outline, Podcast} + alias Radiator.{Accounts, Podcast} + alias Radiator.Outline.NodeRepository describe "POST /api/v1/outline" do setup %{conn: conn} do @@ -31,7 +32,7 @@ defmodule RadiatorWeb.Api.OutlineControllerTest do %{"uuid" => uuid} = json_response(conn, 200) assert %{content: "new node content", creator_id: ^user_id} = - Outline.get_node!(uuid) + NodeRepository.get_node!(uuid) end test "created node is connected to episode", %{ @@ -45,7 +46,9 @@ defmodule RadiatorWeb.Api.OutlineControllerTest do %{"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) + + assert %{content: "new node content", episode_id: ^episode_id} = + NodeRepository.get_node!(uuid) end test "can't create node when content is missing", %{conn: conn} do diff --git a/test/radiator_web/live/episode_live_test.exs b/test/radiator_web/live/episode_live_test.exs index c927d029..2702898d 100644 --- a/test/radiator_web/live/episode_live_test.exs +++ b/test/radiator_web/live/episode_live_test.exs @@ -6,7 +6,7 @@ defmodule RadiatorWeb.EpisodeLiveTest do import Radiator.PodcastFixtures import Radiator.OutlineFixtures - alias Radiator.Outline + alias Radiator.Outline.NodeRepository describe "Episode page is restricted" do setup do @@ -60,7 +60,7 @@ defmodule RadiatorWeb.EpisodeLiveTest do test "lists all nodes", %{conn: conn, show: show} do {:ok, live, _html} = live(conn, ~p"/admin/podcast/#{show.id}") - nodes = Outline.list_nodes() + nodes = NodeRepository.list_nodes() assert_push_event(live, "list", %{nodes: ^nodes}) end @@ -75,14 +75,12 @@ defmodule RadiatorWeb.EpisodeLiveTest do assert live |> render_hook(:create_node, params) node = - Outline.list_nodes() + NodeRepository.list_nodes() |> Enum.find(&(&1.content == "new node temp content")) node_with_temp_id = Map.put(node, :temp_id, temp_id) assert_reply(live, ^node_with_temp_id) - - # FIXME: assert_push_event(other_live, "insert", ^node) end test "update node", %{conn: conn, show: show, episode: episode} do @@ -99,12 +97,11 @@ defmodule RadiatorWeb.EpisodeLiveTest do assert live |> render_hook(:update_node, params) updated_node = - Outline.list_nodes() + NodeRepository.list_nodes() |> Enum.find(&(&1.content == "update node content")) assert updated_node.uuid == params.uuid assert updated_node.content == params.content - # FIXME: assert_push_event(other_live, "update", ^updated_node) end test "delete node", %{conn: conn, show: show, episode: episode} do @@ -115,9 +112,6 @@ defmodule RadiatorWeb.EpisodeLiveTest do params = Map.from_struct(node) assert live |> render_hook(:delete_node, params) - - # FIXME: assert_push_event(other_live, "delete", %{uuid: deleted_uuid}) - # FIXME: assert deleted_uuid == node.uuid end end end diff --git a/test/support/fixtures/outline_fixtures.ex b/test/support/fixtures/outline_fixtures.ex index 0bc54a54..7bbf41af 100644 --- a/test/support/fixtures/outline_fixtures.ex +++ b/test/support/fixtures/outline_fixtures.ex @@ -18,7 +18,7 @@ defmodule Radiator.OutlineFixtures do content: "some content", episode_id: episode.id }) - |> Radiator.Outline.create_node() + |> Radiator.Outline.NodeRepository.create_node() node end