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