Actually put some onformation in the error user, make it actually properly parse
[akkoma] / test / web / twitter_api / views / activity_view_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 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 =
85 "<img height=\"32px\" width=\"32px\" alt=\"woollysocks\" title=\"woollysocks\" src=\"http://localhost:4001/finmoji/128px/woollysocks-128.png\" /> meow"
86
87 assert result["summary"] == expected
88 end
89
90 test "a create activity with a summary containing invalid HTML" do
91 {:ok, activity} =
92 CommonAPI.post(insert(:user), %{
93 "spoiler_text" => "<span style=\"color: magenta; font-size: 32px;\">meow</span>",
94 "status" => "."
95 })
96
97 result = ActivityView.render("activity.json", activity: activity)
98
99 expected = "meow"
100
101 assert result["summary"] == expected
102 end
103
104 test "a create activity with a note" do
105 user = insert(:user)
106 other_user = insert(:user, %{nickname: "shp"})
107
108 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
109
110 result = ActivityView.render("activity.json", activity: activity)
111
112 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
113
114 expected = %{
115 "activity_type" => "post",
116 "attachments" => [],
117 "attentions" => [
118 UserView.render("show.json", %{user: other_user})
119 ],
120 "created_at" => activity.data["object"]["published"] |> Utils.date_to_asctime(),
121 "external_url" => activity.data["object"]["id"],
122 "fave_num" => 0,
123 "favorited" => false,
124 "id" => activity.id,
125 "in_reply_to_status_id" => nil,
126 "in_reply_to_screen_name" => nil,
127 "in_reply_to_user_id" => nil,
128 "in_reply_to_profileurl" => nil,
129 "in_reply_to_ostatus_uri" => nil,
130 "is_local" => true,
131 "is_post_verb" => true,
132 "possibly_sensitive" => false,
133 "repeat_num" => 0,
134 "repeated" => false,
135 "statusnet_conversation_id" => convo_id,
136 "summary" => "",
137 "statusnet_html" =>
138 "Hey <span><a data-user=\"#{other_user.id}\" href=\"#{other_user.ap_id}\">@<span>shp</span></a></span>!",
139 "tags" => [],
140 "text" => "Hey @shp!",
141 "uri" => activity.data["object"]["id"],
142 "user" => UserView.render("show.json", %{user: user}),
143 "visibility" => "direct"
144 }
145
146 assert result == expected
147 end
148
149 test "a list of activities" do
150 user = insert(:user)
151 other_user = insert(:user, %{nickname: "shp"})
152 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
153
154 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
155
156 mocks = [
157 {
158 TwitterAPI,
159 [],
160 [context_to_conversation_id: fn _ -> false end]
161 },
162 {
163 User,
164 [:passthrough],
165 [get_cached_by_ap_id: fn _ -> nil end]
166 }
167 ]
168
169 with_mocks mocks do
170 [result] = ActivityView.render("index.json", activities: [activity])
171
172 assert result["statusnet_conversation_id"] == convo_id
173 assert result["user"]
174 refute called(TwitterAPI.context_to_conversation_id(:_))
175 refute called(User.get_cached_by_ap_id(user.ap_id))
176 refute called(User.get_cached_by_ap_id(other_user.ap_id))
177 end
178 end
179
180 test "an activity that is a reply" do
181 user = insert(:user)
182 other_user = insert(:user, %{nickname: "shp"})
183
184 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
185
186 {:ok, answer} =
187 CommonAPI.post(other_user, %{"status" => "Hi!", "in_reply_to_status_id" => activity.id})
188
189 result = ActivityView.render("activity.json", %{activity: answer})
190
191 assert result["in_reply_to_status_id"] == activity.id
192 end
193
194 test "a like activity" do
195 user = insert(:user)
196 other_user = insert(:user, %{nickname: "shp"})
197
198 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
199 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
200
201 result = ActivityView.render("activity.json", activity: like)
202 activity = Pleroma.Activity.get_by_ap_id(activity.data["id"])
203
204 expected = %{
205 "activity_type" => "like",
206 "created_at" => like.data["published"] |> Utils.date_to_asctime(),
207 "external_url" => like.data["id"],
208 "id" => like.id,
209 "in_reply_to_status_id" => activity.id,
210 "is_local" => true,
211 "is_post_verb" => false,
212 "favorited_status" => ActivityView.render("activity.json", activity: activity),
213 "statusnet_html" => "shp favorited a status.",
214 "text" => "shp favorited a status.",
215 "uri" => "tag:#{like.data["id"]}:objectType=Favourite",
216 "user" => UserView.render("show.json", user: other_user)
217 }
218
219 assert result == expected
220 end
221
222 test "a like activity for deleted post" do
223 user = insert(:user)
224 other_user = insert(:user, %{nickname: "shp"})
225
226 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
227 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
228 CommonAPI.delete(activity.id, user)
229
230 result = ActivityView.render("activity.json", activity: like)
231
232 expected = %{
233 "activity_type" => "like",
234 "created_at" => like.data["published"] |> Utils.date_to_asctime(),
235 "external_url" => like.data["id"],
236 "id" => like.id,
237 "in_reply_to_status_id" => nil,
238 "is_local" => true,
239 "is_post_verb" => false,
240 "favorited_status" => nil,
241 "statusnet_html" => "shp favorited a status.",
242 "text" => "shp favorited a status.",
243 "uri" => "tag:#{like.data["id"]}:objectType=Favourite",
244 "user" => UserView.render("show.json", user: other_user)
245 }
246
247 assert result == expected
248 end
249
250 test "an announce activity" do
251 user = insert(:user)
252 other_user = insert(:user, %{nickname: "shp"})
253
254 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
255 {:ok, announce, _object} = CommonAPI.repeat(activity.id, other_user)
256
257 convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
258
259 activity = Repo.get(Activity, activity.id)
260
261 result = ActivityView.render("activity.json", activity: announce)
262
263 expected = %{
264 "activity_type" => "repeat",
265 "created_at" => announce.data["published"] |> Utils.date_to_asctime(),
266 "external_url" => announce.data["id"],
267 "id" => announce.id,
268 "is_local" => true,
269 "is_post_verb" => false,
270 "statusnet_html" => "shp retweeted a status.",
271 "text" => "shp retweeted a status.",
272 "uri" => "tag:#{announce.data["id"]}:objectType=note",
273 "user" => UserView.render("show.json", user: other_user),
274 "retweeted_status" => ActivityView.render("activity.json", activity: activity),
275 "statusnet_conversation_id" => convo_id
276 }
277
278 assert result == expected
279 end
280
281 test "A follow activity" do
282 user = insert(:user)
283 other_user = insert(:user, %{nickname: "shp"})
284
285 {:ok, follower} = User.follow(user, other_user)
286 {:ok, follow} = ActivityPub.follow(follower, other_user)
287
288 result = ActivityView.render("activity.json", activity: follow)
289
290 expected = %{
291 "activity_type" => "follow",
292 "attentions" => [],
293 "created_at" => follow.data["published"] |> Utils.date_to_asctime(),
294 "external_url" => follow.data["id"],
295 "id" => follow.id,
296 "in_reply_to_status_id" => nil,
297 "is_local" => true,
298 "is_post_verb" => false,
299 "statusnet_html" => "#{user.nickname} started following shp",
300 "text" => "#{user.nickname} started following shp",
301 "user" => UserView.render("show.json", user: user)
302 }
303
304 assert result == expected
305 end
306
307 test "a delete activity" do
308 user = insert(:user)
309
310 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
311 {:ok, delete} = CommonAPI.delete(activity.id, user)
312
313 result = ActivityView.render("activity.json", activity: delete)
314
315 expected = %{
316 "activity_type" => "delete",
317 "attentions" => [],
318 "created_at" => delete.data["published"] |> Utils.date_to_asctime(),
319 "external_url" => delete.data["id"],
320 "id" => delete.id,
321 "in_reply_to_status_id" => nil,
322 "is_local" => true,
323 "is_post_verb" => false,
324 "statusnet_html" => "deleted notice {{tag",
325 "text" => "deleted notice {{tag",
326 "uri" => delete.data["object"],
327 "user" => UserView.render("show.json", user: user)
328 }
329
330 assert result == expected
331 end
332
333 test "a peertube video" do
334 {:ok, object} =
335 ActivityPub.fetch_object_from_id(
336 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
337 )
338
339 %Activity{} = activity = Activity.get_create_activity_by_object_ap_id(object.data["id"])
340
341 result = ActivityView.render("activity.json", activity: activity)
342
343 assert length(result["attachments"]) == 1
344 assert result["summary"] == "Friday Night"
345 end
346 end