Merge branch 'develop' into feature/activitypub
[akkoma] / test / web / twitter_api / twitter_api_controller_test.exs
1 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
2 use Pleroma.Web.ConnCase
3 alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
4 alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
5 alias Pleroma.{Repo, Activity, User, Object}
6 alias Pleroma.Web.ActivityPub.ActivityPub
7 alias Pleroma.Web.TwitterAPI.UserView
8 alias Pleroma.Web.CommonAPI
9 alias Pleroma.Web.TwitterAPI.TwitterAPI
10
11 import Pleroma.Factory
12
13 describe "POST /api/account/verify_credentials" do
14 setup [:valid_user]
15 test "without valid credentials", %{conn: conn} do
16 conn = post conn, "/api/account/verify_credentials.json"
17 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
18 end
19
20 test "with credentials", %{conn: conn, user: user} do
21 conn = conn
22 |> with_credentials(user.nickname, "test")
23 |> post("/api/account/verify_credentials.json")
24
25 assert response = json_response(conn, 200)
26 assert response == UserView.render("show.json", %{user: user, token: response["token"]})
27 end
28 end
29
30 describe "POST /api/account/most_recent_notification" do
31 setup [:valid_user]
32 test "without valid credentials", %{conn: conn} do
33 conn = post conn, "/api/account/most_recent_notification.json"
34 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
35 end
36
37 test "with credentials", %{conn: conn, user: user} do
38 conn = conn
39 |> with_credentials(user.nickname, "test")
40 |> post("/api/account/most_recent_notification.json", %{id: "200"})
41
42 assert json_response(conn, 200)
43 user = User.get_by_nickname(user.nickname)
44 assert user.info["most_recent_notification"] == 200
45 end
46 end
47
48 describe "POST /statuses/update.json" do
49 setup [:valid_user]
50 test "without valid credentials", %{conn: conn} do
51 conn = post conn, "/api/statuses/update.json"
52 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
53 end
54
55 test "with credentials", %{conn: conn, user: user} do
56 conn_with_creds = conn |> with_credentials(user.nickname, "test")
57 request_path = "/api/statuses/update.json"
58
59 error_response = %{"request" => request_path,
60 "error" => "Client must provide a 'status' parameter with a value."}
61 conn = conn_with_creds |> post(request_path)
62 assert json_response(conn, 400) == error_response
63
64 conn = conn_with_creds |> post(request_path, %{ status: "" })
65 assert json_response(conn, 400) == error_response
66
67 conn = conn_with_creds |> post(request_path, %{ status: " " })
68 assert json_response(conn, 400) == error_response
69
70 conn = conn_with_creds |> post(request_path, %{ status: "Nice meme." })
71 assert json_response(conn, 200) == ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
72 end
73 end
74
75 describe "GET /statuses/public_timeline.json" do
76 test "returns statuses", %{conn: conn} do
77 {:ok, user} = UserBuilder.insert
78 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
79 ActivityBuilder.insert_list(10, %{}, %{user: user})
80 since_id = List.last(activities).id
81
82 conn = conn
83 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
84
85 response = json_response(conn, 200)
86
87 assert length(response) == 10
88 end
89 end
90
91 describe "GET /statuses/show/:id.json" do
92 test "returns one status", %{conn: conn} do
93 {:ok, user} = UserBuilder.insert
94 {:ok, activity} = ActivityBuilder.insert(%{}, %{user: user})
95 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
96
97 conn = conn
98 |> get("/api/statuses/show/#{activity.id}.json")
99
100 response = json_response(conn, 200)
101
102 assert response == ActivityRepresenter.to_map(activity, %{user: actor})
103 end
104 end
105
106 describe "GET /users/show.json" do
107 test "gets user with screen_name", %{conn: conn} do
108 user = insert(:user)
109
110 conn = conn
111 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
112
113 response = json_response(conn, 200)
114
115 assert response["id"] == user.id
116 end
117
118 test "gets user with user_id", %{conn: conn} do
119 user = insert(:user)
120
121 conn = conn
122 |> get("/api/users/show.json", %{"user_id" => user.id})
123
124 response = json_response(conn, 200)
125
126 assert response["id"] == user.id
127 end
128
129 test "gets a user for a logged in user", %{conn: conn} do
130 user = insert(:user)
131 logged_in = insert(:user)
132
133 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
134
135 conn = conn
136 |> with_credentials(logged_in.nickname, "test")
137 |> get("/api/users/show.json", %{"user_id" => user.id})
138
139 response = json_response(conn, 200)
140
141 assert response["following"] == true
142 end
143 end
144
145 describe "GET /statusnet/conversation/:id.json" do
146 test "returns the statuses in the conversation", %{conn: conn} do
147 {:ok, _user} = UserBuilder.insert
148 {:ok, _activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
149 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
150 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
151
152 {:ok, object} = Object.context_mapping("2hu") |> Repo.insert
153 conn = conn
154 |> get("/api/statusnet/conversation/#{object.id}.json")
155
156 response = json_response(conn, 200)
157
158 assert length(response) == 2
159 end
160 end
161
162 describe "GET /statuses/friends_timeline.json" do
163 setup [:valid_user]
164 test "without valid credentials", %{conn: conn} do
165 conn = get conn, "/api/statuses/friends_timeline.json"
166 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
167 end
168
169 test "with credentials", %{conn: conn, user: current_user} do
170 user = insert(:user)
171 activities = ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
172 returned_activities = ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
173 other_user = insert(:user)
174 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
175 since_id = List.last(activities).id
176
177 current_user = Ecto.Changeset.change(current_user, following: [User.ap_followers(user)]) |> Repo.update!
178
179 conn = conn
180 |> with_credentials(current_user.nickname, "test")
181 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
182
183 response = json_response(conn, 200)
184
185 assert length(response) == 10
186 assert response == Enum.map(returned_activities, fn (activity) -> ActivityRepresenter.to_map(activity, %{user: User.get_cached_by_ap_id(activity.data["actor"]), for: current_user}) end)
187 end
188 end
189
190 describe "GET /statuses/mentions.json" do
191 setup [:valid_user]
192 test "without valid credentials", %{conn: conn} do
193 conn = get conn, "/api/statuses/mentions.json"
194 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
195 end
196
197 test "with credentials", %{conn: conn, user: current_user} do
198 {:ok, activity} = ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
199
200 conn = conn
201 |> with_credentials(current_user.nickname, "test")
202 |> get("/api/statuses/mentions.json")
203
204 response = json_response(conn, 200)
205
206 assert length(response) == 1
207 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user, mentioned: [current_user]})
208 end
209 end
210
211 describe "GET /statuses/user_timeline.json" do
212 setup [:valid_user]
213 test "without any params", %{conn: conn} do
214 conn = get(conn, "/api/statuses/user_timeline.json")
215 assert json_response(conn, 400) == %{"error" => "You need to specify screen_name or user_id", "request" => "/api/statuses/user_timeline.json"}
216 end
217
218 test "with user_id", %{conn: conn} do
219 user = insert(:user)
220 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
221
222 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
223 response = json_response(conn, 200)
224 assert length(response) == 1
225 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
226 end
227
228 test "with screen_name", %{conn: conn} do
229 user = insert(:user)
230 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
231
232 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
233 response = json_response(conn, 200)
234 assert length(response) == 1
235 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
236 end
237
238 test "with credentials", %{conn: conn, user: current_user} do
239 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
240 conn = conn
241 |> with_credentials(current_user.nickname, "test")
242 |> get("/api/statuses/user_timeline.json")
243
244 response = json_response(conn, 200)
245
246 assert length(response) == 1
247 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
248 end
249
250 test "with credentials with user_id", %{conn: conn, user: current_user} do
251 user = insert(:user)
252 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
253 conn = conn
254 |> with_credentials(current_user.nickname, "test")
255 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
256
257 response = json_response(conn, 200)
258
259 assert length(response) == 1
260 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
261 end
262
263 test "with credentials screen_name", %{conn: conn, user: current_user} do
264 user = insert(:user)
265 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
266 conn = conn
267 |> with_credentials(current_user.nickname, "test")
268 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
269
270 response = json_response(conn, 200)
271
272 assert length(response) == 1
273 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
274 end
275 end
276
277 describe "POST /friendships/create.json" do
278 setup [:valid_user]
279 test "without valid credentials", %{conn: conn} do
280 conn = post conn, "/api/friendships/create.json"
281 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
282 end
283
284 test "with credentials", %{conn: conn, user: current_user} do
285 followed = insert(:user)
286
287 conn = conn
288 |> with_credentials(current_user.nickname, "test")
289 |> post("/api/friendships/create.json", %{user_id: followed.id})
290
291 current_user = Repo.get(User, current_user.id)
292 assert User.ap_followers(followed) in current_user.following
293 assert json_response(conn, 200) == UserView.render("show.json", %{user: followed, for: current_user})
294 end
295 end
296
297 describe "POST /friendships/destroy.json" do
298 setup [:valid_user]
299 test "without valid credentials", %{conn: conn} do
300 conn = post conn, "/api/friendships/destroy.json"
301 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
302 end
303
304 test "with credentials", %{conn: conn, user: current_user} do
305 followed = insert(:user)
306
307 {:ok, current_user} = User.follow(current_user, followed)
308 assert User.ap_followers(followed) in current_user.following
309 ActivityPub.follow(current_user, followed)
310
311 conn = conn
312 |> with_credentials(current_user.nickname, "test")
313 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
314
315 current_user = Repo.get(User, current_user.id)
316 assert current_user.following == [current_user.ap_id]
317 assert json_response(conn, 200) == UserView.render("show.json", %{user: followed, for: current_user})
318 end
319 end
320
321 describe "POST /blocks/create.json" do
322 setup [:valid_user]
323 test "without valid credentials", %{conn: conn} do
324 conn = post conn, "/api/blocks/create.json"
325 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
326 end
327
328 test "with credentials", %{conn: conn, user: current_user} do
329 blocked = insert(:user)
330
331 conn = conn
332 |> with_credentials(current_user.nickname, "test")
333 |> post("/api/blocks/create.json", %{user_id: blocked.id})
334
335 current_user = Repo.get(User, current_user.id)
336 assert User.blocks?(current_user, blocked)
337 assert json_response(conn, 200) == UserView.render("show.json", %{user: blocked, for: current_user})
338 end
339 end
340
341 describe "POST /blocks/destroy.json" do
342 setup [:valid_user]
343 test "without valid credentials", %{conn: conn} do
344 conn = post conn, "/api/blocks/destroy.json"
345 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
346 end
347
348 test "with credentials", %{conn: conn, user: current_user} do
349 blocked = insert(:user)
350
351 {:ok, current_user} = User.block(current_user, blocked)
352 assert User.blocks?(current_user, blocked)
353
354 conn = conn
355 |> with_credentials(current_user.nickname, "test")
356 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
357
358 current_user = Repo.get(User, current_user.id)
359 assert current_user.info["blocks"] == []
360 assert json_response(conn, 200) == UserView.render("show.json", %{user: blocked, for: current_user})
361 end
362 end
363
364 describe "GET /help/test.json" do
365 test "returns \"ok\"", %{conn: conn} do
366 conn = get conn, "/api/help/test.json"
367 assert json_response(conn, 200) == "ok"
368 end
369 end
370
371 describe "POST /api/qvitter/update_avatar.json" do
372 setup [:valid_user]
373 test "without valid credentials", %{conn: conn} do
374 conn = post conn, "/api/qvitter/update_avatar.json"
375 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
376 end
377
378 test "with credentials", %{conn: conn, user: current_user} do
379 avatar_image = File.read!("test/fixtures/avatar_data_uri")
380 conn = conn
381 |> with_credentials(current_user.nickname, "test")
382 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
383
384 current_user = Repo.get(User, current_user.id)
385 assert is_map(current_user.avatar)
386 assert json_response(conn, 200) == UserView.render("show.json", %{user: current_user, for: current_user})
387 end
388 end
389
390 describe "POST /api/favorites/create/:id" do
391 setup [:valid_user]
392 test "without valid credentials", %{conn: conn} do
393 note_activity = insert(:note_activity)
394 conn = post conn, "/api/favorites/create/#{note_activity.id}.json"
395 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
396 end
397
398 test "with credentials", %{conn: conn, user: current_user} do
399 note_activity = insert(:note_activity)
400
401 conn = conn
402 |> with_credentials(current_user.nickname, "test")
403 |> post("/api/favorites/create/#{note_activity.id}.json")
404
405 assert json_response(conn, 200)
406 end
407 end
408
409 describe "POST /api/favorites/destroy/:id" do
410 setup [:valid_user]
411 test "without valid credentials", %{conn: conn} do
412 note_activity = insert(:note_activity)
413 conn = post conn, "/api/favorites/destroy/#{note_activity.id}.json"
414 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
415 end
416
417 test "with credentials", %{conn: conn, user: current_user} do
418 note_activity = insert(:note_activity)
419 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
420 ActivityPub.like(current_user, object)
421
422 conn = conn
423 |> with_credentials(current_user.nickname, "test")
424 |> post("/api/favorites/destroy/#{note_activity.id}.json")
425
426 assert json_response(conn, 200)
427 end
428 end
429
430 describe "POST /api/statuses/retweet/:id" do
431 setup [:valid_user]
432 test "without valid credentials", %{conn: conn} do
433 note_activity = insert(:note_activity)
434 conn = post conn, "/api/statuses/retweet/#{note_activity.id}.json"
435 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
436 end
437
438 test "with credentials", %{conn: conn, user: current_user} do
439 note_activity = insert(:note_activity)
440
441 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
442
443 response = conn
444 |> with_credentials(current_user.nickname, "test")
445 |> post(request_path)
446 activity = Repo.get(Activity, note_activity.id)
447 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
448 assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
449 end
450 end
451
452 describe "POST /api/account/register" do
453 test "it creates a new user", %{conn: conn} do
454 data = %{
455 "nickname" => "lain",
456 "email" => "lain@wired.jp",
457 "fullname" => "lain iwakura",
458 "bio" => "close the world.",
459 "password" => "bear",
460 "confirm" => "bear"
461 }
462
463 conn = conn
464 |> post("/api/account/register", data)
465
466 user = json_response(conn, 200)
467
468 fetched_user = Repo.get_by(User, nickname: "lain")
469 assert user == UserView.render("show.json", %{user: fetched_user})
470 end
471
472 test "it returns errors on a problem", %{conn: conn} do
473 data = %{
474 "email" => "lain@wired.jp",
475 "fullname" => "lain iwakura",
476 "bio" => "close the world.",
477 "password" => "bear",
478 "confirm" => "bear"
479 }
480
481 conn = conn
482 |> post("/api/account/register", data)
483
484 errors = json_response(conn, 400)
485
486 assert is_binary(errors["error"])
487 end
488 end
489
490 describe "GET /api/externalprofile/show" do
491 test "it returns the user", %{conn: conn} do
492 user = insert(:user)
493 other_user = insert(:user)
494
495 conn = conn
496 |> assign(:user, user)
497 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
498
499 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
500 end
501 end
502
503 describe "GET /api/statuses/followers" do
504 test "it returns a user's followers", %{conn: conn} do
505 user = insert(:user)
506 follower_one = insert(:user)
507 follower_two = insert(:user)
508 _not_follower = insert(:user)
509
510 {:ok, follower_one} = User.follow(follower_one, user)
511 {:ok, follower_two} = User.follow(follower_two, user)
512
513 conn = conn
514 |> assign(:user, user)
515 |> get("/api/statuses/followers")
516
517 assert json_response(conn, 200) == UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
518 end
519 end
520
521 describe "GET /api/statuses/friends" do
522 test "it returns the logged in user's friends", %{conn: conn} do
523 user = insert(:user)
524 followed_one = insert(:user)
525 followed_two = insert(:user)
526 _not_followed = insert(:user)
527
528 {:ok, user} = User.follow(user, followed_one)
529 {:ok, user} = User.follow(user, followed_two)
530
531 conn = conn
532 |> assign(:user, user)
533 |> get("/api/statuses/friends")
534
535 assert MapSet.equal?(MapSet.new(json_response(conn, 200)), MapSet.new(UserView.render("index.json", %{users: [followed_one, followed_two], for: user})))
536 end
537
538 test "it returns a given user's friends with user_id", %{conn: conn} do
539 user = insert(:user)
540 followed_one = insert(:user)
541 followed_two = insert(:user)
542 _not_followed = insert(:user)
543
544 {:ok, user} = User.follow(user, followed_one)
545 {:ok, user} = User.follow(user, followed_two)
546
547 conn = conn
548 |> get("/api/statuses/friends", %{"user_id" => user.id})
549
550 assert MapSet.equal?(MapSet.new(json_response(conn, 200)), MapSet.new(UserView.render("index.json", %{users: [followed_one, followed_two], for: user})))
551 end
552
553 test "it returns a given user's friends with screen_name", %{conn: conn} do
554 user = insert(:user)
555 followed_one = insert(:user)
556 followed_two = insert(:user)
557 _not_followed = insert(:user)
558
559 {:ok, user} = User.follow(user, followed_one)
560 {:ok, user} = User.follow(user, followed_two)
561
562 conn = conn
563 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
564
565 assert MapSet.equal?(MapSet.new(json_response(conn, 200)), MapSet.new(UserView.render("index.json", %{users: [followed_one, followed_two], for: user})))
566 end
567 end
568
569 describe "GET /friends/ids" do
570 test "it returns a user's friends", %{conn: conn} do
571 user = insert(:user)
572 followed_one = insert(:user)
573 followed_two = insert(:user)
574 _not_followed = insert(:user)
575
576 {:ok, user} = User.follow(user, followed_one)
577 {:ok, user} = User.follow(user, followed_two)
578
579 conn = conn
580 |> assign(:user, user)
581 |> get("/api/friends/ids")
582
583 expected = [followed_one.id, followed_two.id]
584 assert MapSet.equal?(MapSet.new(Poison.decode!(json_response(conn, 200))), MapSet.new(expected))
585 end
586 end
587
588 describe "POST /api/account/update_profile.json" do
589 test "it updates a user's profile", %{conn: conn} do
590 user = insert(:user)
591
592 conn = conn
593 |> assign(:user, user)
594 |> post("/api/account/update_profile.json", %{"name" => "new name", "description" => "new description"})
595
596 user = Repo.get!(User, user.id)
597 assert user.name == "new name"
598 assert user.bio == "new description"
599
600 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
601 end
602 end
603
604 defp valid_user(_context) do
605 user = insert(:user)
606 [user: user]
607 end
608
609 defp with_credentials(conn, username, password) do
610 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
611 put_req_header(conn, "authorization", header_content)
612 end
613
614 describe "GET /api/search.json" do
615 test "it returns search results", %{conn: conn} do
616 user = insert(:user)
617 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
618
619 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
620 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
621
622 conn = conn
623 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
624
625 assert [status] = json_response(conn, 200)
626 assert status["id"] == activity.id
627 end
628 end
629
630 describe "GET /api/statusnet/tags/timeline/:tag.json" do
631 test "it returns the tags timeline", %{conn: conn} do
632 user = insert(:user)
633 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
634
635 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
636 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
637
638 conn = conn
639 |> get("/api/statusnet/tags/timeline/2hu.json")
640
641 assert [status] = json_response(conn, 200)
642 assert status["id"] == activity.id
643 end
644 end
645 end