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 conn = conn
380 |> with_credentials(current_user.nickname, "test")
381 |> post("/api/qvitter/update_avatar.json", %{img: Pleroma.Web.ActivityPub.ActivityPubTest.data_uri})
382
383 current_user = Repo.get(User, current_user.id)
384 assert is_map(current_user.avatar)
385 assert json_response(conn, 200) == UserView.render("show.json", %{user: current_user, for: current_user})
386 end
387 end
388
389 describe "POST /api/favorites/create/:id" do
390 setup [:valid_user]
391 test "without valid credentials", %{conn: conn} do
392 note_activity = insert(:note_activity)
393 conn = post conn, "/api/favorites/create/#{note_activity.id}.json"
394 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
395 end
396
397 test "with credentials", %{conn: conn, user: current_user} do
398 note_activity = insert(:note_activity)
399
400 conn = conn
401 |> with_credentials(current_user.nickname, "test")
402 |> post("/api/favorites/create/#{note_activity.id}.json")
403
404 assert json_response(conn, 200)
405 end
406 end
407
408 describe "POST /api/favorites/destroy/:id" do
409 setup [:valid_user]
410 test "without valid credentials", %{conn: conn} do
411 note_activity = insert(:note_activity)
412 conn = post conn, "/api/favorites/destroy/#{note_activity.id}.json"
413 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
414 end
415
416 test "with credentials", %{conn: conn, user: current_user} do
417 note_activity = insert(:note_activity)
418 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
419 ActivityPub.like(current_user, object)
420
421 conn = conn
422 |> with_credentials(current_user.nickname, "test")
423 |> post("/api/favorites/destroy/#{note_activity.id}.json")
424
425 assert json_response(conn, 200)
426 end
427 end
428
429 describe "POST /api/statuses/retweet/:id" do
430 setup [:valid_user]
431 test "without valid credentials", %{conn: conn} do
432 note_activity = insert(:note_activity)
433 conn = post conn, "/api/statuses/retweet/#{note_activity.id}.json"
434 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
435 end
436
437 test "with credentials", %{conn: conn, user: current_user} do
438 note_activity = insert(:note_activity)
439
440 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
441
442 response = conn
443 |> with_credentials(current_user.nickname, "test")
444 |> post(request_path)
445 activity = Repo.get(Activity, note_activity.id)
446 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
447 assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
448 end
449 end
450
451 describe "POST /api/account/register" do
452 test "it creates a new user", %{conn: conn} do
453 data = %{
454 "nickname" => "lain",
455 "email" => "lain@wired.jp",
456 "fullname" => "lain iwakura",
457 "bio" => "close the world.",
458 "password" => "bear",
459 "confirm" => "bear"
460 }
461
462 conn = conn
463 |> post("/api/account/register", data)
464
465 user = json_response(conn, 200)
466
467 fetched_user = Repo.get_by(User, nickname: "lain")
468 assert user == UserView.render("show.json", %{user: fetched_user})
469 end
470
471 test "it returns errors on a problem", %{conn: conn} do
472 data = %{
473 "email" => "lain@wired.jp",
474 "fullname" => "lain iwakura",
475 "bio" => "close the world.",
476 "password" => "bear",
477 "confirm" => "bear"
478 }
479
480 conn = conn
481 |> post("/api/account/register", data)
482
483 errors = json_response(conn, 400)
484
485 assert is_binary(errors["error"])
486 end
487 end
488
489 describe "GET /api/externalprofile/show" do
490 test "it returns the user", %{conn: conn} do
491 user = insert(:user)
492 other_user = insert(:user)
493
494 conn = conn
495 |> assign(:user, user)
496 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
497
498 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
499 end
500 end
501
502 describe "GET /api/statuses/followers" do
503 test "it returns a user's followers", %{conn: conn} do
504 user = insert(:user)
505 follower_one = insert(:user)
506 follower_two = insert(:user)
507 not_follower = insert(:user)
508
509 {:ok, follower_one} = User.follow(follower_one, user)
510 {:ok, follower_two} = User.follow(follower_two, user)
511
512 conn = conn
513 |> assign(:user, user)
514 |> get("/api/statuses/followers")
515
516 assert json_response(conn, 200) == UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
517 end
518 end
519
520 describe "GET /api/statuses/friends" do
521 test "it returns a user's friends", %{conn: conn} do
522 user = insert(:user)
523 followed_one = insert(:user)
524 followed_two = insert(:user)
525 not_followed = insert(:user)
526
527 {:ok, user} = User.follow(user, followed_one)
528 {:ok, user} = User.follow(user, followed_two)
529
530 conn = conn
531 |> assign(:user, user)
532 |> get("/api/statuses/friends")
533
534 assert MapSet.equal?(MapSet.new(json_response(conn, 200)), MapSet.new(UserView.render("index.json", %{users: [followed_one, followed_two], for: user})))
535 end
536 end
537
538 describe "GET /friends/ids" do
539 test "it returns a user's friends", %{conn: conn} do
540 user = insert(:user)
541 followed_one = insert(:user)
542 followed_two = insert(:user)
543 not_followed = insert(:user)
544
545 {:ok, user} = User.follow(user, followed_one)
546 {:ok, user} = User.follow(user, followed_two)
547
548 conn = conn
549 |> assign(:user, user)
550 |> get("/api/friends/ids")
551
552 expected = [followed_one.id, followed_two.id]
553 assert MapSet.equal?(MapSet.new(Poison.decode!(json_response(conn, 200))), MapSet.new(expected))
554 end
555 end
556
557 describe "POST /api/account/update_profile.json" do
558 test "it updates a user's profile" do
559 user = insert(:user)
560
561 conn = conn
562 |> assign(:user, user)
563 |> post("/api/account/update_profile.json", %{"name" => "new name", "description" => "new description"})
564
565 user = Repo.get!(User, user.id)
566 assert user.name == "new name"
567 assert user.bio == "new description"
568
569 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
570 end
571 end
572
573 defp valid_user(_context) do
574 user = insert(:user)
575 [user: user]
576 end
577
578 defp with_credentials(conn, username, password) do
579 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
580 put_req_header(conn, "authorization", header_content)
581 end
582
583 describe "GET /api/search.json" do
584 test "it returns search results", %{conn: conn} do
585 user = insert(:user)
586 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
587
588 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
589 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
590
591 conn = conn
592 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
593
594 assert [status] = json_response(conn, 200)
595 assert status["id"] == activity.id
596 end
597 end
598
599 describe "GET /api/statusnet/tags/timeline/:tag.json" do
600 test "it returns the tags timeline" do
601 user = insert(:user)
602 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
603
604 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
605 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
606
607 conn = conn
608 |> get("/api/statusnet/tags/timeline/2hu.json")
609
610 assert [status] = json_response(conn, 200)
611 assert status["id"] == activity.id
612 end
613 end
614 end