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