Merge branch 'feature/activitypub-semantics' into 'develop'
[akkoma] / test / web / activity_pub / activity_pub_test.exs
index 0377d29f6bb89c910834bada031904d66a510b38..8ae946969f46e1a28159d1fa50010a455823ff16 100644 (file)
@@ -21,6 +21,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     :ok
   end
 
+  clear_config([:instance, :federating])
+
   describe "streaming out participations" do
     test "it streams them out" do
       user = insert(:user)
@@ -36,9 +38,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
         stream: fn _, _ -> nil end do
         ActivityPub.stream_out_participations(conversation.participations)
 
-        Enum.each(participations, fn participation ->
-          assert called(Pleroma.Web.Streamer.stream("participation", participation))
-        end)
+        assert called(Pleroma.Web.Streamer.stream("participation", participations))
+      end
+    end
+
+    test "streams them out on activity creation" do
+      user_one = insert(:user)
+      user_two = insert(:user)
+
+      with_mock Pleroma.Web.Streamer,
+        stream: fn _, _ -> nil end do
+        {:ok, activity} =
+          CommonAPI.post(user_one, %{
+            "status" => "@#{user_two.nickname}",
+            "visibility" => "direct"
+          })
+
+        conversation =
+          activity.data["context"]
+          |> Pleroma.Conversation.get_for_ap_id()
+          |> Repo.preload(participations: :user)
+
+        assert called(Pleroma.Web.Streamer.stream("participation", conversation.participations))
       end
     end
   end
@@ -87,6 +108,66 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     end
   end
 
+  describe "fetching excluded by visibility" do
+    test "it excludes by the appropriate visibility" do
+      user = insert(:user)
+
+      {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+
+      {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+
+      {:ok, unlisted_activity} =
+        CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+
+      {:ok, private_activity} =
+        CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+
+      activities =
+        ActivityPub.fetch_activities([], %{
+          "exclude_visibilities" => "direct",
+          "actor_id" => user.ap_id
+        })
+
+      assert public_activity in activities
+      assert unlisted_activity in activities
+      assert private_activity in activities
+      refute direct_activity in activities
+
+      activities =
+        ActivityPub.fetch_activities([], %{
+          "exclude_visibilities" => "unlisted",
+          "actor_id" => user.ap_id
+        })
+
+      assert public_activity in activities
+      refute unlisted_activity in activities
+      assert private_activity in activities
+      assert direct_activity in activities
+
+      activities =
+        ActivityPub.fetch_activities([], %{
+          "exclude_visibilities" => "private",
+          "actor_id" => user.ap_id
+        })
+
+      assert public_activity in activities
+      assert unlisted_activity in activities
+      refute private_activity in activities
+      assert direct_activity in activities
+
+      activities =
+        ActivityPub.fetch_activities([], %{
+          "exclude_visibilities" => "public",
+          "actor_id" => user.ap_id
+        })
+
+      refute public_activity in activities
+      assert unlisted_activity in activities
+      assert private_activity in activities
+      assert direct_activity in activities
+    end
+  end
+
   describe "building a user from his ap id" do
     test "it returns a user" do
       user_id = "http://mastodon.example.org/users/admin"
@@ -98,6 +179,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
     end
 
+    test "it returns a user that is invisible" do
+      user_id = "http://mastodon.example.org/users/relay"
+      {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
+      assert User.invisible?(user)
+    end
+
     test "it fetches the appropriate tag-restricted posts" do
       user = insert(:user)
 
@@ -257,6 +344,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     end
   end
 
+  describe "listen activities" do
+    test "does not increase user note count" do
+      user = insert(:user)
+
+      {:ok, activity} =
+        ActivityPub.listen(%{
+          to: ["https://www.w3.org/ns/activitystreams#Public"],
+          actor: user,
+          context: "",
+          object: %{
+            "actor" => user.ap_id,
+            "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+            "artist" => "lain",
+            "title" => "lain radio episode 1",
+            "length" => 180_000,
+            "type" => "Audio"
+          }
+        })
+
+      assert activity.actor == user.ap_id
+
+      user = User.get_cached_by_id(user.id)
+      assert user.info.note_count == 0
+    end
+
+    test "can be fetched into a timeline" do
+      _listen_activity_1 = insert(:listen)
+      _listen_activity_2 = insert(:listen)
+      _listen_activity_3 = insert(:listen)
+
+      timeline = ActivityPub.fetch_activities([], %{"type" => ["Listen"]})
+
+      assert length(timeline) == 3
+    end
+  end
+
   describe "create activities" do
     test "removes doubled 'to' recipients" do
       user = insert(:user)
@@ -540,24 +663,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
 
   test "doesn't return thread muted activities" do
     user = insert(:user)
-    activity_one = insert(:note_activity)
+    _activity_one = insert(:note_activity)
     note_two = insert(:note, data: %{"context" => "suya.."})
     activity_two = insert(:note_activity, note: note_two)
 
     {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
 
-    assert [activity_one] = ActivityPub.fetch_activities([], %{"muting_user" => user})
+    assert [_activity_one] = ActivityPub.fetch_activities([], %{"muting_user" => user})
   end
 
   test "returns thread muted activities when with_muted is set" do
     user = insert(:user)
-    activity_one = insert(:note_activity)
+    _activity_one = insert(:note_activity)
     note_two = insert(:note, data: %{"context" => "suya.."})
     activity_two = insert(:note_activity, note: note_two)
 
-    {:ok, activity_two} = CommonAPI.add_mute(user, activity_two)
+    {:ok, _activity_two} = CommonAPI.add_mute(user, activity_two)
 
-    assert [activity_two, activity_one] =
+    assert [_activity_two, _activity_one] =
              ActivityPub.fetch_activities([], %{"muting_user" => user, "with_muted" => true})
   end
 
@@ -647,6 +770,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       assert last == last_expected
     end
 
+    test "paginates via offset/limit" do
+      _first_activities = ActivityBuilder.insert_list(10)
+      activities = ActivityBuilder.insert_list(10)
+      _later_activities = ActivityBuilder.insert_list(10)
+      first_expected = List.first(activities)
+
+      activities =
+        ActivityPub.fetch_public_activities(%{"page" => "2", "page_size" => "20"}, :offset)
+
+      first = List.first(activities)
+
+      assert length(activities) == 20
+      assert first == first_expected
+    end
+
     test "doesn't return reblogs for users for whom reblogs have been muted" do
       activity = insert(:note_activity)
       user = insert(:user)
@@ -676,6 +814,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
   end
 
   describe "like an object" do
+    test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
+      Pleroma.Config.put([:instance, :federating], true)
+      note_activity = insert(:note_activity)
+      assert object_activity = Object.normalize(note_activity)
+
+      user = insert(:user)
+
+      {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
+      assert called(Pleroma.Web.Federator.publish(like_activity))
+    end
+
+    test "returns exist activity if object already liked" do
+      note_activity = insert(:note_activity)
+      assert object_activity = Object.normalize(note_activity)
+
+      user = insert(:user)
+
+      {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
+
+      {:ok, like_activity_exist, _object} = ActivityPub.like(user, object_activity)
+      assert like_activity == like_activity_exist
+    end
+
     test "adds a like activity to the db" do
       note_activity = insert(:note_activity)
       assert object = Object.normalize(note_activity)
@@ -706,6 +867,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
   end
 
   describe "unliking" do
+    test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
+      Pleroma.Config.put([:instance, :federating], true)
+
+      note_activity = insert(:note_activity)
+      object = Object.normalize(note_activity)
+      user = insert(:user)
+
+      {:ok, object} = ActivityPub.unlike(user, object)
+      refute called(Pleroma.Web.Federator.publish())
+
+      {:ok, _like_activity, object} = ActivityPub.like(user, object)
+      assert object.data["like_count"] == 1
+
+      {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
+      assert object.data["like_count"] == 0
+
+      assert called(Pleroma.Web.Federator.publish(unlike_activity))
+    end
+
     test "unliking a previously liked object" do
       note_activity = insert(:note_activity)
       object = Object.normalize(note_activity)
@@ -718,10 +898,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       {:ok, like_activity, object} = ActivityPub.like(user, object)
       assert object.data["like_count"] == 1
 
-      {:ok, _, _, object} = ActivityPub.unlike(user, object)
+      {:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
       assert object.data["like_count"] == 0
 
       assert Activity.get_by_id(like_activity.id) == nil
+      assert note_activity.actor in unlike_activity.recipients
     end
   end
 
@@ -746,6 +927,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     end
   end
 
+  describe "announcing a private object" do
+    test "adds an announce activity to the db if the audience is not widened" do
+      user = insert(:user)
+      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+      object = Object.normalize(note_activity)
+
+      {:ok, announce_activity, object} = ActivityPub.announce(user, object, nil, true, false)
+
+      assert announce_activity.data["to"] == [User.ap_followers(user)]
+
+      assert announce_activity.data["object"] == object.data["id"]
+      assert announce_activity.data["actor"] == user.ap_id
+      assert announce_activity.data["context"] == object.data["context"]
+    end
+
+    test "does not add an announce activity to the db if the audience is widened" do
+      user = insert(:user)
+      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+      object = Object.normalize(note_activity)
+
+      assert {:error, _} = ActivityPub.announce(user, object, nil, true, true)
+    end
+
+    test "does not add an announce activity to the db if the announcer is not the author" do
+      user = insert(:user)
+      announcer = insert(:user)
+      {:ok, note_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+      object = Object.normalize(note_activity)
+
+      assert {:error, _} = ActivityPub.announce(announcer, object, nil, true, false)
+    end
+  end
+
   describe "unannouncing an object" do
     test "unannouncing a previously announced object" do
       note_activity = insert(:note_activity)
@@ -764,7 +978,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
 
       assert unannounce_activity.data["to"] == [
                User.ap_followers(user),
-               announce_activity.data["actor"]
+               object.data["actor"]
              ]
 
       assert unannounce_activity.data["type"] == "Undo"