Revert "Merge branch 'streamer-refactoring' into 'develop'"
[akkoma] / test / web / activity_pub / utils_test.exs
index 2e5e95795ef08a278d9751b1f4d5270fed801193..eb429b2c48530d9eb33a7be002e6646844e4ac0a 100644 (file)
@@ -1,10 +1,41 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
 defmodule Pleroma.Web.ActivityPub.UtilsTest do
   use Pleroma.DataCase
-  alias Pleroma.Web.CommonAPI
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.Repo
+  alias Pleroma.User
+  alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Utils
+  alias Pleroma.Web.CommonAPI
 
   import Pleroma.Factory
 
+  require Pleroma.Constants
+
+  describe "fetch the latest Follow" do
+    test "fetches the latest Follow activity" do
+      %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
+      follower = User.get_cached_by_ap_id(activity.data["actor"])
+      followed = User.get_cached_by_ap_id(activity.data["object"])
+
+      assert activity == Utils.fetch_latest_follow(follower, followed)
+    end
+  end
+
+  describe "fetch the latest Block" do
+    test "fetches the latest Block activity" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      {:ok, activity} = ActivityPub.block(blocker, blocked)
+
+      assert activity == Utils.fetch_latest_block(blocker, blocked)
+    end
+  end
+
   describe "determine_explicit_mentions()" do
     test "works with an object that has mentions" do
       object = %{
@@ -58,6 +89,32 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
     end
   end
 
+  describe "make_unlike_data/3" do
+    test "returns data for unlike activity" do
+      user = insert(:user)
+      like_activity = insert(:like_activity, data_attrs: %{"context" => "test context"})
+
+      assert Utils.make_unlike_data(user, like_activity, nil) == %{
+               "type" => "Undo",
+               "actor" => user.ap_id,
+               "object" => like_activity.data,
+               "to" => [user.follower_address, like_activity.data["actor"]],
+               "cc" => [Pleroma.Constants.as_public()],
+               "context" => like_activity.data["context"]
+             }
+
+      assert Utils.make_unlike_data(user, like_activity, "9mJEZK0tky1w2xD2vY") == %{
+               "type" => "Undo",
+               "actor" => user.ap_id,
+               "object" => like_activity.data,
+               "to" => [user.follower_address, like_activity.data["actor"]],
+               "cc" => [Pleroma.Constants.as_public()],
+               "context" => like_activity.data["context"],
+               "id" => "9mJEZK0tky1w2xD2vY"
+             }
+    end
+  end
+
   describe "make_like_data" do
     setup do
       user = insert(:user)
@@ -104,4 +161,244 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
       assert Enum.sort(cc) == expected_cc
     end
   end
+
+  describe "fetch_ordered_collection" do
+    import Tesla.Mock
+
+    test "fetches the first OrderedCollectionPage when an OrderedCollection is encountered" do
+      mock(fn
+        %{method: :get, url: "http://mastodon.com/outbox"} ->
+          json(%{"type" => "OrderedCollection", "first" => "http://mastodon.com/outbox?page=true"})
+
+        %{method: :get, url: "http://mastodon.com/outbox?page=true"} ->
+          json(%{"type" => "OrderedCollectionPage", "orderedItems" => ["ok"]})
+      end)
+
+      assert Utils.fetch_ordered_collection("http://mastodon.com/outbox", 1) == ["ok"]
+    end
+
+    test "fetches several pages in the right order one after another, but only the specified amount" do
+      mock(fn
+        %{method: :get, url: "http://example.com/outbox"} ->
+          json(%{
+            "type" => "OrderedCollectionPage",
+            "orderedItems" => [0],
+            "next" => "http://example.com/outbox?page=1"
+          })
+
+        %{method: :get, url: "http://example.com/outbox?page=1"} ->
+          json(%{
+            "type" => "OrderedCollectionPage",
+            "orderedItems" => [1],
+            "next" => "http://example.com/outbox?page=2"
+          })
+
+        %{method: :get, url: "http://example.com/outbox?page=2"} ->
+          json(%{"type" => "OrderedCollectionPage", "orderedItems" => [2]})
+      end)
+
+      assert Utils.fetch_ordered_collection("http://example.com/outbox", 0) == [0]
+      assert Utils.fetch_ordered_collection("http://example.com/outbox", 1) == [0, 1]
+    end
+
+    test "returns an error if the url doesn't have an OrderedCollection/Page" do
+      mock(fn
+        %{method: :get, url: "http://example.com/not-an-outbox"} ->
+          json(%{"type" => "NotAnOutbox"})
+      end)
+
+      assert {:error, _} = Utils.fetch_ordered_collection("http://example.com/not-an-outbox", 1)
+    end
+
+    test "returns the what was collected if there are less pages than specified" do
+      mock(fn
+        %{method: :get, url: "http://example.com/outbox"} ->
+          json(%{
+            "type" => "OrderedCollectionPage",
+            "orderedItems" => [0],
+            "next" => "http://example.com/outbox?page=1"
+          })
+
+        %{method: :get, url: "http://example.com/outbox?page=1"} ->
+          json(%{"type" => "OrderedCollectionPage", "orderedItems" => [1]})
+      end)
+
+      assert Utils.fetch_ordered_collection("http://example.com/outbox", 5) == [0, 1]
+    end
+  end
+
+  test "make_json_ld_header/0" do
+    assert Utils.make_json_ld_header() == %{
+             "@context" => [
+               "https://www.w3.org/ns/activitystreams",
+               "http://localhost:4001/schemas/litepub-0.1.jsonld",
+               %{
+                 "@language" => "und"
+               }
+             ]
+           }
+  end
+
+  describe "get_existing_votes" do
+    test "fetches existing votes" do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          "status" => "How do I pronounce LaTeX?",
+          "poll" => %{
+            "options" => ["laytekh", "lahtekh", "latex"],
+            "expires_in" => 20,
+            "multiple" => true
+          }
+        })
+
+      object = Object.normalize(activity)
+      {:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
+      assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
+    end
+
+    test "fetches only Create activities" do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          "status" => "Are we living in a society?",
+          "poll" => %{
+            "options" => ["yes", "no"],
+            "expires_in" => 20
+          }
+        })
+
+      object = Object.normalize(activity)
+      {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
+      vote_object = Object.normalize(vote)
+      {:ok, _activity, _object} = ActivityPub.like(user, vote_object)
+      [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
+      assert fetched_vote.id == vote.id
+    end
+  end
+
+  describe "update_follow_state_for_all/2" do
+    test "updates the state of all Follow activities with the same actor and object" do
+      user = insert(:user, info: %{locked: true})
+      follower = insert(:user)
+
+      {:ok, follow_activity} = ActivityPub.follow(follower, user)
+      {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
+
+      data =
+        follow_activity_two.data
+        |> Map.put("state", "accept")
+
+      cng = Ecto.Changeset.change(follow_activity_two, data: data)
+
+      {:ok, follow_activity_two} = Repo.update(cng)
+
+      {:ok, follow_activity_two} =
+        Utils.update_follow_state_for_all(follow_activity_two, "accept")
+
+      assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
+      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
+    end
+  end
+
+  describe "update_follow_state/2" do
+    test "updates the state of the given follow activity" do
+      user = insert(:user, info: %{locked: true})
+      follower = insert(:user)
+
+      {:ok, follow_activity} = ActivityPub.follow(follower, user)
+      {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
+
+      data =
+        follow_activity_two.data
+        |> Map.put("state", "accept")
+
+      cng = Ecto.Changeset.change(follow_activity_two, data: data)
+
+      {:ok, follow_activity_two} = Repo.update(cng)
+
+      {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
+
+      assert Repo.get(Activity, follow_activity.id).data["state"] == "pending"
+      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
+    end
+  end
+
+  describe "update_element_in_object/3" do
+    test "updates likes" do
+      user = insert(:user)
+      activity = insert(:note_activity)
+      object = Object.normalize(activity)
+
+      assert {:ok, updated_object} =
+               Utils.update_element_in_object(
+                 "like",
+                 [user.ap_id],
+                 object
+               )
+
+      assert updated_object.data["likes"] == [user.ap_id]
+      assert updated_object.data["like_count"] == 1
+    end
+  end
+
+  describe "add_like_to_object/2" do
+    test "add actor to likes" do
+      user = insert(:user)
+      user2 = insert(:user)
+      object = insert(:note)
+
+      assert {:ok, updated_object} =
+               Utils.add_like_to_object(
+                 %Activity{data: %{"actor" => user.ap_id}},
+                 object
+               )
+
+      assert updated_object.data["likes"] == [user.ap_id]
+      assert updated_object.data["like_count"] == 1
+
+      assert {:ok, updated_object2} =
+               Utils.add_like_to_object(
+                 %Activity{data: %{"actor" => user2.ap_id}},
+                 updated_object
+               )
+
+      assert updated_object2.data["likes"] == [user2.ap_id, user.ap_id]
+      assert updated_object2.data["like_count"] == 2
+    end
+  end
+
+  describe "remove_like_from_object/2" do
+    test "removes ap_id from likes" do
+      user = insert(:user)
+      user2 = insert(:user)
+      object = insert(:note, data: %{"likes" => [user.ap_id, user2.ap_id], "like_count" => 2})
+
+      assert {:ok, updated_object} =
+               Utils.remove_like_from_object(
+                 %Activity{data: %{"actor" => user.ap_id}},
+                 object
+               )
+
+      assert updated_object.data["likes"] == [user2.ap_id]
+      assert updated_object.data["like_count"] == 1
+    end
+  end
+
+  describe "get_existing_like/2" do
+    test "fetches existing like" do
+      note_activity = insert(:note_activity)
+      assert object = Object.normalize(note_activity)
+
+      user = insert(:user)
+      refute Utils.get_existing_like(user.ap_id, object)
+      {:ok, like_activity, _object} = ActivityPub.like(user, object)
+
+      assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
+    end
+  end
 end