Merge branch 'feature/custom-runtime-modules' into 'develop'
[akkoma] / test / conversation / participation_test.exs
index f430bdf75f5def543af0eab7a9cf9cceb4ae5cbf..ba81c0d4bb2eb42025fcb07eb6996ffebfa94954 100644 (file)
@@ -5,7 +5,9 @@
 defmodule Pleroma.Conversation.ParticipationTest do
   use Pleroma.DataCase
   import Pleroma.Factory
+  alias Pleroma.Conversation
   alias Pleroma.Conversation.Participation
+  alias Pleroma.Repo
   alias Pleroma.User
   alias Pleroma.Web.CommonAPI
 
@@ -23,6 +25,39 @@ defmodule Pleroma.Conversation.ParticipationTest do
     assert %Pleroma.Conversation{} = participation.conversation
   end
 
+  test "for a new conversation or a reply, it doesn't mark the author's participation as unread" do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, _} =
+      CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
+
+    user = User.get_cached_by_id(user.id)
+    other_user = User.get_cached_by_id(other_user.id)
+
+    [%{read: true}] = Participation.for_user(user)
+    [%{read: false} = participation] = Participation.for_user(other_user)
+
+    assert User.get_cached_by_id(user.id).unread_conversation_count == 0
+    assert User.get_cached_by_id(other_user.id).unread_conversation_count == 1
+
+    {:ok, _} =
+      CommonAPI.post(other_user, %{
+        "status" => "Hey @#{user.nickname}.",
+        "visibility" => "direct",
+        "in_reply_to_conversation_id" => participation.id
+      })
+
+    user = User.get_cached_by_id(user.id)
+    other_user = User.get_cached_by_id(other_user.id)
+
+    [%{read: false}] = Participation.for_user(user)
+    [%{read: true}] = Participation.for_user(other_user)
+
+    assert User.get_cached_by_id(user.id).unread_conversation_count == 1
+    assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0
+  end
+
   test "for a new conversation, it sets the recipents of the participation" do
     user = insert(:user)
     other_user = insert(:user)
@@ -32,7 +67,7 @@ defmodule Pleroma.Conversation.ParticipationTest do
       CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
 
     user = User.get_cached_by_id(user.id)
-    other_user = User.get_cached_by_id(user.id)
+    other_user = User.get_cached_by_id(other_user.id)
     [participation] = Participation.for_user(user)
     participation = Pleroma.Repo.preload(participation, :recipients)
 
@@ -65,7 +100,9 @@ defmodule Pleroma.Conversation.ParticipationTest do
     assert participation.user_id == user.id
     assert participation.conversation_id == conversation.id
 
+    # Needed because updated_at is accurate down to a second
     :timer.sleep(1000)
+
     # Creating again returns the same participation
     {:ok, %Participation{} = participation_two} =
       Participation.create_for_user_and_conversation(user, conversation)
@@ -100,12 +137,24 @@ defmodule Pleroma.Conversation.ParticipationTest do
     refute participation.read
   end
 
+  test "it marks all the user's participations as read" do
+    user = insert(:user)
+    other_user = insert(:user)
+    participation1 = insert(:participation, %{read: false, user: user})
+    participation2 = insert(:participation, %{read: false, user: user})
+    participation3 = insert(:participation, %{read: false, user: other_user})
+
+    {:ok, _, [%{read: true}, %{read: true}]} = Participation.mark_all_as_read(user)
+
+    assert Participation.get(participation1.id).read == true
+    assert Participation.get(participation2.id).read == true
+    assert Participation.get(participation3.id).read == false
+  end
+
   test "gets all the participations for a user, ordered by updated at descending" do
     user = insert(:user)
     {:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
-    :timer.sleep(1000)
     {:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
-    :timer.sleep(1000)
 
     {:ok, activity_three} =
       CommonAPI.post(user, %{
@@ -114,6 +163,17 @@ defmodule Pleroma.Conversation.ParticipationTest do
         "in_reply_to_status_id" => activity_one.id
       })
 
+    # Offset participations because the accuracy of updated_at is down to a second
+
+    for {activity, offset} <- [{activity_two, 1}, {activity_three, 2}] do
+      conversation = Conversation.get_for_ap_id(activity.data["context"])
+      participation = Participation.for_user_and_conversation(user, conversation)
+      updated_at = NaiveDateTime.add(Map.get(participation, :updated_at), offset)
+
+      Ecto.Changeset.change(participation, %{updated_at: updated_at})
+      |> Repo.update!()
+    end
+
     assert [participation_one, participation_two] = Participation.for_user(user)
 
     object2 = Pleroma.Object.normalize(activity_two)
@@ -169,4 +229,134 @@ defmodule Pleroma.Conversation.ParticipationTest do
     assert user in participation.recipients
     assert other_user in participation.recipients
   end
+
+  describe "blocking" do
+    test "when the user blocks a recipient, the existing conversations with them are marked as read" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, _direct1} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct2} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct3} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _direct4} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}, @#{third_user.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] =
+               Participation.for_user(blocker)
+
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 4
+
+      {:ok, _user_relationship} = User.block(blocker, blocked)
+
+      # The conversations with the blocked user are marked as read
+      assert [%{read: true}, %{read: true}, %{read: true}, %{read: false}] =
+               Participation.for_user(blocker)
+
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 1
+
+      # The conversation is not marked as read for the blocked user
+      assert [_, _, %{read: false}] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+
+      # The conversation is not marked as read for the third user
+      assert [%{read: false}, _, _] = Participation.for_user(third_user)
+      assert User.get_cached_by_id(third_user.id).unread_conversation_count == 1
+    end
+
+    test "the new conversation with the blocked user is not marked as unread " do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, _user_relationship} = User.block(blocker, blocked)
+
+      # When the blocked user is the author
+      {:ok, _direct1} =
+        CommonAPI.post(blocked, %{
+          "status" => "Hi @#{blocker.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      # When the blocked user is a recipient
+      {:ok, _direct2} =
+        CommonAPI.post(third_user, %{
+          "status" => "Hi @#{blocker.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      assert [%{read: true}, %{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [%{read: false}, _] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+    end
+
+    test "the conversation with the blocked user is not marked as unread on a reply" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      third_user = insert(:user)
+
+      {:ok, _direct1} =
+        CommonAPI.post(blocker, %{
+          "status" => "Hi @#{third_user.nickname}, @#{blocked.nickname}",
+          "visibility" => "direct"
+        })
+
+      {:ok, _user_relationship} = User.block(blocker, blocked)
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [blocked_participation] = Participation.for_user(blocked)
+
+      # When it's a reply from the blocked user
+      {:ok, _direct2} =
+        CommonAPI.post(blocked, %{
+          "status" => "reply",
+          "visibility" => "direct",
+          "in_reply_to_conversation_id" => blocked_participation.id
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      assert [third_user_participation] = Participation.for_user(third_user)
+
+      # When it's a reply from the third user
+      {:ok, _direct3} =
+        CommonAPI.post(third_user, %{
+          "status" => "reply",
+          "visibility" => "direct",
+          "in_reply_to_conversation_id" => third_user_participation.id
+        })
+
+      assert [%{read: true}] = Participation.for_user(blocker)
+      assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0
+
+      # Marked as unread for the blocked user
+      assert [%{read: false}] = Participation.for_user(blocked)
+      assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1
+    end
+  end
 end