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