1 # Pleroma: A lightweight social networking server
2 # Copyright Ā© 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
10 alias Pleroma.Conversation.Participation
15 alias Pleroma.Web.CommonAPI
16 alias Pleroma.Web.CommonAPI.Utils
17 alias Pleroma.Web.MastodonAPI.AccountView
18 alias Pleroma.Web.MastodonAPI.StatusView
19 import Pleroma.Factory
23 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
27 test "has an emoji reaction list" do
29 other_user = insert(:user)
30 third_user = insert(:user)
31 {:ok, activity} = CommonAPI.post(user, %{"status" => "dae cofe??"})
33 {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, user, "ā")
34 {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, third_user, "šµ")
35 {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "ā")
36 activity = Repo.get(Activity, activity.id)
37 status = StatusView.render("show.json", activity: activity)
39 assert status[:pleroma][:emoji_reactions] == [
40 %{emoji: "ā", count: 2},
41 %{emoji: "šµ", count: 1}
45 test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
48 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
49 [participation] = Participation.for_user(user)
52 StatusView.render("show.json",
54 with_direct_conversation_id: true,
58 assert status[:pleroma][:direct_conversation_id] == participation.id
60 status = StatusView.render("show.json", activity: activity, for: user)
61 assert status[:pleroma][:direct_conversation_id] == nil
64 test "returns the direct conversation id when given the `direct_conversation_id` option" do
67 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
68 [participation] = Participation.for_user(user)
71 StatusView.render("show.json",
73 direct_conversation_id: participation.id,
77 assert status[:pleroma][:direct_conversation_id] == participation.id
80 test "returns a temporary ap_id based user for activities missing db users" do
83 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
86 Cachex.clear(:user_cache)
88 %{account: ms_user} = StatusView.render("show.json", activity: activity)
90 assert ms_user.acct == "erroruser@example.com"
93 test "tries to get a user by nickname if fetching by ap_id doesn't work" do
96 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
100 |> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
103 Cachex.clear(:user_cache)
105 result = StatusView.render("show.json", activity: activity)
107 assert result[:account][:id] == to_string(user.id)
110 test "a note with null content" do
111 note = insert(:note_activity)
112 note_object = Object.normalize(note)
116 |> Map.put("content", nil)
118 Object.change(note_object, %{data: data})
119 |> Object.update_and_set_cache()
121 User.get_cached_by_ap_id(note.data["actor"])
123 status = StatusView.render("show.json", %{activity: note})
125 assert status.content == ""
128 test "a note activity" do
129 note = insert(:note_activity)
130 object_data = Object.normalize(note).data
131 user = User.get_cached_by_ap_id(note.data["actor"])
133 convo_id = Utils.context_to_conversation_id(object_data["context"])
135 status = StatusView.render("show.json", %{activity: note})
138 (object_data["published"] || "")
139 |> String.replace(~r/\.\d+Z/, ".000Z")
142 id: to_string(note.id),
143 uri: object_data["id"],
144 url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
145 account: AccountView.render("show.json", %{user: user}),
147 in_reply_to_account_id: nil,
150 content: HTML.filter_tags(object_data["content"]),
151 created_at: created_at,
162 spoiler_text: HTML.filter_tags(object_data["summary"]),
163 visibility: "public",
164 media_attachments: [],
168 name: "#{object_data["tag"]}",
169 url: "/tag/#{object_data["tag"]}"
181 static_url: "corndog.png",
182 visible_in_picker: false
187 conversation_id: convo_id,
188 in_reply_to_account_acct: nil,
189 content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
190 spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
192 direct_conversation_id: nil,
198 assert status == expected
201 test "tells if the message is muted for some reason" do
203 other_user = insert(:user)
205 {:ok, _user_relationships} = User.mute(user, other_user)
207 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
208 status = StatusView.render("show.json", %{activity: activity})
210 assert status.muted == false
212 status = StatusView.render("show.json", %{activity: activity, for: user})
214 assert status.muted == true
217 test "tells if the message is thread muted" do
219 other_user = insert(:user)
221 {:ok, _user_relationships} = User.mute(user, other_user)
223 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
224 status = StatusView.render("show.json", %{activity: activity, for: user})
226 assert status.pleroma.thread_muted == false
228 {:ok, activity} = CommonAPI.add_mute(user, activity)
230 status = StatusView.render("show.json", %{activity: activity, for: user})
232 assert status.pleroma.thread_muted == true
235 test "tells if the status is bookmarked" do
238 {:ok, activity} = CommonAPI.post(user, %{"status" => "Cute girls doing cute things"})
239 status = StatusView.render("show.json", %{activity: activity})
241 assert status.bookmarked == false
243 status = StatusView.render("show.json", %{activity: activity, for: user})
245 assert status.bookmarked == false
247 {:ok, _bookmark} = Bookmark.create(user.id, activity.id)
249 activity = Activity.get_by_id_with_object(activity.id)
251 status = StatusView.render("show.json", %{activity: activity, for: user})
253 assert status.bookmarked == true
257 note = insert(:note_activity)
261 CommonAPI.post(user, %{"status" => "he", "in_reply_to_status_id" => note.id})
263 status = StatusView.render("show.json", %{activity: activity})
265 assert status.in_reply_to_id == to_string(note.id)
267 [status] = StatusView.render("index.json", %{activities: [activity], as: :activity})
269 assert status.in_reply_to_id == to_string(note.id)
272 test "contains mentions" do
274 mentioned = insert(:user)
276 {:ok, activity} = CommonAPI.post(user, %{"status" => "hi @#{mentioned.nickname}"})
278 status = StatusView.render("show.json", %{activity: activity})
280 assert status.mentions ==
281 Enum.map([mentioned], fn u -> AccountView.render("mention.json", %{user: u}) end)
284 test "create mentions from the 'to' field" do
285 %User{ap_id: recipient_ap_id} = insert(:user)
286 cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
291 "to" => [recipient_ap_id],
297 insert(:note_activity, %{
299 recipients: [recipient_ap_id | cc]
302 assert length(activity.recipients) == 3
304 %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
306 assert length(mentions) == 1
307 assert mention.url == recipient_ap_id
310 test "create mentions from the 'tag' field" do
311 recipient = insert(:user)
312 cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
320 "href" => recipient.ap_id,
321 "name" => recipient.nickname,
325 "href" => "https://example.com/search?tag=test",
334 insert(:note_activity, %{
336 recipients: [recipient.ap_id | cc]
339 assert length(activity.recipients) == 3
341 %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
343 assert length(mentions) == 1
344 assert mention.url == recipient.ap_id
347 test "attachments" do
352 "mediaType" => "image/png",
363 remote_url: "someurl",
364 preview_url: "someurl",
367 pleroma: %{mime_type: "image/png"}
370 assert expected == StatusView.render("attachment.json", %{attachment: object})
372 # If theres a "id", use that instead of the generated one
373 object = Map.put(object, "id", 2)
374 assert %{id: "2"} = StatusView.render("attachment.json", %{attachment: object})
377 test "put the url advertised in the Activity in to the url attribute" do
378 id = "https://wedistribute.org/wp-json/pterotype/v1/object/85810"
379 [activity] = Activity.search(nil, id)
381 status = StatusView.render("show.json", %{activity: activity})
383 assert status.uri == id
384 assert status.url == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/"
389 activity = insert(:note_activity)
391 {:ok, reblog, _} = CommonAPI.repeat(activity.id, user)
393 represented = StatusView.render("show.json", %{for: user, activity: reblog})
395 assert represented[:id] == to_string(reblog.id)
396 assert represented[:reblog][:id] == to_string(activity.id)
397 assert represented[:emojis] == []
400 test "a peertube video" do
404 Pleroma.Object.Fetcher.fetch_object_from_id(
405 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
408 %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
410 represented = StatusView.render("show.json", %{for: user, activity: activity})
412 assert represented[:id] == to_string(activity.id)
413 assert length(represented[:media_attachments]) == 1
416 test "a Mobilizon event" do
420 Pleroma.Object.Fetcher.fetch_object_from_id(
421 "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
424 %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
426 represented = StatusView.render("show.json", %{for: user, activity: activity})
428 assert represented[:id] == to_string(activity.id)
431 describe "build_tags/1" do
432 test "it returns a a dictionary tags" do
438 "href" => "https://kawen.space/users/lain",
439 "name" => "@lain@kawen.space",
444 assert StatusView.build_tags(object_tags) == [
445 %{name: "fediverse", url: "/tag/fediverse"},
446 %{name: "mastodon", url: "/tag/mastodon"},
447 %{name: "nextcloud", url: "/tag/nextcloud"}
452 describe "rich media cards" do
453 test "a rich media card without a site name renders correctly" do
454 page_url = "http://example.com"
458 image: page_url <> "/example.jpg",
459 title: "Example website"
462 %{provider_name: "example.com"} =
463 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
466 test "a rich media card without a site name or image renders correctly" do
467 page_url = "http://example.com"
471 title: "Example website"
474 %{provider_name: "example.com"} =
475 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
478 test "a rich media card without an image renders correctly" do
479 page_url = "http://example.com"
483 site_name: "Example site name",
484 title: "Example website"
487 %{provider_name: "Example site name"} =
488 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
491 test "a rich media card with all relevant data renders correctly" do
492 page_url = "http://example.com"
496 site_name: "Example site name",
497 title: "Example website",
498 image: page_url <> "/example.jpg",
499 description: "Example description"
502 %{provider_name: "Example site name"} =
503 StatusView.render("card.json", %{page_url: page_url, rich_media: card})
507 test "embeds a relationship in the account" do
509 other_user = insert(:user)
512 CommonAPI.post(user, %{
513 "status" => "drink more water"
516 result = StatusView.render("show.json", %{activity: activity, for: other_user})
518 assert result[:account][:pleroma][:relationship] ==
519 AccountView.render("relationship.json", %{user: other_user, target: user})
522 test "embeds a relationship in the account in reposts" do
524 other_user = insert(:user)
527 CommonAPI.post(user, %{
528 "status" => "ĖĖÉŹns"
531 {:ok, activity, _object} = CommonAPI.repeat(activity.id, other_user)
533 result = StatusView.render("show.json", %{activity: activity, for: user})
535 assert result[:account][:pleroma][:relationship] ==
536 AccountView.render("relationship.json", %{user: user, target: other_user})
538 assert result[:reblog][:account][:pleroma][:relationship] ==
539 AccountView.render("relationship.json", %{user: user, target: user})
542 test "visibility/list" do
545 {:ok, list} = Pleroma.List.create("foo", user)
548 CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
550 status = StatusView.render("show.json", activity: activity)
552 assert status.visibility == "list"
555 test "successfully renders a Listen activity (pleroma extension)" do
556 listen_activity = insert(:listen)
558 status = StatusView.render("listen.json", activity: listen_activity)
560 assert status.length == listen_activity.data["object"]["length"]
561 assert status.title == listen_activity.data["object"]["title"]