summaryrefslogtreecommitdiff
path: root/test/web/pleroma_api/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'test/web/pleroma_api/controllers')
-rw-r--r--test/web/pleroma_api/controllers/account_controller_test.exs395
-rw-r--r--test/web/pleroma_api/controllers/emoji_api_controller_test.exs463
-rw-r--r--test/web/pleroma_api/controllers/mascot_controller_test.exs77
-rw-r--r--test/web/pleroma_api/controllers/pleroma_api_controller_test.exs150
-rw-r--r--test/web/pleroma_api/controllers/scrobble_controller_test.exs63
5 files changed, 1148 insertions, 0 deletions
diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs
new file mode 100644
index 000000000..3b4665afd
--- /dev/null
+++ b/test/web/pleroma_api/controllers/account_controller_test.exs
@@ -0,0 +1,395 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Config
+ alias Pleroma.Repo
+ alias Pleroma.Tests.ObanHelpers
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+ import Swoosh.TestAssertions
+
+ @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
+
+ describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
+ setup do
+ {:ok, user} =
+ insert(:user)
+ |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
+ |> Repo.update()
+
+ assert user.info.confirmation_pending
+
+ [user: user]
+ end
+
+ clear_config([:instance, :account_activation_required]) do
+ Config.put([:instance, :account_activation_required], true)
+ end
+
+ test "resend account confirmation email", %{conn: conn, user: user} do
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
+ |> json_response(:no_content)
+
+ ObanHelpers.perform_all()
+
+ email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
+
+ assert_email_sent(
+ from: {instance_name, notify_email},
+ to: {user.name, user.email},
+ html_body: email.html_body
+ )
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_avatar" do
+ test "user avatar can be set", %{conn: conn} do
+ user = insert(:user)
+ avatar_image = File.read!("test/fixtures/avatar_data_uri")
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
+
+ user = refresh_record(user)
+
+ assert %{
+ "name" => _,
+ "type" => _,
+ "url" => [
+ %{
+ "href" => _,
+ "mediaType" => _,
+ "type" => _
+ }
+ ]
+ } = user.avatar
+
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "user avatar can be reset", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
+
+ user = User.get_cached_by_id(user.id)
+
+ assert user.avatar == nil
+
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_banner" do
+ test "can set profile banner", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
+
+ user = refresh_record(user)
+ assert user.info.banner["type"] == "Image"
+
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "can reset profile banner", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
+
+ user = refresh_record(user)
+ assert user.info.banner == %{}
+
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "PATCH /api/v1/pleroma/accounts/update_background" do
+ test "background image can be set", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
+
+ user = refresh_record(user)
+ assert user.info.background["type"] == "Image"
+ assert %{"url" => _} = json_response(conn, 200)
+ end
+
+ test "background image can be reset", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
+
+ user = refresh_record(user)
+ assert user.info.background == %{}
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
+ end
+
+ describe "getting favorites timeline of specified user" do
+ setup do
+ [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
+ [current_user: current_user, user: user]
+ end
+
+ test "returns list of statuses favorited by specified user", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ [activity | _] = insert_pair(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ [like] = response
+
+ assert length(response) == 1
+ assert like["id"] == activity.id
+ end
+
+ test "returns favorites for specified user_id when user is not logged in", %{
+ conn: conn,
+ user: user
+ } do
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ response =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert length(response) == 1
+ end
+
+ test "returns favorited DM only when user is logged in and he is one of recipients", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ {:ok, direct} =
+ CommonAPI.post(current_user, %{
+ "status" => "Hi @#{user.nickname}!",
+ "visibility" => "direct"
+ })
+
+ CommonAPI.favorite(direct.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert length(response) == 1
+
+ anonymous_response =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(anonymous_response)
+ end
+
+ test "does not return others' favorited DM when user is not one of recipients", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ user_two = insert(:user)
+
+ {:ok, direct} =
+ CommonAPI.post(user_two, %{
+ "status" => "Hi @#{user.nickname}!",
+ "visibility" => "direct"
+ })
+
+ CommonAPI.favorite(direct.id, user)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(response)
+ end
+
+ test "paginates favorites using since_id and max_id", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ activities = insert_list(10, :note_activity)
+
+ Enum.each(activities, fn activity ->
+ CommonAPI.favorite(activity.id, user)
+ end)
+
+ third_activity = Enum.at(activities, 2)
+ seventh_activity = Enum.at(activities, 6)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
+ since_id: third_activity.id,
+ max_id: seventh_activity.id
+ })
+ |> json_response(:ok)
+
+ assert length(response) == 3
+ refute third_activity in response
+ refute seventh_activity in response
+ end
+
+ test "limits favorites using limit parameter", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ 7
+ |> insert_list(:note_activity)
+ |> Enum.each(fn activity ->
+ CommonAPI.favorite(activity.id, user)
+ end)
+
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
+ |> json_response(:ok)
+
+ assert length(response) == 3
+ end
+
+ test "returns empty response when user does not have any favorited statuses", %{
+ conn: conn,
+ current_user: current_user,
+ user: user
+ } do
+ response =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(:ok)
+
+ assert Enum.empty?(response)
+ end
+
+ test "returns 404 error when specified user is not exist", %{conn: conn} do
+ conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
+
+ assert json_response(conn, 404) == %{"error" => "Record not found"}
+ end
+
+ test "returns 403 error when user has hidden own favorites", %{
+ conn: conn,
+ current_user: current_user
+ } do
+ user = insert(:user, %{info: %{hide_favorites: true}})
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ conn =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+
+ assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ end
+
+ test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
+ user = insert(:user)
+ activity = insert(:note_activity)
+ CommonAPI.favorite(activity.id, user)
+
+ conn =
+ conn
+ |> assign(:user, current_user)
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+
+ assert user.info.hide_favorites
+ assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
+ end
+ end
+
+ describe "subscribing / unsubscribing" do
+ test "subscribing / unsubscribing to a user", %{conn: conn} do
+ user = insert(:user)
+ subscription_target = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
+
+ assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
+
+ assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
+ end
+ end
+
+ describe "subscribing" do
+ test "returns 404 when subscription_target not found", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/target_id/subscribe")
+
+ assert %{"error" => "Record not found"} = json_response(conn, 404)
+ end
+ end
+
+ describe "unsubscribing" do
+ test "returns 404 when subscription_target not found", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
+
+ assert %{"error" => "Record not found"} = json_response(conn, 404)
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
new file mode 100644
index 000000000..5f74460e8
--- /dev/null
+++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
@@ -0,0 +1,463 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Tesla.Mock
+
+ import Pleroma.Factory
+
+ @emoji_dir_path Path.join(
+ Pleroma.Config.get!([:instance, :static_dir]),
+ "emoji"
+ )
+
+ test "shared & non-shared pack information in list_packs is ok" do
+ conn = build_conn()
+ resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+ assert Map.has_key?(resp, "test_pack")
+
+ pack = resp["test_pack"]
+
+ assert Map.has_key?(pack["pack"], "download-sha256")
+ assert pack["pack"]["can-download"]
+
+ assert pack["files"] == %{"blank" => "blank.png"}
+
+ # Non-shared pack
+
+ assert Map.has_key?(resp, "test_pack_nonshared")
+
+ pack = resp["test_pack_nonshared"]
+
+ refute pack["pack"]["shared"]
+ refute pack["pack"]["can-download"]
+ end
+
+ test "listing remote packs" do
+ admin = insert(:user, info: %{is_admin: true})
+ conn = build_conn() |> assign(:user, admin)
+
+ resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
+ json(resp)
+ end)
+
+ assert conn
+ |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"})
+ |> json_response(200) == resp
+ end
+
+ test "downloading a shared pack from download_shared" do
+ conn = build_conn()
+
+ resp =
+ conn
+ |> get(emoji_api_path(conn, :download_shared, "test_pack"))
+ |> response(200)
+
+ {:ok, arch} = :zip.unzip(resp, [:memory])
+
+ assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
+ assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
+ end
+
+ test "downloading shared & unshared packs from another instance via download_from, deleting them" do
+ on_exit(fn ->
+ File.rm_rf!("#{@emoji_dir_path}/test_pack2")
+ File.rm_rf!("#{@emoji_dir_path}/test_pack_nonshared2")
+ end)
+
+ mock(fn
+ %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: []}})
+
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/list"
+ } ->
+ conn = build_conn()
+
+ conn
+ |> get(emoji_api_path(conn, :list_packs))
+ |> json_response(200)
+ |> json()
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/download_shared/test_pack"
+ } ->
+ conn = build_conn()
+
+ conn
+ |> get(emoji_api_path(conn, :download_shared, "test_pack"))
+ |> response(200)
+ |> text()
+
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
+ end)
+
+ admin = insert(:user, info: %{is_admin: true})
+
+ conn = build_conn() |> assign(:user, admin)
+
+ assert (conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ emoji_api_path(
+ conn,
+ :download_from
+ ),
+ %{
+ instance_address: "https://old-instance",
+ pack_name: "test_pack",
+ as: "test_pack2"
+ }
+ |> Jason.encode!()
+ )
+ |> json_response(500))["error"] =~ "does not support"
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ emoji_api_path(
+ conn,
+ :download_from
+ ),
+ %{
+ instance_address: "https://example.com",
+ pack_name: "test_pack",
+ as: "test_pack2"
+ }
+ |> Jason.encode!()
+ )
+ |> json_response(200) == "ok"
+
+ assert File.exists?("#{@emoji_dir_path}/test_pack2/pack.json")
+ assert File.exists?("#{@emoji_dir_path}/test_pack2/blank.png")
+
+ assert conn
+ |> delete(emoji_api_path(conn, :delete, "test_pack2"))
+ |> json_response(200) == "ok"
+
+ refute File.exists?("#{@emoji_dir_path}/test_pack2")
+
+ # non-shared, downloaded from the fallback URL
+
+ conn = build_conn() |> assign(:user, admin)
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> post(
+ emoji_api_path(
+ conn,
+ :download_from
+ ),
+ %{
+ instance_address: "https://example.com",
+ pack_name: "test_pack_nonshared",
+ as: "test_pack_nonshared2"
+ }
+ |> Jason.encode!()
+ )
+ |> json_response(200) == "ok"
+
+ assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/pack.json")
+ assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/blank.png")
+
+ assert conn
+ |> delete(emoji_api_path(conn, :delete, "test_pack_nonshared2"))
+ |> json_response(200) == "ok"
+
+ refute File.exists?("#{@emoji_dir_path}/test_pack_nonshared2")
+ end
+
+ describe "updating pack metadata" do
+ setup do
+ pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
+ original_content = File.read!(pack_file)
+
+ on_exit(fn ->
+ File.write!(pack_file, original_content)
+ end)
+
+ {:ok,
+ admin: insert(:user, info: %{is_admin: true}),
+ pack_file: pack_file,
+ new_data: %{
+ "license" => "Test license changed",
+ "homepage" => "https://pleroma.social",
+ "description" => "Test description",
+ "share-files" => false
+ }}
+ end
+
+ test "for a pack without a fallback source", ctx do
+ conn = build_conn()
+
+ assert conn
+ |> assign(:user, ctx[:admin])
+ |> post(
+ emoji_api_path(conn, :update_metadata, "test_pack"),
+ %{
+ "new_data" => ctx[:new_data]
+ }
+ )
+ |> json_response(200) == ctx[:new_data]
+
+ assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
+ end
+
+ test "for a pack with a fallback source", ctx do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
+ end)
+
+ new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
+
+ new_data_with_sha =
+ Map.put(
+ new_data,
+ "fallback-src-sha256",
+ "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
+ )
+
+ conn = build_conn()
+
+ assert conn
+ |> assign(:user, ctx[:admin])
+ |> post(
+ emoji_api_path(conn, :update_metadata, "test_pack"),
+ %{
+ "new_data" => new_data
+ }
+ )
+ |> json_response(200) == new_data_with_sha
+
+ assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
+ end
+
+ test "when the fallback source doesn't have all the files", ctx do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
+ text(empty_arch)
+ end)
+
+ new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
+
+ conn = build_conn()
+
+ assert (conn
+ |> assign(:user, ctx[:admin])
+ |> post(
+ emoji_api_path(conn, :update_metadata, "test_pack"),
+ %{
+ "new_data" => new_data
+ }
+ )
+ |> json_response(:bad_request))["error"] =~ "does not have all"
+ end
+ end
+
+ test "updating pack files" do
+ pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
+ original_content = File.read!(pack_file)
+
+ on_exit(fn ->
+ File.write!(pack_file, original_content)
+
+ File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
+ File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
+ File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
+ end)
+
+ admin = insert(:user, info: %{is_admin: true})
+
+ conn = build_conn()
+
+ same_name = %{
+ "action" => "add",
+ "shortcode" => "blank",
+ "filename" => "dir/blank.png",
+ "file" => %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_dir_path}/test_pack/blank.png"
+ }
+ }
+
+ different_name = %{same_name | "shortcode" => "blank_2"}
+
+ conn = conn |> assign(:user, admin)
+
+ assert (conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
+ |> json_response(:conflict))["error"] =~ "already exists"
+
+ assert conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
+ |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"}
+
+ assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
+
+ assert conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+ "action" => "update",
+ "shortcode" => "blank_2",
+ "new_shortcode" => "blank_3",
+ "new_filename" => "dir_2/blank_3.png"
+ })
+ |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"}
+
+ refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
+ assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
+
+ assert conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+ "action" => "remove",
+ "shortcode" => "blank_3"
+ })
+ |> json_response(200) == %{"blank" => "blank.png"}
+
+ refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
+
+ mock(fn
+ %{
+ method: :get,
+ url: "https://test-blank/blank_url.png"
+ } ->
+ text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
+ end)
+
+ # The name should be inferred from the URL ending
+ from_url = %{
+ "action" => "add",
+ "shortcode" => "blank_url",
+ "file" => "https://test-blank/blank_url.png"
+ }
+
+ assert conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
+ |> json_response(200) == %{
+ "blank" => "blank.png",
+ "blank_url" => "blank_url.png"
+ }
+
+ assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+
+ assert conn
+ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
+ "action" => "remove",
+ "shortcode" => "blank_url"
+ })
+ |> json_response(200) == %{"blank" => "blank.png"}
+
+ refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+ end
+
+ test "creating and deleting a pack" do
+ on_exit(fn ->
+ File.rm_rf!("#{@emoji_dir_path}/test_created")
+ end)
+
+ admin = insert(:user, info: %{is_admin: true})
+
+ conn = build_conn() |> assign(:user, admin)
+
+ assert conn
+ |> put_req_header("content-type", "application/json")
+ |> put(
+ emoji_api_path(
+ conn,
+ :create,
+ "test_created"
+ )
+ )
+ |> json_response(200) == "ok"
+
+ assert File.exists?("#{@emoji_dir_path}/test_created/pack.json")
+
+ assert Jason.decode!(File.read!("#{@emoji_dir_path}/test_created/pack.json")) == %{
+ "pack" => %{},
+ "files" => %{}
+ }
+
+ assert conn
+ |> delete(emoji_api_path(conn, :delete, "test_created"))
+ |> json_response(200) == "ok"
+
+ refute File.exists?("#{@emoji_dir_path}/test_created/pack.json")
+ end
+
+ test "filesystem import" do
+ on_exit(fn ->
+ File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt")
+ File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+ end)
+
+ conn = build_conn()
+ resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+ refute Map.has_key?(resp, "test_pack_for_import")
+
+ admin = insert(:user, info: %{is_admin: true})
+
+ assert conn
+ |> assign(:user, admin)
+ |> post(emoji_api_path(conn, :import_from_fs))
+ |> json_response(200) == ["test_pack_for_import"]
+
+ resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+ assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
+
+ File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+ refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+
+ emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png"
+
+ File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
+
+ assert conn
+ |> assign(:user, admin)
+ |> post(emoji_api_path(conn, :import_from_fs))
+ |> json_response(200) == ["test_pack_for_import"]
+
+ resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+
+ assert resp["test_pack_for_import"]["files"] == %{
+ "blank" => "blank.png",
+ "blank2" => "blank.png"
+ }
+ end
+end
diff --git a/test/web/pleroma_api/controllers/mascot_controller_test.exs b/test/web/pleroma_api/controllers/mascot_controller_test.exs
new file mode 100644
index 000000000..ae9539b04
--- /dev/null
+++ b/test/web/pleroma_api/controllers/mascot_controller_test.exs
@@ -0,0 +1,77 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.MascotControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.User
+
+ import Pleroma.Factory
+
+ test "mascot upload", %{conn: conn} do
+ user = insert(:user)
+
+ non_image_file = %Plug.Upload{
+ content_type: "audio/mpeg",
+ path: Path.absname("test/fixtures/sound.mp3"),
+ filename: "sound.mp3"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
+
+ assert json_response(conn, 415)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert %{"id" => _, "type" => image} = json_response(conn, 200)
+ end
+
+ test "mascot retrieving", %{conn: conn} do
+ user = insert(:user)
+ # When user hasn't set a mascot, we should just get pleroma tan back
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url} = json_response(conn, 200)
+ assert url =~ "pleroma-fox-tan-smol"
+
+ # When a user sets their mascot, we should get that back
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
+ assert url =~ "an_image"
+ end
+end
diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
new file mode 100644
index 000000000..7eaeda4a0
--- /dev/null
+++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
@@ -0,0 +1,150 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Conversation.Participation
+ alias Pleroma.Notification
+ alias Pleroma.Repo
+ alias Pleroma.Web.CommonAPI
+
+ import Pleroma.Factory
+
+ test "/api/v1/pleroma/conversations/:id", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
+
+ [participation] = Participation.for_user(other_user)
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/pleroma/conversations/#{participation.id}")
+ |> json_response(200)
+
+ assert result["id"] == participation.id |> to_string()
+ end
+
+ test "/api/v1/pleroma/conversations/:id/statuses", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+ third_user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{"status" => "Hi @#{third_user.nickname}!", "visibility" => "direct"})
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}!", "visibility" => "direct"})
+
+ [participation] = Participation.for_user(other_user)
+
+ {:ok, activity_two} =
+ CommonAPI.post(other_user, %{
+ "status" => "Hi!",
+ "in_reply_to_status_id" => activity.id,
+ "in_reply_to_conversation_id" => participation.id
+ })
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> get("/api/v1/pleroma/conversations/#{participation.id}/statuses")
+ |> json_response(200)
+
+ assert length(result) == 2
+
+ id_one = activity.id
+ id_two = activity_two.id
+ assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result
+ end
+
+ test "PATCH /api/v1/pleroma/conversations/:id", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _activity} = CommonAPI.post(user, %{"status" => "Hi", "visibility" => "direct"})
+
+ [participation] = Participation.for_user(user)
+
+ participation = Repo.preload(participation, :recipients)
+
+ assert [user] == participation.recipients
+ assert other_user not in participation.recipients
+
+ result =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/conversations/#{participation.id}", %{
+ "recipients" => [user.id, other_user.id]
+ })
+ |> json_response(200)
+
+ assert result["id"] == participation.id |> to_string
+
+ [participation] = Participation.for_user(user)
+ participation = Repo.preload(participation, :recipients)
+
+ assert user in participation.recipients
+ assert other_user in participation.recipients
+ end
+
+ describe "POST /api/v1/pleroma/notifications/read" do
+ test "it marks a single notification as read", %{conn: conn} do
+ user1 = insert(:user)
+ user2 = insert(:user)
+ {:ok, activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
+ {:ok, activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
+ {:ok, [notification1]} = Notification.create_notifications(activity1)
+ {:ok, [notification2]} = Notification.create_notifications(activity2)
+
+ response =
+ conn
+ |> assign(:user, user1)
+ |> post("/api/v1/pleroma/notifications/read", %{"id" => "#{notification1.id}"})
+ |> json_response(:ok)
+
+ assert %{"pleroma" => %{"is_seen" => true}} = response
+ assert Repo.get(Notification, notification1.id).seen
+ refute Repo.get(Notification, notification2.id).seen
+ end
+
+ test "it marks multiple notifications as read", %{conn: conn} do
+ user1 = insert(:user)
+ user2 = insert(:user)
+ {:ok, _activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
+ {:ok, _activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
+ {:ok, _activity3} = CommonAPI.post(user2, %{"status" => "HIE @#{user1.nickname}"})
+
+ [notification3, notification2, notification1] = Notification.for_user(user1, %{limit: 3})
+
+ [response1, response2] =
+ conn
+ |> assign(:user, user1)
+ |> post("/api/v1/pleroma/notifications/read", %{"max_id" => "#{notification2.id}"})
+ |> json_response(:ok)
+
+ assert %{"pleroma" => %{"is_seen" => true}} = response1
+ assert %{"pleroma" => %{"is_seen" => true}} = response2
+ assert Repo.get(Notification, notification1.id).seen
+ assert Repo.get(Notification, notification2.id).seen
+ refute Repo.get(Notification, notification3.id).seen
+ end
+
+ test "it returns error when notification not found", %{conn: conn} do
+ user1 = insert(:user)
+
+ response =
+ conn
+ |> assign(:user, user1)
+ |> post("/api/v1/pleroma/notifications/read", %{"id" => "22222222222222"})
+ |> json_response(:bad_request)
+
+ assert response == %{"error" => "Cannot get notification"}
+ end
+ end
+end
diff --git a/test/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
new file mode 100644
index 000000000..881f8012c
--- /dev/null
+++ b/test/web/pleroma_api/controllers/scrobble_controller_test.exs
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Web.CommonAPI
+ import Pleroma.Factory
+
+ describe "POST /api/v1/pleroma/scrobble" do
+ test "works correctly", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/scrobble", %{
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio",
+ "length" => "180000"
+ })
+
+ assert %{"title" => "lain radio episode 1"} = json_response(conn, 200)
+ end
+ end
+
+ describe "GET /api/v1/pleroma/accounts/:id/scrobbles" do
+ test "works correctly", %{conn: conn} do
+ user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 1",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 2",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ {:ok, _activity} =
+ CommonAPI.listen(user, %{
+ "title" => "lain radio episode 3",
+ "artist" => "lain",
+ "album" => "lain radio"
+ })
+
+ conn =
+ conn
+ |> get("/api/v1/pleroma/accounts/#{user.id}/scrobbles")
+
+ result = json_response(conn, 200)
+
+ assert length(result) == 3
+ end
+ end
+end