Add `pleroma.in_reply_to_account_acct` to MastoAPI status entity
[akkoma] / test / web / mastodon_api / status_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.MastodonAPI.StatusViewTest do
6 use Pleroma.DataCase
7
8 alias Pleroma.Activity
9 alias Pleroma.Object
10 alias Pleroma.Repo
11 alias Pleroma.User
12 alias Pleroma.Web.CommonAPI
13 alias Pleroma.Web.CommonAPI.Utils
14 alias Pleroma.Web.MastodonAPI.AccountView
15 alias Pleroma.Web.MastodonAPI.StatusView
16 alias Pleroma.Web.OStatus
17 import Pleroma.Factory
18 import Tesla.Mock
19
20 setup do
21 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
22 :ok
23 end
24
25 test "returns a temporary ap_id based user for activities missing db users" do
26 user = insert(:user)
27
28 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
29
30 Repo.delete(user)
31 Cachex.clear(:user_cache)
32
33 %{account: ms_user} = StatusView.render("status.json", activity: activity)
34
35 assert ms_user.acct == "erroruser@example.com"
36 end
37
38 test "tries to get a user by nickname if fetching by ap_id doesn't work" do
39 user = insert(:user)
40
41 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
42
43 {:ok, user} =
44 user
45 |> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
46 |> Repo.update()
47
48 Cachex.clear(:user_cache)
49
50 result = StatusView.render("status.json", activity: activity)
51
52 assert result[:account][:id] == to_string(user.id)
53 end
54
55 test "a note with null content" do
56 note = insert(:note_activity)
57 note_object = Object.normalize(note.data["object"])
58
59 data =
60 note_object.data
61 |> Map.put("content", nil)
62
63 Object.change(note_object, %{data: data})
64 |> Object.update_and_set_cache()
65
66 User.get_cached_by_ap_id(note.data["actor"])
67
68 status = StatusView.render("status.json", %{activity: note})
69
70 assert status.content == ""
71 end
72
73 test "a note activity" do
74 note = insert(:note_activity)
75 user = User.get_cached_by_ap_id(note.data["actor"])
76
77 convo_id = Utils.context_to_conversation_id(note.data["object"]["context"])
78
79 status = StatusView.render("status.json", %{activity: note})
80
81 created_at =
82 (note.data["object"]["published"] || "")
83 |> String.replace(~r/\.\d+Z/, ".000Z")
84
85 expected = %{
86 id: to_string(note.id),
87 uri: note.data["object"]["id"],
88 url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
89 account: AccountView.render("account.json", %{user: user}),
90 in_reply_to_id: nil,
91 in_reply_to_account_id: nil,
92 card: nil,
93 reblog: nil,
94 content: HtmlSanitizeEx.basic_html(note.data["object"]["content"]),
95 created_at: created_at,
96 reblogs_count: 0,
97 replies_count: 0,
98 favourites_count: 0,
99 reblogged: false,
100 bookmarked: false,
101 favourited: false,
102 muted: false,
103 pinned: false,
104 sensitive: false,
105 spoiler_text: HtmlSanitizeEx.basic_html(note.data["object"]["summary"]),
106 visibility: "public",
107 media_attachments: [],
108 mentions: [],
109 tags: [
110 %{
111 name: "#{note.data["object"]["tag"]}",
112 url: "/tag/#{note.data["object"]["tag"]}"
113 }
114 ],
115 application: %{
116 name: "Web",
117 website: nil
118 },
119 language: nil,
120 emojis: [
121 %{
122 shortcode: "2hu",
123 url: "corndog.png",
124 static_url: "corndog.png",
125 visible_in_picker: false
126 }
127 ],
128 pleroma: %{
129 local: true,
130 conversation_id: convo_id,
131 in_reply_to_account_acct: nil,
132 content: %{"text/plain" => HtmlSanitizeEx.strip_tags(note.data["object"]["content"])},
133 spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(note.data["object"]["summary"])}
134 }
135 }
136
137 assert status == expected
138 end
139
140 test "tells if the message is muted for some reason" do
141 user = insert(:user)
142 other_user = insert(:user)
143
144 {:ok, user} = User.mute(user, other_user)
145
146 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
147 status = StatusView.render("status.json", %{activity: activity})
148
149 assert status.muted == false
150
151 status = StatusView.render("status.json", %{activity: activity, for: user})
152
153 assert status.muted == true
154 end
155
156 test "a reply" do
157 note = insert(:note_activity)
158 user = insert(:user)
159
160 {:ok, activity} =
161 CommonAPI.post(user, %{"status" => "he", "in_reply_to_status_id" => note.id})
162
163 status = StatusView.render("status.json", %{activity: activity})
164
165 assert status.in_reply_to_id == to_string(note.id)
166
167 [status] = StatusView.render("index.json", %{activities: [activity], as: :activity})
168
169 assert status.in_reply_to_id == to_string(note.id)
170 end
171
172 test "contains mentions" do
173 incoming = File.read!("test/fixtures/incoming_reply_mastodon.xml")
174 # a user with this ap id might be in the cache.
175 recipient = "https://pleroma.soykaf.com/users/lain"
176 user = insert(:user, %{ap_id: recipient})
177
178 {:ok, [activity]} = OStatus.handle_incoming(incoming)
179
180 status = StatusView.render("status.json", %{activity: activity})
181
182 actor = User.get_cached_by_ap_id(activity.actor)
183
184 assert status.mentions ==
185 Enum.map([user, actor], fn u -> AccountView.render("mention.json", %{user: u}) end)
186 end
187
188 test "attachments" do
189 object = %{
190 "type" => "Image",
191 "url" => [
192 %{
193 "mediaType" => "image/png",
194 "href" => "someurl"
195 }
196 ],
197 "uuid" => 6
198 }
199
200 expected = %{
201 id: "1638338801",
202 type: "image",
203 url: "someurl",
204 remote_url: "someurl",
205 preview_url: "someurl",
206 text_url: "someurl",
207 description: nil,
208 pleroma: %{mime_type: "image/png"}
209 }
210
211 assert expected == StatusView.render("attachment.json", %{attachment: object})
212
213 # If theres a "id", use that instead of the generated one
214 object = Map.put(object, "id", 2)
215 assert %{id: "2"} = StatusView.render("attachment.json", %{attachment: object})
216 end
217
218 test "a reblog" do
219 user = insert(:user)
220 activity = insert(:note_activity)
221
222 {:ok, reblog, _} = CommonAPI.repeat(activity.id, user)
223
224 represented = StatusView.render("status.json", %{for: user, activity: reblog})
225
226 assert represented[:id] == to_string(reblog.id)
227 assert represented[:reblog][:id] == to_string(activity.id)
228 assert represented[:emojis] == []
229 end
230
231 test "a peertube video" do
232 user = insert(:user)
233
234 {:ok, object} =
235 Pleroma.Object.Fetcher.fetch_object_from_id(
236 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
237 )
238
239 %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
240
241 represented = StatusView.render("status.json", %{for: user, activity: activity})
242
243 assert represented[:id] == to_string(activity.id)
244 assert length(represented[:media_attachments]) == 1
245 end
246
247 describe "build_tags/1" do
248 test "it returns a a dictionary tags" do
249 object_tags = [
250 "fediverse",
251 "mastodon",
252 "nextcloud",
253 %{
254 "href" => "https://kawen.space/users/lain",
255 "name" => "@lain@kawen.space",
256 "type" => "Mention"
257 }
258 ]
259
260 assert StatusView.build_tags(object_tags) == [
261 %{name: "fediverse", url: "/tag/fediverse"},
262 %{name: "mastodon", url: "/tag/mastodon"},
263 %{name: "nextcloud", url: "/tag/nextcloud"}
264 ]
265 end
266 end
267
268 describe "rich media cards" do
269 test "a rich media card without a site name renders correctly" do
270 page_url = "http://example.com"
271
272 card = %{
273 url: page_url,
274 image: page_url <> "/example.jpg",
275 title: "Example website"
276 }
277
278 %{provider_name: "example.com"} =
279 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
280 end
281
282 test "a rich media card without a site name or image renders correctly" do
283 page_url = "http://example.com"
284
285 card = %{
286 url: page_url,
287 title: "Example website"
288 }
289
290 %{provider_name: "example.com"} =
291 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
292 end
293
294 test "a rich media card without an image renders correctly" do
295 page_url = "http://example.com"
296
297 card = %{
298 url: page_url,
299 site_name: "Example site name",
300 title: "Example website"
301 }
302
303 %{provider_name: "Example site name"} =
304 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
305 end
306
307 test "a rich media card with all relevant data renders correctly" do
308 page_url = "http://example.com"
309
310 card = %{
311 url: page_url,
312 site_name: "Example site name",
313 title: "Example website",
314 image: page_url <> "/example.jpg",
315 description: "Example description"
316 }
317
318 %{provider_name: "Example site name"} =
319 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
320 end
321 end
322 end