86b3648ac2f05806707e67955f4c082da818e565
[akkoma] / test / web / common_api / common_api_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.CommonAPITest do
6 use Pleroma.DataCase
7 alias Pleroma.Activity
8 alias Pleroma.Chat
9 alias Pleroma.Conversation.Participation
10 alias Pleroma.Object
11 alias Pleroma.User
12 alias Pleroma.Web.ActivityPub.ActivityPub
13 alias Pleroma.Web.ActivityPub.Visibility
14 alias Pleroma.Web.AdminAPI.AccountView
15 alias Pleroma.Web.CommonAPI
16
17 import Pleroma.Factory
18
19 require Pleroma.Constants
20
21 setup do: clear_config([:instance, :safe_dm_mentions])
22 setup do: clear_config([:instance, :limit])
23 setup do: clear_config([:instance, :max_pinned_statuses])
24
25 describe "posting chat messages" do
26 setup do: clear_config([:instance, :chat_limit])
27
28 test "it posts a chat message" do
29 author = insert(:user)
30 recipient = insert(:user)
31
32 {:ok, activity} =
33 CommonAPI.post_chat_message(
34 author,
35 recipient,
36 "a test message <script>alert('uuu')</script> :firefox:"
37 )
38
39 assert activity.data["type"] == "Create"
40 assert activity.local
41 object = Object.normalize(activity)
42
43 assert object.data["type"] == "ChatMessage"
44 assert object.data["to"] == [recipient.ap_id]
45
46 assert object.data["content"] ==
47 "a test message &lt;script&gt;alert(&#39;uuu&#39;)&lt;/script&gt; :firefox:"
48
49 assert object.data["emoji"] == %{
50 "firefox" => "http://localhost:4001/emoji/Firefox.gif"
51 }
52
53 assert Chat.get(author.id, recipient.ap_id)
54 assert Chat.get(recipient.id, author.ap_id)
55 end
56
57 test "it reject messages over the local limit" do
58 Pleroma.Config.put([:instance, :chat_limit], 2)
59
60 author = insert(:user)
61 recipient = insert(:user)
62
63 {:error, message} =
64 CommonAPI.post_chat_message(
65 author,
66 recipient,
67 "123"
68 )
69
70 assert message == :content_too_long
71 end
72 end
73
74 test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
75 user = insert(:user)
76 {:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
77
78 [participation] = Participation.for_user(user)
79
80 {:ok, convo_reply} =
81 CommonAPI.post(user, %{"status" => ".", "in_reply_to_conversation_id" => participation.id})
82
83 assert Visibility.is_direct?(convo_reply)
84
85 assert activity.data["context"] == convo_reply.data["context"]
86 end
87
88 test "when replying to a conversation / participation, it only mentions the recipients explicitly declared in the participation" do
89 har = insert(:user)
90 jafnhar = insert(:user)
91 tridi = insert(:user)
92
93 {:ok, activity} =
94 CommonAPI.post(har, %{
95 "status" => "@#{jafnhar.nickname} hey",
96 "visibility" => "direct"
97 })
98
99 assert har.ap_id in activity.recipients
100 assert jafnhar.ap_id in activity.recipients
101
102 [participation] = Participation.for_user(har)
103
104 {:ok, activity} =
105 CommonAPI.post(har, %{
106 "status" => "I don't really like @#{tridi.nickname}",
107 "visibility" => "direct",
108 "in_reply_to_status_id" => activity.id,
109 "in_reply_to_conversation_id" => participation.id
110 })
111
112 assert har.ap_id in activity.recipients
113 assert jafnhar.ap_id in activity.recipients
114 refute tridi.ap_id in activity.recipients
115 end
116
117 test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do
118 har = insert(:user)
119 jafnhar = insert(:user)
120 tridi = insert(:user)
121
122 Pleroma.Config.put([:instance, :safe_dm_mentions], true)
123
124 {:ok, activity} =
125 CommonAPI.post(har, %{
126 "status" => "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again",
127 "visibility" => "direct"
128 })
129
130 refute tridi.ap_id in activity.recipients
131 assert jafnhar.ap_id in activity.recipients
132 end
133
134 test "it de-duplicates tags" do
135 user = insert(:user)
136 {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu #2HU"})
137
138 object = Object.normalize(activity)
139
140 assert object.data["tag"] == ["2hu"]
141 end
142
143 test "it adds emoji in the object" do
144 user = insert(:user)
145 {:ok, activity} = CommonAPI.post(user, %{"status" => ":firefox:"})
146
147 assert Object.normalize(activity).data["emoji"]["firefox"]
148 end
149
150 describe "posting" do
151 test "it supports explicit addressing" do
152 user = insert(:user)
153 user_two = insert(:user)
154 user_three = insert(:user)
155 user_four = insert(:user)
156
157 {:ok, activity} =
158 CommonAPI.post(user, %{
159 "status" =>
160 "Hey, I think @#{user_three.nickname} is ugly. @#{user_four.nickname} is alright though.",
161 "to" => [user_two.nickname, user_four.nickname, "nonexistent"]
162 })
163
164 assert user.ap_id in activity.recipients
165 assert user_two.ap_id in activity.recipients
166 assert user_four.ap_id in activity.recipients
167 refute user_three.ap_id in activity.recipients
168 end
169
170 test "it filters out obviously bad tags when accepting a post as HTML" do
171 user = insert(:user)
172
173 post = "<p><b>2hu</b></p><script>alert('xss')</script>"
174
175 {:ok, activity} =
176 CommonAPI.post(user, %{
177 "status" => post,
178 "content_type" => "text/html"
179 })
180
181 object = Object.normalize(activity)
182
183 assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
184 end
185
186 test "it filters out obviously bad tags when accepting a post as Markdown" do
187 user = insert(:user)
188
189 post = "<p><b>2hu</b></p><script>alert('xss')</script>"
190
191 {:ok, activity} =
192 CommonAPI.post(user, %{
193 "status" => post,
194 "content_type" => "text/markdown"
195 })
196
197 object = Object.normalize(activity)
198
199 assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
200 end
201
202 test "it does not allow replies to direct messages that are not direct messages themselves" do
203 user = insert(:user)
204
205 {:ok, activity} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"})
206
207 assert {:ok, _} =
208 CommonAPI.post(user, %{
209 "status" => "suya..",
210 "visibility" => "direct",
211 "in_reply_to_status_id" => activity.id
212 })
213
214 Enum.each(["public", "private", "unlisted"], fn visibility ->
215 assert {:error, "The message visibility must be direct"} =
216 CommonAPI.post(user, %{
217 "status" => "suya..",
218 "visibility" => visibility,
219 "in_reply_to_status_id" => activity.id
220 })
221 end)
222 end
223
224 test "it allows to address a list" do
225 user = insert(:user)
226 {:ok, list} = Pleroma.List.create("foo", user)
227
228 {:ok, activity} =
229 CommonAPI.post(user, %{"status" => "foobar", "visibility" => "list:#{list.id}"})
230
231 assert activity.data["bcc"] == [list.ap_id]
232 assert activity.recipients == [list.ap_id, user.ap_id]
233 assert activity.data["listMessage"] == list.ap_id
234 end
235
236 test "it returns error when status is empty and no attachments" do
237 user = insert(:user)
238
239 assert {:error, "Cannot post an empty status without attachments"} =
240 CommonAPI.post(user, %{"status" => ""})
241 end
242
243 test "it validates character limits are correctly enforced" do
244 Pleroma.Config.put([:instance, :limit], 5)
245
246 user = insert(:user)
247
248 assert {:error, "The status is over the character limit"} =
249 CommonAPI.post(user, %{"status" => "foobar"})
250
251 assert {:ok, activity} = CommonAPI.post(user, %{"status" => "12345"})
252 end
253
254 test "it can handle activities that expire" do
255 user = insert(:user)
256
257 expires_at =
258 NaiveDateTime.utc_now()
259 |> NaiveDateTime.truncate(:second)
260 |> NaiveDateTime.add(1_000_000, :second)
261
262 assert {:ok, activity} =
263 CommonAPI.post(user, %{"status" => "chai", "expires_in" => 1_000_000})
264
265 assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
266 assert expiration.scheduled_at == expires_at
267 end
268 end
269
270 describe "reactions" do
271 test "reacting to a status with an emoji" do
272 user = insert(:user)
273 other_user = insert(:user)
274
275 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
276
277 {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
278
279 assert reaction.data["actor"] == user.ap_id
280 assert reaction.data["content"] == "👍"
281
282 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
283
284 {:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".")
285 end
286
287 test "unreacting to a status with an emoji" do
288 user = insert(:user)
289 other_user = insert(:user)
290
291 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
292 {:ok, reaction, _} = CommonAPI.react_with_emoji(activity.id, user, "👍")
293
294 {:ok, unreaction, _} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
295
296 assert unreaction.data["type"] == "Undo"
297 assert unreaction.data["object"] == reaction.data["id"]
298 end
299
300 test "repeating a status" do
301 user = insert(:user)
302 other_user = insert(:user)
303
304 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
305
306 {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)
307 end
308
309 test "repeating a status privately" do
310 user = insert(:user)
311 other_user = insert(:user)
312
313 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
314
315 {:ok, %Activity{} = announce_activity, _} =
316 CommonAPI.repeat(activity.id, user, %{"visibility" => "private"})
317
318 assert Visibility.is_private?(announce_activity)
319 end
320
321 test "favoriting a status" do
322 user = insert(:user)
323 other_user = insert(:user)
324
325 {:ok, post_activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
326
327 {:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
328 assert data["type"] == "Like"
329 assert data["actor"] == user.ap_id
330 assert data["object"] == post_activity.data["object"]
331 end
332
333 test "retweeting a status twice returns the status" do
334 user = insert(:user)
335 other_user = insert(:user)
336
337 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
338 {:ok, %Activity{} = activity, object} = CommonAPI.repeat(activity.id, user)
339 {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user)
340 end
341
342 test "favoriting a status twice returns ok, but without the like activity" do
343 user = insert(:user)
344 other_user = insert(:user)
345
346 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
347 {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
348 assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)
349 end
350 end
351
352 describe "pinned statuses" do
353 setup do
354 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
355
356 user = insert(:user)
357 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
358
359 [user: user, activity: activity]
360 end
361
362 test "pin status", %{user: user, activity: activity} do
363 assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
364
365 id = activity.id
366 user = refresh_record(user)
367
368 assert %User{pinned_activities: [^id]} = user
369 end
370
371 test "pin poll", %{user: user} do
372 {:ok, activity} =
373 CommonAPI.post(user, %{
374 "status" => "How is fediverse today?",
375 "poll" => %{"options" => ["Absolutely outstanding", "Not good"], "expires_in" => 20}
376 })
377
378 assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
379
380 id = activity.id
381 user = refresh_record(user)
382
383 assert %User{pinned_activities: [^id]} = user
384 end
385
386 test "unlisted statuses can be pinned", %{user: user} do
387 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!", "visibility" => "unlisted"})
388 assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
389 end
390
391 test "only self-authored can be pinned", %{activity: activity} do
392 user = insert(:user)
393
394 assert {:error, "Could not pin"} = CommonAPI.pin(activity.id, user)
395 end
396
397 test "max pinned statuses", %{user: user, activity: activity_one} do
398 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
399
400 assert {:ok, ^activity_one} = CommonAPI.pin(activity_one.id, user)
401
402 user = refresh_record(user)
403
404 assert {:error, "You have already pinned the maximum number of statuses"} =
405 CommonAPI.pin(activity_two.id, user)
406 end
407
408 test "unpin status", %{user: user, activity: activity} do
409 {:ok, activity} = CommonAPI.pin(activity.id, user)
410
411 user = refresh_record(user)
412
413 assert {:ok, ^activity} = CommonAPI.unpin(activity.id, user)
414
415 user = refresh_record(user)
416
417 assert %User{pinned_activities: []} = user
418 end
419
420 test "should unpin when deleting a status", %{user: user, activity: activity} do
421 {:ok, activity} = CommonAPI.pin(activity.id, user)
422
423 user = refresh_record(user)
424
425 assert {:ok, _} = CommonAPI.delete(activity.id, user)
426
427 user = refresh_record(user)
428
429 assert %User{pinned_activities: []} = user
430 end
431 end
432
433 describe "mute tests" do
434 setup do
435 user = insert(:user)
436
437 activity = insert(:note_activity)
438
439 [user: user, activity: activity]
440 end
441
442 test "add mute", %{user: user, activity: activity} do
443 {:ok, _} = CommonAPI.add_mute(user, activity)
444 assert CommonAPI.thread_muted?(user, activity)
445 end
446
447 test "remove mute", %{user: user, activity: activity} do
448 CommonAPI.add_mute(user, activity)
449 {:ok, _} = CommonAPI.remove_mute(user, activity)
450 refute CommonAPI.thread_muted?(user, activity)
451 end
452
453 test "check that mutes can't be duplicate", %{user: user, activity: activity} do
454 CommonAPI.add_mute(user, activity)
455 {:error, _} = CommonAPI.add_mute(user, activity)
456 end
457 end
458
459 describe "reports" do
460 test "creates a report" do
461 reporter = insert(:user)
462 target_user = insert(:user)
463
464 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
465
466 reporter_ap_id = reporter.ap_id
467 target_ap_id = target_user.ap_id
468 activity_ap_id = activity.data["id"]
469 comment = "foobar"
470
471 report_data = %{
472 "account_id" => target_user.id,
473 "comment" => comment,
474 "status_ids" => [activity.id]
475 }
476
477 note_obj = %{
478 "type" => "Note",
479 "id" => activity_ap_id,
480 "content" => "foobar",
481 "published" => activity.object.data["published"],
482 "actor" => AccountView.render("show.json", %{user: target_user})
483 }
484
485 assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
486
487 assert %Activity{
488 actor: ^reporter_ap_id,
489 data: %{
490 "type" => "Flag",
491 "content" => ^comment,
492 "object" => [^target_ap_id, ^note_obj],
493 "state" => "open"
494 }
495 } = flag_activity
496 end
497
498 test "updates report state" do
499 [reporter, target_user] = insert_pair(:user)
500 activity = insert(:note_activity, user: target_user)
501
502 {:ok, %Activity{id: report_id}} =
503 CommonAPI.report(reporter, %{
504 "account_id" => target_user.id,
505 "comment" => "I feel offended",
506 "status_ids" => [activity.id]
507 })
508
509 {:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
510
511 assert report.data["state"] == "resolved"
512
513 [reported_user, activity_id] = report.data["object"]
514
515 assert reported_user == target_user.ap_id
516 assert activity_id == activity.data["id"]
517 end
518
519 test "does not update report state when state is unsupported" do
520 [reporter, target_user] = insert_pair(:user)
521 activity = insert(:note_activity, user: target_user)
522
523 {:ok, %Activity{id: report_id}} =
524 CommonAPI.report(reporter, %{
525 "account_id" => target_user.id,
526 "comment" => "I feel offended",
527 "status_ids" => [activity.id]
528 })
529
530 assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
531 end
532
533 test "updates state of multiple reports" do
534 [reporter, target_user] = insert_pair(:user)
535 activity = insert(:note_activity, user: target_user)
536
537 {:ok, %Activity{id: first_report_id}} =
538 CommonAPI.report(reporter, %{
539 "account_id" => target_user.id,
540 "comment" => "I feel offended",
541 "status_ids" => [activity.id]
542 })
543
544 {:ok, %Activity{id: second_report_id}} =
545 CommonAPI.report(reporter, %{
546 "account_id" => target_user.id,
547 "comment" => "I feel very offended!",
548 "status_ids" => [activity.id]
549 })
550
551 {:ok, report_ids} =
552 CommonAPI.update_report_state([first_report_id, second_report_id], "resolved")
553
554 first_report = Activity.get_by_id(first_report_id)
555 second_report = Activity.get_by_id(second_report_id)
556
557 assert report_ids -- [first_report_id, second_report_id] == []
558 assert first_report.data["state"] == "resolved"
559 assert second_report.data["state"] == "resolved"
560 end
561 end
562
563 describe "reblog muting" do
564 setup do
565 muter = insert(:user)
566
567 muted = insert(:user)
568
569 [muter: muter, muted: muted]
570 end
571
572 test "add a reblog mute", %{muter: muter, muted: muted} do
573 {:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
574
575 assert User.showing_reblogs?(muter, muted) == false
576 end
577
578 test "remove a reblog mute", %{muter: muter, muted: muted} do
579 {:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
580 {:ok, _reblog_mute} = CommonAPI.show_reblogs(muter, muted)
581
582 assert User.showing_reblogs?(muter, muted) == true
583 end
584 end
585
586 describe "unfollow/2" do
587 test "also unsubscribes a user" do
588 [follower, followed] = insert_pair(:user)
589 {:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
590 {:ok, _subscription} = User.subscribe(follower, followed)
591
592 assert User.subscribed_to?(follower, followed)
593
594 {:ok, follower} = CommonAPI.unfollow(follower, followed)
595
596 refute User.subscribed_to?(follower, followed)
597 end
598
599 test "cancels a pending follow for a local user" do
600 follower = insert(:user)
601 followed = insert(:user, locked: true)
602
603 assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
604 CommonAPI.follow(follower, followed)
605
606 assert User.get_follow_state(follower, followed) == :follow_pending
607 assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
608 assert User.get_follow_state(follower, followed) == nil
609
610 assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
611 Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
612
613 assert %{
614 data: %{
615 "type" => "Undo",
616 "object" => %{"type" => "Follow", "state" => "cancelled"}
617 }
618 } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
619 end
620
621 test "cancels a pending follow for a remote user" do
622 follower = insert(:user)
623 followed = insert(:user, locked: true, local: false, ap_enabled: true)
624
625 assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
626 CommonAPI.follow(follower, followed)
627
628 assert User.get_follow_state(follower, followed) == :follow_pending
629 assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
630 assert User.get_follow_state(follower, followed) == nil
631
632 assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
633 Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)
634
635 assert %{
636 data: %{
637 "type" => "Undo",
638 "object" => %{"type" => "Follow", "state" => "cancelled"}
639 }
640 } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
641 end
642 end
643
644 describe "accept_follow_request/2" do
645 test "after acceptance, it sets all existing pending follow request states to 'accept'" do
646 user = insert(:user, locked: true)
647 follower = insert(:user)
648 follower_two = insert(:user)
649
650 {:ok, follow_activity} = ActivityPub.follow(follower, user)
651 {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
652 {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)
653
654 assert follow_activity.data["state"] == "pending"
655 assert follow_activity_two.data["state"] == "pending"
656 assert follow_activity_three.data["state"] == "pending"
657
658 {:ok, _follower} = CommonAPI.accept_follow_request(follower, user)
659
660 assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
661 assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
662 assert Repo.get(Activity, follow_activity_three.id).data["state"] == "pending"
663 end
664
665 test "after rejection, it sets all existing pending follow request states to 'reject'" do
666 user = insert(:user, locked: true)
667 follower = insert(:user)
668 follower_two = insert(:user)
669
670 {:ok, follow_activity} = ActivityPub.follow(follower, user)
671 {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
672 {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)
673
674 assert follow_activity.data["state"] == "pending"
675 assert follow_activity_two.data["state"] == "pending"
676 assert follow_activity_three.data["state"] == "pending"
677
678 {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
679
680 assert Repo.get(Activity, follow_activity.id).data["state"] == "reject"
681 assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
682 assert Repo.get(Activity, follow_activity_three.id).data["state"] == "pending"
683 end
684 end
685
686 describe "vote/3" do
687 test "does not allow to vote twice" do
688 user = insert(:user)
689 other_user = insert(:user)
690
691 {:ok, activity} =
692 CommonAPI.post(user, %{
693 "status" => "Am I cute?",
694 "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}
695 })
696
697 object = Object.normalize(activity)
698
699 {:ok, _, object} = CommonAPI.vote(other_user, object, [0])
700
701 assert {:error, "Already voted"} == CommonAPI.vote(other_user, object, [1])
702 end
703 end
704
705 describe "listen/2" do
706 test "returns a valid activity" do
707 user = insert(:user)
708
709 {:ok, activity} =
710 CommonAPI.listen(user, %{
711 "title" => "lain radio episode 1",
712 "album" => "lain radio",
713 "artist" => "lain",
714 "length" => 180_000
715 })
716
717 object = Object.normalize(activity)
718
719 assert object.data["title"] == "lain radio episode 1"
720
721 assert Visibility.get_visibility(activity) == "public"
722 end
723
724 test "respects visibility=private" do
725 user = insert(:user)
726
727 {:ok, activity} =
728 CommonAPI.listen(user, %{
729 "title" => "lain radio episode 1",
730 "album" => "lain radio",
731 "artist" => "lain",
732 "length" => 180_000,
733 "visibility" => "private"
734 })
735
736 object = Object.normalize(activity)
737
738 assert object.data["title"] == "lain radio episode 1"
739
740 assert Visibility.get_visibility(activity) == "private"
741 end
742 end
743 end