aa3e40be116a269b7ffab8ec5b4adc407c9b87d3
[akkoma] / test / web / activity_pub / side_effects_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
6 use Oban.Testing, repo: Pleroma.Repo
7 use Pleroma.DataCase
8
9 alias Pleroma.Activity
10 alias Pleroma.Notification
11 alias Pleroma.Object
12 alias Pleroma.Repo
13 alias Pleroma.Tests.ObanHelpers
14 alias Pleroma.User
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Builder
17 alias Pleroma.Web.ActivityPub.SideEffects
18 alias Pleroma.Web.CommonAPI
19
20 import Pleroma.Factory
21 import Mock
22
23 describe "delete objects" do
24 setup do
25 user = insert(:user)
26 other_user = insert(:user)
27
28 {:ok, op} = CommonAPI.post(other_user, %{"status" => "big oof"})
29 {:ok, post} = CommonAPI.post(user, %{"status" => "hey", "in_reply_to_id" => op})
30 object = Object.normalize(post)
31 {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
32 {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
33 {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
34 {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
35 %{user: user, delete: delete, post: post, object: object, delete_user: delete_user, op: op}
36 end
37
38 test "it handles object deletions", %{
39 delete: delete,
40 post: post,
41 object: object,
42 user: user,
43 op: op
44 } do
45 with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
46 stream_out: fn _ -> nil end,
47 stream_out_participations: fn _, _ -> nil end do
48 {:ok, delete, _} = SideEffects.handle(delete)
49 user = User.get_cached_by_ap_id(object.data["actor"])
50
51 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
52 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
53 end
54
55 object = Object.get_by_id(object.id)
56 assert object.data["type"] == "Tombstone"
57 refute Activity.get_by_id(post.id)
58
59 user = User.get_by_id(user.id)
60 assert user.note_count == 0
61
62 object = Object.normalize(op.data["object"], false)
63
64 assert object.data["repliesCount"] == 0
65 end
66
67 test "it handles object deletions when the object itself has been pruned", %{
68 delete: delete,
69 post: post,
70 object: object,
71 user: user,
72 op: op
73 } do
74 with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
75 stream_out: fn _ -> nil end,
76 stream_out_participations: fn _, _ -> nil end do
77 {:ok, delete, _} = SideEffects.handle(delete)
78 user = User.get_cached_by_ap_id(object.data["actor"])
79
80 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
81 assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
82 end
83
84 object = Object.get_by_id(object.id)
85 assert object.data["type"] == "Tombstone"
86 refute Activity.get_by_id(post.id)
87
88 user = User.get_by_id(user.id)
89 assert user.note_count == 0
90
91 object = Object.normalize(op.data["object"], false)
92
93 assert object.data["repliesCount"] == 0
94 end
95
96 test "it handles user deletions", %{delete_user: delete, user: user} do
97 {:ok, _delete, _} = SideEffects.handle(delete)
98 ObanHelpers.perform_all()
99
100 assert User.get_cached_by_ap_id(user.ap_id).deactivated
101 end
102 end
103
104 describe "EmojiReact objects" do
105 setup do
106 poster = insert(:user)
107 user = insert(:user)
108
109 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
110
111 {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
112 {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
113
114 %{emoji_react: emoji_react, user: user, poster: poster}
115 end
116
117 test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
118 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
119 object = Object.get_by_ap_id(emoji_react.data["object"])
120
121 assert object.data["reaction_count"] == 1
122 assert ["👌", [user.ap_id]] in object.data["reactions"]
123 end
124
125 test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
126 {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
127 assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
128 end
129 end
130
131 describe "Undo objects" do
132 setup do
133 poster = insert(:user)
134 user = insert(:user)
135 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
136 {:ok, like} = CommonAPI.favorite(user, post.id)
137 {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
138 {:ok, announce, _} = CommonAPI.repeat(post.id, user)
139 {:ok, block} = ActivityPub.block(user, poster)
140 User.block(user, poster)
141
142 {:ok, undo_data, _meta} = Builder.undo(user, like)
143 {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
144
145 {:ok, undo_data, _meta} = Builder.undo(user, reaction)
146 {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
147
148 {:ok, undo_data, _meta} = Builder.undo(user, announce)
149 {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
150
151 {:ok, undo_data, _meta} = Builder.undo(user, block)
152 {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
153
154 %{
155 like_undo: like_undo,
156 post: post,
157 like: like,
158 reaction_undo: reaction_undo,
159 reaction: reaction,
160 announce_undo: announce_undo,
161 announce: announce,
162 block_undo: block_undo,
163 block: block,
164 poster: poster,
165 user: user
166 }
167 end
168
169 test "deletes the original block", %{block_undo: block_undo, block: block} do
170 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
171 refute Activity.get_by_id(block.id)
172 end
173
174 test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
175 blocker = User.get_by_ap_id(block.data["actor"])
176 blocked = User.get_by_ap_id(block.data["object"])
177
178 {:ok, _block_undo, _} = SideEffects.handle(block_undo)
179 refute User.blocks?(blocker, blocked)
180 end
181
182 test "an announce undo removes the announce from the object", %{
183 announce_undo: announce_undo,
184 post: post
185 } do
186 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
187
188 object = Object.get_by_ap_id(post.data["object"])
189
190 assert object.data["announcement_count"] == 0
191 assert object.data["announcements"] == []
192 end
193
194 test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
195 {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
196 refute Activity.get_by_id(announce.id)
197 end
198
199 test "a reaction undo removes the reaction from the object", %{
200 reaction_undo: reaction_undo,
201 post: post
202 } do
203 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
204
205 object = Object.get_by_ap_id(post.data["object"])
206
207 assert object.data["reaction_count"] == 0
208 assert object.data["reactions"] == []
209 end
210
211 test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
212 {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
213 refute Activity.get_by_id(reaction.id)
214 end
215
216 test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
217 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
218
219 object = Object.get_by_ap_id(post.data["object"])
220
221 assert object.data["like_count"] == 0
222 assert object.data["likes"] == []
223 end
224
225 test "deletes the original like", %{like_undo: like_undo, like: like} do
226 {:ok, _like_undo, _} = SideEffects.handle(like_undo)
227 refute Activity.get_by_id(like.id)
228 end
229 end
230
231 describe "like objects" do
232 setup do
233 poster = insert(:user)
234 user = insert(:user)
235 {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
236
237 {:ok, like_data, _meta} = Builder.like(user, post.object)
238 {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
239
240 %{like: like, user: user, poster: poster}
241 end
242
243 test "add the like to the original object", %{like: like, user: user} do
244 {:ok, like, _} = SideEffects.handle(like)
245 object = Object.get_by_ap_id(like.data["object"])
246 assert object.data["like_count"] == 1
247 assert user.ap_id in object.data["likes"]
248 end
249
250 test "creates a notification", %{like: like, poster: poster} do
251 {:ok, like, _} = SideEffects.handle(like)
252 assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
253 end
254 end
255 end