move to 2.5.5
[anni] / test / pleroma / web / mastodon_api / views / status_view_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 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.Bookmark
10   alias Pleroma.Conversation.Participation
11   alias Pleroma.HTML
12   alias Pleroma.Object
13   alias Pleroma.Repo
14   alias Pleroma.User
15   alias Pleroma.UserRelationship
16   alias Pleroma.Web.CommonAPI
17   alias Pleroma.Web.MastodonAPI.AccountView
18   alias Pleroma.Web.MastodonAPI.StatusView
19
20   require Bitwise
21
22   import Pleroma.Factory
23   import Tesla.Mock
24   import OpenApiSpex.TestAssertions
25
26   setup do
27     mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
28     :ok
29   end
30
31   test "has an emoji reaction list" do
32     user = insert(:user)
33     other_user = insert(:user)
34     third_user = insert(:user)
35     {:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
36
37     {:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "☕")
38     {:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "🍵")
39     {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
40     activity = Repo.get(Activity, activity.id)
41     status = StatusView.render("show.json", activity: activity)
42
43     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
44
45     assert status[:pleroma][:emoji_reactions] == [
46              %{name: "☕", count: 2, me: false},
47              %{name: "🍵", count: 1, me: false}
48            ]
49
50     status = StatusView.render("show.json", activity: activity, for: user)
51
52     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
53
54     assert status[:pleroma][:emoji_reactions] == [
55              %{name: "☕", count: 2, me: true},
56              %{name: "🍵", count: 1, me: false}
57            ]
58   end
59
60   test "works correctly with badly formatted emojis" do
61     user = insert(:user)
62     {:ok, activity} = CommonAPI.post(user, %{status: "yo"})
63
64     activity
65     |> Object.normalize(fetch: false)
66     |> Object.update_data(%{"reactions" => %{"☕" => [user.ap_id], "x" => 1}})
67
68     activity = Activity.get_by_id(activity.id)
69
70     status = StatusView.render("show.json", activity: activity, for: user)
71
72     assert status[:pleroma][:emoji_reactions] == [
73              %{name: "☕", count: 1, me: true}
74            ]
75   end
76
77   test "doesn't show reactions from muted and blocked users" do
78     user = insert(:user)
79     other_user = insert(:user)
80     third_user = insert(:user)
81
82     {:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
83
84     {:ok, _} = User.mute(user, other_user)
85     {:ok, _} = User.block(other_user, third_user)
86
87     {:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
88
89     activity = Repo.get(Activity, activity.id)
90     status = StatusView.render("show.json", activity: activity)
91
92     assert status[:pleroma][:emoji_reactions] == [
93              %{name: "☕", count: 1, me: false}
94            ]
95
96     status = StatusView.render("show.json", activity: activity, for: user)
97
98     assert status[:pleroma][:emoji_reactions] == []
99
100     {:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "☕")
101
102     status = StatusView.render("show.json", activity: activity)
103
104     assert status[:pleroma][:emoji_reactions] == [
105              %{name: "☕", count: 2, me: false}
106            ]
107
108     status = StatusView.render("show.json", activity: activity, for: user)
109
110     assert status[:pleroma][:emoji_reactions] == [
111              %{name: "☕", count: 1, me: false}
112            ]
113
114     status = StatusView.render("show.json", activity: activity, for: other_user)
115
116     assert status[:pleroma][:emoji_reactions] == [
117              %{name: "☕", count: 1, me: true}
118            ]
119   end
120
121   test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
122     user = insert(:user)
123
124     {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
125     [participation] = Participation.for_user(user)
126
127     status =
128       StatusView.render("show.json",
129         activity: activity,
130         with_direct_conversation_id: true,
131         for: user
132       )
133
134     assert status[:pleroma][:direct_conversation_id] == participation.id
135
136     status = StatusView.render("show.json", activity: activity, for: user)
137     assert status[:pleroma][:direct_conversation_id] == nil
138     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
139   end
140
141   test "returns the direct conversation id when given the `direct_conversation_id` option" do
142     user = insert(:user)
143
144     {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
145     [participation] = Participation.for_user(user)
146
147     status =
148       StatusView.render("show.json",
149         activity: activity,
150         direct_conversation_id: participation.id,
151         for: user
152       )
153
154     assert status[:pleroma][:direct_conversation_id] == participation.id
155     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
156   end
157
158   test "returns a temporary ap_id based user for activities missing db users" do
159     user = insert(:user)
160
161     {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
162
163     Repo.delete(user)
164     User.invalidate_cache(user)
165
166     finger_url =
167       "https://localhost/.well-known/webfinger?resource=acct:#{user.nickname}@localhost"
168
169     Tesla.Mock.mock_global(fn
170       %{method: :get, url: "http://localhost/.well-known/host-meta"} ->
171         %Tesla.Env{status: 404, body: ""}
172
173       %{method: :get, url: "https://localhost/.well-known/host-meta"} ->
174         %Tesla.Env{status: 404, body: ""}
175
176       %{
177         method: :get,
178         url: ^finger_url
179       } ->
180         %Tesla.Env{status: 404, body: ""}
181     end)
182
183     %{account: ms_user} = StatusView.render("show.json", activity: activity)
184
185     assert ms_user.acct == "erroruser@example.com"
186   end
187
188   test "tries to get a user by nickname if fetching by ap_id doesn't work" do
189     user = insert(:user)
190
191     {:ok, activity} = CommonAPI.post(user, %{status: "Hey @shp!", visibility: "direct"})
192
193     {:ok, user} =
194       user
195       |> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
196       |> Repo.update()
197
198     User.invalidate_cache(user)
199
200     result = StatusView.render("show.json", activity: activity)
201
202     assert result[:account][:id] == to_string(user.id)
203     assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
204   end
205
206   test "a note with null content" do
207     note = insert(:note_activity)
208     note_object = Object.normalize(note, fetch: false)
209
210     data =
211       note_object.data
212       |> Map.put("content", nil)
213
214     Object.change(note_object, %{data: data})
215     |> Object.update_and_set_cache()
216
217     User.get_cached_by_ap_id(note.data["actor"])
218
219     status = StatusView.render("show.json", %{activity: note})
220
221     assert status.content == ""
222     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
223   end
224
225   test "a note activity" do
226     note = insert(:note_activity)
227     object_data = Object.normalize(note, fetch: false).data
228     user = User.get_cached_by_ap_id(note.data["actor"])
229
230     convo_id = :erlang.crc32(object_data["context"]) |> Bitwise.band(Bitwise.bnot(0x8000_0000))
231
232     status = StatusView.render("show.json", %{activity: note})
233
234     created_at =
235       (object_data["published"] || "")
236       |> String.replace(~r/\.\d+Z/, ".000Z")
237
238     expected = %{
239       id: to_string(note.id),
240       uri: object_data["id"],
241       url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
242       account: AccountView.render("show.json", %{user: user, skip_visibility_check: true}),
243       in_reply_to_id: nil,
244       in_reply_to_account_id: nil,
245       card: nil,
246       reblog: nil,
247       content: HTML.filter_tags(object_data["content"]),
248       text: nil,
249       created_at: created_at,
250       edited_at: nil,
251       reblogs_count: 0,
252       replies_count: 0,
253       favourites_count: 0,
254       reblogged: false,
255       bookmarked: false,
256       favourited: false,
257       muted: false,
258       pinned: false,
259       sensitive: false,
260       poll: nil,
261       spoiler_text: HTML.filter_tags(object_data["summary"]),
262       visibility: "public",
263       media_attachments: [],
264       mentions: [],
265       tags: [
266         %{
267           name: "#{hd(object_data["tag"])}",
268           url: "http://localhost:4001/tag/#{hd(object_data["tag"])}"
269         }
270       ],
271       application: nil,
272       language: nil,
273       emojis: [
274         %{
275           shortcode: "2hu",
276           url: "corndog.png",
277           static_url: "corndog.png",
278           visible_in_picker: false
279         }
280       ],
281       pleroma: %{
282         local: true,
283         conversation_id: convo_id,
284         context: object_data["context"],
285         in_reply_to_account_acct: nil,
286         content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
287         spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
288         expires_at: nil,
289         direct_conversation_id: nil,
290         thread_muted: false,
291         emoji_reactions: [],
292         parent_visible: false,
293         pinned_at: nil
294       }
295     }
296
297     assert status == expected
298     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
299   end
300
301   test "tells if the message is muted for some reason" do
302     user = insert(:user)
303     other_user = insert(:user)
304
305     {:ok, _user_relationships} = User.mute(user, other_user)
306
307     {:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
308
309     relationships_opt = UserRelationship.view_relationships_option(user, [other_user])
310
311     opts = %{activity: activity}
312     status = StatusView.render("show.json", opts)
313     assert status.muted == false
314     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
315
316     status = StatusView.render("show.json", Map.put(opts, :relationships, relationships_opt))
317     assert status.muted == false
318
319     for_opts = %{activity: activity, for: user}
320     status = StatusView.render("show.json", for_opts)
321     assert status.muted == true
322
323     status = StatusView.render("show.json", Map.put(for_opts, :relationships, relationships_opt))
324     assert status.muted == true
325     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
326   end
327
328   test "tells if the message is thread muted" do
329     user = insert(:user)
330     other_user = insert(:user)
331
332     {:ok, _user_relationships} = User.mute(user, other_user)
333
334     {:ok, activity} = CommonAPI.post(other_user, %{status: "test"})
335     status = StatusView.render("show.json", %{activity: activity, for: user})
336
337     assert status.pleroma.thread_muted == false
338
339     {:ok, activity} = CommonAPI.add_mute(user, activity)
340
341     status = StatusView.render("show.json", %{activity: activity, for: user})
342
343     assert status.pleroma.thread_muted == true
344   end
345
346   test "tells if the status is bookmarked" do
347     user = insert(:user)
348
349     {:ok, activity} = CommonAPI.post(user, %{status: "Cute girls doing cute things"})
350     status = StatusView.render("show.json", %{activity: activity})
351
352     assert status.bookmarked == false
353
354     status = StatusView.render("show.json", %{activity: activity, for: user})
355
356     assert status.bookmarked == false
357
358     {:ok, _bookmark} = Bookmark.create(user.id, activity.id)
359
360     activity = Activity.get_by_id_with_object(activity.id)
361
362     status = StatusView.render("show.json", %{activity: activity, for: user})
363
364     assert status.bookmarked == true
365   end
366
367   test "a reply" do
368     note = insert(:note_activity)
369     user = insert(:user)
370
371     {:ok, activity} = CommonAPI.post(user, %{status: "he", in_reply_to_status_id: note.id})
372
373     status = StatusView.render("show.json", %{activity: activity})
374
375     assert status.in_reply_to_id == to_string(note.id)
376
377     [status] = StatusView.render("index.json", %{activities: [activity], as: :activity})
378
379     assert status.in_reply_to_id == to_string(note.id)
380   end
381
382   test "contains mentions" do
383     user = insert(:user)
384     mentioned = insert(:user)
385
386     {:ok, activity} = CommonAPI.post(user, %{status: "hi @#{mentioned.nickname}"})
387
388     status = StatusView.render("show.json", %{activity: activity})
389
390     assert status.mentions ==
391              Enum.map([mentioned], fn u -> AccountView.render("mention.json", %{user: u}) end)
392
393     assert_schema(status, "Status", Pleroma.Web.ApiSpec.spec())
394   end
395
396   test "create mentions from the 'to' field" do
397     %User{ap_id: recipient_ap_id} = insert(:user)
398     cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
399
400     object =
401       insert(:note, %{
402         data: %{
403           "to" => [recipient_ap_id],
404           "cc" => cc
405         }
406       })
407
408     activity =
409       insert(:note_activity, %{
410         note: object,
411         recipients: [recipient_ap_id | cc]
412       })
413
414     assert length(activity.recipients) == 3
415
416     %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
417
418     assert length(mentions) == 1
419     assert mention.url == recipient_ap_id
420   end
421
422   test "create mentions from the 'tag' field" do
423     recipient = insert(:user)
424     cc = insert_pair(:user) |> Enum.map(& &1.ap_id)
425
426     object =
427       insert(:note, %{
428         data: %{
429           "cc" => cc,
430           "tag" => [
431             %{
432               "href" => recipient.ap_id,
433               "name" => recipient.nickname,
434               "type" => "Mention"
435             },
436             %{
437               "href" => "https://example.com/search?tag=test",
438               "name" => "#test",
439               "type" => "Hashtag"
440             }
441           ]
442         }
443       })
444
445     activity =
446       insert(:note_activity, %{
447         note: object,
448         recipients: [recipient.ap_id | cc]
449       })
450
451     assert length(activity.recipients) == 3
452
453     %{mentions: [mention] = mentions} = StatusView.render("show.json", %{activity: activity})
454
455     assert length(mentions) == 1
456     assert mention.url == recipient.ap_id
457   end
458
459   test "attachments" do
460     object = %{
461       "type" => "Image",
462       "url" => [
463         %{
464           "mediaType" => "image/png",
465           "href" => "someurl",
466           "width" => 200,
467           "height" => 100
468         }
469       ],
470       "blurhash" => "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn",
471       "uuid" => 6
472     }
473
474     expected = %{
475       id: "1638338801",
476       type: "image",
477       url: "someurl",
478       remote_url: "someurl",
479       preview_url: "someurl",
480       text_url: "someurl",
481       description: nil,
482       pleroma: %{mime_type: "image/png"},
483       meta: %{original: %{width: 200, height: 100, aspect: 2}},
484       blurhash: "UJJ8X[xYW,%Jtq%NNFbXB5j]IVM|9GV=WHRn"
485     }
486
487     api_spec = Pleroma.Web.ApiSpec.spec()
488
489     assert expected == StatusView.render("attachment.json", %{attachment: object})
490     assert_schema(expected, "Attachment", api_spec)
491
492     # If theres a "id", use that instead of the generated one
493     object = Map.put(object, "id", 2)
494     result = StatusView.render("attachment.json", %{attachment: object})
495
496     assert %{id: "2"} = result
497     assert_schema(result, "Attachment", api_spec)
498   end
499
500   test "put the url advertised in the Activity in to the url attribute" do
501     id = "https://wedistribute.org/wp-json/pterotype/v1/object/85810"
502     [activity] = Activity.search(nil, id)
503
504     status = StatusView.render("show.json", %{activity: activity})
505
506     assert status.uri == id
507     assert status.url == "https://wedistribute.org/2019/07/mastodon-drops-ostatus/"
508   end
509
510   test "a reblog" do
511     user = insert(:user)
512     activity = insert(:note_activity)
513
514     {:ok, reblog} = CommonAPI.repeat(activity.id, user)
515
516     represented = StatusView.render("show.json", %{for: user, activity: reblog})
517
518     assert represented[:id] == to_string(reblog.id)
519     assert represented[:reblog][:id] == to_string(activity.id)
520     assert represented[:emojis] == []
521     assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
522   end
523
524   test "a peertube video" do
525     user = insert(:user)
526
527     {:ok, object} =
528       Pleroma.Object.Fetcher.fetch_object_from_id(
529         "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
530       )
531
532     %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
533
534     represented = StatusView.render("show.json", %{for: user, activity: activity})
535
536     assert represented[:id] == to_string(activity.id)
537     assert length(represented[:media_attachments]) == 1
538     assert_schema(represented, "Status", Pleroma.Web.ApiSpec.spec())
539   end
540
541   test "funkwhale audio" do
542     user = insert(:user)
543
544     {:ok, object} =
545       Pleroma.Object.Fetcher.fetch_object_from_id(
546         "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871"
547       )
548
549     %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
550
551     represented = StatusView.render("show.json", %{for: user, activity: activity})
552
553     assert represented[:id] == to_string(activity.id)
554     assert length(represented[:media_attachments]) == 1
555   end
556
557   test "a Mobilizon event" do
558     user = insert(:user)
559
560     {:ok, object} =
561       Pleroma.Object.Fetcher.fetch_object_from_id(
562         "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
563       )
564
565     %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
566
567     represented = StatusView.render("show.json", %{for: user, activity: activity})
568
569     assert represented[:id] == to_string(activity.id)
570
571     assert represented[:url] ==
572              "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"
573
574     assert represented[:content] ==
575              "<p><a href=\"https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39\">Mobilizon Launching Party</a></p><p>Mobilizon is now federated! 🎉</p><p></p><p>You can view this event from other instances if they are subscribed to mobilizon.org, and soon directly from Mastodon and Pleroma. It is possible that you may see some comments from other instances, including Mastodon ones, just below.</p><p></p><p>With a Mobilizon account on an instance, you may <strong>participate</strong> at events from other instances and <strong>add comments</strong> on events.</p><p></p><p>Of course, it&#39;s still <u>a work in progress</u>: if reports made from an instance on events and comments can be federated, you can&#39;t block people right now, and moderators actions are rather limited, but this <strong>will definitely get fixed over time</strong> until first stable version next year.</p><p></p><p>Anyway, if you want to come up with some feedback, head over to our forum or - if you feel you have technical skills and are familiar with it - on our Gitlab repository.</p><p></p><p>Also, to people that want to set Mobilizon themselves even though we really don&#39;t advise to do that for now, we have a little documentation but it&#39;s quite the early days and you&#39;ll probably need some help. No worries, you can chat with us on our Forum or though our Matrix channel.</p><p></p><p>Check our website for more informations and follow us on Twitter or Mastodon.</p>"
576   end
577
578   describe "build_tags/1" do
579     test "it returns a a dictionary tags" do
580       object_tags = [
581         "fediverse",
582         "mastodon",
583         "nextcloud",
584         %{
585           "href" => "https://kawen.space/users/lain",
586           "name" => "@lain@kawen.space",
587           "type" => "Mention"
588         }
589       ]
590
591       assert StatusView.build_tags(object_tags) == [
592                %{name: "fediverse", url: "http://localhost:4001/tag/fediverse"},
593                %{name: "mastodon", url: "http://localhost:4001/tag/mastodon"},
594                %{name: "nextcloud", url: "http://localhost:4001/tag/nextcloud"}
595              ]
596     end
597   end
598
599   describe "rich media cards" do
600     test "a rich media card without a site name renders correctly" do
601       page_url = "http://example.com"
602
603       card = %{
604         url: page_url,
605         image: page_url <> "/example.jpg",
606         title: "Example website"
607       }
608
609       %{provider_name: "example.com"} =
610         StatusView.render("card.json", %{page_url: page_url, rich_media: card})
611     end
612
613     test "a rich media card without a site name or image renders correctly" do
614       page_url = "http://example.com"
615
616       card = %{
617         url: page_url,
618         title: "Example website"
619       }
620
621       %{provider_name: "example.com"} =
622         StatusView.render("card.json", %{page_url: page_url, rich_media: card})
623     end
624
625     test "a rich media card without an image renders correctly" do
626       page_url = "http://example.com"
627
628       card = %{
629         url: page_url,
630         site_name: "Example site name",
631         title: "Example website"
632       }
633
634       %{provider_name: "example.com"} =
635         StatusView.render("card.json", %{page_url: page_url, rich_media: card})
636     end
637
638     test "a rich media card with all relevant data renders correctly" do
639       page_url = "http://example.com"
640
641       card = %{
642         url: page_url,
643         site_name: "Example site name",
644         title: "Example website",
645         image: page_url <> "/example.jpg",
646         description: "Example description"
647       }
648
649       %{provider_name: "example.com"} =
650         StatusView.render("card.json", %{page_url: page_url, rich_media: card})
651     end
652   end
653
654   test "does not embed a relationship in the account" do
655     user = insert(:user)
656     other_user = insert(:user)
657
658     {:ok, activity} =
659       CommonAPI.post(user, %{
660         status: "drink more water"
661       })
662
663     result = StatusView.render("show.json", %{activity: activity, for: other_user})
664
665     assert result[:account][:pleroma][:relationship] == %{}
666     assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
667   end
668
669   test "does not embed a relationship in the account in reposts" do
670     user = insert(:user)
671     other_user = insert(:user)
672
673     {:ok, activity} =
674       CommonAPI.post(user, %{
675         status: "˙˙ɐʎns"
676       })
677
678     {:ok, activity} = CommonAPI.repeat(activity.id, other_user)
679
680     result = StatusView.render("show.json", %{activity: activity, for: user})
681
682     assert result[:account][:pleroma][:relationship] == %{}
683     assert result[:reblog][:account][:pleroma][:relationship] == %{}
684     assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
685   end
686
687   test "visibility/list" do
688     user = insert(:user)
689
690     {:ok, list} = Pleroma.List.create("foo", user)
691
692     {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
693
694     status = StatusView.render("show.json", activity: activity)
695
696     assert status.visibility == "list"
697   end
698
699   test "has a field for parent visibility" do
700     user = insert(:user)
701     poster = insert(:user)
702
703     {:ok, invisible} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
704
705     {:ok, visible} =
706       CommonAPI.post(poster, %{status: "hey", visibility: "private", in_reply_to_id: invisible.id})
707
708     status = StatusView.render("show.json", activity: visible, for: user)
709     refute status.pleroma.parent_visible
710
711     status = StatusView.render("show.json", activity: visible, for: poster)
712     assert status.pleroma.parent_visible
713   end
714
715   test "it shows edited_at" do
716     poster = insert(:user)
717
718     {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
719
720     status = StatusView.render("show.json", activity: post)
721     refute status.edited_at
722
723     {:ok, _} = CommonAPI.update(poster, post, %{status: "mew mew"})
724     edited = Pleroma.Activity.normalize(post)
725
726     status = StatusView.render("show.json", activity: edited)
727     assert status.edited_at
728   end
729
730   test "with a source object" do
731     note =
732       insert(:note,
733         data: %{"source" => %{"content" => "object source", "mediaType" => "text/markdown"}}
734       )
735
736     activity = insert(:note_activity, note: note)
737
738     status = StatusView.render("show.json", activity: activity, with_source: true)
739     assert status.text == "object source"
740   end
741
742   describe "source.json" do
743     test "with a source object, renders both source and content type" do
744       note =
745         insert(:note,
746           data: %{"source" => %{"content" => "object source", "mediaType" => "text/markdown"}}
747         )
748
749       activity = insert(:note_activity, note: note)
750
751       status = StatusView.render("source.json", activity: activity)
752       assert status.text == "object source"
753       assert status.content_type == "text/markdown"
754     end
755
756     test "with a source string, renders source and put text/plain as the content type" do
757       note = insert(:note, data: %{"source" => "string source"})
758       activity = insert(:note_activity, note: note)
759
760       status = StatusView.render("source.json", activity: activity)
761       assert status.text == "string source"
762       assert status.content_type == "text/plain"
763     end
764   end
765 end