Merge branch 'feature/bbcode' 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 hide_followers status", %{conn: conn} do
2218 user = insert(:user)
2219
2220 conn =
2221 conn
2222 |> assign(:user, user)
2223 |> patch("/api/v1/accounts/update_credentials", %{hide_followers: "true"})
2224
2225 assert user = json_response(conn, 200)
2226 assert user["pleroma"]["hide_followers"] == true
2227 end
2228
2229 test "updates the user's hide_follows 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_follows: "true"})
2236
2237 assert user = json_response(conn, 200)
2238 assert user["pleroma"]["hide_follows"] == true
2239 end
2240
2241 test "updates the user's hide_favorites 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_favorites: "true"})
2248
2249 assert user = json_response(conn, 200)
2250 assert user["pleroma"]["hide_favorites"] == true
2251 end
2252
2253 test "updates the user's show_role status", %{conn: conn} do
2254 user = insert(:user)
2255
2256 conn =
2257 conn
2258 |> assign(:user, user)
2259 |> patch("/api/v1/accounts/update_credentials", %{show_role: "false"})
2260
2261 assert user = json_response(conn, 200)
2262 assert user["source"]["pleroma"]["show_role"] == false
2263 end
2264
2265 test "updates the user's no_rich_text status", %{conn: conn} do
2266 user = insert(:user)
2267
2268 conn =
2269 conn
2270 |> assign(:user, user)
2271 |> patch("/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
2272
2273 assert user = json_response(conn, 200)
2274 assert user["source"]["pleroma"]["no_rich_text"] == true
2275 end
2276
2277 test "updates the user's name", %{conn: conn} do
2278 user = insert(:user)
2279
2280 conn =
2281 conn
2282 |> assign(:user, user)
2283 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
2284
2285 assert user = json_response(conn, 200)
2286 assert user["display_name"] == "markorepairs"
2287 end
2288
2289 test "updates the user's avatar", %{conn: conn} do
2290 user = insert(:user)
2291
2292 new_avatar = %Plug.Upload{
2293 content_type: "image/jpg",
2294 path: Path.absname("test/fixtures/image.jpg"),
2295 filename: "an_image.jpg"
2296 }
2297
2298 conn =
2299 conn
2300 |> assign(:user, user)
2301 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
2302
2303 assert user_response = json_response(conn, 200)
2304 assert user_response["avatar"] != User.avatar_url(user)
2305 end
2306
2307 test "updates the user's banner", %{conn: conn} do
2308 user = insert(:user)
2309
2310 new_header = %Plug.Upload{
2311 content_type: "image/jpg",
2312 path: Path.absname("test/fixtures/image.jpg"),
2313 filename: "an_image.jpg"
2314 }
2315
2316 conn =
2317 conn
2318 |> assign(:user, user)
2319 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
2320
2321 assert user_response = json_response(conn, 200)
2322 assert user_response["header"] != User.banner_url(user)
2323 end
2324
2325 test "requires 'write' permission", %{conn: conn} do
2326 token1 = insert(:oauth_token, scopes: ["read"])
2327 token2 = insert(:oauth_token, scopes: ["write", "follow"])
2328
2329 for token <- [token1, token2] do
2330 conn =
2331 conn
2332 |> put_req_header("authorization", "Bearer #{token.token}")
2333 |> patch("/api/v1/accounts/update_credentials", %{})
2334
2335 if token == token1 do
2336 assert %{"error" => "Insufficient permissions: write."} == json_response(conn, 403)
2337 else
2338 assert json_response(conn, 200)
2339 end
2340 end
2341 end
2342 end
2343
2344 test "get instance information", %{conn: conn} do
2345 conn = get(conn, "/api/v1/instance")
2346 assert result = json_response(conn, 200)
2347
2348 email = Pleroma.Config.get([:instance, :email])
2349 # Note: not checking for "max_toot_chars" since it's optional
2350 assert %{
2351 "uri" => _,
2352 "title" => _,
2353 "description" => _,
2354 "version" => _,
2355 "email" => from_config_email,
2356 "urls" => %{
2357 "streaming_api" => _
2358 },
2359 "stats" => _,
2360 "thumbnail" => _,
2361 "languages" => _,
2362 "registrations" => _
2363 } = result
2364
2365 assert email == from_config_email
2366 end
2367
2368 test "get instance stats", %{conn: conn} do
2369 user = insert(:user, %{local: true})
2370
2371 user2 = insert(:user, %{local: true})
2372 {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
2373
2374 insert(:user, %{local: false, nickname: "u@peer1.com"})
2375 insert(:user, %{local: false, nickname: "u@peer2.com"})
2376
2377 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
2378
2379 # Stats should count users with missing or nil `info.deactivated` value
2380 user = User.get_cached_by_id(user.id)
2381 info_change = Changeset.change(user.info, %{deactivated: nil})
2382
2383 {:ok, _user} =
2384 user
2385 |> Changeset.change()
2386 |> Changeset.put_embed(:info, info_change)
2387 |> User.update_and_set_cache()
2388
2389 Pleroma.Stats.update_stats()
2390
2391 conn = get(conn, "/api/v1/instance")
2392
2393 assert result = json_response(conn, 200)
2394
2395 stats = result["stats"]
2396
2397 assert stats
2398 assert stats["user_count"] == 1
2399 assert stats["status_count"] == 1
2400 assert stats["domain_count"] == 2
2401 end
2402
2403 test "get peers", %{conn: conn} do
2404 insert(:user, %{local: false, nickname: "u@peer1.com"})
2405 insert(:user, %{local: false, nickname: "u@peer2.com"})
2406
2407 Pleroma.Stats.update_stats()
2408
2409 conn = get(conn, "/api/v1/instance/peers")
2410
2411 assert result = json_response(conn, 200)
2412
2413 assert ["peer1.com", "peer2.com"] == Enum.sort(result)
2414 end
2415
2416 test "put settings", %{conn: conn} do
2417 user = insert(:user)
2418
2419 conn =
2420 conn
2421 |> assign(:user, user)
2422 |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
2423
2424 assert _result = json_response(conn, 200)
2425
2426 user = User.get_cached_by_ap_id(user.ap_id)
2427 assert user.info.settings == %{"programming" => "socks"}
2428 end
2429
2430 describe "pinned statuses" do
2431 setup do
2432 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
2433
2434 user = insert(:user)
2435 {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
2436
2437 [user: user, activity: activity]
2438 end
2439
2440 test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
2441 {:ok, _} = CommonAPI.pin(activity.id, user)
2442
2443 result =
2444 conn
2445 |> assign(:user, user)
2446 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2447 |> json_response(200)
2448
2449 id_str = to_string(activity.id)
2450
2451 assert [%{"id" => ^id_str, "pinned" => true}] = result
2452 end
2453
2454 test "pin status", %{conn: conn, user: user, activity: activity} do
2455 id_str = to_string(activity.id)
2456
2457 assert %{"id" => ^id_str, "pinned" => true} =
2458 conn
2459 |> assign(:user, user)
2460 |> post("/api/v1/statuses/#{activity.id}/pin")
2461 |> json_response(200)
2462
2463 assert [%{"id" => ^id_str, "pinned" => true}] =
2464 conn
2465 |> assign(:user, user)
2466 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2467 |> json_response(200)
2468 end
2469
2470 test "unpin status", %{conn: conn, user: user, activity: activity} do
2471 {:ok, _} = CommonAPI.pin(activity.id, user)
2472
2473 id_str = to_string(activity.id)
2474 user = refresh_record(user)
2475
2476 assert %{"id" => ^id_str, "pinned" => false} =
2477 conn
2478 |> assign(:user, user)
2479 |> post("/api/v1/statuses/#{activity.id}/unpin")
2480 |> json_response(200)
2481
2482 assert [] =
2483 conn
2484 |> assign(:user, user)
2485 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
2486 |> json_response(200)
2487 end
2488
2489 test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
2490 {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
2491
2492 id_str_one = to_string(activity_one.id)
2493
2494 assert %{"id" => ^id_str_one, "pinned" => true} =
2495 conn
2496 |> assign(:user, user)
2497 |> post("/api/v1/statuses/#{id_str_one}/pin")
2498 |> json_response(200)
2499
2500 user = refresh_record(user)
2501
2502 assert %{"error" => "You have already pinned the maximum number of statuses"} =
2503 conn
2504 |> assign(:user, user)
2505 |> post("/api/v1/statuses/#{activity_two.id}/pin")
2506 |> json_response(400)
2507 end
2508
2509 test "Status rich-media Card", %{conn: conn, user: user} do
2510 Pleroma.Config.put([:rich_media, :enabled], true)
2511 {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
2512
2513 response =
2514 conn
2515 |> get("/api/v1/statuses/#{activity.id}/card")
2516 |> json_response(200)
2517
2518 assert response == %{
2519 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2520 "provider_name" => "www.imdb.com",
2521 "provider_url" => "http://www.imdb.com",
2522 "title" => "The Rock",
2523 "type" => "link",
2524 "url" => "http://www.imdb.com/title/tt0117500/",
2525 "description" => nil,
2526 "pleroma" => %{
2527 "opengraph" => %{
2528 "image" => "http://ia.media-imdb.com/images/rock.jpg",
2529 "title" => "The Rock",
2530 "type" => "video.movie",
2531 "url" => "http://www.imdb.com/title/tt0117500/"
2532 }
2533 }
2534 }
2535
2536 # works with private posts
2537 {:ok, activity} =
2538 CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"})
2539
2540 response_two =
2541 conn
2542 |> assign(:user, user)
2543 |> get("/api/v1/statuses/#{activity.id}/card")
2544 |> json_response(200)
2545
2546 assert response_two == response
2547
2548 Pleroma.Config.put([:rich_media, :enabled], false)
2549 end
2550 end
2551
2552 test "bookmarks" do
2553 user = insert(:user)
2554 for_user = insert(:user)
2555
2556 {:ok, activity1} =
2557 CommonAPI.post(user, %{
2558 "status" => "heweoo?"
2559 })
2560
2561 {:ok, activity2} =
2562 CommonAPI.post(user, %{
2563 "status" => "heweoo!"
2564 })
2565
2566 response1 =
2567 build_conn()
2568 |> assign(:user, for_user)
2569 |> post("/api/v1/statuses/#{activity1.id}/bookmark")
2570
2571 assert json_response(response1, 200)["bookmarked"] == true
2572
2573 response2 =
2574 build_conn()
2575 |> assign(:user, for_user)
2576 |> post("/api/v1/statuses/#{activity2.id}/bookmark")
2577
2578 assert json_response(response2, 200)["bookmarked"] == true
2579
2580 bookmarks =
2581 build_conn()
2582 |> assign(:user, for_user)
2583 |> get("/api/v1/bookmarks")
2584
2585 assert [json_response(response2, 200), json_response(response1, 200)] ==
2586 json_response(bookmarks, 200)
2587
2588 response1 =
2589 build_conn()
2590 |> assign(:user, for_user)
2591 |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
2592
2593 assert json_response(response1, 200)["bookmarked"] == false
2594
2595 bookmarks =
2596 build_conn()
2597 |> assign(:user, for_user)
2598 |> get("/api/v1/bookmarks")
2599
2600 assert [json_response(response2, 200)] == json_response(bookmarks, 200)
2601 end
2602
2603 describe "conversation muting" do
2604 setup do
2605 user = insert(:user)
2606 {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
2607
2608 [user: user, activity: activity]
2609 end
2610
2611 test "mute conversation", %{conn: conn, user: user, activity: activity} do
2612 id_str = to_string(activity.id)
2613
2614 assert %{"id" => ^id_str, "muted" => true} =
2615 conn
2616 |> assign(:user, user)
2617 |> post("/api/v1/statuses/#{activity.id}/mute")
2618 |> json_response(200)
2619 end
2620
2621 test "unmute conversation", %{conn: conn, user: user, activity: activity} do
2622 {:ok, _} = CommonAPI.add_mute(user, activity)
2623
2624 id_str = to_string(activity.id)
2625 user = refresh_record(user)
2626
2627 assert %{"id" => ^id_str, "muted" => false} =
2628 conn
2629 |> assign(:user, user)
2630 |> post("/api/v1/statuses/#{activity.id}/unmute")
2631 |> json_response(200)
2632 end
2633 end
2634
2635 test "flavours switching (Pleroma Extension)", %{conn: conn} do
2636 user = insert(:user)
2637
2638 get_old_flavour =
2639 conn
2640 |> assign(:user, user)
2641 |> get("/api/v1/pleroma/flavour")
2642
2643 assert "glitch" == json_response(get_old_flavour, 200)
2644
2645 set_flavour =
2646 conn
2647 |> assign(:user, user)
2648 |> post("/api/v1/pleroma/flavour/vanilla")
2649
2650 assert "vanilla" == json_response(set_flavour, 200)
2651
2652 get_new_flavour =
2653 conn
2654 |> assign(:user, user)
2655 |> post("/api/v1/pleroma/flavour/vanilla")
2656
2657 assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
2658 end
2659
2660 describe "reports" do
2661 setup do
2662 reporter = insert(:user)
2663 target_user = insert(:user)
2664
2665 {:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
2666
2667 [reporter: reporter, target_user: target_user, activity: activity]
2668 end
2669
2670 test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
2671 assert %{"action_taken" => false, "id" => _} =
2672 conn
2673 |> assign(:user, reporter)
2674 |> post("/api/v1/reports", %{"account_id" => target_user.id})
2675 |> json_response(200)
2676 end
2677
2678 test "submit a report with statuses and comment", %{
2679 conn: conn,
2680 reporter: reporter,
2681 target_user: target_user,
2682 activity: activity
2683 } do
2684 assert %{"action_taken" => false, "id" => _} =
2685 conn
2686 |> assign(:user, reporter)
2687 |> post("/api/v1/reports", %{
2688 "account_id" => target_user.id,
2689 "status_ids" => [activity.id],
2690 "comment" => "bad status!"
2691 })
2692 |> json_response(200)
2693 end
2694
2695 test "account_id is required", %{
2696 conn: conn,
2697 reporter: reporter,
2698 activity: activity
2699 } do
2700 assert %{"error" => "Valid `account_id` required"} =
2701 conn
2702 |> assign(:user, reporter)
2703 |> post("/api/v1/reports", %{"status_ids" => [activity.id]})
2704 |> json_response(400)
2705 end
2706
2707 test "comment must be up to the size specified in the config", %{
2708 conn: conn,
2709 reporter: reporter,
2710 target_user: target_user
2711 } do
2712 max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
2713 comment = String.pad_trailing("a", max_size + 1, "a")
2714
2715 error = %{"error" => "Comment must be up to #{max_size} characters"}
2716
2717 assert ^error =
2718 conn
2719 |> assign(:user, reporter)
2720 |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
2721 |> json_response(400)
2722 end
2723 end
2724
2725 describe "link headers" do
2726 test "preserves parameters in link headers", %{conn: conn} do
2727 user = insert(:user)
2728 other_user = insert(:user)
2729
2730 {:ok, activity1} =
2731 CommonAPI.post(other_user, %{
2732 "status" => "hi @#{user.nickname}",
2733 "visibility" => "public"
2734 })
2735
2736 {:ok, activity2} =
2737 CommonAPI.post(other_user, %{
2738 "status" => "hi @#{user.nickname}",
2739 "visibility" => "public"
2740 })
2741
2742 notification1 = Repo.get_by(Notification, activity_id: activity1.id)
2743 notification2 = Repo.get_by(Notification, activity_id: activity2.id)
2744
2745 conn =
2746 conn
2747 |> assign(:user, user)
2748 |> get("/api/v1/notifications", %{media_only: true})
2749
2750 assert [link_header] = get_resp_header(conn, "link")
2751 assert link_header =~ ~r/media_only=true/
2752 assert link_header =~ ~r/min_id=#{notification2.id}/
2753 assert link_header =~ ~r/max_id=#{notification1.id}/
2754 end
2755 end
2756
2757 test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
2758 # Need to set an old-style integer ID to reproduce the problem
2759 # (these are no longer assigned to new accounts but were preserved
2760 # for existing accounts during the migration to flakeIDs)
2761 user_one = insert(:user, %{id: 1212})
2762 user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
2763
2764 resp_one =
2765 conn
2766 |> get("/api/v1/accounts/#{user_one.id}")
2767
2768 resp_two =
2769 conn
2770 |> get("/api/v1/accounts/#{user_two.nickname}")
2771
2772 resp_three =
2773 conn
2774 |> get("/api/v1/accounts/#{user_two.id}")
2775
2776 acc_one = json_response(resp_one, 200)
2777 acc_two = json_response(resp_two, 200)
2778 acc_three = json_response(resp_three, 200)
2779 refute acc_one == acc_two
2780 assert acc_two == acc_three
2781 end
2782
2783 describe "custom emoji" do
2784 test "with tags", %{conn: conn} do
2785 [emoji | _body] =
2786 conn
2787 |> get("/api/v1/custom_emojis")
2788 |> json_response(200)
2789
2790 assert Map.has_key?(emoji, "shortcode")
2791 assert Map.has_key?(emoji, "static_url")
2792 assert Map.has_key?(emoji, "tags")
2793 assert is_list(emoji["tags"])
2794 assert Map.has_key?(emoji, "url")
2795 assert Map.has_key?(emoji, "visible_in_picker")
2796 end
2797 end
2798
2799 describe "index/2 redirections" do
2800 setup %{conn: conn} do
2801 session_opts = [
2802 store: :cookie,
2803 key: "_test",
2804 signing_salt: "cooldude"
2805 ]
2806
2807 conn =
2808 conn
2809 |> Plug.Session.call(Plug.Session.init(session_opts))
2810 |> fetch_session()
2811
2812 test_path = "/web/statuses/test"
2813 %{conn: conn, path: test_path}
2814 end
2815
2816 test "redirects not logged-in users to the login page", %{conn: conn, path: path} do
2817 conn = get(conn, path)
2818
2819 assert conn.status == 302
2820 assert redirected_to(conn) == "/web/login"
2821 end
2822
2823 test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
2824 token = insert(:oauth_token)
2825
2826 conn =
2827 conn
2828 |> assign(:user, token.user)
2829 |> put_session(:oauth_token, token.token)
2830 |> get(path)
2831
2832 assert conn.status == 200
2833 end
2834
2835 test "saves referer path to session", %{conn: conn, path: path} do
2836 conn = get(conn, path)
2837 return_to = Plug.Conn.get_session(conn, :return_to)
2838
2839 assert return_to == path
2840 end
2841
2842 test "redirects to the saved path after log in", %{conn: conn, path: path} do
2843 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2844 auth = insert(:oauth_authorization, app: app)
2845
2846 conn =
2847 conn
2848 |> put_session(:return_to, path)
2849 |> get("/web/login", %{code: auth.token})
2850
2851 assert conn.status == 302
2852 assert redirected_to(conn) == path
2853 end
2854
2855 test "redirects to the getting-started page when referer is not present", %{conn: conn} do
2856 app = insert(:oauth_app, client_name: "Mastodon-Local", redirect_uris: ".")
2857 auth = insert(:oauth_authorization, app: app)
2858
2859 conn = get(conn, "/web/login", %{code: auth.token})
2860
2861 assert conn.status == 302
2862 assert redirected_to(conn) == "/web/getting-started"
2863 end
2864 end
2865
2866 describe "scheduled activities" do
2867 test "creates a scheduled activity", %{conn: conn} do
2868 user = insert(:user)
2869 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2870
2871 conn =
2872 conn
2873 |> assign(:user, user)
2874 |> post("/api/v1/statuses", %{
2875 "status" => "scheduled",
2876 "scheduled_at" => scheduled_at
2877 })
2878
2879 assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
2880 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
2881 assert [] == Repo.all(Activity)
2882 end
2883
2884 test "creates a scheduled activity with a media attachment", %{conn: conn} do
2885 user = insert(:user)
2886 scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
2887
2888 file = %Plug.Upload{
2889 content_type: "image/jpg",
2890 path: Path.absname("test/fixtures/image.jpg"),
2891 filename: "an_image.jpg"
2892 }
2893
2894 {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
2895
2896 conn =
2897 conn
2898 |> assign(:user, user)
2899 |> post("/api/v1/statuses", %{
2900 "media_ids" => [to_string(upload.id)],
2901 "status" => "scheduled",
2902 "scheduled_at" => scheduled_at
2903 })
2904
2905 assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
2906 assert %{"type" => "image"} = media_attachment
2907 end
2908
2909 test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
2910 %{conn: conn} do
2911 user = insert(:user)
2912
2913 scheduled_at =
2914 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
2915
2916 conn =
2917 conn
2918 |> assign(:user, user)
2919 |> post("/api/v1/statuses", %{
2920 "status" => "not scheduled",
2921 "scheduled_at" => scheduled_at
2922 })
2923
2924 assert %{"content" => "not scheduled"} = json_response(conn, 200)
2925 assert [] == Repo.all(ScheduledActivity)
2926 end
2927
2928 test "returns error when daily user limit is exceeded", %{conn: conn} do
2929 user = insert(:user)
2930
2931 today =
2932 NaiveDateTime.utc_now()
2933 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2934 |> NaiveDateTime.to_iso8601()
2935
2936 attrs = %{params: %{}, scheduled_at: today}
2937 {:ok, _} = ScheduledActivity.create(user, attrs)
2938 {:ok, _} = ScheduledActivity.create(user, attrs)
2939
2940 conn =
2941 conn
2942 |> assign(:user, user)
2943 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
2944
2945 assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
2946 end
2947
2948 test "returns error when total user limit is exceeded", %{conn: conn} do
2949 user = insert(:user)
2950
2951 today =
2952 NaiveDateTime.utc_now()
2953 |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
2954 |> NaiveDateTime.to_iso8601()
2955
2956 tomorrow =
2957 NaiveDateTime.utc_now()
2958 |> NaiveDateTime.add(:timer.hours(36), :millisecond)
2959 |> NaiveDateTime.to_iso8601()
2960
2961 attrs = %{params: %{}, scheduled_at: today}
2962 {:ok, _} = ScheduledActivity.create(user, attrs)
2963 {:ok, _} = ScheduledActivity.create(user, attrs)
2964 {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
2965
2966 conn =
2967 conn
2968 |> assign(:user, user)
2969 |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
2970
2971 assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
2972 end
2973
2974 test "shows scheduled activities", %{conn: conn} do
2975 user = insert(:user)
2976 scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
2977 scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
2978 scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
2979 scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
2980
2981 conn =
2982 conn
2983 |> assign(:user, user)
2984
2985 # min_id
2986 conn_res =
2987 conn
2988 |> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
2989
2990 result = json_response(conn_res, 200)
2991 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
2992
2993 # since_id
2994 conn_res =
2995 conn
2996 |> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
2997
2998 result = json_response(conn_res, 200)
2999 assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
3000
3001 # max_id
3002 conn_res =
3003 conn
3004 |> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
3005
3006 result = json_response(conn_res, 200)
3007 assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
3008 end
3009
3010 test "shows a scheduled activity", %{conn: conn} do
3011 user = insert(:user)
3012 scheduled_activity = insert(:scheduled_activity, user: user)
3013
3014 res_conn =
3015 conn
3016 |> assign(:user, user)
3017 |> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3018
3019 assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
3020 assert scheduled_activity_id == scheduled_activity.id |> to_string()
3021
3022 res_conn =
3023 conn
3024 |> assign(:user, user)
3025 |> get("/api/v1/scheduled_statuses/404")
3026
3027 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3028 end
3029
3030 test "updates a scheduled activity", %{conn: conn} do
3031 user = insert(:user)
3032 scheduled_activity = insert(:scheduled_activity, user: user)
3033
3034 new_scheduled_at =
3035 NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
3036
3037 res_conn =
3038 conn
3039 |> assign(:user, user)
3040 |> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
3041 scheduled_at: new_scheduled_at
3042 })
3043
3044 assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
3045 assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
3046
3047 res_conn =
3048 conn
3049 |> assign(:user, user)
3050 |> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
3051
3052 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3053 end
3054
3055 test "deletes a scheduled activity", %{conn: conn} do
3056 user = insert(:user)
3057 scheduled_activity = insert(:scheduled_activity, user: user)
3058
3059 res_conn =
3060 conn
3061 |> assign(:user, user)
3062 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3063
3064 assert %{} = json_response(res_conn, 200)
3065 assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
3066
3067 res_conn =
3068 conn
3069 |> assign(:user, user)
3070 |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
3071
3072 assert %{"error" => "Record not found"} = json_response(res_conn, 404)
3073 end
3074 end
3075
3076 test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
3077 user1 = insert(:user)
3078 user2 = insert(:user)
3079 user3 = insert(:user)
3080
3081 {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"})
3082
3083 # Reply to status from another user
3084 conn1 =
3085 conn
3086 |> assign(:user, user2)
3087 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
3088
3089 assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
3090
3091 activity = Activity.get_by_id_with_object(id)
3092
3093 assert Object.normalize(activity).data["inReplyTo"] == Object.normalize(replied_to).data["id"]
3094 assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
3095
3096 # Reblog from the third user
3097 conn2 =
3098 conn
3099 |> assign(:user, user3)
3100 |> post("/api/v1/statuses/#{activity.id}/reblog")
3101
3102 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
3103 json_response(conn2, 200)
3104
3105 assert to_string(activity.id) == id
3106
3107 # Getting third user status
3108 conn3 =
3109 conn
3110 |> assign(:user, user3)
3111 |> get("api/v1/timelines/home")
3112
3113 [reblogged_activity] = json_response(conn3, 200)
3114
3115 assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
3116
3117 replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
3118 assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id
3119 end
3120 end