Merge branch 'fix/embeded-relationship-in-follows' into 'develop'
[akkoma] / test / web / mastodon_api / mastodon_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
6 use Pleroma.Web.ConnCase
7
8 alias Ecto.Changeset
9 alias Pleroma.Activity
10 alias Pleroma.Notification
11 alias Pleroma.Object
12 alias Pleroma.Repo
13 alias Pleroma.ScheduledActivity
14 alias Pleroma.User
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.CommonAPI
17 alias Pleroma.Web.MastodonAPI.FilterView
18 alias Pleroma.Web.OAuth.App
19 alias Pleroma.Web.OStatus
20 alias Pleroma.Web.Push
21 alias Pleroma.Web.TwitterAPI.TwitterAPI
22 import Pleroma.Factory
23 import ExUnit.CaptureLog
24 import Tesla.Mock
25
26 setup do
27 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
28 :ok
29 end
30
31 test "the home timeline", %{conn: conn} do
32 user = insert(:user)
33 following = insert(:user)
34
35 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
36
37 conn =
38 conn
39 |> assign(:user, user)
40 |> get("/api/v1/timelines/home")
41
42 assert Enum.empty?(json_response(conn, 200))
43
44 {:ok, user} = User.follow(user, following)
45
46 conn =
47 build_conn()
48 |> assign(:user, user)
49 |> get("/api/v1/timelines/home")
50
51 assert [%{"content" => "test"}] = json_response(conn, 200)
52 end
53
54 test "the public timeline", %{conn: conn} do
55 following = insert(:user)
56
57 capture_log(fn ->
58 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
59
60 {:ok, [_activity]} =
61 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
62
63 conn =
64 conn
65 |> get("/api/v1/timelines/public", %{"local" => "False"})
66
67 assert length(json_response(conn, 200)) == 2
68
69 conn =
70 build_conn()
71 |> get("/api/v1/timelines/public", %{"local" => "True"})
72
73 assert [%{"content" => "test"}] = json_response(conn, 200)
74
75 conn =
76 build_conn()
77 |> get("/api/v1/timelines/public", %{"local" => "1"})
78
79 assert [%{"content" => "test"}] = json_response(conn, 200)
80 end)
81 end
82
83 test "posting a status", %{conn: conn} do
84 user = insert(:user)
85
86 idempotency_key = "Pikachu rocks!"
87
88 conn_one =
89 conn
90 |> assign(:user, user)
91 |> put_req_header("idempotency-key", idempotency_key)
92 |> post("/api/v1/statuses", %{
93 "status" => "cofe",
94 "spoiler_text" => "2hu",
95 "sensitive" => "false"
96 })
97
98 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
99 # Six hours
100 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
101
102 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
103 json_response(conn_one, 200)
104
105 assert Activity.get_by_id(id)
106
107 conn_two =
108 conn
109 |> assign(:user, user)
110 |> put_req_header("idempotency-key", idempotency_key)
111 |> post("/api/v1/statuses", %{
112 "status" => "cofe",
113 "spoiler_text" => "2hu",
114 "sensitive" => "false"
115 })
116
117 assert %{"id" => second_id} = json_response(conn_two, 200)
118
119 assert id == second_id
120
121 conn_three =
122 conn
123 |> assign(:user, user)
124 |> post("/api/v1/statuses", %{
125 "status" => "cofe",
126 "spoiler_text" => "2hu",
127 "sensitive" => "false"
128 })
129
130 assert %{"id" => third_id} = json_response(conn_three, 200)
131
132 refute id == third_id
133 end
134
135 test "posting a sensitive status", %{conn: conn} do
136 user = insert(:user)
137
138 conn =
139 conn
140 |> assign(:user, user)
141 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
142
143 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
144 assert Activity.get_by_id(id)
145 end
146
147 test "posting a fake status", %{conn: conn} do
148 user = insert(:user)
149
150 real_conn =
151 conn
152 |> assign(:user, user)
153 |> post("/api/v1/statuses", %{
154 "status" =>
155 "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it"
156 })
157
158 real_status = json_response(real_conn, 200)
159
160 assert real_status
161 assert Object.get_by_ap_id(real_status["uri"])
162
163 real_status =
164 real_status
165 |> Map.put("id", nil)
166 |> Map.put("url", nil)
167 |> Map.put("uri", nil)
168 |> Map.put("created_at", nil)
169 |> Kernel.put_in(["pleroma", "conversation_id"], nil)
170
171 fake_conn =
172 conn
173 |> assign(:user, user)
174 |> post("/api/v1/statuses", %{
175 "status" =>
176 "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it",
177 "preview" => true
178 })
179
180 fake_status = json_response(fake_conn, 200)
181
182 assert fake_status
183 refute Object.get_by_ap_id(fake_status["uri"])
184
185 fake_status =
186 fake_status
187 |> Map.put("id", nil)
188 |> Map.put("url", nil)
189 |> Map.put("uri", nil)
190 |> Map.put("created_at", nil)
191 |> Kernel.put_in(["pleroma", "conversation_id"], nil)
192
193 assert real_status == fake_status
194 end
195
196 test "posting a status with OGP link preview", %{conn: conn} do
197 Pleroma.Config.put([:rich_media, :enabled], true)
198 user = insert(:user)
199
200 conn =
201 conn
202 |> assign(:user, user)
203 |> post("/api/v1/statuses", %{
204 "status" => "http://example.com/ogp"
205 })
206
207 assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
208 assert Activity.get_by_id(id)
209 Pleroma.Config.put([:rich_media, :enabled], false)
210 end
211
212 test "posting a direct status", %{conn: conn} do
213 user1 = insert(:user)
214 user2 = insert(:user)
215 content = "direct cofe @#{user2.nickname}"
216
217 conn =
218 conn
219 |> assign(:user, user1)
220 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
221
222 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
223 assert activity = Activity.get_by_id(id)
224 assert activity.recipients == [user2.ap_id, user1.ap_id]
225 assert activity.data["to"] == [user2.ap_id]
226 assert activity.data["cc"] == []
227 end
228
229 test "direct timeline", %{conn: conn} do
230 user_one = insert(:user)
231 user_two = insert(:user)
232
233 {:ok, user_two} = User.follow(user_two, user_one)
234
235 {:ok, direct} =
236 CommonAPI.post(user_one, %{
237 "status" => "Hi @#{user_two.nickname}!",
238 "visibility" => "direct"
239 })
240
241 {:ok, _follower_only} =
242 CommonAPI.post(user_one, %{
243 "status" => "Hi @#{user_two.nickname}!",
244 "visibility" => "private"
245 })
246
247 # Only direct should be visible here
248 res_conn =
249 conn
250 |> assign(:user, user_two)
251 |> get("api/v1/timelines/direct")
252
253 [status] = json_response(res_conn, 200)
254
255 assert %{"visibility" => "direct"} = status
256 assert status["url"] != direct.data["id"]
257
258 # User should be able to see his own direct message
259 res_conn =
260 build_conn()
261 |> assign(:user, user_one)
262 |> get("api/v1/timelines/direct")
263
264 [status] = json_response(res_conn, 200)
265
266 assert %{"visibility" => "direct"} = status
267
268 # Both should be visible here
269 res_conn =
270 conn
271 |> assign(:user, user_two)
272 |> get("api/v1/timelines/home")
273
274 [_s1, _s2] = json_response(res_conn, 200)
275
276 # Test pagination
277 Enum.each(1..20, fn _ ->
278 {:ok, _} =
279 CommonAPI.post(user_one, %{
280 "status" => "Hi @#{user_two.nickname}!",
281 "visibility" => "direct"
282 })
283 end)
284
285 res_conn =
286 conn
287 |> assign(:user, user_two)
288 |> get("api/v1/timelines/direct")
289
290 statuses = json_response(res_conn, 200)
291 assert length(statuses) == 20
292
293 res_conn =
294 conn
295 |> assign(:user, user_two)
296 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
297
298 [status] = json_response(res_conn, 200)
299
300 assert status["url"] != direct.data["id"]
301 end
302
303 test "doesn't include DMs from blocked users", %{conn: conn} do
304 blocker = insert(:user)
305 blocked = insert(:user)
306 user = insert(:user)
307 {:ok, blocker} = User.block(blocker, blocked)
308
309 {:ok, _blocked_direct} =
310 CommonAPI.post(blocked, %{
311 "status" => "Hi @#{blocker.nickname}!",
312 "visibility" => "direct"
313 })
314
315 {:ok, direct} =
316 CommonAPI.post(user, %{
317 "status" => "Hi @#{blocker.nickname}!",
318 "visibility" => "direct"
319 })
320
321 res_conn =
322 conn
323 |> assign(:user, user)
324 |> get("api/v1/timelines/direct")
325
326 [status] = json_response(res_conn, 200)
327 assert status["id"] == direct.id
328 end
329
330 test "replying to a status", %{conn: conn} do
331 user = insert(:user)
332
333 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
334
335 conn =
336 conn
337 |> assign(:user, user)
338 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
339
340 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
341
342 activity = Activity.get_by_id(id)
343
344 assert activity.data["context"] == replied_to.data["context"]
345 assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
346 end
347
348 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
349 user = insert(:user)
350
351 conn =
352 conn
353 |> assign(:user, user)
354 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
355
356 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
357
358 activity = Activity.get_by_id(id)
359
360 assert activity
361 end
362
363 test "verify_credentials", %{conn: conn} do
364 user = insert(:user)
365
366 conn =
367 conn
368 |> assign(:user, user)
369 |> get("/api/v1/accounts/verify_credentials")
370
371 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
372 assert id == to_string(user.id)
373 end
374
375 test "verify_credentials default scope unlisted", %{conn: conn} do
376 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
377
378 conn =
379 conn
380 |> assign(:user, user)
381 |> get("/api/v1/accounts/verify_credentials")
382
383 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
384 assert id == to_string(user.id)
385 end
386
387 test "apps/verify_credentials", %{conn: conn} do
388 token = insert(:oauth_token)
389
390 conn =
391 conn
392 |> assign(:user, token.user)
393 |> assign(:token, token)
394 |> get("/api/v1/apps/verify_credentials")
395
396 app = Repo.preload(token, :app).app
397
398 expected = %{
399 "name" => app.client_name,
400 "website" => app.website,
401 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
402 }
403
404 assert expected == json_response(conn, 200)
405 end
406
407 test "creates an oauth app", %{conn: conn} do
408 user = insert(:user)
409 app_attrs = build(:oauth_app)
410
411 conn =
412 conn
413 |> assign(:user, user)
414 |> post("/api/v1/apps", %{
415 client_name: app_attrs.client_name,
416 redirect_uris: app_attrs.redirect_uris
417 })
418
419 [app] = Repo.all(App)
420
421 expected = %{
422 "name" => app.client_name,
423 "website" => app.website,
424 "client_id" => app.client_id,
425 "client_secret" => app.client_secret,
426 "id" => app.id |> to_string(),
427 "redirect_uri" => app.redirect_uris,
428 "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
429 }
430
431 assert expected == json_response(conn, 200)
432 end
433
434 test "get a status", %{conn: conn} do
435 activity = insert(:note_activity)
436
437 conn =
438 conn
439 |> get("/api/v1/statuses/#{activity.id}")
440
441 assert %{"id" => id} = json_response(conn, 200)
442 assert id == to_string(activity.id)
443 end
444
445 describe "deleting a status" do
446 test "when you created it", %{conn: conn} do
447 activity = insert(:note_activity)
448 author = User.get_cached_by_ap_id(activity.data["actor"])
449
450 conn =
451 conn
452 |> assign(:user, author)
453 |> delete("/api/v1/statuses/#{activity.id}")
454
455 assert %{} = json_response(conn, 200)
456
457 refute Activity.get_by_id(activity.id)
458 end
459
460 test "when you didn't create it", %{conn: conn} do
461 activity = insert(:note_activity)
462 user = insert(:user)
463
464 conn =
465 conn
466 |> assign(:user, user)
467 |> delete("/api/v1/statuses/#{activity.id}")
468
469 assert %{"error" => _} = json_response(conn, 403)
470
471 assert Activity.get_by_id(activity.id) == activity
472 end
473
474 test "when you're an admin or moderator", %{conn: conn} do
475 activity1 = insert(:note_activity)
476 activity2 = insert(:note_activity)
477 admin = insert(:user, info: %{is_admin: true})
478 moderator = insert(:user, info: %{is_moderator: true})
479
480 res_conn =
481 conn
482 |> assign(:user, admin)
483 |> delete("/api/v1/statuses/#{activity1.id}")
484
485 assert %{} = json_response(res_conn, 200)
486
487 res_conn =
488 conn
489 |> assign(:user, moderator)
490 |> delete("/api/v1/statuses/#{activity2.id}")
491
492 assert %{} = json_response(res_conn, 200)
493
494 refute Activity.get_by_id(activity1.id)
495 refute Activity.get_by_id(activity2.id)
496 end
497 end
498
499 describe "filters" do
500 test "creating a filter", %{conn: conn} do
501 user = insert(:user)
502
503 filter = %Pleroma.Filter{
504 phrase: "knights",
505 context: ["home"]
506 }
507
508 conn =
509 conn
510 |> assign(:user, user)
511 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
512
513 assert response = json_response(conn, 200)
514 assert response["phrase"] == filter.phrase
515 assert response["context"] == filter.context
516 assert response["id"] != nil
517 assert response["id"] != ""
518 end
519
520 test "fetching a list of filters", %{conn: conn} do
521 user = insert(:user)
522
523 query_one = %Pleroma.Filter{
524 user_id: user.id,
525 filter_id: 1,
526 phrase: "knights",
527 context: ["home"]
528 }
529
530 query_two = %Pleroma.Filter{
531 user_id: user.id,
532 filter_id: 2,
533 phrase: "who",
534 context: ["home"]
535 }
536
537 {:ok, filter_one} = Pleroma.Filter.create(query_one)
538 {:ok, filter_two} = Pleroma.Filter.create(query_two)
539
540 response =
541 conn
542 |> assign(:user, user)
543 |> get("/api/v1/filters")
544 |> json_response(200)
545
546 assert response ==
547 render_json(
548 FilterView,
549 "filters.json",
550 filters: [filter_two, filter_one]
551 )
552 end
553
554 test "get a filter", %{conn: conn} do
555 user = insert(:user)
556
557 query = %Pleroma.Filter{
558 user_id: user.id,
559 filter_id: 2,
560 phrase: "knight",
561 context: ["home"]
562 }
563
564 {:ok, filter} = Pleroma.Filter.create(query)
565
566 conn =
567 conn
568 |> assign(:user, user)
569 |> get("/api/v1/filters/#{filter.filter_id}")
570
571 assert _response = json_response(conn, 200)
572 end
573
574 test "update a filter", %{conn: conn} do
575 user = insert(:user)
576
577 query = %Pleroma.Filter{
578 user_id: user.id,
579 filter_id: 2,
580 phrase: "knight",
581 context: ["home"]
582 }
583
584 {:ok, _filter} = Pleroma.Filter.create(query)
585
586 new = %Pleroma.Filter{
587 phrase: "nii",
588 context: ["home"]
589 }
590
591 conn =
592 conn
593 |> assign(:user, user)
594 |> put("/api/v1/filters/#{query.filter_id}", %{
595 phrase: new.phrase,
596 context: new.context
597 })
598
599 assert response = json_response(conn, 200)
600 assert response["phrase"] == new.phrase
601 assert response["context"] == new.context
602 end
603
604 test "delete a filter", %{conn: conn} do
605 user = insert(:user)
606
607 query = %Pleroma.Filter{
608 user_id: user.id,
609 filter_id: 2,
610 phrase: "knight",
611 context: ["home"]
612 }
613
614 {:ok, filter} = Pleroma.Filter.create(query)
615
616 conn =
617 conn
618 |> assign(:user, user)
619 |> delete("/api/v1/filters/#{filter.filter_id}")
620
621 assert response = json_response(conn, 200)
622 assert response == %{}
623 end
624 end
625
626 describe "lists" do
627 test "creating a list", %{conn: conn} do
628 user = insert(:user)
629
630 conn =
631 conn
632 |> assign(:user, user)
633 |> post("/api/v1/lists", %{"title" => "cuties"})
634
635 assert %{"title" => title} = json_response(conn, 200)
636 assert title == "cuties"
637 end
638
639 test "adding users to a list", %{conn: conn} do
640 user = insert(:user)
641 other_user = insert(:user)
642 {:ok, list} = Pleroma.List.create("name", user)
643
644 conn =
645 conn
646 |> assign(:user, user)
647 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
648
649 assert %{} == json_response(conn, 200)
650 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
651 assert following == [other_user.follower_address]
652 end
653
654 test "removing users from a list", %{conn: conn} do
655 user = insert(:user)
656 other_user = insert(:user)
657 third_user = insert(:user)
658 {:ok, list} = Pleroma.List.create("name", user)
659 {:ok, list} = Pleroma.List.follow(list, other_user)
660 {:ok, list} = Pleroma.List.follow(list, third_user)
661
662 conn =
663 conn
664 |> assign(:user, user)
665 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
666
667 assert %{} == json_response(conn, 200)
668 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
669 assert following == [third_user.follower_address]
670 end
671
672 test "listing users in a list", %{conn: conn} do
673 user = insert(:user)
674 other_user = insert(:user)
675 {:ok, list} = Pleroma.List.create("name", user)
676 {:ok, list} = Pleroma.List.follow(list, other_user)
677
678 conn =
679 conn
680 |> assign(:user, user)
681 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
682
683 assert [%{"id" => id}] = json_response(conn, 200)
684 assert id == to_string(other_user.id)
685 end
686
687 test "retrieving a list", %{conn: conn} do
688 user = insert(:user)
689 {:ok, list} = Pleroma.List.create("name", user)
690
691 conn =
692 conn
693 |> assign(:user, user)
694 |> get("/api/v1/lists/#{list.id}")
695
696 assert %{"id" => id} = json_response(conn, 200)
697 assert id == to_string(list.id)
698 end
699
700 test "renaming a list", %{conn: conn} do
701 user = insert(:user)
702 {:ok, list} = Pleroma.List.create("name", user)
703
704 conn =
705 conn
706 |> assign(:user, user)
707 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
708
709 assert %{"title" => name} = json_response(conn, 200)
710 assert name == "newname"
711 end
712
713 test "deleting a list", %{conn: conn} do
714 user = insert(:user)
715 {:ok, list} = Pleroma.List.create("name", user)
716
717 conn =
718 conn
719 |> assign(:user, user)
720 |> delete("/api/v1/lists/#{list.id}")
721
722 assert %{} = json_response(conn, 200)
723 assert is_nil(Repo.get(Pleroma.List, list.id))
724 end
725
726 test "list timeline", %{conn: conn} do
727 user = insert(:user)
728 other_user = insert(:user)
729 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
730 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
731 {:ok, list} = Pleroma.List.create("name", user)
732 {:ok, list} = Pleroma.List.follow(list, other_user)
733
734 conn =
735 conn
736 |> assign(:user, user)
737 |> get("/api/v1/timelines/list/#{list.id}")
738
739 assert [%{"id" => id}] = json_response(conn, 200)
740
741 assert id == to_string(activity_two.id)
742 end
743
744 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
745 user = insert(:user)
746 other_user = insert(:user)
747 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
748
749 {:ok, _activity_two} =
750 TwitterAPI.create_status(other_user, %{
751 "status" => "Marisa is cute.",
752 "visibility" => "private"
753 })
754
755 {:ok, list} = Pleroma.List.create("name", user)
756 {:ok, list} = Pleroma.List.follow(list, other_user)
757
758 conn =
759 conn
760 |> assign(:user, user)
761 |> get("/api/v1/timelines/list/#{list.id}")
762
763 assert [%{"id" => id}] = json_response(conn, 200)
764
765 assert id == to_string(activity_one.id)
766 end
767 end
768
769 describe "notifications" do
770 test "list of notifications", %{conn: conn} do
771 user = insert(:user)
772 other_user = insert(:user)
773
774 {:ok, activity} =
775 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
776
777 {:ok, [_notification]} = Notification.create_notifications(activity)
778
779 conn =
780 conn
781 |> assign(:user, user)
782 |> get("/api/v1/notifications")
783
784 expected_response =
785 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
786 user.ap_id
787 }\">@<span>#{user.nickname}</span></a></span>"
788
789 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
790 assert response == expected_response
791 end
792
793 test "getting a single notification", %{conn: conn} do
794 user = insert(:user)
795 other_user = insert(:user)
796
797 {:ok, activity} =
798 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
799
800 {:ok, [notification]} = Notification.create_notifications(activity)
801
802 conn =
803 conn
804 |> assign(:user, user)
805 |> get("/api/v1/notifications/#{notification.id}")
806
807 expected_response =
808 "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
809 user.ap_id
810 }\">@<span>#{user.nickname}</span></a></span>"
811
812 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
813 assert response == expected_response
814 end
815
816 test "dismissing a single notification", %{conn: conn} do
817 user = insert(:user)
818 other_user = insert(:user)
819
820 {:ok, activity} =
821 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
822
823 {:ok, [notification]} = Notification.create_notifications(activity)
824
825 conn =
826 conn
827 |> assign(:user, user)
828 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
829
830 assert %{} = json_response(conn, 200)
831 end
832
833 test "clearing all notifications", %{conn: conn} do
834 user = insert(:user)
835 other_user = insert(:user)
836
837 {:ok, activity} =
838 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
839
840 {:ok, [_notification]} = Notification.create_notifications(activity)
841
842 conn =
843 conn
844 |> assign(:user, user)
845 |> post("/api/v1/notifications/clear")
846
847 assert %{} = json_response(conn, 200)
848
849 conn =
850 build_conn()
851 |> assign(:user, user)
852 |> get("/api/v1/notifications")
853
854 assert all = json_response(conn, 200)
855 assert all == []
856 end
857
858 test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
859 user = insert(:user)
860 other_user = insert(:user)
861
862 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
863 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
864 {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
865 {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
866
867 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
868 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
869 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
870 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
871
872 conn =
873 conn
874 |> assign(:user, user)
875
876 # min_id
877 conn_res =
878 conn
879 |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
880
881 result = json_response(conn_res, 200)
882 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
883
884 # since_id
885 conn_res =
886 conn
887 |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
888
889 result = json_response(conn_res, 200)
890 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
891
892 # max_id
893 conn_res =
894 conn
895 |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
896
897 result = json_response(conn_res, 200)
898 assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
899 end
900
901 test "filters notifications using exclude_types", %{conn: conn} do
902 user = insert(:user)
903 other_user = insert(:user)
904
905 {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
906 {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
907 {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
908 {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
909 {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
910
911 mention_notification_id =
912 Repo.get_by(Notification, activity_id: mention_activity.id).id |> to_string()
913
914 favorite_notification_id =
915 Repo.get_by(Notification, activity_id: favorite_activity.id).id |> to_string()
916
917 reblog_notification_id =
918 Repo.get_by(Notification, activity_id: reblog_activity.id).id |> to_string()
919
920 follow_notification_id =
921 Repo.get_by(Notification, activity_id: follow_activity.id).id |> to_string()
922
923 conn =
924 conn
925 |> assign(:user, user)
926
927 conn_res =
928 get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
929
930 assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
931
932 conn_res =
933 get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
934
935 assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
936
937 conn_res =
938 get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
939
940 assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
941
942 conn_res =
943 get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
944
945 assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
946 end
947
948 test "destroy multiple", %{conn: conn} do
949 user = insert(:user)
950 other_user = insert(:user)
951
952 {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
953 {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
954 {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
955 {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
956
957 notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
958 notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
959 notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
960 notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
961
962 conn =
963 conn
964 |> assign(:user, user)
965
966 conn_res =
967 conn
968 |> get("/api/v1/notifications")
969
970 result = json_response(conn_res, 200)
971 assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
972
973 conn2 =
974 conn
975 |> assign(:user, other_user)
976
977 conn_res =
978 conn2
979 |> get("/api/v1/notifications")
980
981 result = json_response(conn_res, 200)
982 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
983
984 conn_destroy =
985 conn
986 |> delete("/api/v1/notifications/destroy_multiple", %{
987 "ids" => [notification1_id, notification2_id]
988 })
989
990 assert json_response(conn_destroy, 200) == %{}
991
992 conn_res =
993 conn2
994 |> get("/api/v1/notifications")
995
996 result = json_response(conn_res, 200)
997 assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
998 end
999 end
1000
1001 describe "reblogging" do
1002 test "reblogs and returns the reblogged status", %{conn: conn} do
1003 activity = insert(:note_activity)
1004 user = insert(:user)
1005
1006 conn =
1007 conn
1008 |> assign(:user, user)
1009 |> post("/api/v1/statuses/#{activity.id}/reblog")
1010
1011 assert %{
1012 "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
1013 "reblogged" => true
1014 } = json_response(conn, 200)
1015
1016 assert to_string(activity.id) == id
1017 end
1018
1019 test "reblogged status for another user", %{conn: conn} do
1020 activity = insert(:note_activity)
1021 user1 = insert(:user)
1022 user2 = insert(:user)
1023 user3 = insert(:user)
1024 CommonAPI.favorite(activity.id, user2)
1025 {:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
1026 {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
1027 {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
1028
1029 conn_res =
1030 conn
1031 |> assign(:user, user3)
1032 |> get("/api/v1/statuses/#{reblog_activity1.id}")
1033
1034 assert %{
1035 "reblog" => %{"id" => id, "reblogged" => false, "reblogs_count" => 2},
1036 "reblogged" => false,
1037 "favourited" => false,
1038 "bookmarked" => false
1039 } = json_response(conn_res, 200)
1040
1041 conn_res =
1042 conn
1043 |> assign(:user, user2)
1044 |> get("/api/v1/statuses/#{reblog_activity1.id}")
1045
1046 assert %{
1047 "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 2},
1048 "reblogged" => true,
1049 "favourited" => true,
1050 "bookmarked" => true
1051 } = json_response(conn_res, 200)
1052
1053 assert to_string(activity.id) == id
1054 end
1055 end
1056
1057 describe "unreblogging" do
1058 test "unreblogs and returns the unreblogged status", %{conn: conn} do
1059 activity = insert(:note_activity)
1060 user = insert(:user)
1061
1062 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
1063
1064 conn =
1065 conn
1066 |> assign(:user, user)
1067 |> post("/api/v1/statuses/#{activity.id}/unreblog")
1068
1069 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
1070
1071 assert to_string(activity.id) == id
1072 end
1073 end
1074
1075 describe "favoriting" do
1076 test "favs a status and returns it", %{conn: conn} do
1077 activity = insert(:note_activity)
1078 user = insert(:user)
1079
1080 conn =
1081 conn
1082 |> assign(:user, user)
1083 |> post("/api/v1/statuses/#{activity.id}/favourite")
1084
1085 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
1086 json_response(conn, 200)
1087
1088 assert to_string(activity.id) == id
1089 end
1090
1091 test "returns 500 for a wrong id", %{conn: conn} do
1092 user = insert(:user)
1093
1094 resp =
1095 conn
1096 |> assign(:user, user)
1097 |> post("/api/v1/statuses/1/favourite")
1098 |> json_response(500)
1099
1100 assert resp == "Something went wrong"
1101 end
1102 end
1103
1104 describe "unfavoriting" do
1105 test "unfavorites a status and returns it", %{conn: conn} do
1106 activity = insert(:note_activity)
1107 user = insert(:user)
1108
1109 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1110
1111 conn =
1112 conn
1113 |> assign(:user, user)
1114 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
1115
1116 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
1117 json_response(conn, 200)
1118
1119 assert to_string(activity.id) == id
1120 end
1121 end
1122
1123 describe "user timelines" do
1124 test "gets a users statuses", %{conn: conn} do
1125 user_one = insert(:user)
1126 user_two = insert(:user)
1127 user_three = insert(:user)
1128
1129 {:ok, user_three} = User.follow(user_three, user_one)
1130
1131 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
1132
1133 {:ok, direct_activity} =
1134 CommonAPI.post(user_one, %{
1135 "status" => "Hi, @#{user_two.nickname}.",
1136 "visibility" => "direct"
1137 })
1138
1139 {:ok, private_activity} =
1140 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
1141
1142 resp =
1143 conn
1144 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1145
1146 assert [%{"id" => id}] = json_response(resp, 200)
1147 assert id == to_string(activity.id)
1148
1149 resp =
1150 conn
1151 |> assign(:user, user_two)
1152 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1153
1154 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1155 assert id_one == to_string(direct_activity.id)
1156 assert id_two == to_string(activity.id)
1157
1158 resp =
1159 conn
1160 |> assign(:user, user_three)
1161 |> get("/api/v1/accounts/#{user_one.id}/statuses")
1162
1163 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
1164 assert id_one == to_string(private_activity.id)
1165 assert id_two == to_string(activity.id)
1166 end
1167
1168 test "unimplemented pinned statuses feature", %{conn: conn} do
1169 note = insert(:note_activity)
1170 user = User.get_cached_by_ap_id(note.data["actor"])
1171
1172 conn =
1173 conn
1174 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
1175
1176 assert json_response(conn, 200) == []
1177 end
1178
1179 test "gets an users media", %{conn: conn} do
1180 note = insert(:note_activity)
1181 user = User.get_cached_by_ap_id(note.data["actor"])
1182
1183 file = %Plug.Upload{
1184 content_type: "image/jpg",
1185 path: Path.absname("test/fixtures/image.jpg"),
1186 filename: "an_image.jpg"
1187 }
1188
1189 media =
1190 TwitterAPI.upload(file, user, "json")
1191 |> Poison.decode!()
1192
1193 {:ok, image_post} =
1194 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
1195
1196 conn =
1197 conn
1198 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
1199
1200 assert [%{"id" => id}] = json_response(conn, 200)
1201 assert id == to_string(image_post.id)
1202
1203 conn =
1204 build_conn()
1205 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
1206
1207 assert [%{"id" => id}] = json_response(conn, 200)
1208 assert id == to_string(image_post.id)
1209 end
1210
1211 test "gets a user's statuses without reblogs", %{conn: conn} do
1212 user = insert(:user)
1213 {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
1214 {:ok, _, _} = CommonAPI.repeat(post.id, user)
1215
1216 conn =
1217 conn
1218 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
1219
1220 assert [%{"id" => id}] = json_response(conn, 200)
1221 assert id == to_string(post.id)
1222
1223 conn =
1224 conn
1225 |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
1226
1227 assert [%{"id" => id}] = json_response(conn, 200)
1228 assert id == to_string(post.id)
1229 end
1230 end
1231
1232 describe "user relationships" do
1233 test "returns the relationships for the current user", %{conn: conn} do
1234 user = insert(:user)
1235 other_user = insert(:user)
1236 {:ok, user} = User.follow(user, other_user)
1237
1238 conn =
1239 conn
1240 |> assign(:user, user)
1241 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
1242
1243 assert [relationship] = json_response(conn, 200)
1244
1245 assert to_string(other_user.id) == relationship["id"]
1246 end
1247 end
1248
1249 describe "locked accounts" do
1250 test "/api/v1/follow_requests works" do
1251 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1252 other_user = insert(:user)
1253
1254 {:ok, _activity} = ActivityPub.follow(other_user, user)
1255
1256 user = User.get_cached_by_id(user.id)
1257 other_user = User.get_cached_by_id(other_user.id)
1258
1259 assert User.following?(other_user, user) == false
1260
1261 conn =
1262 build_conn()
1263 |> assign(:user, user)
1264 |> get("/api/v1/follow_requests")
1265
1266 assert [relationship] = json_response(conn, 200)
1267 assert to_string(other_user.id) == relationship["id"]
1268 end
1269
1270 test "/api/v1/follow_requests/:id/authorize works" do
1271 user = insert(:user, %{info: %User.Info{locked: true}})
1272 other_user = insert(:user)
1273
1274 {:ok, _activity} = ActivityPub.follow(other_user, user)
1275
1276 user = User.get_cached_by_id(user.id)
1277 other_user = User.get_cached_by_id(other_user.id)
1278
1279 assert User.following?(other_user, user) == false
1280
1281 conn =
1282 build_conn()
1283 |> assign(:user, user)
1284 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
1285
1286 assert relationship = json_response(conn, 200)
1287 assert to_string(other_user.id) == relationship["id"]
1288
1289 user = User.get_cached_by_id(user.id)
1290 other_user = User.get_cached_by_id(other_user.id)
1291
1292 assert User.following?(other_user, user) == true
1293 end
1294
1295 test "verify_credentials", %{conn: conn} do
1296 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
1297
1298 conn =
1299 conn
1300 |> assign(:user, user)
1301 |> get("/api/v1/accounts/verify_credentials")
1302
1303 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
1304 assert id == to_string(user.id)
1305 end
1306
1307 test "/api/v1/follow_requests/:id/reject works" do
1308 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
1309 other_user = insert(:user)
1310
1311 {:ok, _activity} = ActivityPub.follow(other_user, user)
1312
1313 user = User.get_cached_by_id(user.id)
1314
1315 conn =
1316 build_conn()
1317 |> assign(:user, user)
1318 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
1319
1320 assert relationship = json_response(conn, 200)
1321 assert to_string(other_user.id) == relationship["id"]
1322
1323 user = User.get_cached_by_id(user.id)
1324 other_user = User.get_cached_by_id(other_user.id)
1325
1326 assert User.following?(other_user, user) == false
1327 end
1328 end
1329
1330 test "account fetching", %{conn: conn} do
1331 user = insert(:user)
1332
1333 conn =
1334 conn
1335 |> get("/api/v1/accounts/#{user.id}")
1336
1337 assert %{"id" => id} = json_response(conn, 200)
1338 assert id == to_string(user.id)
1339
1340 conn =
1341 build_conn()
1342 |> get("/api/v1/accounts/-1")
1343
1344 assert %{"error" => "Can't find user"} = json_response(conn, 404)
1345 end
1346
1347 test "account fetching also works nickname", %{conn: conn} do
1348 user = insert(:user)
1349
1350 conn =
1351 conn
1352 |> get("/api/v1/accounts/#{user.nickname}")
1353
1354 assert %{"id" => id} = json_response(conn, 200)
1355 assert id == user.id
1356 end
1357
1358 test "media upload", %{conn: conn} do
1359 file = %Plug.Upload{
1360 content_type: "image/jpg",
1361 path: Path.absname("test/fixtures/image.jpg"),
1362 filename: "an_image.jpg"
1363 }
1364
1365 desc = "Description of the image"
1366
1367 user = insert(:user)
1368
1369 conn =
1370 conn
1371 |> assign(:user, user)
1372 |> post("/api/v1/media", %{"file" => file, "description" => desc})
1373
1374 assert media = json_response(conn, 200)
1375
1376 assert media["type"] == "image"
1377 assert media["description"] == desc
1378 assert media["id"]
1379
1380 object = Repo.get(Object, media["id"])
1381 assert object.data["actor"] == User.ap_id(user)
1382 end
1383
1384 test "hashtag timeline", %{conn: conn} do
1385 following = insert(:user)
1386
1387 capture_log(fn ->
1388 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
1389
1390 {:ok, [_activity]} =
1391 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
1392
1393 nconn =
1394 conn
1395 |> get("/api/v1/timelines/tag/2hu")
1396
1397 assert [%{"id" => id}] = json_response(nconn, 200)
1398
1399 assert id == to_string(activity.id)
1400
1401 # works for different capitalization too
1402 nconn =
1403 conn
1404 |> get("/api/v1/timelines/tag/2HU")
1405
1406 assert [%{"id" => id}] = json_response(nconn, 200)
1407
1408 assert id == to_string(activity.id)
1409 end)
1410 end
1411
1412 test "multi-hashtag timeline", %{conn: conn} do
1413 user = insert(:user)
1414
1415 {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
1416 {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
1417 {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
1418
1419 any_test =
1420 conn
1421 |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
1422
1423 [status_none, status_test1, status_test] = json_response(any_test, 200)
1424
1425 assert to_string(activity_test.id) == status_test["id"]
1426 assert to_string(activity_test1.id) == status_test1["id"]
1427 assert to_string(activity_none.id) == status_none["id"]
1428
1429 restricted_test =
1430 conn
1431 |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
1432
1433 assert [status_test1] == json_response(restricted_test, 200)
1434
1435 all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
1436
1437 assert [status_none] == json_response(all_test, 200)
1438 end
1439
1440 test "getting followers", %{conn: conn} do
1441 user = insert(:user)
1442 other_user = insert(:user)
1443 {:ok, user} = User.follow(user, other_user)
1444
1445 conn =
1446 conn
1447 |> get("/api/v1/accounts/#{other_user.id}/followers")
1448
1449 assert [%{"id" => id}] = json_response(conn, 200)
1450 assert id == to_string(user.id)
1451 end
1452
1453 test "getting followers, hide_followers", %{conn: conn} do
1454 user = insert(:user)
1455 other_user = insert(:user, %{info: %{hide_followers: true}})
1456 {:ok, _user} = User.follow(user, other_user)
1457
1458 conn =
1459 conn
1460 |> get("/api/v1/accounts/#{other_user.id}/followers")
1461
1462 assert [] == json_response(conn, 200)
1463 end
1464
1465 test "getting followers, hide_followers, same user requesting", %{conn: conn} do
1466 user = insert(:user)
1467 other_user = insert(:user, %{info: %{hide_followers: true}})
1468 {:ok, _user} = User.follow(user, other_user)
1469
1470 conn =
1471 conn
1472 |> assign(:user, other_user)
1473 |> get("/api/v1/accounts/#{other_user.id}/followers")
1474
1475 refute [] == json_response(conn, 200)
1476 end
1477
1478 test "getting followers, pagination", %{conn: conn} do
1479 user = insert(:user)
1480 follower1 = insert(:user)
1481 follower2 = insert(:user)
1482 follower3 = insert(:user)
1483 {:ok, _} = User.follow(follower1, user)
1484 {:ok, _} = User.follow(follower2, user)
1485 {:ok, _} = User.follow(follower3, user)
1486
1487 conn =
1488 conn
1489 |> assign(:user, user)
1490
1491 res_conn =
1492 conn
1493 |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
1494
1495 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1496 assert id3 == follower3.id
1497 assert id2 == follower2.id
1498
1499 res_conn =
1500 conn
1501 |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
1502
1503 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1504 assert id2 == follower2.id
1505 assert id1 == follower1.id
1506
1507 res_conn =
1508 conn
1509 |> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
1510
1511 assert [%{"id" => id2}] = json_response(res_conn, 200)
1512 assert id2 == follower2.id
1513
1514 assert [link_header] = get_resp_header(res_conn, "link")
1515 assert link_header =~ ~r/min_id=#{follower2.id}/
1516 assert link_header =~ ~r/max_id=#{follower2.id}/
1517 end
1518
1519 test "getting following", %{conn: conn} do
1520 user = insert(:user)
1521 other_user = insert(:user)
1522 {:ok, user} = User.follow(user, other_user)
1523
1524 conn =
1525 conn
1526 |> get("/api/v1/accounts/#{user.id}/following")
1527
1528 assert [%{"id" => id}] = json_response(conn, 200)
1529 assert id == to_string(other_user.id)
1530 end
1531
1532 test "getting following, hide_follows", %{conn: conn} do
1533 user = insert(:user, %{info: %{hide_follows: true}})
1534 other_user = insert(:user)
1535 {:ok, user} = User.follow(user, other_user)
1536
1537 conn =
1538 conn
1539 |> get("/api/v1/accounts/#{user.id}/following")
1540
1541 assert [] == json_response(conn, 200)
1542 end
1543
1544 test "getting following, hide_follows, same user requesting", %{conn: conn} do
1545 user = insert(:user, %{info: %{hide_follows: true}})
1546 other_user = insert(:user)
1547 {:ok, user} = User.follow(user, other_user)
1548
1549 conn =
1550 conn
1551 |> assign(:user, user)
1552 |> get("/api/v1/accounts/#{user.id}/following")
1553
1554 refute [] == json_response(conn, 200)
1555 end
1556
1557 test "getting following, pagination", %{conn: conn} do
1558 user = insert(:user)
1559 following1 = insert(:user)
1560 following2 = insert(:user)
1561 following3 = insert(:user)
1562 {:ok, _} = User.follow(user, following1)
1563 {:ok, _} = User.follow(user, following2)
1564 {:ok, _} = User.follow(user, following3)
1565
1566 conn =
1567 conn
1568 |> assign(:user, user)
1569
1570 res_conn =
1571 conn
1572 |> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
1573
1574 assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
1575 assert id3 == following3.id
1576 assert id2 == following2.id
1577
1578 res_conn =
1579 conn
1580 |> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
1581
1582 assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
1583 assert id2 == following2.id
1584 assert id1 == following1.id
1585
1586 res_conn =
1587 conn
1588 |> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
1589
1590 assert [%{"id" => id2}] = json_response(res_conn, 200)
1591 assert id2 == following2.id
1592
1593 assert [link_header] = get_resp_header(res_conn, "link")
1594 assert link_header =~ ~r/min_id=#{following2.id}/
1595 assert link_header =~ ~r/max_id=#{following2.id}/
1596 end
1597
1598 test "following / unfollowing a user", %{conn: conn} do
1599 user = insert(:user)
1600 other_user = insert(:user)
1601
1602 conn =
1603 conn
1604 |> assign(:user, user)
1605 |> post("/api/v1/accounts/#{other_user.id}/follow")
1606
1607 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1608
1609 user = User.get_cached_by_id(user.id)
1610
1611 conn =
1612 build_conn()
1613 |> assign(:user, user)
1614 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1615
1616 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1617
1618 user = User.get_cached_by_id(user.id)
1619
1620 conn =
1621 build_conn()
1622 |> assign(:user, user)
1623 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1624
1625 assert %{"id" => id} = json_response(conn, 200)
1626 assert id == to_string(other_user.id)
1627 end
1628
1629 test "following without reblogs" do
1630 follower = insert(:user)
1631 followed = insert(:user)
1632 other_user = insert(:user)
1633
1634 conn =
1635 build_conn()
1636 |> assign(:user, follower)
1637 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
1638
1639 assert %{"showing_reblogs" => false} = json_response(conn, 200)
1640
1641 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
1642 {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
1643
1644 conn =
1645 build_conn()
1646 |> assign(:user, User.get_cached_by_id(follower.id))
1647 |> get("/api/v1/timelines/home")
1648
1649 assert [] == json_response(conn, 200)
1650
1651 conn =
1652 build_conn()
1653 |> assign(:user, follower)
1654 |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
1655
1656 assert %{"showing_reblogs" => true} = json_response(conn, 200)
1657
1658 conn =
1659 build_conn()
1660 |> assign(:user, User.get_cached_by_id(follower.id))
1661 |> get("/api/v1/timelines/home")
1662
1663 expected_activity_id = reblog.id
1664 assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
1665 end
1666
1667 test "following / unfollowing errors" do
1668 user = insert(:user)
1669
1670 conn =
1671 build_conn()
1672 |> assign(:user, user)
1673
1674 # self follow
1675 conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
1676 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1677
1678 # self unfollow
1679 user = User.get_cached_by_id(user.id)
1680 conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
1681 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1682
1683 # self follow via uri
1684 user = User.get_cached_by_id(user.id)
1685 conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
1686 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1687
1688 # follow non existing user
1689 conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
1690 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1691
1692 # follow non existing user via uri
1693 conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
1694 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1695
1696 # unfollow non existing user
1697 conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
1698 assert %{"error" => "Record not found"} = json_response(conn_res, 404)
1699 end
1700
1701 test "muting / unmuting a user", %{conn: conn} do
1702 user = insert(:user)
1703 other_user = insert(:user)
1704
1705 conn =
1706 conn
1707 |> assign(:user, user)
1708 |> post("/api/v1/accounts/#{other_user.id}/mute")
1709
1710 assert %{"id" => _id, "muting" => true} = json_response(conn, 200)
1711
1712 user = User.get_cached_by_id(user.id)
1713
1714 conn =
1715 build_conn()
1716 |> assign(:user, user)
1717 |> post("/api/v1/accounts/#{other_user.id}/unmute")
1718
1719 assert %{"id" => _id, "muting" => false} = json_response(conn, 200)
1720 end
1721
1722 test "subscribing / unsubscribing to a user", %{conn: conn} do
1723 user = insert(:user)
1724 subscription_target = insert(:user)
1725
1726 conn =
1727 conn
1728 |> assign(:user, user)
1729 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
1730
1731 assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
1732
1733 conn =
1734 build_conn()
1735 |> assign(:user, user)
1736 |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
1737
1738 assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
1739 end
1740
1741 test "getting a list of mutes", %{conn: conn} do
1742 user = insert(:user)
1743 other_user = insert(:user)
1744
1745 {:ok, user} = User.mute(user, other_user)
1746
1747 conn =
1748 conn
1749 |> assign(:user, user)
1750 |> get("/api/v1/mutes")
1751
1752 other_user_id = to_string(other_user.id)
1753 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1754 end
1755
1756 test "blocking / unblocking a user", %{conn: conn} do
1757 user = insert(:user)
1758 other_user = insert(:user)
1759
1760 conn =
1761 conn
1762 |> assign(:user, user)
1763 |> post("/api/v1/accounts/#{other_user.id}/block")
1764
1765 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1766
1767 user = User.get_cached_by_id(user.id)
1768
1769 conn =
1770 build_conn()
1771 |> assign(:user, user)
1772 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1773
1774 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1775 end
1776
1777 test "getting a list of blocks", %{conn: conn} do
1778 user = insert(:user)
1779 other_user = insert(:user)
1780
1781 {:ok, user} = User.block(user, other_user)
1782
1783 conn =
1784 conn
1785 |> assign(:user, user)
1786 |> get("/api/v1/blocks")
1787
1788 other_user_id = to_string(other_user.id)
1789 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1790 end
1791
1792 test "blocking / unblocking a domain", %{conn: conn} do
1793 user = insert(:user)
1794 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1795
1796 conn =
1797 conn
1798 |> assign(:user, user)
1799 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1800
1801 assert %{} = json_response(conn, 200)
1802 user = User.get_cached_by_ap_id(user.ap_id)
1803 assert User.blocks?(user, other_user)
1804
1805 conn =
1806 build_conn()
1807 |> assign(:user, user)
1808 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1809
1810 assert %{} = json_response(conn, 200)
1811 user = User.get_cached_by_ap_id(user.ap_id)
1812 refute User.blocks?(user, other_user)
1813 end
1814
1815 test "getting a list of domain blocks", %{conn: conn} do
1816 user = insert(:user)
1817
1818 {:ok, user} = User.block_domain(user, "bad.site")
1819 {:ok, user} = User.block_domain(user, "even.worse.site")
1820
1821 conn =
1822 conn
1823 |> assign(:user, user)
1824 |> get("/api/v1/domain_blocks")
1825
1826 domain_blocks = json_response(conn, 200)
1827
1828 assert "bad.site" in domain_blocks
1829 assert "even.worse.site" in domain_blocks
1830 end
1831
1832 test "unimplemented follow_requests, blocks, domain blocks" do
1833 user = insert(:user)
1834
1835 ["blocks", "domain_blocks", "follow_requests"]
1836 |> Enum.each(fn endpoint ->
1837 conn =
1838 build_conn()
1839 |> assign(:user, user)
1840 |> get("/api/v1/#{endpoint}")
1841
1842 assert [] = json_response(conn, 200)
1843 end)
1844 end
1845
1846 test "account search", %{conn: conn} do
1847 user = insert(:user)
1848 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1849 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1850
1851 results =
1852 conn
1853 |> assign(:user, user)
1854 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1855 |> json_response(200)
1856
1857 result_ids = for result <- results, do: result["acct"]
1858
1859 assert user_two.nickname in result_ids
1860 assert user_three.nickname in result_ids
1861
1862 results =
1863 conn
1864 |> assign(:user, user)
1865 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1866 |> json_response(200)
1867
1868 result_ids = for result <- results, do: result["acct"]
1869
1870 assert user_three.nickname in result_ids
1871 end
1872
1873 test "search", %{conn: conn} do
1874 user = insert(:user)
1875 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1876 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1877
1878 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1879
1880 {:ok, _activity} =
1881 CommonAPI.post(user, %{
1882 "status" => "This is about 2hu, but private",
1883 "visibility" => "private"
1884 })
1885
1886 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1887
1888 conn =
1889 conn
1890 |> get("/api/v1/search", %{"q" => "2hu"})
1891
1892 assert results = json_response(conn, 200)
1893
1894 [account | _] = results["accounts"]
1895 assert account["id"] == to_string(user_three.id)
1896
1897 assert results["hashtags"] == []
1898
1899 [status] = results["statuses"]
1900 assert status["id"] == to_string(activity.id)
1901 end
1902
1903 test "search fetches remote statuses", %{conn: conn} do
1904 capture_log(fn ->
1905 conn =
1906 conn
1907 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1908
1909 assert results = json_response(conn, 200)
1910
1911 [status] = results["statuses"]
1912 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1913 end)
1914 end
1915
1916 test "search doesn't show statuses that it shouldn't", %{conn: conn} do
1917 {:ok, activity} =
1918 CommonAPI.post(insert(:user), %{
1919 "status" => "This is about 2hu, but private",
1920 "visibility" => "private"
1921 })
1922
1923 capture_log(fn ->
1924 conn =
1925 conn
1926 |> get("/api/v1/search", %{"q" => Object.normalize(activity).data["id"]})
1927
1928 assert results = json_response(conn, 200)
1929
1930 [] = results["statuses"]
1931 end)
1932 end
1933
1934 test "search fetches remote accounts", %{conn: conn} do
1935 conn =
1936 conn
1937 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1938
1939 assert results = json_response(conn, 200)
1940 [account] = results["accounts"]
1941 assert account["acct"] == "shp@social.heldscal.la"
1942 end
1943
1944 test "returns the favorites of a user", %{conn: conn} do
1945 user = insert(:user)
1946 other_user = insert(:user)
1947
1948 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1949 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1950
1951 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1952
1953 first_conn =
1954 conn
1955 |> assign(:user, user)
1956 |> get("/api/v1/favourites")
1957
1958 assert [status] = json_response(first_conn, 200)
1959 assert status["id"] == to_string(activity.id)
1960
1961 assert [{"link", _link_header}] =
1962 Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
1963
1964 # Honours query params
1965 {:ok, second_activity} =
1966 CommonAPI.post(other_user, %{
1967 "status" =>
1968 "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
1969 })
1970
1971 {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
1972
1973 last_like = status["id"]
1974
1975 second_conn =
1976 conn
1977 |> assign(:user, user)
1978 |> get("/api/v1/favourites?since_id=#{last_like}")
1979
1980 assert [second_status] = json_response(second_conn, 200)
1981 assert second_status["id"] == to_string(second_activity.id)
1982
1983 third_conn =
1984 conn
1985 |> assign(:user, user)
1986 |> get("/api/v1/favourites?limit=0")
1987
1988 assert [] = json_response(third_conn, 200)
1989 end
1990
1991 describe "getting favorites timeline of specified user" do
1992 setup do
1993 [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
1994 [current_user: current_user, user: user]
1995 end
1996
1997 test "returns list of statuses favorited by specified user", %{
1998 conn: conn,
1999 current_user: current_user,
2000 user: user
2001 } do
2002 [activity | _] = insert_pair(:note_activity)
2003 CommonAPI.favorite(activity.id, user)
2004
2005 response =
2006 conn
2007 |> assign(:user, current_user)
2008 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2009 |> json_response(:ok)
2010
2011 [like] = response
2012
2013 assert length(response) == 1
2014 assert like["id"] == activity.id
2015 end
2016
2017 test "returns favorites for specified user_id when user is not logged in", %{
2018 conn: conn,
2019 user: user
2020 } do
2021 activity = insert(:note_activity)
2022 CommonAPI.favorite(activity.id, user)
2023
2024 response =
2025 conn
2026 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2027 |> json_response(:ok)
2028
2029 assert length(response) == 1
2030 end
2031
2032 test "returns favorited DM only when user is logged in and he is one of recipients", %{
2033 conn: conn,
2034 current_user: current_user,
2035 user: user
2036 } do
2037 {:ok, direct} =
2038 CommonAPI.post(current_user, %{
2039 "status" => "Hi @#{user.nickname}!",
2040 "visibility" => "direct"
2041 })
2042
2043 CommonAPI.favorite(direct.id, user)
2044
2045 response =
2046 conn
2047 |> assign(:user, current_user)
2048 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2049 |> json_response(:ok)
2050
2051 assert length(response) == 1
2052
2053 anonymous_response =
2054 conn
2055 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2056 |> json_response(:ok)
2057
2058 assert length(anonymous_response) == 0
2059 end
2060
2061 test "does not return others' favorited DM when user is not one of recipients", %{
2062 conn: conn,
2063 current_user: current_user,
2064 user: user
2065 } do
2066 user_two = insert(:user)
2067
2068 {:ok, direct} =
2069 CommonAPI.post(user_two, %{
2070 "status" => "Hi @#{user.nickname}!",
2071 "visibility" => "direct"
2072 })
2073
2074 CommonAPI.favorite(direct.id, user)
2075
2076 response =
2077 conn
2078 |> assign(:user, current_user)
2079 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2080 |> json_response(:ok)
2081
2082 assert length(response) == 0
2083 end
2084
2085 test "paginates favorites using since_id and max_id", %{
2086 conn: conn,
2087 current_user: current_user,
2088 user: user
2089 } do
2090 activities = insert_list(10, :note_activity)
2091
2092 Enum.each(activities, fn activity ->
2093 CommonAPI.favorite(activity.id, user)
2094 end)
2095
2096 third_activity = Enum.at(activities, 2)
2097 seventh_activity = Enum.at(activities, 6)
2098
2099 response =
2100 conn
2101 |> assign(:user, current_user)
2102 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
2103 since_id: third_activity.id,
2104 max_id: seventh_activity.id
2105 })
2106 |> json_response(:ok)
2107
2108 assert length(response) == 3
2109 refute third_activity in response
2110 refute seventh_activity in response
2111 end
2112
2113 test "limits favorites using limit parameter", %{
2114 conn: conn,
2115 current_user: current_user,
2116 user: user
2117 } do
2118 7
2119 |> insert_list(:note_activity)
2120 |> Enum.each(fn activity ->
2121 CommonAPI.favorite(activity.id, user)
2122 end)
2123
2124 response =
2125 conn
2126 |> assign(:user, current_user)
2127 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
2128 |> json_response(:ok)
2129
2130 assert length(response) == 3
2131 end
2132
2133 test "returns empty response when user does not have any favorited statuses", %{
2134 conn: conn,
2135 current_user: current_user,
2136 user: user
2137 } do
2138 response =
2139 conn
2140 |> assign(:user, current_user)
2141 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2142 |> json_response(:ok)
2143
2144 assert Enum.empty?(response)
2145 end
2146
2147 test "returns 404 error when specified user is not exist", %{conn: conn} do
2148 conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
2149
2150 assert json_response(conn, 404) == %{"error" => "Record not found"}
2151 end
2152
2153 test "returns 403 error when user has hidden own favorites", %{
2154 conn: conn,
2155 current_user: current_user
2156 } do
2157 user = insert(:user, %{info: %{hide_favorites: true}})
2158 activity = insert(:note_activity)
2159 CommonAPI.favorite(activity.id, user)
2160
2161 conn =
2162 conn
2163 |> assign(:user, current_user)
2164 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2165
2166 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
2167 end
2168
2169 test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
2170 user = insert(:user)
2171 activity = insert(:note_activity)
2172 CommonAPI.favorite(activity.id, user)
2173
2174 conn =
2175 conn
2176 |> assign(:user, current_user)
2177 |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
2178
2179 assert user.info.hide_favorites
2180 assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
2181 end
2182 end
2183
2184 describe "updating credentials" do
2185 test "updates the user's bio", %{conn: conn} do
2186 user = insert(:user)
2187 user2 = insert(:user)
2188
2189 conn =
2190 conn
2191 |> assign(:user, user)
2192 |> patch("/api/v1/accounts/update_credentials", %{
2193 "note" => "I drink #cofe with @#{user2.nickname}"
2194 })
2195
2196 assert user = json_response(conn, 200)
2197
2198 assert user["note"] ==
2199 ~s(I drink <a class="hashtag" data-tag="cofe" href="http://localhost:4001/tag/cofe" rel="tag">#cofe</a> with <span class="h-card"><a data-user=") <>
2200 user2.id <>
2201 ~s(" class="u-url mention" href=") <>
2202 user2.ap_id <> ~s(">@<span>) <> user2.nickname <> ~s(</span></a></span>)
2203 end
2204
2205 test "updates the user's locking status", %{conn: conn} do
2206 user = insert(:user)
2207
2208 conn =
2209 conn
2210 |> assign(:user, user)
2211 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
2212
2213 assert user = json_response(conn, 200)
2214 assert user["locked"] == true
2215 end
2216
2217 test "updates the user's default scope", %{conn: conn} do
2218 user = insert(:user)
2219
2220 conn =
2221 conn
2222 |> assign(:user, user)
2223 |> patch("/api/v1/accounts/update_credentials", %{default_scope: "cofe"})
2224
2225 assert user = json_response(conn, 200)
2226 assert user["source"]["privacy"] == "cofe"
2227 end
2228
2229 test "updates the user's hide_followers status", %{conn: conn} do
2230 user = insert(:user)
2231
2232 conn =
2233 conn
2234 |> assign(:user, user)
2235 |> patch("/api/v1/accounts/update_credentials", %{hide_followers: "true"})
2236
2237 assert user = json_response(conn, 200)
2238 assert user["pleroma"]["hide_followers"] == true
2239 end
2240
2241 test "updates the user's hide_follows status", %{conn: conn} do
2242 user = insert(:user)
2243
2244 conn =
2245 conn
2246 |> assign(:user, user)
2247 |> patch("/api/v1/accounts/update_credentials", %{hide_follows: "true"})
2248
2249 assert user = json_response(conn, 200)
2250 assert user["pleroma"]["hide_follows"] == true
2251 end
2252
2253 test "updates the user's hide_favorites status", %{conn: conn} do
2254 user = insert(:user)
2255
2256 conn =
2257 conn
2258 |> assign(:user, user)
2259 |> patch("/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
2260
2261 assert user = json_response(conn, 200)
2262 assert user["pleroma"]["hide_favorites"] == true
2263 end
2264
2265 test "updates the user's show_role status", %{conn: conn} do
2266 user = insert(:user)
2267
2268 conn =
2269 conn
2270 |> assign(:user, user)
2271 |> patch("/api/v1/accounts/update_credentials", %{show_role: "false"})
2272
2273 assert user = json_response(conn, 200)
2274 assert user["source"]["pleroma"]["show_role"] == false
2275 end
2276
2277 test "updates the user's no_rich_text status", %{conn: conn} do
2278 user = insert(:user)
2279
2280 conn =
2281 conn
2282 |> assign(:user, user)
2283 |> patch("/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
2284
2285 assert user = json_response(conn, 200)
2286 assert user["source"]["pleroma"]["no_rich_text"] == true
2287 end
2288
2289 test "updates the user's name", %{conn: conn} do
2290 user = insert(:user)
2291
2292 conn =
2293 conn
2294 |> assign(:user, user)
2295 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
2296
2297 assert user = json_response(conn, 200)
2298 assert user["display_name"] == "markorepairs"
2299 end
2300
2301 test "updates the user's avatar", %{conn: conn} do
2302 user = insert(:user)
2303
2304 new_avatar = %Plug.Upload{
2305 content_type: "image/jpg",
2306 path: Path.absname("test/fixtures/image.jpg"),
2307 filename: "an_image.jpg"
2308 }
2309
2310 conn =
2311 conn
2312 |> assign(:user, user)
2313 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
2314
2315 assert user_response = json_response(conn, 200)
2316 assert user_response["avatar"] != User.avatar_url(user)
2317 end
2318
2319 test "updates the user's banner", %{conn: conn} do
2320 user = insert(:user)
2321
2322 new_header = %Plug.Upload{
2323 content_type: "image/jpg",
2324 path: Path.absname("test/fixtures/image.jpg"),
2325 filename: "an_image.jpg"
2326 }
2327
2328 conn =
2329 conn
2330 |> assign(:user, user)
2331 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
2332
2333 assert user_response = json_response(conn, 200)
2334 assert user_response["header"] != User.banner_url(user)
2335 end
2336
2337 test "requires 'write' permission", %{conn: conn} do
2338 token1 = insert(:oauth_token, scopes: ["read"])
2339 token2 = insert(:oauth_token, scopes: ["write", "follow"])
2340
2341 for token <- [token1, token2] do
2342 conn =
2343 conn
2344 |> put_req_header("authorization", "Bearer #{token.token}")
2345 |> patch("/api/v1/accounts/update_credentials", %{})
2346
2347 if token == token1 do
2348 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
2349 else
2350 assert json_response(conn, 200)
2351 end
2352 end
2353 end
2354
2355 test "updates profile emojos", %{conn: conn} do
2356 user = insert(:user)
2357
2358 note = "*sips :blank:*"
2359 name = "I am :firefox:"
2360
2361 conn =
2362 conn
2363 |> assign(:user, user)
2364 |> patch("/api/v1/accounts/update_credentials", %{
2365 "note" => note,
2366 "display_name" => name
2367 })
2368
2369 assert json_response(conn, 200)
2370
2371 conn =
2372 conn
2373 |> get("/api/v1/accounts/#{user.id}")
2374
2375 assert user = json_response(conn, 200)
2376
2377 assert user["note"] == note
2378 assert user["display_name"] == name
2379 assert [%{"shortcode" => "blank"}, %{"shortcode" => "firefox"}] = user["emojis"]
2380 end
2381 end
2382
2383 test "get instance information", %{conn: conn} do
2384 conn = get(conn, "/api/v1/instance")
2385 assert result = json_response(conn, 200)
2386
2387 email = Pleroma.Config.get([:instance, :email])
2388 # Note: not checking for "max_toot_chars" since it's optional
2389 assert %{
2390 "uri" => _,
2391 "title" => _,
2392 "description" => _,
2393 "version" => _,
2394 "email" => from_config_email,
2395 "urls" => %{
2396 "streaming_api" => _
2397 },
2398 "stats" => _,
2399 "thumbnail" => _,
2400 "languages" => _,
2401 "registrations" => _
2402 } = result
2403
2404 assert email == from_config_email
2405 end
2406
2407 test "get instance stats", %{conn: conn} do
2408 user = insert(:user, %{local: true})
2409
2410 user2 = insert(:user, %{local: true})
2411 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
2412
2413 insert(:user, %{local: false, nickname: "u@peer1.com"})
2414 insert(:user, %{local: false, nickname: "u@peer2.com"})
2415
2416 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
2417
2418 # Stats should count users with missing or nil `info.deactivated` value
2419 user = User.get_cached_by_id(user.id)
2420 info_change = Changeset.change(user.info, %{deactivated: nil})
2421
2422 {:ok, _user} =
2423 user
2424 |> Changeset.change()
2425 |> Changeset.put_embed(:info, info_change)
2426 |> User.update_and_set_cache()
2427
2428 Pleroma.Stats.update_stats()
2429
2430 conn = get(conn, "/api/v1/instance")
2431
2432 assert result = json_response(conn, 200)
2433
2434 stats = result["stats"]
2435
2436 assert stats
2437 assert stats["user_count"] == 1
2438 assert stats["status_count"] == 1
2439 assert stats["domain_count"] == 2
2440 end
2441
2442 test "get peers", %{conn: conn} do
2443 insert(:user, %{local: false, nickname: "u@peer1.com"})
2444 insert(:user, %{local: false, nickname: "u@peer2.com"})
2445
2446 Pleroma.Stats.update_stats()
2447
2448 conn = get(conn, "/api/v1/instance/peers")
2449
2450 assert result = json_response(conn, 200)
2451
2452 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
2453 end
2454
2455 test "put settings", %{conn: conn} do
2456 user = insert(:user)
2457
2458 conn =
2459 conn
2460 |> assign(:user, user)
2461 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
2462
2463 assert _result = json_response(conn, 200)
2464
2465 user = User.get_cached_by_ap_id(user.ap_id)
2466 assert user.info.settings == %{"programming" => "socks"}
2467 end
2468
2469 describe "pinned statuses" do
2470 setup do
2471 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2472
2473 user = insert(:user)
2474 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2475
2476 [user: user, activity: activity]
2477 end
2478
2479 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2480 {:ok, _} = CommonAPI.pin(activity.id, user)
2481
2482 result =
2483 conn
2484 |> assign(:user, user)
2485 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2486 |> json_response(200)
2487
2488 id_str = to_string(activity.id)
2489
2490 assert [%{"id" => ^id_str, "pinned" => true}] = result
2491 end
2492
2493 test "pin status", %{conn: conn, user: user, activity: activity} do
2494 id_str = to_string(activity.id)
2495
2496 assert %{"id" => ^id_str, "pinned" => true} =
2497 conn
2498 |> assign(:user, user)
2499 |> post("/api/v1/statuses/#{activity.id}/pin")
2500 |> json_response(200)
2501
2502 assert [%{"id" => ^id_str, "pinned" => true}] =
2503 conn
2504 |> assign(:user, user)
2505 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2506 |> json_response(200)
2507 end
2508
2509 test "unpin status", %{conn: conn, user: user, activity: activity} do
2510 {:ok, _} = CommonAPI.pin(activity.id, user)
2511
2512 id_str = to_string(activity.id)
2513 user = refresh_record(user)
2514
2515 assert %{"id" => ^id_str, "pinned" => false} =
2516 conn
2517 |> assign(:user, user)
2518 |> post("/api/v1/statuses/#{activity.id}/unpin")
2519 |> json_response(200)
2520
2521 assert [] =
2522 conn
2523 |> assign(:user, user)
2524 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2525 |> json_response(200)
2526 end
2527
2528 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2529 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2530
2531 id_str_one = to_string(activity_one.id)
2532
2533 assert %{"id" => ^id_str_one, "pinned" => true} =
2534 conn
2535 |> assign(:user, user)
2536 |> post("/api/v1/statuses/#{id_str_one}/pin")
2537 |> json_response(200)
2538
2539 user = refresh_record(user)
2540
2541 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2542 conn
2543 |> assign(:user, user)
2544 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2545 |> json_response(400)
2546 end
2547
2548 test "Status rich-media Card", %{conn: conn, user: user} do
2549 Pleroma.Config.put([:rich_media, :enabled], true)
2550 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2551
2552 response =
2553 conn
2554 |> get("/api/v1/statuses/#{activity.id}/card")
2555 |> json_response(200)
2556
2557 assert response == %{
2558 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2559 "provider_name" => "www.imdb.com",
2560 "provider_url" => "http://www.imdb.com",
2561 "title" => "The Rock",
2562 "type" => "link",
2563 "url" => "http://www.imdb.com/title/tt0117500/",
2564 "description" => nil,
2565 "pleroma" => %{
2566 "opengraph" => %{
2567 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2568 "title" => "The Rock",
2569 "type" => "video.movie",
2570 "url" => "http://www.imdb.com/title/tt0117500/"
2571 }
2572 }
2573 }
2574
2575 # works with private posts
2576 {:ok, activity} =
2577 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2578
2579 response_two =
2580 conn
2581 |> assign(:user, user)
2582 |> get("/api/v1/statuses/#{activity.id}/card")
2583 |> json_response(200)
2584
2585 assert response_two == response
2586
2587 Pleroma.Config.put([:rich_media, :enabled], false)
2588 end
2589 end
2590
2591 test "bookmarks" do
2592 user = insert(:user)
2593 for_user = insert(:user)
2594
2595 {:ok, activity1} =
2596 CommonAPI.post(user, %{
2597 "status" => "heweoo?"
2598 })
2599
2600 {:ok, activity2} =
2601 CommonAPI.post(user, %{
2602 "status" => "heweoo!"
2603 })
2604
2605 response1 =
2606 build_conn()
2607 |> assign(:user, for_user)
2608 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2609
2610 assert json_response(response1, 200)["bookmarked"] == true
2611
2612 response2 =
2613 build_conn()
2614 |> assign(:user, for_user)
2615 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2616
2617 assert json_response(response2, 200)["bookmarked"] == true
2618
2619 bookmarks =
2620 build_conn()
2621 |> assign(:user, for_user)
2622 |> get("/api/v1/bookmarks")
2623
2624 assert [json_response(response2, 200), json_response(response1, 200)] ==
2625 json_response(bookmarks, 200)
2626
2627 response1 =
2628 build_conn()
2629 |> assign(:user, for_user)
2630 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2631
2632 assert json_response(response1, 200)["bookmarked"] == false
2633
2634 bookmarks =
2635 build_conn()
2636 |> assign(:user, for_user)
2637 |> get("/api/v1/bookmarks")
2638
2639 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2640 end
2641
2642 describe "conversation muting" do
2643 setup do
2644 user = insert(:user)
2645 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2646
2647 [user: user, activity: activity]
2648 end
2649
2650 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2651 id_str = to_string(activity.id)
2652
2653 assert %{"id" => ^id_str, "muted" => true} =
2654 conn
2655 |> assign(:user, user)
2656 |> post("/api/v1/statuses/#{activity.id}/mute")
2657 |> json_response(200)
2658 end
2659
2660 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2661 {:ok, _} = CommonAPI.add_mute(user, activity)
2662
2663 id_str = to_string(activity.id)
2664 user = refresh_record(user)
2665
2666 assert %{"id" => ^id_str, "muted" => false} =
2667 conn
2668 |> assign(:user, user)
2669 |> post("/api/v1/statuses/#{activity.id}/unmute")
2670 |> json_response(200)
2671 end
2672 end
2673
2674 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2675 user = insert(:user)
2676
2677 get_old_flavour =
2678 conn
2679 |> assign(:user, user)
2680 |> get("/api/v1/pleroma/flavour")
2681
2682 assert "glitch" == json_response(get_old_flavour, 200)
2683
2684 set_flavour =
2685 conn
2686 |> assign(:user, user)
2687 |> post("/api/v1/pleroma/flavour/vanilla")
2688
2689 assert "vanilla" == json_response(set_flavour, 200)
2690
2691 get_new_flavour =
2692 conn
2693 |> assign(:user, user)
2694 |> post("/api/v1/pleroma/flavour/vanilla")
2695
2696 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2697 end
2698
2699 describe "reports" do
2700 setup do
2701 reporter = insert(:user)
2702 target_user = insert(:user)
2703
2704 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2705
2706 [reporter: reporter, target_user: target_user, activity: activity]
2707 end
2708
2709 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2710 assert %{"action_taken" => false, "id" => _} =
2711 conn
2712 |> assign(:user, reporter)
2713 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2714 |> json_response(200)
2715 end
2716
2717 test "submit a report with statuses and comment", %{
2718 conn: conn,
2719 reporter: reporter,
2720 target_user: target_user,
2721 activity: activity
2722 } do
2723 assert %{"action_taken" => false, "id" => _} =
2724 conn
2725 |> assign(:user, reporter)
2726 |> post("/api/v1/reports", %{
2727 "account_id" => target_user.id,
2728 "status_ids" => [activity.id],
2729 "comment" => "bad status!"
2730 })
2731 |> json_response(200)
2732 end
2733
2734 test "account_id is required", %{
2735 conn: conn,
2736 reporter: reporter,
2737 activity: activity
2738 } do
2739 assert %{"error" => "Valid `account_id` required"} =
2740 conn
2741 |> assign(:user, reporter)
2742 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2743 |> json_response(400)
2744 end
2745
2746 test "comment must be up to the size specified in the config", %{
2747 conn: conn,
2748 reporter: reporter,
2749 target_user: target_user
2750 } do
2751 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2752 comment = String.pad_trailing("a", max_size + 1, "a")
2753
2754 error = %{"error" => "Comment must be up to #{max_size} characters"}
2755
2756 assert ^error =
2757 conn
2758 |> assign(:user, reporter)
2759 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2760 |> json_response(400)
2761 end
2762 end
2763
2764 describe "link headers" do
2765 test "preserves parameters in link headers", %{conn: conn} do
2766 user = insert(:user)
2767 other_user = insert(:user)
2768
2769 {:ok, activity1} =
2770 CommonAPI.post(other_user, %{
2771 "status" => "hi @#{user.nickname}",
2772 "visibility" => "public"
2773 })
2774
2775 {:ok, activity2} =
2776 CommonAPI.post(other_user, %{
2777 "status" => "hi @#{user.nickname}",
2778 "visibility" => "public"
2779 })
2780
2781 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2782 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2783
2784 conn =
2785 conn
2786 |> assign(:user, user)
2787 |> get("/api/v1/notifications", %{media_only: true})
2788
2789 assert [link_header] = get_resp_header(conn, "link")
2790 assert link_header =~ ~r/media_only=true/
2791 assert link_header =~ ~r/min_id=#{notification2.id}/
2792 assert link_header =~ ~r/max_id=#{notification1.id}/
2793 end
2794 end
2795
2796 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
2797 # Need to set an old-style integer ID to reproduce the problem
2798 # (these are no longer assigned to new accounts but were preserved
2799 # for existing accounts during the migration to flakeIDs)
2800 user_one = insert(:user, %{id: 1212})
2801 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
2802
2803 resp_one =
2804 conn
2805 |> get("/api/v1/accounts/#{user_one.id}")
2806
2807 resp_two =
2808 conn
2809 |> get("/api/v1/accounts/#{user_two.nickname}")
2810
2811 resp_three =
2812 conn
2813 |> get("/api/v1/accounts/#{user_two.id}")
2814
2815 acc_one = json_response(resp_one, 200)
2816 acc_two = json_response(resp_two, 200)
2817 acc_three = json_response(resp_three, 200)
2818 refute acc_one == acc_two
2819 assert acc_two == acc_three
2820 end
2821
2822 describe "custom emoji" do
2823 test "with tags", %{conn: conn} do
2824 [emoji | _body] =
2825 conn
2826 |> get("/api/v1/custom_emojis")
2827 |> json_response(200)
2828
2829 assert Map.has_key?(emoji, "shortcode")
2830 assert Map.has_key?(emoji, "static_url")
2831 assert Map.has_key?(emoji, "tags")
2832 assert is_list(emoji["tags"])
2833 assert Map.has_key?(emoji, "url")
2834 assert Map.has_key?(emoji, "visible_in_picker")
2835 end
2836 end
2837
2838 describe "index/2 redirections" do
2839 setup %{conn: conn} do
2840 session_opts = [
2841 store: :cookie,
2842 key: "_test",
2843 signing_salt: "cooldude"
2844 ]
2845
2846 conn =
2847 conn
2848 |> Plug.Session.call(Plug.Session.init(session_opts))
2849 |> fetch_session()
2850
2851 test_path = "/web/statuses/test"
2852 %{conn: conn, path: test_path}
2853 end
2854
2855 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
2856 conn = get(conn, path)
2857
2858 assert conn.status == 302
2859 assert redirected_to(conn) == "/web/login"
2860 end
2861
2862 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
2863 token = insert(:oauth_token)
2864
2865 conn =
2866 conn
2867 |> assign(:user, token.user)
2868 |> put_session(:oauth_token, token.token)
2869 |> get(path)
2870
2871 assert conn.status == 200
2872 end
2873
2874 test "saves referer path to session", %{conn: conn, path: path} do
2875 conn = get(conn, path)
2876 return_to = Plug.Conn.get_session(conn, :return_to)
2877
2878 assert return_to == path
2879 end
2880
2881 test "redirects to the saved path after log in", %{conn: conn, path: path} do
2882 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2883 auth = insert(:oauth_authorization, app: app)
2884
2885 conn =
2886 conn
2887 |> put_session(:return_to, path)
2888 |> get("/web/login", %{code: auth.token})
2889
2890 assert conn.status == 302
2891 assert redirected_to(conn) == path
2892 end
2893
2894 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
2895 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2896 auth = insert(:oauth_authorization, app: app)
2897
2898 conn = get(conn, "/web/login", %{code: auth.token})
2899
2900 assert conn.status == 302
2901 assert redirected_to(conn) == "/web/getting-started"
2902 end
2903 end
2904
2905 describe "scheduled activities" do
2906 test "creates a scheduled activity", %{conn: conn} do
2907 user = insert(:user)
2908 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2909
2910 conn =
2911 conn
2912 |> assign(:user, user)
2913 |> post("/api/v1/statuses", %{
2914 "status" => "scheduled",
2915 "scheduled_at" => scheduled_at
2916 })
2917
2918 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
2919 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
2920 assert [] == Repo.all(Activity)
2921 end
2922
2923 test "creates a scheduled activity with a media attachment", %{conn: conn} do
2924 user = insert(:user)
2925 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2926
2927 file = %Plug.Upload{
2928 content_type: "image/jpg",
2929 path: Path.absname("test/fixtures/image.jpg"),
2930 filename: "an_image.jpg"
2931 }
2932
2933 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
2934
2935 conn =
2936 conn
2937 |> assign(:user, user)
2938 |> post("/api/v1/statuses", %{
2939 "media_ids" => [to_string(upload.id)],
2940 "status" => "scheduled",
2941 "scheduled_at" => scheduled_at
2942 })
2943
2944 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
2945 assert %{"type" => "image"} = media_attachment
2946 end
2947
2948 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
2949 %{conn: conn} do
2950 user = insert(:user)
2951
2952 scheduled_at =
2953 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
2954
2955 conn =
2956 conn
2957 |> assign(:user, user)
2958 |> post("/api/v1/statuses", %{
2959 "status" => "not scheduled",
2960 "scheduled_at" => scheduled_at
2961 })
2962
2963 assert %{"content" => "not scheduled"} = json_response(conn, 200)
2964 assert [] == Repo.all(ScheduledActivity)
2965 end
2966
2967 test "returns error when daily user limit is exceeded", %{conn: conn} do
2968 user = insert(:user)
2969
2970 today =
2971 NaiveDateTime.utc_now()
2972 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2973 |> NaiveDateTime.to_iso8601()
2974
2975 attrs = %{params: %{}, scheduled_at: today}
2976 {:ok, _} = ScheduledActivity.create(user, attrs)
2977 {:ok, _} = ScheduledActivity.create(user, attrs)
2978
2979 conn =
2980 conn
2981 |> assign(:user, user)
2982 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
2983
2984 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
2985 end
2986
2987 test "returns error when total user limit is exceeded", %{conn: conn} do
2988 user = insert(:user)
2989
2990 today =
2991 NaiveDateTime.utc_now()
2992 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2993 |> NaiveDateTime.to_iso8601()
2994
2995 tomorrow =
2996 NaiveDateTime.utc_now()
2997 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
2998 |> NaiveDateTime.to_iso8601()
2999
3000 attrs = %{params: %{}, scheduled_at: today}
3001 {:ok, _} = ScheduledActivity.create(user, attrs)
3002 {:ok, _} = ScheduledActivity.create(user, attrs)
3003 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
3004
3005 conn =
3006 conn
3007 |> assign(:user, user)
3008 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
3009
3010 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
3011 end
3012
3013 test "shows scheduled activities", %{conn: conn} do
3014 user = insert(:user)
3015 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
3016 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
3017 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
3018 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
3019
3020 conn =
3021 conn
3022 |> assign(:user, user)
3023
3024 # min_id
3025 conn_res =
3026 conn
3027 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
3028
3029 result = json_response(conn_res, 200)
3030 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
3031
3032 # since_id
3033 conn_res =
3034 conn
3035 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
3036
3037 result = json_response(conn_res, 200)
3038 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
3039
3040 # max_id
3041 conn_res =
3042 conn
3043 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
3044
3045 result = json_response(conn_res, 200)
3046 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
3047 end
3048
3049 test "shows a scheduled activity", %{conn: conn} do
3050 user = insert(:user)
3051 scheduled_activity = insert(:scheduled_activity, user: user)
3052
3053 res_conn =
3054 conn
3055 |> assign(:user, user)
3056 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3057
3058 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
3059 assert scheduled_activity_id == scheduled_activity.id |> to_string()
3060
3061 res_conn =
3062 conn
3063 |> assign(:user, user)
3064 |> get("/api/v1/scheduled_statuses/404")
3065
3066 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3067 end
3068
3069 test "updates a scheduled activity", %{conn: conn} do
3070 user = insert(:user)
3071 scheduled_activity = insert(:scheduled_activity, user: user)
3072
3073 new_scheduled_at =
3074 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
3075
3076 res_conn =
3077 conn
3078 |> assign(:user, user)
3079 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
3080 scheduled_at: new_scheduled_at
3081 })
3082
3083 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
3084 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
3085
3086 res_conn =
3087 conn
3088 |> assign(:user, user)
3089 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
3090
3091 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3092 end
3093
3094 test "deletes a scheduled activity", %{conn: conn} do
3095 user = insert(:user)
3096 scheduled_activity = insert(:scheduled_activity, user: user)
3097
3098 res_conn =
3099 conn
3100 |> assign(:user, user)
3101 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3102
3103 assert %{} = json_response(res_conn, 200)
3104 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
3105
3106 res_conn =
3107 conn
3108 |> assign(:user, user)
3109 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3110
3111 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3112 end
3113 end
3114
3115 test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
3116 user1 = insert(:user)
3117 user2 = insert(:user)
3118 user3 = insert(:user)
3119
3120 {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"})
3121
3122 # Reply to status from another user
3123 conn1 =
3124 conn
3125 |> assign(:user, user2)
3126 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
3127
3128 assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
3129
3130 activity = Activity.get_by_id_with_object(id)
3131
3132 assert Object.normalize(activity).data["inReplyTo"] == Object.normalize(replied_to).data["id"]
3133 assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
3134
3135 # Reblog from the third user
3136 conn2 =
3137 conn
3138 |> assign(:user, user3)
3139 |> post("/api/v1/statuses/#{activity.id}/reblog")
3140
3141 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
3142 json_response(conn2, 200)
3143
3144 assert to_string(activity.id) == id
3145
3146 # Getting third user status
3147 conn3 =
3148 conn
3149 |> assign(:user, user3)
3150 |> get("api/v1/timelines/home")
3151
3152 [reblogged_activity] = json_response(conn3, 200)
3153
3154 assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
3155
3156 replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
3157 assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id
3158 end
3159 end