Add current user to mentioned
[akkoma] / test / web / twitter_api / views / activity_view_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
6 use Pleroma.DataCase
7
8 alias Pleroma.Web.CommonAPI
9 alias Pleroma.Web.CommonAPI.Utils
10 alias Pleroma.Web.TwitterAPI.ActivityView
11 alias Pleroma.Web.TwitterAPI.UserView
12 alias Pleroma.Web.TwitterAPI.TwitterAPI
13 alias Pleroma.Repo
14 alias Pleroma.Activity
15 alias Pleroma.User
16 alias Pleroma.Web.ActivityPub.ActivityPub
17
18 import Pleroma.Factory
19 import Tesla.Mock
20
21 setup do
22 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
23 :ok
24 end
25
26 import Mock
27
28 test "returns a temporary ap_id based user for activities missing db users" do
29 user = insert(:user)
30
31 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
32
33 Repo.delete(user)
34 Cachex.clear(:user_cache)
35
36 %{"user" => tw_user} = ActivityView.render("activity.json", activity: activity)
37
38 assert tw_user["screen_name"] == "erroruser@example.com"
39 assert tw_user["name"] == user.ap_id
40 assert tw_user["statusnet_profile_url"] == user.ap_id
41 end
42
43 test "tries to get a user by nickname if fetching by ap_id doesn't work" do
44 user = insert(:user)
45
46 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
47
48 {:ok, user} =
49 user
50 |> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
51 |> Repo.update()
52
53 Cachex.clear(:user_cache)
54
55 result = ActivityView.render("activity.json", activity: activity)
56 assert result["user"]["id"] == user.id
57 end
58
59 test "a create activity with a html status" do
60 text = """
61 #Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg
62 """
63
64 {:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text})
65
66 result = ActivityView.render("activity.json", activity: activity)
67
68 assert result["statusnet_html"] ==
69 "<a data-tag=\"bike\" href=\"http://localhost:4001/tag/bike\">#Bike</a> log - Commute Tuesday<br /><a href=\"https://pla.bike/posts/20181211/\">https://pla.bike/posts/20181211/</a><br /><a data-tag=\"cycling\" href=\"http://localhost:4001/tag/cycling\">#cycling</a> <a data-tag=\"chscycling\" href=\"http://localhost:4001/tag/chscycling\">#CHScycling</a> <a data-tag=\"commute\" href=\"http://localhost:4001/tag/commute\">#commute</a><br />MVIMG_20181211_054020.jpg"
70
71 assert result["text"] ==
72 "#Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg"
73 end
74
75 test "a create activity with a summary containing emoji" do
76 {:ok, activity} =
77 CommonAPI.post(insert(:user), %{
78 "spoiler_text" => ":woollysocks: meow",
79 "status" => "."
80 })
81
82 result = ActivityView.render("activity.json", activity: activity)
83
84 expected = ":woollysocks: meow"
85
86 expected_html =
87 "<img height=\"32px\" width=\"32px\" alt=\"woollysocks\" title=\"woollysocks\" src=\"http://localhost:4001/finmoji/128px/woollysocks-128.png\" /> meow"
88
89 assert result["summary"] == expected
90 assert result["summary_html"] == expected_html
91 end
92
93 test "a create activity with a summary containing invalid HTML" do
94 {:ok, activity} =
95 CommonAPI.post(insert(:user), %{
96 "spoiler_text" => "<span style=\"color: magenta; font-size: 32px;\">meow</span>",
97 "status" => "."
98 })
99
100 result = ActivityView.render("activity.json", activity: activity)
101
102 expected = "meow"
103
104 assert result["summary"] == expected
105 assert result["summary_html"] == expected
106 end
107
108 test "a create activity with a note" do
109 user = insert(:user)
110 other_user = insert(:user, %{nickname: "shp"})
111
112 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
113
114 result = ActivityView.render("activity.json", activity: activity)
115
116 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
117
118 expected = %{
119 "activity_type" => "post",
120 "attachments" => [],
121 "attentions" => Enum.map([other_user, user], fn u -> UserView.render("show.json", %{user: u}) end),
122 "created_at" => activity.data["object"]["published"] |> Utils.date_to_asctime(),
123 "external_url" => activity.data["object"]["id"],
124 "fave_num" => 0,
125 "favorited" => false,
126 "id" => activity.id,
127 "in_reply_to_status_id" => nil,
128 "in_reply_to_screen_name" => nil,
129 "in_reply_to_user_id" => nil,
130 "in_reply_to_profileurl" => nil,
131 "in_reply_to_ostatus_uri" => nil,
132 "is_local" => true,
133 "is_post_verb" => true,
134 "possibly_sensitive" => false,
135 "repeat_num" => 0,
136 "repeated" => false,
137 "pinned" => false,
138 "statusnet_conversation_id" => convo_id,
139 "summary" => "",
140 "summary_html" => "",
141 "statusnet_html" =>
142 "Hey <span><a data-user=\"#{other_user.id}\" href=\"#{other_user.ap_id}\">@<span>shp</span></a></span>!",
143 "tags" => [],
144 "text" => "Hey @shp!",
145 "uri" => activity.data["object"]["id"],
146 "user" => UserView.render("show.json", %{user: user}),
147 "visibility" => "direct"
148 }
149
150 assert result == expected
151 end
152
153 test "a list of activities" do
154 user = insert(:user)
155 other_user = insert(:user, %{nickname: "shp"})
156 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
157
158 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
159
160 mocks = [
161 {
162 TwitterAPI,
163 [],
164 [context_to_conversation_id: fn _ -> false end]
165 },
166 {
167 User,
168 [:passthrough],
169 [get_cached_by_ap_id: fn _ -> nil end]
170 }
171 ]
172
173 with_mocks mocks do
174 [result] = ActivityView.render("index.json", activities: [activity])
175
176 assert result["statusnet_conversation_id"] == convo_id
177 assert result["user"]
178 refute called(TwitterAPI.context_to_conversation_id(:_))
179 refute called(User.get_cached_by_ap_id(user.ap_id))
180 refute called(User.get_cached_by_ap_id(other_user.ap_id))
181 end
182 end
183
184 test "an activity that is a reply" do
185 user = insert(:user)
186 other_user = insert(:user, %{nickname: "shp"})
187
188 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
189
190 {:ok, answer} =
191 CommonAPI.post(other_user, %{"status" => "Hi!", "in_reply_to_status_id" => activity.id})
192
193 result = ActivityView.render("activity.json", %{activity: answer})
194
195 assert result["in_reply_to_status_id"] == activity.id
196 end
197
198 test "a like activity" do
199 user = insert(:user)
200 other_user = insert(:user, %{nickname: "shp"})
201
202 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
203 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
204
205 result = ActivityView.render("activity.json", activity: like)
206 activity = Pleroma.Activity.get_by_ap_id(activity.data["id"])
207
208 expected = %{
209 "activity_type" => "like",
210 "created_at" => like.data["published"] |> Utils.date_to_asctime(),
211 "external_url" => like.data["id"],
212 "id" => like.id,
213 "in_reply_to_status_id" => activity.id,
214 "is_local" => true,
215 "is_post_verb" => false,
216 "favorited_status" => ActivityView.render("activity.json", activity: activity),
217 "statusnet_html" => "shp favorited a status.",
218 "text" => "shp favorited a status.",
219 "uri" => "tag:#{like.data["id"]}:objectType=Favourite",
220 "user" => UserView.render("show.json", user: other_user)
221 }
222
223 assert result == expected
224 end
225
226 test "a like activity for deleted post" do
227 user = insert(:user)
228 other_user = insert(:user, %{nickname: "shp"})
229
230 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
231 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
232 CommonAPI.delete(activity.id, user)
233
234 result = ActivityView.render("activity.json", activity: like)
235
236 expected = %{
237 "activity_type" => "like",
238 "created_at" => like.data["published"] |> Utils.date_to_asctime(),
239 "external_url" => like.data["id"],
240 "id" => like.id,
241 "in_reply_to_status_id" => nil,
242 "is_local" => true,
243 "is_post_verb" => false,
244 "favorited_status" => nil,
245 "statusnet_html" => "shp favorited a status.",
246 "text" => "shp favorited a status.",
247 "uri" => "tag:#{like.data["id"]}:objectType=Favourite",
248 "user" => UserView.render("show.json", user: other_user)
249 }
250
251 assert result == expected
252 end
253
254 test "an announce activity" do
255 user = insert(:user)
256 other_user = insert(:user, %{nickname: "shp"})
257
258 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
259 {:ok, announce, _object} = CommonAPI.repeat(activity.id, other_user)
260
261 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
262
263 activity = Repo.get(Activity, activity.id)
264
265 result = ActivityView.render("activity.json", activity: announce)
266
267 expected = %{
268 "activity_type" => "repeat",
269 "created_at" => announce.data["published"] |> Utils.date_to_asctime(),
270 "external_url" => announce.data["id"],
271 "id" => announce.id,
272 "is_local" => true,
273 "is_post_verb" => false,
274 "statusnet_html" => "shp retweeted a status.",
275 "text" => "shp retweeted a status.",
276 "uri" => "tag:#{announce.data["id"]}:objectType=note",
277 "user" => UserView.render("show.json", user: other_user),
278 "retweeted_status" => ActivityView.render("activity.json", activity: activity),
279 "statusnet_conversation_id" => convo_id
280 }
281
282 assert result == expected
283 end
284
285 test "A follow activity" do
286 user = insert(:user)
287 other_user = insert(:user, %{nickname: "shp"})
288
289 {:ok, follower} = User.follow(user, other_user)
290 {:ok, follow} = ActivityPub.follow(follower, other_user)
291
292 result = ActivityView.render("activity.json", activity: follow)
293
294 expected = %{
295 "activity_type" => "follow",
296 "attentions" => [],
297 "created_at" => follow.data["published"] |> Utils.date_to_asctime(),
298 "external_url" => follow.data["id"],
299 "id" => follow.id,
300 "in_reply_to_status_id" => nil,
301 "is_local" => true,
302 "is_post_verb" => false,
303 "statusnet_html" => "#{user.nickname} started following shp",
304 "text" => "#{user.nickname} started following shp",
305 "user" => UserView.render("show.json", user: user)
306 }
307
308 assert result == expected
309 end
310
311 test "a delete activity" do
312 user = insert(:user)
313
314 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
315 {:ok, delete} = CommonAPI.delete(activity.id, user)
316
317 result = ActivityView.render("activity.json", activity: delete)
318
319 expected = %{
320 "activity_type" => "delete",
321 "attentions" => [],
322 "created_at" => delete.data["published"] |> Utils.date_to_asctime(),
323 "external_url" => delete.data["id"],
324 "id" => delete.id,
325 "in_reply_to_status_id" => nil,
326 "is_local" => true,
327 "is_post_verb" => false,
328 "statusnet_html" => "deleted notice {{tag",
329 "text" => "deleted notice {{tag",
330 "uri" => delete.data["object"],
331 "user" => UserView.render("show.json", user: user)
332 }
333
334 assert result == expected
335 end
336
337 test "a peertube video" do
338 {:ok, object} =
339 ActivityPub.fetch_object_from_id(
340 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
341 )
342
343 %Activity{} = activity = Activity.get_create_activity_by_object_ap_id(object.data["id"])
344
345 result = ActivityView.render("activity.json", activity: activity)
346
347 assert length(result["attachments"]) == 1
348 assert result["summary"] == "Friday Night"
349 end
350 end