twitter_api_controller_test.exs 54.9 KB
Newer Older
kaniini's avatar
kaniini committed
1
# Pleroma: A lightweight social networking server
2
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
kaniini's avatar
kaniini committed
3 4
# SPDX-License-Identifier: AGPL-3.0-only

5 6
defmodule Pleroma.Web.TwitterAPI.ControllerTest do
  use Pleroma.Web.ConnCase
dtluna's avatar
dtluna committed
7
  alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
lain's avatar
lain committed
8
  alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
9
  alias Pleroma.{Repo, Activity, User, Object, Notification}
lain's avatar
lain committed
10
  alias Pleroma.Web.ActivityPub.ActivityPub
dtluna's avatar
dtluna committed
11
  alias Pleroma.Web.TwitterAPI.UserView
12
  alias Pleroma.Web.TwitterAPI.NotificationView
lain's avatar
lain committed
13
  alias Pleroma.Web.CommonAPI
eal's avatar
eal committed
14
  alias Pleroma.Web.TwitterAPI.TwitterAPI
15
  alias Comeonin.Pbkdf2
16
  alias Ecto.Changeset
17

lain's avatar
lain committed
18
  import Pleroma.Factory
19

Maksim's avatar
Maksim committed
20 21
  @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"

22 23 24 25
  describe "POST /api/account/update_profile_banner" do
    test "it updates the banner", %{conn: conn} do
      user = insert(:user)

Maksim's avatar
Maksim committed
26 27 28 29
      conn
      |> assign(:user, user)
      |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
      |> json_response(200)
lain's avatar
lain committed
30

Maksim's avatar
Maksim committed
31
      user = refresh_record(user)
lain's avatar
lain committed
32
      assert user.info.banner["type"] == "Image"
33 34 35 36 37 38 39
    end
  end

  describe "POST /api/qvitter/update_background_image" do
    test "it updates the background", %{conn: conn} do
      user = insert(:user)

Maksim's avatar
Maksim committed
40 41 42 43
      conn
      |> assign(:user, user)
      |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
      |> json_response(200)
lain's avatar
lain committed
44

Maksim's avatar
Maksim committed
45
      user = refresh_record(user)
lain's avatar
lain committed
46
      assert user.info.background["type"] == "Image"
47 48 49
    end
  end

50 51
  describe "POST /api/account/verify_credentials" do
    setup [:valid_user]
lain's avatar
lain committed
52

53
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
54
      conn = post(conn, "/api/account/verify_credentials.json")
55 56 57 58
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: user} do
Maksim's avatar
Maksim committed
59
      response =
lain's avatar
lain committed
60
        conn
61 62
        |> with_credentials(user.nickname, "test")
        |> post("/api/account/verify_credentials.json")
Maksim's avatar
Maksim committed
63
        |> json_response(200)
64

lain's avatar
lain committed
65
      assert response == UserView.render("show.json", %{user: user, token: response["token"]})
66 67 68
    end
  end

lain's avatar
lain committed
69 70
  describe "POST /statuses/update.json" do
    setup [:valid_user]
lain's avatar
lain committed
71

lain's avatar
lain committed
72
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
73
      conn = post(conn, "/api/statuses/update.json")
lain's avatar
lain committed
74 75 76 77
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: user} do
dtluna's avatar
dtluna committed
78 79 80
      conn_with_creds = conn |> with_credentials(user.nickname, "test")
      request_path = "/api/statuses/update.json"

lain's avatar
lain committed
81 82 83 84 85
      error_response = %{
        "request" => request_path,
        "error" => "Client must provide a 'status' parameter with a value."
      }

Maksim's avatar
Maksim committed
86 87 88 89
      conn =
        conn_with_creds
        |> post(request_path)

dtluna's avatar
dtluna committed
90 91
      assert json_response(conn, 400) == error_response

Maksim's avatar
Maksim committed
92 93 94 95
      conn =
        conn_with_creds
        |> post(request_path, %{status: ""})

dtluna's avatar
dtluna committed
96
      assert json_response(conn, 400) == error_response
lain's avatar
lain committed
97

Maksim's avatar
Maksim committed
98 99 100 101
      conn =
        conn_with_creds
        |> post(request_path, %{status: " "})

dtluna's avatar
dtluna committed
102 103
      assert json_response(conn, 400) == error_response

104
      # we post with visibility private in order to avoid triggering relay
Maksim's avatar
Maksim committed
105 106 107
      conn =
        conn_with_creds
        |> post(request_path, %{status: "Nice meme.", visibility: "private"})
lain's avatar
lain committed
108 109 110

      assert json_response(conn, 200) ==
               ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
lain's avatar
lain committed
111 112 113
    end
  end

lain's avatar
lain committed
114
  describe "GET /statuses/public_timeline.json" do
115 116
    setup [:valid_user]

lain's avatar
lain committed
117
    test "returns statuses", %{conn: conn} do
lain's avatar
lain committed
118
      user = insert(:user)
lain's avatar
lain committed
119 120 121 122
      activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
      ActivityBuilder.insert_list(10, %{}, %{user: user})
      since_id = List.last(activities).id

lain's avatar
lain committed
123 124
      conn =
        conn
lain's avatar
lain committed
125 126 127 128 129 130
        |> get("/api/statuses/public_timeline.json", %{since_id: since_id})

      response = json_response(conn, 200)

      assert length(response) == 10
    end
href's avatar
href committed
131

Maksim's avatar
Maksim committed
132
    test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
href's avatar
href committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, false)

      Application.put_env(:pleroma, :instance, instance)

      conn
      |> get("/api/statuses/public_timeline.json")
      |> json_response(403)

      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, true)

      Application.put_env(:pleroma, :instance, instance)
    end

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    test "returns 200 to authenticated request when the instance is not public",
         %{conn: conn, user: user} do
      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, false)

      Application.put_env(:pleroma, :instance, instance)

      conn
      |> with_credentials(user.nickname, "test")
      |> get("/api/statuses/public_timeline.json")
      |> json_response(200)

      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, true)

      Application.put_env(:pleroma, :instance, instance)
    end

Maksim's avatar
Maksim committed
170
    test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
href's avatar
href committed
171 172 173 174
      conn
      |> get("/api/statuses/public_timeline.json")
      |> json_response(200)
    end
175 176 177 178 179 180 181 182

    test "returns 200 to authenticated request when the instance is public",
         %{conn: conn, user: user} do
      conn
      |> with_credentials(user.nickname, "test")
      |> get("/api/statuses/public_timeline.json")
      |> json_response(200)
    end
href's avatar
href committed
183 184 185
  end

  describe "GET /statuses/public_and_external_timeline.json" do
186 187
    setup [:valid_user]

Maksim's avatar
Maksim committed
188
    test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
href's avatar
href committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, false)

      Application.put_env(:pleroma, :instance, instance)

      conn
      |> get("/api/statuses/public_and_external_timeline.json")
      |> json_response(403)

      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, true)

      Application.put_env(:pleroma, :instance, instance)
    end

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    test "returns 200 to authenticated request when the instance is not public",
         %{conn: conn, user: user} do
      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, false)

      Application.put_env(:pleroma, :instance, instance)

      conn
      |> with_credentials(user.nickname, "test")
      |> get("/api/statuses/public_and_external_timeline.json")
      |> json_response(200)

      instance =
        Application.get_env(:pleroma, :instance)
        |> Keyword.put(:public, true)

      Application.put_env(:pleroma, :instance, instance)
    end

Maksim's avatar
Maksim committed
226
    test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
href's avatar
href committed
227 228 229 230
      conn
      |> get("/api/statuses/public_and_external_timeline.json")
      |> json_response(200)
    end
231 232 233 234 235 236 237 238

    test "returns 200 to authenticated request when the instance is public",
         %{conn: conn, user: user} do
      conn
      |> with_credentials(user.nickname, "test")
      |> get("/api/statuses/public_and_external_timeline.json")
      |> json_response(200)
    end
lain's avatar
lain committed
239 240
  end

lain's avatar
lain committed
241 242
  describe "GET /statuses/show/:id.json" do
    test "returns one status", %{conn: conn} do
lain's avatar
lain committed
243 244
      user = insert(:user)
      {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
lain's avatar
lain committed
245 246
      actor = Repo.get_by!(User, ap_id: activity.data["actor"])

lain's avatar
lain committed
247 248 249
      conn =
        conn
        |> get("/api/statuses/show/#{activity.id}.json")
lain's avatar
lain committed
250 251 252

      response = json_response(conn, 200)

lain's avatar
lain committed
253
      assert response == ActivityRepresenter.to_map(activity, %{user: actor})
lain's avatar
lain committed
254 255 256
    end
  end

eal's avatar
eal committed
257 258 259 260
  describe "GET /users/show.json" do
    test "gets user with screen_name", %{conn: conn} do
      user = insert(:user)

lain's avatar
lain committed
261 262 263
      conn =
        conn
        |> get("/api/users/show.json", %{"screen_name" => user.nickname})
eal's avatar
eal committed
264 265 266 267 268 269 270 271 272

      response = json_response(conn, 200)

      assert response["id"] == user.id
    end

    test "gets user with user_id", %{conn: conn} do
      user = insert(:user)

lain's avatar
lain committed
273 274 275
      conn =
        conn
        |> get("/api/users/show.json", %{"user_id" => user.id})
eal's avatar
eal committed
276 277 278 279 280 281 282 283 284 285 286 287

      response = json_response(conn, 200)

      assert response["id"] == user.id
    end

    test "gets a user for a logged in user", %{conn: conn} do
      user = insert(:user)
      logged_in = insert(:user)

      {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})

lain's avatar
lain committed
288 289 290 291
      conn =
        conn
        |> with_credentials(logged_in.nickname, "test")
        |> get("/api/users/show.json", %{"user_id" => user.id})
eal's avatar
eal committed
292 293 294 295 296 297 298

      response = json_response(conn, 200)

      assert response["following"] == true
    end
  end

299 300
  describe "GET /statusnet/conversation/:id.json" do
    test "returns the statuses in the conversation", %{conn: conn} do
lain's avatar
lain committed
301
      {:ok, _user} = UserBuilder.insert()
302
      {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
303 304
      {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
      {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
305

lain's avatar
lain committed
306 307
      conn =
        conn
308
        |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
309 310 311 312 313 314 315

      response = json_response(conn, 200)

      assert length(response) == 2
    end
  end

lain's avatar
lain committed
316 317
  describe "GET /statuses/friends_timeline.json" do
    setup [:valid_user]
lain's avatar
lain committed
318

lain's avatar
lain committed
319
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
320
      conn = get(conn, "/api/statuses/friends_timeline.json")
lain's avatar
lain committed
321 322 323 324
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
325
      user = insert(:user)
lain's avatar
lain committed
326 327 328 329 330 331 332

      activities =
        ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})

      returned_activities =
        ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})

lain's avatar
lain committed
333
      other_user = insert(:user)
lain's avatar
lain committed
334 335 336
      ActivityBuilder.insert_list(10, %{}, %{user: other_user})
      since_id = List.last(activities).id

lain's avatar
lain committed
337
      current_user =
338
        Changeset.change(current_user, following: [User.ap_followers(user)])
lain's avatar
lain committed
339
        |> Repo.update!()
lain's avatar
lain committed
340

lain's avatar
lain committed
341 342
      conn =
        conn
lain's avatar
lain committed
343 344 345 346 347 348
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})

      response = json_response(conn, 200)

      assert length(response) == 10
lain's avatar
lain committed
349 350 351 352 353 354 355 356

      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)
lain's avatar
lain committed
357 358 359
    end
  end

lain's avatar
lain committed
360 361 362 363 364 365 366 367 368 369 370 371 372
  describe "GET /statuses/dm_timeline.json" do
    test "it show direct messages", %{conn: conn} do
      user_one = insert(:user)
      user_two = insert(:user)

      {:ok, user_two} = User.follow(user_two, user_one)

      {:ok, direct} =
        CommonAPI.post(user_one, %{
          "status" => "Hi @#{user_two.nickname}!",
          "visibility" => "direct"
        })

373 374 375 376 377 378
      {:ok, direct_two} =
        CommonAPI.post(user_two, %{
          "status" => "Hi @#{user_one.nickname}!",
          "visibility" => "direct"
        })

lain's avatar
lain committed
379 380 381 382 383 384 385 386 387 388 389 390
      {:ok, _follower_only} =
        CommonAPI.post(user_one, %{
          "status" => "Hi @#{user_two.nickname}!",
          "visibility" => "private"
        })

      # Only direct should be visible here
      res_conn =
        conn
        |> assign(:user, user_two)
        |> get("/api/statuses/dm_timeline.json")

391 392 393
      [status, status_two] = json_response(res_conn, 200)
      assert status["id"] == direct_two.id
      assert status_two["id"] == direct.id
lain's avatar
lain committed
394 395 396
    end
  end

dtluna's avatar
dtluna committed
397 398
  describe "GET /statuses/mentions.json" do
    setup [:valid_user]
lain's avatar
lain committed
399

dtluna's avatar
dtluna committed
400
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
401
      conn = get(conn, "/api/statuses/mentions.json")
dtluna's avatar
dtluna committed
402 403 404 405
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
406 407
      {:ok, activity} =
        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
dtluna's avatar
dtluna committed
408

lain's avatar
lain committed
409 410
      conn =
        conn
dtluna's avatar
dtluna committed
411 412 413 414 415 416
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/mentions.json")

      response = json_response(conn, 200)

      assert length(response) == 1
lain's avatar
lain committed
417 418 419 420 421 422

      assert Enum.at(response, 0) ==
               ActivityRepresenter.to_map(activity, %{
                 user: current_user,
                 mentioned: [current_user]
               })
dtluna's avatar
dtluna committed
423 424 425
    end
  end

426 427 428 429 430 431 432 433 434
  describe "GET /api/qvitter/statuses/notifications.json" do
    setup [:valid_user]

    test "without valid credentials", %{conn: conn} do
      conn = get(conn, "/api/qvitter/statuses/notifications.json")
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
435 436
      other_user = insert(:user)

437
      {:ok, _activity} =
438
        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
439 440 441 442 443 444 445 446 447 448 449

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/qvitter/statuses/notifications.json")

      response = json_response(conn, 200)

      assert length(response) == 1

      assert response ==
lain's avatar
lain committed
450 451 452 453
               NotificationView.render("notification.json", %{
                 notifications: Notification.for_user(current_user),
                 for: current_user
               })
454 455 456
    end
  end

457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
  describe "POST /api/qvitter/statuses/notifications/read" do
    setup [:valid_user]

    test "without valid credentials", %{conn: conn} do
      conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials, without any params", %{conn: conn, user: current_user} do
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/qvitter/statuses/notifications/read")

      assert json_response(conn, 400) == %{
               "error" => "You need to specify latest_id",
               "request" => "/api/qvitter/statuses/notifications/read"
             }
    end

    test "with credentials, with params", %{conn: conn, user: current_user} do
      other_user = insert(:user)

      {:ok, _activity} =
        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})

      response_conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/qvitter/statuses/notifications.json")

      [notification] = response = json_response(response_conn, 200)

      assert length(response) == 1

      assert notification["is_seen"] == 0

      response_conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})

      [notification] = response = json_response(response_conn, 200)

      assert length(response) == 1

      assert notification["is_seen"] == 1
    end
  end

dtluna's avatar
dtluna committed
507 508
  describe "GET /statuses/user_timeline.json" do
    setup [:valid_user]
lain's avatar
lain committed
509

dtluna's avatar
dtluna committed
510 511
    test "without any params", %{conn: conn} do
      conn = get(conn, "/api/statuses/user_timeline.json")
lain's avatar
lain committed
512 513 514 515 516

      assert json_response(conn, 400) == %{
               "error" => "You need to specify screen_name or user_id",
               "request" => "/api/statuses/user_timeline.json"
             }
dtluna's avatar
dtluna committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    end

    test "with user_id", %{conn: conn} do
      user = insert(:user)
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})

      conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
      response = json_response(conn, 200)
      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end

    test "with screen_name", %{conn: conn} do
      user = insert(:user)
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})

      conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
      response = json_response(conn, 200)
      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end

    test "with credentials", %{conn: conn, user: current_user} do
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
lain's avatar
lain committed
541 542 543 544 545

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json")
dtluna's avatar
dtluna committed
546 547 548 549 550 551 552 553 554 555

      response = json_response(conn, 200)

      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
    end

    test "with credentials with user_id", %{conn: conn, user: current_user} do
      user = insert(:user)
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
lain's avatar
lain committed
556 557 558 559 560

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
dtluna's avatar
dtluna committed
561 562 563 564 565 566 567 568 569 570

      response = json_response(conn, 200)

      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end

    test "with credentials screen_name", %{conn: conn, user: current_user} do
      user = insert(:user)
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
lain's avatar
lain committed
571 572 573 574 575

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
dtluna's avatar
dtluna committed
576 577 578

      response = json_response(conn, 200)

579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end

    test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
      user = insert(:user)
      {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
      {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json", %{
          "user_id" => user.id,
          "include_rts" => "false"
        })

      response = json_response(conn, 200)

      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})

      conn =
        conn
        |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})

      response = json_response(conn, 200)

dtluna's avatar
dtluna committed
607 608 609 610 611
      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end
  end

lain's avatar
lain committed
612 613
  describe "POST /friendships/create.json" do
    setup [:valid_user]
lain's avatar
lain committed
614

lain's avatar
lain committed
615
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
616
      conn = post(conn, "/api/friendships/create.json")
lain's avatar
lain committed
617 618 619 620
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
621
      followed = insert(:user)
lain's avatar
lain committed
622

lain's avatar
lain committed
623 624 625 626
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/friendships/create.json", %{user_id: followed.id})
lain's avatar
lain committed
627 628

      current_user = Repo.get(User, current_user.id)
629
      assert User.ap_followers(followed) in current_user.following
lain's avatar
lain committed
630 631 632

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: followed, for: current_user})
lain's avatar
lain committed
633 634 635
    end
  end

lain's avatar
lain committed
636 637
  describe "POST /friendships/destroy.json" do
    setup [:valid_user]
lain's avatar
lain committed
638

lain's avatar
lain committed
639
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
640
      conn = post(conn, "/api/friendships/destroy.json")
lain's avatar
lain committed
641 642 643 644
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
645
      followed = insert(:user)
lain's avatar
lain committed
646 647

      {:ok, current_user} = User.follow(current_user, followed)
648
      assert User.ap_followers(followed) in current_user.following
649
      ActivityPub.follow(current_user, followed)
lain's avatar
lain committed
650

lain's avatar
lain committed
651 652 653 654
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/friendships/destroy.json", %{user_id: followed.id})
lain's avatar
lain committed
655 656

      current_user = Repo.get(User, current_user.id)
657
      assert current_user.following == [current_user.ap_id]
lain's avatar
lain committed
658 659 660

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: followed, for: current_user})
lain's avatar
lain committed
661 662 663
    end
  end

eal's avatar
eal committed
664 665
  describe "POST /blocks/create.json" do
    setup [:valid_user]
lain's avatar
lain committed
666

eal's avatar
eal committed
667
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
668
      conn = post(conn, "/api/blocks/create.json")
eal's avatar
eal committed
669 670 671 672 673 674
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      blocked = insert(:user)

lain's avatar
lain committed
675 676 677 678
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/blocks/create.json", %{user_id: blocked.id})
eal's avatar
eal committed
679 680 681

      current_user = Repo.get(User, current_user.id)
      assert User.blocks?(current_user, blocked)
lain's avatar
lain committed
682 683 684

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: blocked, for: current_user})
eal's avatar
eal committed
685 686 687 688 689
    end
  end

  describe "POST /blocks/destroy.json" do
    setup [:valid_user]
lain's avatar
lain committed
690

eal's avatar
eal committed
691
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
692
      conn = post(conn, "/api/blocks/destroy.json")
eal's avatar
eal committed
693 694 695 696 697 698
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      blocked = insert(:user)

normandy's avatar
normandy committed
699
      {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
eal's avatar
eal committed
700 701
      assert User.blocks?(current_user, blocked)

lain's avatar
lain committed
702 703 704 705
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
eal's avatar
eal committed
706 707

      current_user = Repo.get(User, current_user.id)
lain's avatar
lain committed
708
      assert current_user.info.blocks == []
lain's avatar
lain committed
709 710 711

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: blocked, for: current_user})
eal's avatar
eal committed
712 713 714
    end
  end

dtluna's avatar
dtluna committed
715 716
  describe "GET /help/test.json" do
    test "returns \"ok\"", %{conn: conn} do
lain's avatar
lain committed
717
      conn = get(conn, "/api/help/test.json")
dtluna's avatar
dtluna committed
718
      assert json_response(conn, 200) == "ok"
lain's avatar
lain committed
719
    end
720 721
  end

lain's avatar
lain committed
722 723
  describe "POST /api/qvitter/update_avatar.json" do
    setup [:valid_user]
lain's avatar
lain committed
724

lain's avatar
lain committed
725
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
726
      conn = post(conn, "/api/qvitter/update_avatar.json")
lain's avatar
lain committed
727 728 729 730
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
731
      avatar_image = File.read!("test/fixtures/avatar_data_uri")
lain's avatar
lain committed
732 733 734 735 736

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
lain's avatar
lain committed
737 738 739

      current_user = Repo.get(User, current_user.id)
      assert is_map(current_user.avatar)
lain's avatar
lain committed
740 741 742

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: current_user, for: current_user})
lain's avatar
lain committed
743 744 745
    end
  end

746 747 748 749 750 751 752 753 754
  describe "GET /api/qvitter/mutes.json" do
    setup [:valid_user]

    test "unimplemented mutes without valid credentials", %{conn: conn} do
      conn = get(conn, "/api/qvitter/mutes.json")
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
Maksim's avatar
Maksim committed
755
      response =
756 757 758
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/qvitter/mutes.json")
Maksim's avatar
Maksim committed
759
        |> json_response(200)
Vivian Lim's avatar
Vivian Lim committed
760

Maksim's avatar
Maksim committed
761
      assert [] = response
762 763 764
    end
  end

lain's avatar
lain committed
765 766
  describe "POST /api/favorites/create/:id" do
    setup [:valid_user]
lain's avatar
lain committed
767

lain's avatar
lain committed
768 769
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
770
      conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
lain's avatar
lain committed
771 772 773 774 775 776
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      note_activity = insert(:note_activity)

lain's avatar
lain committed
777 778 779 780
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/create/#{note_activity.id}.json")
lain's avatar
lain committed
781 782 783

      assert json_response(conn, 200)
    end
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801

    test "with credentials, invalid param", %{conn: conn, user: current_user} do
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/create/wrong.json")

      assert json_response(conn, 400)
    end

    test "with credentials, invalid activity", %{conn: conn, user: current_user} do
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/create/1.json")

      assert json_response(conn, 500)
    end
lain's avatar
lain committed
802 803
  end

lain's avatar
lain committed
804 805
  describe "POST /api/favorites/destroy/:id" do
    setup [:valid_user]
lain's avatar
lain committed
806

lain's avatar
lain committed
807 808
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
809
      conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
lain's avatar
lain committed
810 811 812 813 814 815 816 817
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      note_activity = insert(:note_activity)
      object = Object.get_by_ap_id(note_activity.data["object"]["id"])
      ActivityPub.like(current_user, object)

lain's avatar
lain committed
818 819 820 821
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/destroy/#{note_activity.id}.json")
lain's avatar
lain committed
822 823 824 825 826

      assert json_response(conn, 200)
    end
  end

lain's avatar
lain committed
827 828
  describe "POST /api/statuses/retweet/:id" do
    setup [:valid_user]
lain's avatar
lain committed
829

lain's avatar
lain committed
830 831
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
832
      conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
lain's avatar
lain committed
833 834 835 836 837 838
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      note_activity = insert(:note_activity)

dtluna's avatar
dtluna committed
839
      request_path = "/api/statuses/retweet/#{note_activity.id}.json"
lain's avatar
lain committed
840

lain's avatar
lain committed
841 842 843 844 845
      response =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post(request_path)

dtluna's avatar
dtluna committed
846
      activity = Repo.get(Activity, note_activity.id)
lain's avatar
lain committed
847
      activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
lain's avatar
lain committed
848 849 850

      assert json_response(response, 200) ==
               ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
lain's avatar
lain committed
851 852 853
    end
  end

854 855 856 857 858
  describe "POST /api/statuses/unretweet/:id" do
    setup [:valid_user]

    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
normandy's avatar
normandy committed
859
      conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
      note_activity = insert(:note_activity)

      request_path = "/api/statuses/retweet/#{note_activity.id}.json"

      _response =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post(request_path)

      request_path = String.replace(request_path, "retweet", "unretweet")

      response =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post(request_path)

      activity = Repo.get(Activity, note_activity.id)
      activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])

      assert json_response(response, 200) ==
               ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
    end
  end

888 889 890 891 892 893 894 895 896 897 898
  describe "POST /api/account/register" do
    test "it creates a new user", %{conn: conn} do
      data = %{
        "nickname" => "lain",
        "email" => "lain@wired.jp",
        "fullname" => "lain iwakura",
        "bio" => "close the world.",
        "password" => "bear",
        "confirm" => "bear"
      }

lain's avatar
lain committed
899 900 901
      conn =
        conn
        |> post("/api/account/register", data)
902 903 904 905

      user = json_response(conn, 200)

      fetched_user = Repo.get_by(User, nickname: "lain")
dtluna's avatar
dtluna committed
906
      assert user == UserView.render("show.json", %{user: fetched_user})
907 908 909 910 911 912 913 914 915 916 917
    end

    test "it returns errors on a problem", %{conn: conn} do
      data = %{
        "email" => "lain@wired.jp",
        "fullname" => "lain iwakura",
        "bio" => "close the world.",
        "password" => "bear",
        "confirm" => "bear"
      }

lain's avatar
lain committed
918 919 920
      conn =
        conn
        |> post("/api/account/register", data)
921 922 923 924

      errors = json_response(conn, 400)

      assert is_binary(errors["error"])
dtluna's avatar
dtluna committed
925 926 927
    end
  end

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
  describe "POST /api/account/password_reset, with valid parameters" do
    setup %{conn: conn} do
      user = insert(:user)
      conn = post(conn, "/api/account/password_reset?email=#{user.email}")
      %{conn: conn, user: user}
    end

    test "it returns 204", %{conn: conn} do
      assert json_response(conn, :no_content)
    end

    test "it creates a PasswordResetToken record for user", %{user: user} do
      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
      assert token_record
    end

    test "it sends an email to user", %{user: user} do
      token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)

      Swoosh.TestAssertions.assert_email_sent(
        Pleroma.UserEmail.password_reset_email(user, token_record.token)
      )
    end
  end

  describe "POST /api/account/password_reset, with invalid parameters" do
    setup [:valid_user]

    test "it returns 500 when user is not found", %{conn: conn, user: user} do
      conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
      assert json_response(conn, :internal_server_error)
    end

    test "it returns 500 when user is not local", %{conn: conn, user: user} do
      {:ok, user} = Repo.update(Changeset.change(user, local: false))
      conn = post(conn, "/api/account/password_reset?email=#{user.email}")
      assert json_response(conn, :internal_server_error)
    end
  end

968
  describe "GET /api/account/confirm_email/:id/:token" do
969 970
    setup do
      user = insert(:user)
971
      info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
972 973 974 975 976 977 978 979 980 981 982 983 984

      {:ok, user} =
        user
        |> Changeset.change()
        |> Changeset.put_embed(:info, info_change)
        |> Repo.update()

      assert user.info.confirmation_pending

      [user: user]
    end

    test "it redirects to root url", %{conn: conn, user: user} do
985
      conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
986 987 988 989 990

      assert 302 == conn.status
    end

    test "it confirms the user account", %{conn: conn, user: user} do
991
      get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
992 993 994 995 996 997

      user = Repo.get(User, user.id)

      refute user.info.confirmation_pending
      refute user.info.confirmation_token
    end
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009

    test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
      conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")

      assert 500 == conn.status
    end

    test "it returns 500 if token is invalid", %{conn: conn, user: user} do
      conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")

      assert 500 == conn.status
    end
1010 1011 1012 1013
  end

  describe "POST /api/account/resend_confirmation_email" do
    setup do
1014 1015 1016 1017 1018 1019 1020
      setting = Pleroma.Config.get([:instance, :account_activation_required])

      unless setting do
        Pleroma.Config.put([:instance, :account_activation_required], true)
        on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
      end

1021
      user = insert(:user)
1022
      info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050

      {:ok, user} =
        user
        |> Changeset.change()
        |> Changeset.put_embed(:info, info_change)
        |> Repo.update()

      assert user.info.confirmation_pending

      [user: user]
    end

    test "it returns 204 No Content", %{conn: conn, user: user} do
      conn
      |> assign(:user, user)
      |> post("/api/account/resend_confirmation_email?email=#{user.email}")
      |> json_response(:no_content)
    end

    test "it sends confirmation email", %{conn: conn, user: user} do
      conn
      |> assign(:user, user)
      |> post("/api/account/resend_confirmation_email?email=#{user.email}")

      Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
    end
  end

lain's avatar
lain committed
1051 1052 1053
  describe "GET /api/externalprofile/show" do
    test "it returns the user", %{conn: conn} do
      user = insert(:user)
1054
      other_user = insert(:user)
lain's avatar
lain committed
1055

lain's avatar
lain committed
1056 1057 1058 1059
      conn =
        conn
        |> assign(:user, user)
        |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
lain's avatar
lain committed
1060

1061
      assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
lain's avatar
lain committed
1062 1063 1064
    end
  end

lain's avatar
lain committed
1065 1066 1067 1068 1069
  describe "GET /api/statuses/followers" do
    test "it returns a user's followers", %{conn: conn} do
      user = insert(:user)
      follower_one = insert(:user)
      follower_two = insert(:user)
lain's avatar
lain committed
1070
      _not_follower = insert(:user)
lain's avatar
lain committed
1071 1072 1073 1074

      {:ok, follower_one} = User.follow(follower_one, user)
      {:ok, follower_two} = User.follow(follower_two, user)

lain's avatar
lain committed
1075 1076 1077 1078
      conn =
        conn
        |> assign(:user, user)
        |> get("/api/statuses/followers")
lain's avatar
lain committed
1079

lain's avatar
lain committed
1080 1081 1082
      expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
      result = json_response(conn, 200)
      assert Enum.sort(expected) == Enum.sort(result)
lain's avatar
lain committed
1083
    end
lain's avatar
lain committed
1084

1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
    test "it returns 20 followers per page", %{conn: conn} do
      user = insert(:user)
      followers = insert_list(21, :user)

      Enum.each(followers, fn follower ->
        User.follow(follower, user)
      end)

      res_conn =
        conn
        |> assign(:user, user)
        |> get("/api/statuses/followers")

      result = json_response(res_conn, 200)
      assert length(result) == 20

      res_conn =
        conn
        |> assign(:user, user)
lain's avatar
lain committed
1104
        |> get("/api/statuses/followers?page=2")
1105 1106 1107 1108 1109

      result = json_response(res_conn, 200)
      assert length(result) == 1
    end

lain's avatar
lain committed
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
    test "it returns a given user's followers with user_id", %{conn: conn} do
      user = insert(:user)
      follower_one = insert(:user)
      follower_two = insert(:user)
      not_follower = insert(:user)

      {:ok, follower_one} = User.follow(follower_one, user)
      {:ok, follower_two} = User.follow(follower_two, user)

      conn =
        conn
        |> assign(:user, not_follower)
        |> get("/api/statuses/followers", %{"user_id" => user.id})

      assert MapSet.equal?(