Merge branch '210_twitter_api_uploads_alt_text' into 'develop'
[akkoma] / test / web / mastodon_api / mastodon_api_controller_test.exs
1 defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
2 use Pleroma.Web.ConnCase
3
4 alias Pleroma.Web.TwitterAPI.TwitterAPI
5 alias Pleroma.{Repo, User, Object, Activity, Notification}
6 alias Pleroma.Web.{OStatus, CommonAPI}
7 alias Pleroma.Web.ActivityPub.ActivityPub
8
9 import Pleroma.Factory
10 import ExUnit.CaptureLog
11 import Tesla.Mock
12
13 setup do
14 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
15 :ok
16 end
17
18 test "the home timeline", %{conn: conn} do
19 user = insert(:user)
20 following = insert(:user)
21
22 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
23
24 conn =
25 conn
26 |> assign(:user, user)
27 |> get("/api/v1/timelines/home")
28
29 assert length(json_response(conn, 200)) == 0
30
31 {:ok, user} = User.follow(user, following)
32
33 conn =
34 build_conn()
35 |> assign(:user, user)
36 |> get("/api/v1/timelines/home")
37
38 assert [%{"content" => "test"}] = json_response(conn, 200)
39 end
40
41 test "the public timeline", %{conn: conn} do
42 following = insert(:user)
43
44 capture_log(fn ->
45 {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
46
47 {:ok, [_activity]} =
48 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
49
50 conn =
51 conn
52 |> get("/api/v1/timelines/public", %{"local" => "False"})
53
54 assert length(json_response(conn, 200)) == 2
55
56 conn =
57 build_conn()
58 |> get("/api/v1/timelines/public", %{"local" => "True"})
59
60 assert [%{"content" => "test"}] = json_response(conn, 200)
61
62 conn =
63 build_conn()
64 |> get("/api/v1/timelines/public", %{"local" => "1"})
65
66 assert [%{"content" => "test"}] = json_response(conn, 200)
67 end)
68 end
69
70 test "posting a status", %{conn: conn} do
71 user = insert(:user)
72
73 idempotency_key = "Pikachu rocks!"
74
75 conn_one =
76 conn
77 |> assign(:user, user)
78 |> put_req_header("idempotency-key", idempotency_key)
79 |> post("/api/v1/statuses", %{
80 "status" => "cofe",
81 "spoiler_text" => "2hu",
82 "sensitive" => "false"
83 })
84
85 {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
86 # Six hours
87 assert ttl > :timer.seconds(6 * 60 * 60 - 1)
88
89 assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
90 json_response(conn_one, 200)
91
92 assert Repo.get(Activity, id)
93
94 conn_two =
95 conn
96 |> assign(:user, user)
97 |> put_req_header("idempotency-key", idempotency_key)
98 |> post("/api/v1/statuses", %{
99 "status" => "cofe",
100 "spoiler_text" => "2hu",
101 "sensitive" => "false"
102 })
103
104 assert %{"id" => second_id} = json_response(conn_two, 200)
105
106 assert id == second_id
107
108 conn_three =
109 conn
110 |> assign(:user, user)
111 |> post("/api/v1/statuses", %{
112 "status" => "cofe",
113 "spoiler_text" => "2hu",
114 "sensitive" => "false"
115 })
116
117 assert %{"id" => third_id} = json_response(conn_three, 200)
118
119 refute id == third_id
120 end
121
122 test "posting a sensitive status", %{conn: conn} do
123 user = insert(:user)
124
125 conn =
126 conn
127 |> assign(:user, user)
128 |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true})
129
130 assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200)
131 assert Repo.get(Activity, id)
132 end
133
134 test "posting a direct status", %{conn: conn} do
135 user1 = insert(:user)
136 user2 = insert(:user)
137 content = "direct cofe @#{user2.nickname}"
138
139 conn =
140 conn
141 |> assign(:user, user1)
142 |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"})
143
144 assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200)
145 assert activity = Repo.get(Activity, id)
146 assert activity.recipients == [user2.ap_id]
147 assert activity.data["to"] == [user2.ap_id]
148 assert activity.data["cc"] == []
149 end
150
151 test "direct timeline", %{conn: conn} do
152 user_one = insert(:user)
153 user_two = insert(:user)
154
155 {:ok, user_two} = User.follow(user_two, user_one)
156
157 {:ok, direct} =
158 CommonAPI.post(user_one, %{
159 "status" => "Hi @#{user_two.nickname}!",
160 "visibility" => "direct"
161 })
162
163 {:ok, _follower_only} =
164 CommonAPI.post(user_one, %{
165 "status" => "Hi @#{user_two.nickname}!",
166 "visibility" => "private"
167 })
168
169 # Only direct should be visible here
170 res_conn =
171 conn
172 |> assign(:user, user_two)
173 |> get("api/v1/timelines/direct")
174
175 [status] = json_response(res_conn, 200)
176
177 assert %{"visibility" => "direct"} = status
178 assert status["url"] != direct.data["id"]
179
180 # Both should be visible here
181 res_conn =
182 conn
183 |> assign(:user, user_two)
184 |> get("api/v1/timelines/home")
185
186 [_s1, _s2] = json_response(res_conn, 200)
187
188 # Test pagination
189 Enum.each(1..20, fn _ ->
190 {:ok, _} =
191 CommonAPI.post(user_one, %{
192 "status" => "Hi @#{user_two.nickname}!",
193 "visibility" => "direct"
194 })
195 end)
196
197 res_conn =
198 conn
199 |> assign(:user, user_two)
200 |> get("api/v1/timelines/direct")
201
202 statuses = json_response(res_conn, 200)
203 assert length(statuses) == 20
204
205 res_conn =
206 conn
207 |> assign(:user, user_two)
208 |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
209
210 [status] = json_response(res_conn, 200)
211
212 assert status["url"] != direct.data["id"]
213 end
214
215 test "replying to a status", %{conn: conn} do
216 user = insert(:user)
217
218 {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
219
220 conn =
221 conn
222 |> assign(:user, user)
223 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
224
225 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
226
227 activity = Repo.get(Activity, id)
228
229 assert activity.data["context"] == replied_to.data["context"]
230 assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
231 end
232
233 test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
234 user = insert(:user)
235
236 conn =
237 conn
238 |> assign(:user, user)
239 |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
240
241 assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
242
243 activity = Repo.get(Activity, id)
244
245 assert activity
246 end
247
248 test "verify_credentials", %{conn: conn} do
249 user = insert(:user)
250
251 conn =
252 conn
253 |> assign(:user, user)
254 |> get("/api/v1/accounts/verify_credentials")
255
256 assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
257 assert id == to_string(user.id)
258 end
259
260 test "verify_credentials default scope unlisted", %{conn: conn} do
261 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
262
263 conn =
264 conn
265 |> assign(:user, user)
266 |> get("/api/v1/accounts/verify_credentials")
267
268 assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
269 assert id == to_string(user.id)
270 end
271
272 test "get a status", %{conn: conn} do
273 activity = insert(:note_activity)
274
275 conn =
276 conn
277 |> get("/api/v1/statuses/#{activity.id}")
278
279 assert %{"id" => id} = json_response(conn, 200)
280 assert id == to_string(activity.id)
281 end
282
283 describe "deleting a status" do
284 test "when you created it", %{conn: conn} do
285 activity = insert(:note_activity)
286 author = User.get_by_ap_id(activity.data["actor"])
287
288 conn =
289 conn
290 |> assign(:user, author)
291 |> delete("/api/v1/statuses/#{activity.id}")
292
293 assert %{} = json_response(conn, 200)
294
295 assert Repo.get(Activity, activity.id) == nil
296 end
297
298 test "when you didn't create it", %{conn: conn} do
299 activity = insert(:note_activity)
300 user = insert(:user)
301
302 conn =
303 conn
304 |> assign(:user, user)
305 |> delete("/api/v1/statuses/#{activity.id}")
306
307 assert %{"error" => _} = json_response(conn, 403)
308
309 assert Repo.get(Activity, activity.id) == activity
310 end
311 end
312
313 describe "filters" do
314 test "creating a filter", %{conn: conn} do
315 user = insert(:user)
316
317 filter = %Pleroma.Filter{
318 phrase: "knights",
319 context: ["home"]
320 }
321
322 conn =
323 conn
324 |> assign(:user, user)
325 |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
326
327 assert response = json_response(conn, 200)
328 assert response["phrase"] == filter.phrase
329 assert response["context"] == filter.context
330 assert response["id"] != nil
331 assert response["id"] != ""
332 end
333
334 test "fetching a list of filters", %{conn: conn} do
335 user = insert(:user)
336
337 query_one = %Pleroma.Filter{
338 user_id: user.id,
339 filter_id: 1,
340 phrase: "knights",
341 context: ["home"]
342 }
343
344 query_two = %Pleroma.Filter{
345 user_id: user.id,
346 filter_id: 2,
347 phrase: "who",
348 context: ["home"]
349 }
350
351 {:ok, filter_one} = Pleroma.Filter.create(query_one)
352 {:ok, filter_two} = Pleroma.Filter.create(query_two)
353
354 conn =
355 conn
356 |> assign(:user, user)
357 |> get("/api/v1/filters")
358
359 assert response = json_response(conn, 200)
360 end
361
362 test "get a filter", %{conn: conn} do
363 user = insert(:user)
364
365 query = %Pleroma.Filter{
366 user_id: user.id,
367 filter_id: 2,
368 phrase: "knight",
369 context: ["home"]
370 }
371
372 {:ok, filter} = Pleroma.Filter.create(query)
373
374 conn =
375 conn
376 |> assign(:user, user)
377 |> get("/api/v1/filters/#{filter.filter_id}")
378
379 assert response = json_response(conn, 200)
380 end
381
382 test "update a filter", %{conn: conn} do
383 user = insert(:user)
384
385 query = %Pleroma.Filter{
386 user_id: user.id,
387 filter_id: 2,
388 phrase: "knight",
389 context: ["home"]
390 }
391
392 {:ok, filter} = Pleroma.Filter.create(query)
393
394 new = %Pleroma.Filter{
395 phrase: "nii",
396 context: ["home"]
397 }
398
399 conn =
400 conn
401 |> assign(:user, user)
402 |> put("/api/v1/filters/#{query.filter_id}", %{
403 phrase: new.phrase,
404 context: new.context
405 })
406
407 assert response = json_response(conn, 200)
408 assert response["phrase"] == new.phrase
409 assert response["context"] == new.context
410 end
411
412 test "delete a filter", %{conn: conn} do
413 user = insert(:user)
414
415 query = %Pleroma.Filter{
416 user_id: user.id,
417 filter_id: 2,
418 phrase: "knight",
419 context: ["home"]
420 }
421
422 {:ok, filter} = Pleroma.Filter.create(query)
423
424 conn =
425 conn
426 |> assign(:user, user)
427 |> delete("/api/v1/filters/#{filter.filter_id}")
428
429 assert response = json_response(conn, 200)
430 assert response == %{}
431 end
432 end
433
434 describe "lists" do
435 test "creating a list", %{conn: conn} do
436 user = insert(:user)
437
438 conn =
439 conn
440 |> assign(:user, user)
441 |> post("/api/v1/lists", %{"title" => "cuties"})
442
443 assert %{"title" => title} = json_response(conn, 200)
444 assert title == "cuties"
445 end
446
447 test "adding users to a list", %{conn: conn} do
448 user = insert(:user)
449 other_user = insert(:user)
450 {:ok, list} = Pleroma.List.create("name", user)
451
452 conn =
453 conn
454 |> assign(:user, user)
455 |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
456
457 assert %{} == json_response(conn, 200)
458 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
459 assert following == [other_user.follower_address]
460 end
461
462 test "removing users from a list", %{conn: conn} do
463 user = insert(:user)
464 other_user = insert(:user)
465 third_user = insert(:user)
466 {:ok, list} = Pleroma.List.create("name", user)
467 {:ok, list} = Pleroma.List.follow(list, other_user)
468 {:ok, list} = Pleroma.List.follow(list, third_user)
469
470 conn =
471 conn
472 |> assign(:user, user)
473 |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
474
475 assert %{} == json_response(conn, 200)
476 %Pleroma.List{following: following} = Pleroma.List.get(list.id, user)
477 assert following == [third_user.follower_address]
478 end
479
480 test "listing users in a list", %{conn: conn} do
481 user = insert(:user)
482 other_user = insert(:user)
483 {:ok, list} = Pleroma.List.create("name", user)
484 {:ok, list} = Pleroma.List.follow(list, other_user)
485
486 conn =
487 conn
488 |> assign(:user, user)
489 |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]})
490
491 assert [%{"id" => id}] = json_response(conn, 200)
492 assert id == to_string(other_user.id)
493 end
494
495 test "retrieving a list", %{conn: conn} do
496 user = insert(:user)
497 {:ok, list} = Pleroma.List.create("name", user)
498
499 conn =
500 conn
501 |> assign(:user, user)
502 |> get("/api/v1/lists/#{list.id}")
503
504 assert %{"id" => id} = json_response(conn, 200)
505 assert id == to_string(list.id)
506 end
507
508 test "renaming a list", %{conn: conn} do
509 user = insert(:user)
510 {:ok, list} = Pleroma.List.create("name", user)
511
512 conn =
513 conn
514 |> assign(:user, user)
515 |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"})
516
517 assert %{"title" => name} = json_response(conn, 200)
518 assert name == "newname"
519 end
520
521 test "deleting a list", %{conn: conn} do
522 user = insert(:user)
523 {:ok, list} = Pleroma.List.create("name", user)
524
525 conn =
526 conn
527 |> assign(:user, user)
528 |> delete("/api/v1/lists/#{list.id}")
529
530 assert %{} = json_response(conn, 200)
531 assert is_nil(Repo.get(Pleroma.List, list.id))
532 end
533
534 test "list timeline", %{conn: conn} do
535 user = insert(:user)
536 other_user = insert(:user)
537 {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."})
538 {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
539 {:ok, list} = Pleroma.List.create("name", user)
540 {:ok, list} = Pleroma.List.follow(list, other_user)
541
542 conn =
543 conn
544 |> assign(:user, user)
545 |> get("/api/v1/timelines/list/#{list.id}")
546
547 assert [%{"id" => id}] = json_response(conn, 200)
548
549 assert id == to_string(activity_two.id)
550 end
551
552 test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
553 user = insert(:user)
554 other_user = insert(:user)
555 {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
556
557 {:ok, activity_two} =
558 TwitterAPI.create_status(other_user, %{
559 "status" => "Marisa is cute.",
560 "visibility" => "private"
561 })
562
563 {:ok, list} = Pleroma.List.create("name", user)
564 {:ok, list} = Pleroma.List.follow(list, other_user)
565
566 conn =
567 conn
568 |> assign(:user, user)
569 |> get("/api/v1/timelines/list/#{list.id}")
570
571 assert [%{"id" => id}] = json_response(conn, 200)
572
573 assert id == to_string(activity_one.id)
574 end
575 end
576
577 describe "notifications" do
578 test "list of notifications", %{conn: conn} do
579 user = insert(:user)
580 other_user = insert(:user)
581
582 {:ok, activity} =
583 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
584
585 {:ok, [_notification]} = Notification.create_notifications(activity)
586
587 conn =
588 conn
589 |> assign(:user, user)
590 |> get("/api/v1/notifications")
591
592 expected_response =
593 "hi <span><a data-user=\"#{user.id}\" href=\"#{user.ap_id}\">@<span>#{user.nickname}</span></a></span>"
594
595 assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
596 assert response == expected_response
597 end
598
599 test "getting a single notification", %{conn: conn} do
600 user = insert(:user)
601 other_user = insert(:user)
602
603 {:ok, activity} =
604 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
605
606 {:ok, [notification]} = Notification.create_notifications(activity)
607
608 conn =
609 conn
610 |> assign(:user, user)
611 |> get("/api/v1/notifications/#{notification.id}")
612
613 expected_response =
614 "hi <span><a data-user=\"#{user.id}\" href=\"#{user.ap_id}\">@<span>#{user.nickname}</span></a></span>"
615
616 assert %{"status" => %{"content" => response}} = json_response(conn, 200)
617 assert response == expected_response
618 end
619
620 test "dismissing a single notification", %{conn: conn} do
621 user = insert(:user)
622 other_user = insert(:user)
623
624 {:ok, activity} =
625 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
626
627 {:ok, [notification]} = Notification.create_notifications(activity)
628
629 conn =
630 conn
631 |> assign(:user, user)
632 |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
633
634 assert %{} = json_response(conn, 200)
635 end
636
637 test "clearing all notifications", %{conn: conn} do
638 user = insert(:user)
639 other_user = insert(:user)
640
641 {:ok, activity} =
642 TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"})
643
644 {:ok, [_notification]} = Notification.create_notifications(activity)
645
646 conn =
647 conn
648 |> assign(:user, user)
649 |> post("/api/v1/notifications/clear")
650
651 assert %{} = json_response(conn, 200)
652
653 conn =
654 build_conn()
655 |> assign(:user, user)
656 |> get("/api/v1/notifications")
657
658 assert all = json_response(conn, 200)
659 assert all == []
660 end
661 end
662
663 describe "reblogging" do
664 test "reblogs and returns the reblogged status", %{conn: conn} do
665 activity = insert(:note_activity)
666 user = insert(:user)
667
668 conn =
669 conn
670 |> assign(:user, user)
671 |> post("/api/v1/statuses/#{activity.id}/reblog")
672
673 assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
674 json_response(conn, 200)
675
676 assert to_string(activity.id) == id
677 end
678 end
679
680 describe "unreblogging" do
681 test "unreblogs and returns the unreblogged status", %{conn: conn} do
682 activity = insert(:note_activity)
683 user = insert(:user)
684
685 {:ok, _, _} = CommonAPI.repeat(activity.id, user)
686
687 conn =
688 conn
689 |> assign(:user, user)
690 |> post("/api/v1/statuses/#{activity.id}/unreblog")
691
692 assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
693
694 assert to_string(activity.id) == id
695 end
696 end
697
698 describe "favoriting" do
699 test "favs a status and returns it", %{conn: conn} do
700 activity = insert(:note_activity)
701 user = insert(:user)
702
703 conn =
704 conn
705 |> assign(:user, user)
706 |> post("/api/v1/statuses/#{activity.id}/favourite")
707
708 assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
709 json_response(conn, 200)
710
711 assert to_string(activity.id) == id
712 end
713
714 test "returns 500 for a wrong id", %{conn: conn} do
715 user = insert(:user)
716
717 resp =
718 conn
719 |> assign(:user, user)
720 |> post("/api/v1/statuses/1/favourite")
721 |> json_response(500)
722
723 assert resp == "Something went wrong"
724 end
725 end
726
727 describe "unfavoriting" do
728 test "unfavorites a status and returns it", %{conn: conn} do
729 activity = insert(:note_activity)
730 user = insert(:user)
731
732 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
733
734 conn =
735 conn
736 |> assign(:user, user)
737 |> post("/api/v1/statuses/#{activity.id}/unfavourite")
738
739 assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
740 json_response(conn, 200)
741
742 assert to_string(activity.id) == id
743 end
744 end
745
746 describe "user timelines" do
747 test "gets a users statuses", %{conn: conn} do
748 user_one = insert(:user)
749 user_two = insert(:user)
750 user_three = insert(:user)
751
752 {:ok, user_three} = User.follow(user_three, user_one)
753
754 {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
755
756 {:ok, direct_activity} =
757 CommonAPI.post(user_one, %{
758 "status" => "Hi, @#{user_two.nickname}.",
759 "visibility" => "direct"
760 })
761
762 {:ok, private_activity} =
763 CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
764
765 resp =
766 conn
767 |> get("/api/v1/accounts/#{user_one.id}/statuses")
768
769 assert [%{"id" => id}] = json_response(resp, 200)
770 assert id == to_string(activity.id)
771
772 resp =
773 conn
774 |> assign(:user, user_two)
775 |> get("/api/v1/accounts/#{user_one.id}/statuses")
776
777 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
778 assert id_one == to_string(direct_activity.id)
779 assert id_two == to_string(activity.id)
780
781 resp =
782 conn
783 |> assign(:user, user_three)
784 |> get("/api/v1/accounts/#{user_one.id}/statuses")
785
786 assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
787 assert id_one == to_string(private_activity.id)
788 assert id_two == to_string(activity.id)
789 end
790
791 test "unimplemented pinned statuses feature", %{conn: conn} do
792 note = insert(:note_activity)
793 user = User.get_by_ap_id(note.data["actor"])
794
795 conn =
796 conn
797 |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
798
799 assert json_response(conn, 200) == []
800 end
801
802 test "gets an users media", %{conn: conn} do
803 note = insert(:note_activity)
804 user = User.get_by_ap_id(note.data["actor"])
805
806 file = %Plug.Upload{
807 content_type: "image/jpg",
808 path: Path.absname("test/fixtures/image.jpg"),
809 filename: "an_image.jpg"
810 }
811
812 media =
813 TwitterAPI.upload(file, user, "json")
814 |> Poison.decode!()
815
816 {:ok, image_post} =
817 TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]})
818
819 conn =
820 conn
821 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
822
823 assert [%{"id" => id}] = json_response(conn, 200)
824 assert id == to_string(image_post.id)
825
826 conn =
827 build_conn()
828 |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
829
830 assert [%{"id" => id}] = json_response(conn, 200)
831 assert id == to_string(image_post.id)
832 end
833 end
834
835 describe "user relationships" do
836 test "returns the relationships for the current user", %{conn: conn} do
837 user = insert(:user)
838 other_user = insert(:user)
839 {:ok, user} = User.follow(user, other_user)
840
841 conn =
842 conn
843 |> assign(:user, user)
844 |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
845
846 assert [relationship] = json_response(conn, 200)
847
848 assert to_string(other_user.id) == relationship["id"]
849 end
850 end
851
852 describe "locked accounts" do
853 test "/api/v1/follow_requests works" do
854 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
855 other_user = insert(:user)
856
857 {:ok, activity} = ActivityPub.follow(other_user, user)
858
859 user = Repo.get(User, user.id)
860 other_user = Repo.get(User, other_user.id)
861
862 assert User.following?(other_user, user) == false
863
864 conn =
865 build_conn()
866 |> assign(:user, user)
867 |> get("/api/v1/follow_requests")
868
869 assert [relationship] = json_response(conn, 200)
870 assert to_string(other_user.id) == relationship["id"]
871 end
872
873 test "/api/v1/follow_requests/:id/authorize works" do
874 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
875 other_user = insert(:user)
876
877 {:ok, activity} = ActivityPub.follow(other_user, user)
878
879 user = Repo.get(User, user.id)
880 other_user = Repo.get(User, other_user.id)
881
882 assert User.following?(other_user, user) == false
883
884 conn =
885 build_conn()
886 |> assign(:user, user)
887 |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
888
889 assert relationship = json_response(conn, 200)
890 assert to_string(other_user.id) == relationship["id"]
891
892 user = Repo.get(User, user.id)
893 other_user = Repo.get(User, other_user.id)
894
895 assert User.following?(other_user, user) == true
896 end
897
898 test "verify_credentials", %{conn: conn} do
899 user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
900
901 conn =
902 conn
903 |> assign(:user, user)
904 |> get("/api/v1/accounts/verify_credentials")
905
906 assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
907 assert id == to_string(user.id)
908 end
909
910 test "/api/v1/follow_requests/:id/reject works" do
911 user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
912 other_user = insert(:user)
913
914 {:ok, activity} = ActivityPub.follow(other_user, user)
915
916 conn =
917 build_conn()
918 |> assign(:user, user)
919 |> post("/api/v1/follow_requests/#{other_user.id}/reject")
920
921 assert relationship = json_response(conn, 200)
922 assert to_string(other_user.id) == relationship["id"]
923
924 user = Repo.get(User, user.id)
925 other_user = Repo.get(User, other_user.id)
926
927 assert User.following?(other_user, user) == false
928 end
929 end
930
931 test "account fetching", %{conn: conn} do
932 user = insert(:user)
933
934 conn =
935 conn
936 |> get("/api/v1/accounts/#{user.id}")
937
938 assert %{"id" => id} = json_response(conn, 200)
939 assert id == to_string(user.id)
940
941 conn =
942 build_conn()
943 |> get("/api/v1/accounts/-1")
944
945 assert %{"error" => "Can't find user"} = json_response(conn, 404)
946 end
947
948 test "media upload", %{conn: conn} do
949 file = %Plug.Upload{
950 content_type: "image/jpg",
951 path: Path.absname("test/fixtures/image.jpg"),
952 filename: "an_image.jpg"
953 }
954
955 desc = "Description of the image"
956
957 user = insert(:user)
958
959 conn =
960 conn
961 |> assign(:user, user)
962 |> post("/api/v1/media", %{"file" => file, "description" => desc})
963
964 assert media = json_response(conn, 200)
965
966 assert media["type"] == "image"
967 assert media["description"] == desc
968 assert media["id"]
969
970 object = Repo.get(Object, media["id"])
971 assert object.data["actor"] == User.ap_id(user)
972 end
973
974 test "hashtag timeline", %{conn: conn} do
975 following = insert(:user)
976
977 capture_log(fn ->
978 {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"})
979
980 {:ok, [_activity]} =
981 OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
982
983 nconn =
984 conn
985 |> get("/api/v1/timelines/tag/2hu")
986
987 assert [%{"id" => id}] = json_response(nconn, 200)
988
989 assert id == to_string(activity.id)
990
991 # works for different capitalization too
992 nconn =
993 conn
994 |> get("/api/v1/timelines/tag/2HU")
995
996 assert [%{"id" => id}] = json_response(nconn, 200)
997
998 assert id == to_string(activity.id)
999 end)
1000 end
1001
1002 test "getting followers", %{conn: conn} do
1003 user = insert(:user)
1004 other_user = insert(:user)
1005 {:ok, user} = User.follow(user, other_user)
1006
1007 conn =
1008 conn
1009 |> get("/api/v1/accounts/#{other_user.id}/followers")
1010
1011 assert [%{"id" => id}] = json_response(conn, 200)
1012 assert id == to_string(user.id)
1013 end
1014
1015 test "getting followers, hide_network", %{conn: conn} do
1016 user = insert(:user)
1017 other_user = insert(:user, %{info: %{hide_network: true}})
1018 {:ok, user} = User.follow(user, other_user)
1019
1020 conn =
1021 conn
1022 |> get("/api/v1/accounts/#{other_user.id}/followers")
1023
1024 assert [] == json_response(conn, 200)
1025 end
1026
1027 test "getting followers, hide_network, same user requesting", %{conn: conn} do
1028 user = insert(:user)
1029 other_user = insert(:user, %{info: %{hide_network: true}})
1030 {:ok, user} = User.follow(user, other_user)
1031
1032 conn =
1033 conn
1034 |> assign(:user, other_user)
1035 |> get("/api/v1/accounts/#{other_user.id}/followers")
1036
1037 refute [] == json_response(conn, 200)
1038 end
1039
1040 test "getting following", %{conn: conn} do
1041 user = insert(:user)
1042 other_user = insert(:user)
1043 {:ok, user} = User.follow(user, other_user)
1044
1045 conn =
1046 conn
1047 |> get("/api/v1/accounts/#{user.id}/following")
1048
1049 assert [%{"id" => id}] = json_response(conn, 200)
1050 assert id == to_string(other_user.id)
1051 end
1052
1053 test "getting following, hide_network", %{conn: conn} do
1054 user = insert(:user, %{info: %{hide_network: true}})
1055 other_user = insert(:user)
1056 {:ok, user} = User.follow(user, other_user)
1057
1058 conn =
1059 conn
1060 |> get("/api/v1/accounts/#{user.id}/following")
1061
1062 assert [] == json_response(conn, 200)
1063 end
1064
1065 test "getting following, hide_network, same user requesting", %{conn: conn} do
1066 user = insert(:user, %{info: %{hide_network: true}})
1067 other_user = insert(:user)
1068 {:ok, user} = User.follow(user, other_user)
1069
1070 conn =
1071 conn
1072 |> assign(:user, user)
1073 |> get("/api/v1/accounts/#{user.id}/following")
1074
1075 refute [] == json_response(conn, 200)
1076 end
1077
1078 test "following / unfollowing a user", %{conn: conn} do
1079 user = insert(:user)
1080 other_user = insert(:user)
1081
1082 conn =
1083 conn
1084 |> assign(:user, user)
1085 |> post("/api/v1/accounts/#{other_user.id}/follow")
1086
1087 assert %{"id" => _id, "following" => true} = json_response(conn, 200)
1088
1089 user = Repo.get(User, user.id)
1090
1091 conn =
1092 build_conn()
1093 |> assign(:user, user)
1094 |> post("/api/v1/accounts/#{other_user.id}/unfollow")
1095
1096 assert %{"id" => _id, "following" => false} = json_response(conn, 200)
1097
1098 user = Repo.get(User, user.id)
1099
1100 conn =
1101 build_conn()
1102 |> assign(:user, user)
1103 |> post("/api/v1/follows", %{"uri" => other_user.nickname})
1104
1105 assert %{"id" => id} = json_response(conn, 200)
1106 assert id == to_string(other_user.id)
1107 end
1108
1109 test "blocking / unblocking a user", %{conn: conn} do
1110 user = insert(:user)
1111 other_user = insert(:user)
1112
1113 conn =
1114 conn
1115 |> assign(:user, user)
1116 |> post("/api/v1/accounts/#{other_user.id}/block")
1117
1118 assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
1119
1120 user = Repo.get(User, user.id)
1121
1122 conn =
1123 build_conn()
1124 |> assign(:user, user)
1125 |> post("/api/v1/accounts/#{other_user.id}/unblock")
1126
1127 assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
1128 end
1129
1130 test "getting a list of blocks", %{conn: conn} do
1131 user = insert(:user)
1132 other_user = insert(:user)
1133
1134 {:ok, user} = User.block(user, other_user)
1135
1136 conn =
1137 conn
1138 |> assign(:user, user)
1139 |> get("/api/v1/blocks")
1140
1141 other_user_id = to_string(other_user.id)
1142 assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
1143 end
1144
1145 test "blocking / unblocking a domain", %{conn: conn} do
1146 user = insert(:user)
1147 other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
1148
1149 conn =
1150 conn
1151 |> assign(:user, user)
1152 |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1153
1154 assert %{} = json_response(conn, 200)
1155 user = User.get_cached_by_ap_id(user.ap_id)
1156 assert User.blocks?(user, other_user)
1157
1158 conn =
1159 build_conn()
1160 |> assign(:user, user)
1161 |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
1162
1163 assert %{} = json_response(conn, 200)
1164 user = User.get_cached_by_ap_id(user.ap_id)
1165 refute User.blocks?(user, other_user)
1166 end
1167
1168 test "getting a list of domain blocks", %{conn: conn} do
1169 user = insert(:user)
1170
1171 {:ok, user} = User.block_domain(user, "bad.site")
1172 {:ok, user} = User.block_domain(user, "even.worse.site")
1173
1174 conn =
1175 conn
1176 |> assign(:user, user)
1177 |> get("/api/v1/domain_blocks")
1178
1179 domain_blocks = json_response(conn, 200)
1180
1181 assert "bad.site" in domain_blocks
1182 assert "even.worse.site" in domain_blocks
1183 end
1184
1185 test "unimplemented mute endpoints" do
1186 user = insert(:user)
1187 other_user = insert(:user)
1188
1189 ["mute", "unmute"]
1190 |> Enum.each(fn endpoint ->
1191 conn =
1192 build_conn()
1193 |> assign(:user, user)
1194 |> post("/api/v1/accounts/#{other_user.id}/#{endpoint}")
1195
1196 assert %{"id" => id} = json_response(conn, 200)
1197 assert id == to_string(other_user.id)
1198 end)
1199 end
1200
1201 test "unimplemented mutes, follow_requests, blocks, domain blocks" do
1202 user = insert(:user)
1203
1204 ["blocks", "domain_blocks", "mutes", "follow_requests"]
1205 |> Enum.each(fn endpoint ->
1206 conn =
1207 build_conn()
1208 |> assign(:user, user)
1209 |> get("/api/v1/#{endpoint}")
1210
1211 assert [] = json_response(conn, 200)
1212 end)
1213 end
1214
1215 test "account search", %{conn: conn} do
1216 user = insert(:user)
1217 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1218 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1219
1220 results =
1221 conn
1222 |> assign(:user, user)
1223 |> get("/api/v1/accounts/search", %{"q" => "shp"})
1224 |> json_response(200)
1225
1226 result_ids = for result <- results, do: result["acct"]
1227
1228 assert user_two.nickname in result_ids
1229 assert user_three.nickname in result_ids
1230
1231 results =
1232 conn
1233 |> assign(:user, user)
1234 |> get("/api/v1/accounts/search", %{"q" => "2hu"})
1235 |> json_response(200)
1236
1237 result_ids = for result <- results, do: result["acct"]
1238
1239 assert user_three.nickname in result_ids
1240 end
1241
1242 test "search", %{conn: conn} do
1243 user = insert(:user)
1244 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1245 user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
1246
1247 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1248
1249 {:ok, _activity} =
1250 CommonAPI.post(user, %{
1251 "status" => "This is about 2hu, but private",
1252 "visibility" => "private"
1253 })
1254
1255 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1256
1257 conn =
1258 conn
1259 |> get("/api/v1/search", %{"q" => "2hu"})
1260
1261 assert results = json_response(conn, 200)
1262
1263 [account | _] = results["accounts"]
1264 assert account["id"] == to_string(user_three.id)
1265
1266 assert results["hashtags"] == []
1267
1268 [status] = results["statuses"]
1269 assert status["id"] == to_string(activity.id)
1270 end
1271
1272 test "search fetches remote statuses", %{conn: conn} do
1273 capture_log(fn ->
1274 conn =
1275 conn
1276 |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
1277
1278 assert results = json_response(conn, 200)
1279
1280 [status] = results["statuses"]
1281 assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
1282 end)
1283 end
1284
1285 test "search fetches remote accounts", %{conn: conn} do
1286 conn =
1287 conn
1288 |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
1289
1290 assert results = json_response(conn, 200)
1291 [account] = results["accounts"]
1292 assert account["acct"] == "shp@social.heldscal.la"
1293 end
1294
1295 test "returns the favorites of a user", %{conn: conn} do
1296 user = insert(:user)
1297 other_user = insert(:user)
1298
1299 {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
1300 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
1301
1302 {:ok, _, _} = CommonAPI.favorite(activity.id, user)
1303
1304 conn =
1305 conn
1306 |> assign(:user, user)
1307 |> get("/api/v1/favourites")
1308
1309 assert [status] = json_response(conn, 200)
1310 assert status["id"] == to_string(activity.id)
1311 end
1312
1313 describe "updating credentials" do
1314 test "updates the user's bio", %{conn: conn} do
1315 user = insert(:user)
1316 user2 = insert(:user)
1317
1318 conn =
1319 conn
1320 |> assign(:user, user)
1321 |> patch("/api/v1/accounts/update_credentials", %{
1322 "note" => "I drink #cofe with @#{user2.nickname}"
1323 })
1324
1325 assert user = json_response(conn, 200)
1326
1327 assert user["note"] ==
1328 "I drink <a data-tag=\"cofe\" href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span><a data-user=\"#{
1329 user2.id
1330 }\" href=\"#{user2.ap_id}\">@<span>#{user2.nickname}</span></a></span>"
1331 end
1332
1333 test "updates the user's locking status", %{conn: conn} do
1334 user = insert(:user)
1335
1336 conn =
1337 conn
1338 |> assign(:user, user)
1339 |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
1340
1341 assert user = json_response(conn, 200)
1342 assert user["locked"] == true
1343 end
1344
1345 test "updates the user's name", %{conn: conn} do
1346 user = insert(:user)
1347
1348 conn =
1349 conn
1350 |> assign(:user, user)
1351 |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
1352
1353 assert user = json_response(conn, 200)
1354 assert user["display_name"] == "markorepairs"
1355 end
1356
1357 test "updates the user's avatar", %{conn: conn} do
1358 user = insert(:user)
1359
1360 new_avatar = %Plug.Upload{
1361 content_type: "image/jpg",
1362 path: Path.absname("test/fixtures/image.jpg"),
1363 filename: "an_image.jpg"
1364 }
1365
1366 conn =
1367 conn
1368 |> assign(:user, user)
1369 |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
1370
1371 assert user_response = json_response(conn, 200)
1372 assert user_response["avatar"] != User.avatar_url(user)
1373 end
1374
1375 test "updates the user's banner", %{conn: conn} do
1376 user = insert(:user)
1377
1378 new_header = %Plug.Upload{
1379 content_type: "image/jpg",
1380 path: Path.absname("test/fixtures/image.jpg"),
1381 filename: "an_image.jpg"
1382 }
1383
1384 conn =
1385 conn
1386 |> assign(:user, user)
1387 |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
1388
1389 assert user_response = json_response(conn, 200)
1390 assert user_response["header"] != User.banner_url(user)
1391 end
1392 end
1393
1394 test "get instance information", %{conn: conn} do
1395 insert(:user, %{local: true})
1396 user = insert(:user, %{local: true})
1397 insert(:user, %{local: false})
1398
1399 {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
1400
1401 Pleroma.Stats.update_stats()
1402
1403 conn =
1404 conn
1405 |> get("/api/v1/instance")
1406
1407 assert result = json_response(conn, 200)
1408
1409 assert result["stats"]["user_count"] == 2
1410 assert result["stats"]["status_count"] == 1
1411 end
1412 end