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