twitter_api_controller_test.exs 49.6 KB
Newer Older
kaniini's avatar
kaniini committed
1 2 3 4
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# 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 115
  describe "GET /statuses/public_timeline.json" do
    test "returns statuses", %{conn: conn} do
lain's avatar
lain committed
116
      user = insert(:user)
lain's avatar
lain committed
117 118 119 120
      activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
      ActivityBuilder.insert_list(10, %{}, %{user: user})
      since_id = List.last(activities).id

lain's avatar
lain committed
121 122
      conn =
        conn
lain's avatar
lain committed
123 124 125 126 127 128
        |> 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
129

Maksim's avatar
Maksim committed
130
    test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
href's avatar
href committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
      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

Maksim's avatar
Maksim committed
148
    test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
href's avatar
href committed
149 150 151 152 153 154 155
      conn
      |> get("/api/statuses/public_timeline.json")
      |> json_response(200)
    end
  end

  describe "GET /statuses/public_and_external_timeline.json" do
Maksim's avatar
Maksim committed
156
    test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
href's avatar
href committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
      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

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

lain's avatar
lain committed
181 182
  describe "GET /statuses/show/:id.json" do
    test "returns one status", %{conn: conn} do
lain's avatar
lain committed
183 184
      user = insert(:user)
      {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
lain's avatar
lain committed
185 186
      actor = Repo.get_by!(User, ap_id: activity.data["actor"])

lain's avatar
lain committed
187 188 189
      conn =
        conn
        |> get("/api/statuses/show/#{activity.id}.json")
lain's avatar
lain committed
190 191 192

      response = json_response(conn, 200)

lain's avatar
lain committed
193
      assert response == ActivityRepresenter.to_map(activity, %{user: actor})
lain's avatar
lain committed
194 195 196
    end
  end

eal's avatar
eal committed
197 198 199 200
  describe "GET /users/show.json" do
    test "gets user with screen_name", %{conn: conn} do
      user = insert(:user)

lain's avatar
lain committed
201 202 203
      conn =
        conn
        |> get("/api/users/show.json", %{"screen_name" => user.nickname})
eal's avatar
eal committed
204 205 206 207 208 209 210 211 212

      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
213 214 215
      conn =
        conn
        |> get("/api/users/show.json", %{"user_id" => user.id})
eal's avatar
eal committed
216 217 218 219 220 221 222 223 224 225 226 227

      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
228 229 230 231
      conn =
        conn
        |> with_credentials(logged_in.nickname, "test")
        |> get("/api/users/show.json", %{"user_id" => user.id})
eal's avatar
eal committed
232 233 234 235 236 237 238

      response = json_response(conn, 200)

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

239 240
  describe "GET /statusnet/conversation/:id.json" do
    test "returns the statuses in the conversation", %{conn: conn} do
lain's avatar
lain committed
241
      {:ok, _user} = UserBuilder.insert()
242
      {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
243 244
      {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
      {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
245

lain's avatar
lain committed
246 247
      conn =
        conn
248
        |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
249 250 251 252 253 254 255

      response = json_response(conn, 200)

      assert length(response) == 2
    end
  end

lain's avatar
lain committed
256 257
  describe "GET /statuses/friends_timeline.json" do
    setup [:valid_user]
lain's avatar
lain committed
258

lain's avatar
lain committed
259
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
260
      conn = get(conn, "/api/statuses/friends_timeline.json")
lain's avatar
lain committed
261 262 263 264
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
265
      user = insert(:user)
lain's avatar
lain committed
266 267 268 269 270 271 272

      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
273
      other_user = insert(:user)
lain's avatar
lain committed
274 275 276
      ActivityBuilder.insert_list(10, %{}, %{user: other_user})
      since_id = List.last(activities).id

lain's avatar
lain committed
277
      current_user =
278
        Changeset.change(current_user, following: [User.ap_followers(user)])
lain's avatar
lain committed
279
        |> Repo.update!()
lain's avatar
lain committed
280

lain's avatar
lain committed
281 282
      conn =
        conn
lain's avatar
lain committed
283 284 285 286 287 288
        |> 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
289 290 291 292 293 294 295 296

      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
297 298 299
    end
  end

lain's avatar
lain committed
300 301 302 303 304 305 306 307 308 309 310 311 312
  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"
        })

313 314 315 316 317 318
      {:ok, direct_two} =
        CommonAPI.post(user_two, %{
          "status" => "Hi @#{user_one.nickname}!",
          "visibility" => "direct"
        })

lain's avatar
lain committed
319 320 321 322 323 324 325 326 327 328 329 330
      {: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")

331 332 333
      [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
334 335 336
    end
  end

dtluna's avatar
dtluna committed
337 338
  describe "GET /statuses/mentions.json" do
    setup [:valid_user]
lain's avatar
lain committed
339

dtluna's avatar
dtluna committed
340
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
341
      conn = get(conn, "/api/statuses/mentions.json")
dtluna's avatar
dtluna committed
342 343 344 345
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

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

lain's avatar
lain committed
349 350
      conn =
        conn
dtluna's avatar
dtluna committed
351 352 353 354 355 356
        |> 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
357 358 359 360 361 362

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

366 367 368 369 370 371 372 373 374
  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
375 376
      other_user = insert(:user)

377
      {:ok, _activity} =
378
        ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
379 380 381 382 383 384 385 386 387 388 389

      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
390 391 392 393
               NotificationView.render("notification.json", %{
                 notifications: Notification.for_user(current_user),
                 for: current_user
               })
394 395 396
    end
  end

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
  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
447 448
  describe "GET /statuses/user_timeline.json" do
    setup [:valid_user]
lain's avatar
lain committed
449

dtluna's avatar
dtluna committed
450 451
    test "without any params", %{conn: conn} do
      conn = get(conn, "/api/statuses/user_timeline.json")
lain's avatar
lain committed
452 453 454 455 456

      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
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
    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
481 482 483 484 485

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json")
dtluna's avatar
dtluna committed
486 487 488 489 490 491 492 493 494 495

      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
496 497 498 499 500

      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
dtluna's avatar
dtluna committed
501 502 503 504 505 506 507 508 509 510

      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
511 512 513 514 515

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

      response = json_response(conn, 200)

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
      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
547 548 549 550 551
      assert length(response) == 1
      assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
    end
  end

lain's avatar
lain committed
552 553
  describe "POST /friendships/create.json" do
    setup [:valid_user]
lain's avatar
lain committed
554

lain's avatar
lain committed
555
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
556
      conn = post(conn, "/api/friendships/create.json")
lain's avatar
lain committed
557 558 559 560
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

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

lain's avatar
lain committed
563 564 565 566
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/friendships/create.json", %{user_id: followed.id})
lain's avatar
lain committed
567 568

      current_user = Repo.get(User, current_user.id)
569
      assert User.ap_followers(followed) in current_user.following
lain's avatar
lain committed
570 571 572

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

lain's avatar
lain committed
576 577
  describe "POST /friendships/destroy.json" do
    setup [:valid_user]
lain's avatar
lain committed
578

lain's avatar
lain committed
579
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
580
      conn = post(conn, "/api/friendships/destroy.json")
lain's avatar
lain committed
581 582 583 584
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

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

      {:ok, current_user} = User.follow(current_user, followed)
588
      assert User.ap_followers(followed) in current_user.following
589
      ActivityPub.follow(current_user, followed)
lain's avatar
lain committed
590

lain's avatar
lain committed
591 592 593 594
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/friendships/destroy.json", %{user_id: followed.id})
lain's avatar
lain committed
595 596

      current_user = Repo.get(User, current_user.id)
597
      assert current_user.following == [current_user.ap_id]
lain's avatar
lain committed
598 599 600

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

eal's avatar
eal committed
604 605
  describe "POST /blocks/create.json" do
    setup [:valid_user]
lain's avatar
lain committed
606

eal's avatar
eal committed
607
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
608
      conn = post(conn, "/api/blocks/create.json")
eal's avatar
eal committed
609 610 611 612 613 614
      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
615 616 617 618
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/blocks/create.json", %{user_id: blocked.id})
eal's avatar
eal committed
619 620 621

      current_user = Repo.get(User, current_user.id)
      assert User.blocks?(current_user, blocked)
lain's avatar
lain committed
622 623 624

      assert json_response(conn, 200) ==
               UserView.render("show.json", %{user: blocked, for: current_user})
eal's avatar
eal committed
625 626 627 628 629
    end
  end

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

eal's avatar
eal committed
631
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
632
      conn = post(conn, "/api/blocks/destroy.json")
eal's avatar
eal committed
633 634 635 636 637 638
      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
639
      {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
eal's avatar
eal committed
640 641
      assert User.blocks?(current_user, blocked)

lain's avatar
lain committed
642 643 644 645
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
eal's avatar
eal committed
646 647

      current_user = Repo.get(User, current_user.id)
lain's avatar
lain committed
648
      assert current_user.info.blocks == []
lain's avatar
lain committed
649 650 651

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

dtluna's avatar
dtluna committed
655 656
  describe "GET /help/test.json" do
    test "returns \"ok\"", %{conn: conn} do
lain's avatar
lain committed
657
      conn = get(conn, "/api/help/test.json")
dtluna's avatar
dtluna committed
658
      assert json_response(conn, 200) == "ok"
lain's avatar
lain committed
659
    end
660 661
  end

lain's avatar
lain committed
662 663
  describe "POST /api/qvitter/update_avatar.json" do
    setup [:valid_user]
lain's avatar
lain committed
664

lain's avatar
lain committed
665
    test "without valid credentials", %{conn: conn} do
lain's avatar
lain committed
666
      conn = post(conn, "/api/qvitter/update_avatar.json")
lain's avatar
lain committed
667 668 669 670
      assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
    end

    test "with credentials", %{conn: conn, user: current_user} do
lain's avatar
lain committed
671
      avatar_image = File.read!("test/fixtures/avatar_data_uri")
lain's avatar
lain committed
672 673 674 675 676

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

      current_user = Repo.get(User, current_user.id)
      assert is_map(current_user.avatar)
lain's avatar
lain committed
680 681 682

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

686 687 688 689 690 691 692 693 694
  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
695
      response =
696 697 698
        conn
        |> with_credentials(current_user.nickname, "test")
        |> get("/api/qvitter/mutes.json")
Maksim's avatar
Maksim committed
699
        |> json_response(200)
Vivian Lim's avatar
Vivian Lim committed
700

Maksim's avatar
Maksim committed
701
      assert [] = response
702 703 704
    end
  end

lain's avatar
lain committed
705 706
  describe "POST /api/favorites/create/:id" do
    setup [:valid_user]
lain's avatar
lain committed
707

lain's avatar
lain committed
708 709
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
710
      conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
lain's avatar
lain committed
711 712 713 714 715 716
      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
717 718 719 720
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/create/#{note_activity.id}.json")
lain's avatar
lain committed
721 722 723

      assert json_response(conn, 200)
    end
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741

    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
742 743
  end

lain's avatar
lain committed
744 745
  describe "POST /api/favorites/destroy/:id" do
    setup [:valid_user]
lain's avatar
lain committed
746

lain's avatar
lain committed
747 748
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
749
      conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
lain's avatar
lain committed
750 751 752 753 754 755 756 757
      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
758 759 760 761
      conn =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post("/api/favorites/destroy/#{note_activity.id}.json")
lain's avatar
lain committed
762 763 764 765 766

      assert json_response(conn, 200)
    end
  end

lain's avatar
lain committed
767 768
  describe "POST /api/statuses/retweet/:id" do
    setup [:valid_user]
lain's avatar
lain committed
769

lain's avatar
lain committed
770 771
    test "without valid credentials", %{conn: conn} do
      note_activity = insert(:note_activity)
lain's avatar
lain committed
772
      conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
lain's avatar
lain committed
773 774 775 776 777 778
      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
779
      request_path = "/api/statuses/retweet/#{note_activity.id}.json"
lain's avatar
lain committed
780

lain's avatar
lain committed
781 782 783 784 785
      response =
        conn
        |> with_credentials(current_user.nickname, "test")
        |> post(request_path)

dtluna's avatar
dtluna committed
786
      activity = Repo.get(Activity, note_activity.id)
lain's avatar
lain committed
787
      activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
lain's avatar
lain committed
788 789 790

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

794 795 796 797 798
  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
799
      conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
      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

828 829 830 831 832 833 834 835 836 837 838
  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
839 840 841
      conn =
        conn
        |> post("/api/account/register", data)
842 843 844 845

      user = json_response(conn, 200)

      fetched_user = Repo.get_by(User, nickname: "lain")
dtluna's avatar
dtluna committed
846
      assert user == UserView.render("show.json", %{user: fetched_user})
847 848 849 850 851 852 853 854 855 856 857
    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
858 859 860
      conn =
        conn
        |> post("/api/account/register", data)
861 862 863 864

      errors = json_response(conn, 400)

      assert is_binary(errors["error"])
dtluna's avatar
dtluna committed
865 866 867
    end
  end

868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
  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

908
  describe "GET /api/account/confirm_email/:id/:token" do
909 910
    setup do
      user = insert(:user)
911
      info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
912 913 914 915 916 917 918 919 920 921 922 923 924

      {: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
925
      conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
926 927 928 929 930

      assert 302 == conn.status
    end

    test "it confirms the user account", %{conn: conn, user: user} do
931
      get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
932 933 934 935 936 937

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

      refute user.info.confirmation_pending
      refute user.info.confirmation_token
    end
938 939 940 941 942 943 944 945 946 947 948 949

    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
950 951 952 953
  end

  describe "POST /api/account/resend_confirmation_email" do
    setup do
954 955 956 957 958 959 960
      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

961
      user = insert(:user)
962
      info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990

      {: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
991 992 993
  describe "GET /api/externalprofile/show" do
    test "it returns the user", %{conn: conn} do
      user = insert(:user)
994
      other_user = insert(:user)
lain's avatar
lain committed
995

lain's avatar
lain committed
996 997 998 999
      conn =
        conn
        |> assign(:user, user)
        |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
lain's avatar
lain committed
1000

1001
      assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
lain's avatar
lain committed
1002 1003 1004
    end
  end

lain's avatar
lain committed
1005 1006 1007 1008 1009
  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
1010
      _not_follower = insert(:user)
lain's avatar
lain committed
1011 1012 1013 1014

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

lain's avatar
lain committed
1015 1016 1017 1018
      conn =
        conn
        |> assign(:user, user)
        |> get("/api/statuses/followers")
lain's avatar
lain committed
1019

lain's avatar
lain committed
1020 1021 1022
      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
1023
    end
lain's avatar
lain committed
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 1051 1052 1053 1054 1055

    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?(
               MapSet.new(json_response(conn, 200)),
               MapSet.new(
                 UserView.render("index.json", %{
                   users: [follower_one, follower_two],
                   for: not_follower
                 })
               )
             )
    end

    test "it returns empty for a hidden network", %{conn: conn} do
      user = insert(:user, %{info: %{hide_network: true}})
      follower_one = insert(:user)
      follower_two = insert(:user)
      not_follower = insert(:user)

Maksim's avatar
Maksim committed
1056 1057
      {:ok, _follower_one} = User.follow(follower_one, user)
      {:ok, _follower_two} = User.follow(follower_two, user)
lain's avatar
lain committed
1058

Maksim's avatar
Maksim committed
1059
      response =
lain's avatar
lain committed
1060 1061 1062
        conn
        |> assign(:user, not_follower)
        |> get("/api/statuses/followers", %{"user_id" => user.id})
Maksim's avatar
Maksim committed
1063
        |> json_response(200)
lain's avatar
lain committed
1064

Maksim's avatar
Maksim committed
1065
      assert [] == response
lain's avatar
lain committed
1066
    end
1067 1068 1069 1070 1071 1072 1073

    test "it returns the followers for a hidden network if requested by the user themselves", %{
      conn: conn
    } do
      user = insert(:user, %{info: %{hide_network: true}})
      follower_one = insert(:user)
      follower_two = insert(:user)
Maksim's avatar
Maksim committed
1074
      _not_follower = insert(:user)
1075

Maksim's avatar
Maksim committed
1076 1077
      {:ok, _follower_one} = User.follow(follower_one, user)
      {:ok, _follower_two} = User.follow(follower_two, user)
1078 1079 1080 1081 1082 1083 1084 1085

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

      refute [] == json_response(conn, 200)
    end
lain's avatar
lain committed
1086 1087
  end

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
  describe "GET /api/statuses/blocks" do
    test "it returns the list of users blocked by requester", %{conn: conn} do
      user = insert(:user)
      other_user = insert(:user)

      {:ok, user} = User.block(user, other_user)

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

      expected = UserView.render("index.json", %{users: [other_user], for: user})
      result = json_response(conn, 200)
      assert Enum.sort(expected) == Enum.sort(result)
    end
  end

lain's avatar
lain committed
1106
  describe "GET /api/statuses/friends" do
eal's avatar
eal committed
1107
    test "it returns the logged in user's friends", %{conn: conn} do
lain's avatar
lain committed
1108 1109 1110
      user = insert(:user)
      followed_one = insert(:user)
      followed_two = insert(:user)
lain's avatar
lain committed
1111
      _not_followed = insert(:user)
lain's avatar
lain committed
1112 1113