X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Fweb%2Fmastodon_api%2Fmastodon_api_controller_test.exs;h=d9d8dafdbebafb352480f1e30faf37901b621c1a;hb=ce73d5f6a53826c85e46bbe45835b99ceaab67cd;hp=707723421fab1e06d46ceddd55118727f4f2c1a8;hpb=135c19676994defd6de729a497af5fb1f9c7b0ad;p=akkoma diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 707723421..d9d8dafdb 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -23,6 +23,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do import Pleroma.Factory import ExUnit.CaptureLog import Tesla.Mock + import Swoosh.TestAssertions + + @image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" setup do mock(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -33,7 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) following = insert(:user) - {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"}) + {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"}) conn = conn @@ -56,7 +59,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do following = insert(:user) capture_log(fn -> - {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"}) + {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"}) {:ok, [_activity]} = OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") @@ -94,56 +97,186 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> json_response(403) == %{"error" => "This resource requires authentication."} end - test "posting a status", %{conn: conn} do - user = insert(:user) + describe "posting statuses" do + setup do + user = insert(:user) - idempotency_key = "Pikachu rocks!" + conn = + build_conn() + |> assign(:user, user) - conn_one = - conn - |> assign(:user, user) - |> put_req_header("idempotency-key", idempotency_key) - |> post("/api/v1/statuses", %{ - "status" => "cofe", - "spoiler_text" => "2hu", - "sensitive" => "false" - }) + [conn: conn] + end - {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key) - # Six hours - assert ttl > :timer.seconds(6 * 60 * 60 - 1) + test "posting a status", %{conn: conn} do + idempotency_key = "Pikachu rocks!" - assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = - json_response(conn_one, 200) + conn_one = + conn + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) - assert Activity.get_by_id(id) + {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key) + # Six hours + assert ttl > :timer.seconds(6 * 60 * 60 - 1) - conn_two = - conn - |> assign(:user, user) - |> put_req_header("idempotency-key", idempotency_key) - |> post("/api/v1/statuses", %{ - "status" => "cofe", - "spoiler_text" => "2hu", - "sensitive" => "false" - }) + assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = + json_response(conn_one, 200) + + assert Activity.get_by_id(id) - assert %{"id" => second_id} = json_response(conn_two, 200) + conn_two = + conn + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) - assert id == second_id + assert %{"id" => second_id} = json_response(conn_two, 200) + assert id == second_id - conn_three = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{ - "status" => "cofe", - "spoiler_text" => "2hu", - "sensitive" => "false" - }) + conn_three = + conn + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + assert %{"id" => third_id} = json_response(conn_three, 200) + refute id == third_id + end + + test "replying to a status", %{conn: conn} do + user = insert(:user) + {:ok, replied_to} = CommonAPI.post(user, %{"status" => "cofe"}) + + conn = + conn + |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) + + assert %{"content" => "xD", "id" => id} = json_response(conn, 200) + + activity = Activity.get_by_id(id) + + assert activity.data["context"] == replied_to.data["context"] + assert Activity.get_in_reply_to_activity(activity).id == replied_to.id + end + + test "replying to a direct message with visibility other than direct", %{conn: conn} do + user = insert(:user) + {:ok, replied_to} = CommonAPI.post(user, %{"status" => "suya..", "visibility" => "direct"}) + + Enum.each(["public", "private", "unlisted"], fn visibility -> + conn = + conn + |> post("/api/v1/statuses", %{ + "status" => "@#{user.nickname} hey", + "in_reply_to_id" => replied_to.id, + "visibility" => visibility + }) + + assert json_response(conn, 422) == %{"error" => "The message visibility must be direct"} + end) + end + + test "posting a status with an invalid in_reply_to_id", %{conn: conn} do + conn = + conn + |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""}) + + assert %{"content" => "xD", "id" => id} = json_response(conn, 200) + assert Activity.get_by_id(id) + end + + test "posting a sensitive status", %{conn: conn} do + conn = + conn + |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) + + assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200) + assert Activity.get_by_id(id) + end + + test "posting a fake status", %{conn: conn} do + real_conn = + conn + |> post("/api/v1/statuses", %{ + "status" => + "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it" + }) - assert %{"id" => third_id} = json_response(conn_three, 200) + real_status = json_response(real_conn, 200) - refute id == third_id + assert real_status + assert Object.get_by_ap_id(real_status["uri"]) + + real_status = + real_status + |> Map.put("id", nil) + |> Map.put("url", nil) + |> Map.put("uri", nil) + |> Map.put("created_at", nil) + |> Kernel.put_in(["pleroma", "conversation_id"], nil) + + fake_conn = + conn + |> post("/api/v1/statuses", %{ + "status" => + "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it", + "preview" => true + }) + + fake_status = json_response(fake_conn, 200) + + assert fake_status + refute Object.get_by_ap_id(fake_status["uri"]) + + fake_status = + fake_status + |> Map.put("id", nil) + |> Map.put("url", nil) + |> Map.put("uri", nil) + |> Map.put("created_at", nil) + |> Kernel.put_in(["pleroma", "conversation_id"], nil) + + assert real_status == fake_status + end + + test "posting a status with OGP link preview", %{conn: conn} do + Pleroma.Config.put([:rich_media, :enabled], true) + + conn = + conn + |> post("/api/v1/statuses", %{ + "status" => "https://example.com/ogp" + }) + + assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200) + assert Activity.get_by_id(id) + Pleroma.Config.put([:rich_media, :enabled], false) + end + + test "posting a direct status", %{conn: conn} do + user2 = insert(:user) + content = "direct cofe @#{user2.nickname}" + + conn = + conn + |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"}) + + assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200) + assert activity = Activity.get_by_id(id) + assert activity.recipients == [user2.ap_id, conn.assigns[:user].ap_id] + assert activity.data["to"] == [user2.ap_id] + assert activity.data["cc"] == [] + end end describe "posting polls" do @@ -243,100 +376,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end end - test "posting a sensitive status", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) - - assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200) - assert Activity.get_by_id(id) - end - - test "posting a fake status", %{conn: conn} do - user = insert(:user) - - real_conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{ - "status" => - "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it" - }) - - real_status = json_response(real_conn, 200) - - assert real_status - assert Object.get_by_ap_id(real_status["uri"]) - - real_status = - real_status - |> Map.put("id", nil) - |> Map.put("url", nil) - |> Map.put("uri", nil) - |> Map.put("created_at", nil) - |> Kernel.put_in(["pleroma", "conversation_id"], nil) - - fake_conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{ - "status" => - "\"Tenshi Eating a Corndog\" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it", - "preview" => true - }) - - fake_status = json_response(fake_conn, 200) - - assert fake_status - refute Object.get_by_ap_id(fake_status["uri"]) - - fake_status = - fake_status - |> Map.put("id", nil) - |> Map.put("url", nil) - |> Map.put("uri", nil) - |> Map.put("created_at", nil) - |> Kernel.put_in(["pleroma", "conversation_id"], nil) - - assert real_status == fake_status - end - - test "posting a status with OGP link preview", %{conn: conn} do - Pleroma.Config.put([:rich_media, :enabled], true) - user = insert(:user) - - conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{ - "status" => "http://example.com/ogp" - }) - - assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200) - assert Activity.get_by_id(id) - Pleroma.Config.put([:rich_media, :enabled], false) - end - - test "posting a direct status", %{conn: conn} do - user1 = insert(:user) - user2 = insert(:user) - content = "direct cofe @#{user2.nickname}" - - conn = - conn - |> assign(:user, user1) - |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"}) - - assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200) - assert activity = Activity.get_by_id(id) - assert activity.recipients == [user2.ap_id, user1.ap_id] - assert activity.data["to"] == [user2.ap_id] - assert activity.data["cc"] == [] - end - test "direct timeline", %{conn: conn} do user_one = insert(:user) user_two = insert(:user) @@ -501,39 +540,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert status["id"] == direct.id end - test "replying to a status", %{conn: conn} do - user = insert(:user) - - {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"}) - - conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) - - assert %{"content" => "xD", "id" => id} = json_response(conn, 200) - - activity = Activity.get_by_id(id) - - assert activity.data["context"] == replied_to.data["context"] - assert Activity.get_in_reply_to_activity(activity).id == replied_to.id - end - - test "posting a status with an invalid in_reply_to_id", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""}) - - assert %{"content" => "xD", "id" => id} = json_response(conn, 200) - - activity = Activity.get_by_id(id) - - assert activity - end - test "verify_credentials", %{conn: conn} do user = insert(:user) @@ -581,6 +587,101 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert expected == json_response(conn, 200) end + 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 + + 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 + + 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 + test "creates an oauth app", %{conn: conn} do user = insert(:user) app_attrs = build(:oauth_app) @@ -904,8 +1005,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do test "list timeline", %{conn: conn} do user = insert(:user) other_user = insert(:user) - {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."}) - {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."}) + {:ok, _activity_one} = CommonAPI.post(user, %{"status" => "Marisa is cute."}) + {:ok, activity_two} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."}) {:ok, list} = Pleroma.List.create("name", user) {:ok, list} = Pleroma.List.follow(list, other_user) @@ -922,10 +1023,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do user = insert(:user) other_user = insert(:user) - {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."}) + {:ok, activity_one} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."}) {:ok, _activity_two} = - TwitterAPI.create_status(other_user, %{ + CommonAPI.post(other_user, %{ "status" => "Marisa is cute.", "visibility" => "private" }) @@ -949,8 +1050,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = - TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) {:ok, [_notification]} = Notification.create_notifications(activity) @@ -972,8 +1072,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = - TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) {:ok, [notification]} = Notification.create_notifications(activity) @@ -995,8 +1094,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = - TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) {:ok, [notification]} = Notification.create_notifications(activity) @@ -1012,8 +1110,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = - TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"}) {:ok, [_notification]} = Notification.create_notifications(activity) @@ -1174,6 +1271,71 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do result = json_response(conn_res, 200) assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result end + + test "doesn't see notifications after muting user with notifications", %{conn: conn} do + user = insert(:user) + user2 = insert(:user) + + {:ok, _, _, _} = CommonAPI.follow(user, user2) + {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + + conn = assign(conn, :user, user) + + conn = get(conn, "/api/v1/notifications") + + assert length(json_response(conn, 200)) == 1 + + {:ok, user} = User.mute(user, user2) + + conn = assign(build_conn(), :user, user) + conn = get(conn, "/api/v1/notifications") + + assert json_response(conn, 200) == [] + end + + test "see notifications after muting user without notifications", %{conn: conn} do + user = insert(:user) + user2 = insert(:user) + + {:ok, _, _, _} = CommonAPI.follow(user, user2) + {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + + conn = assign(conn, :user, user) + + conn = get(conn, "/api/v1/notifications") + + assert length(json_response(conn, 200)) == 1 + + {:ok, user} = User.mute(user, user2, false) + + conn = assign(build_conn(), :user, user) + conn = get(conn, "/api/v1/notifications") + + assert length(json_response(conn, 200)) == 1 + end + + test "see notifications after muting user with notifications and with_muted parameter", %{ + conn: conn + } do + user = insert(:user) + user2 = insert(:user) + + {:ok, _, _, _} = CommonAPI.follow(user, user2) + {:ok, _} = CommonAPI.post(user2, %{"status" => "hey @#{user.nickname}"}) + + conn = assign(conn, :user, user) + + conn = get(conn, "/api/v1/notifications") + + assert length(json_response(conn, 200)) == 1 + + {:ok, user} = User.mute(user, user2) + + conn = assign(build_conn(), :user, user) + conn = get(conn, "/api/v1/notifications", %{"with_muted" => "true"}) + + assert length(json_response(conn, 200)) == 1 + end end describe "reblogging" do @@ -1230,6 +1392,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert to_string(activity.id) == id end + + test "returns 400 error when activity is not exist", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/foo/reblog") + + assert json_response(conn, 400) == %{"error" => "Could not repeat"} + end end describe "unreblogging" do @@ -1248,6 +1421,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert to_string(activity.id) == id end + + test "returns 400 error when activity is not exist", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/foo/unreblog") + + assert json_response(conn, 400) == %{"error" => "Could not unrepeat"} + end end describe "favoriting" do @@ -1266,16 +1450,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert to_string(activity.id) == id end - test "returns 500 for a wrong id", %{conn: conn} do + test "returns 400 error for a wrong id", %{conn: conn} do user = insert(:user) - resp = + conn = conn |> assign(:user, user) |> post("/api/v1/statuses/1/favourite") - |> json_response(500) - assert resp == "Something went wrong" + assert json_response(conn, 400) == %{"error" => "Could not favorite"} end end @@ -1296,6 +1479,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert to_string(activity.id) == id end + + test "returns 400 error for a wrong id", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/1/unfavourite") + + assert json_response(conn, 400) == %{"error" => "Could not unfavorite"} + end end describe "user timelines" do @@ -1366,10 +1560,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do media = TwitterAPI.upload(file, user, "json") - |> Poison.decode!() + |> Jason.decode!() {:ok, image_post} = - TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]}) + CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]}) conn = conn @@ -1405,6 +1599,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert [%{"id" => id}] = json_response(conn, 200) assert id == to_string(post.id) end + + test "filters user's statuses by a hashtag", %{conn: conn} do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"}) + {:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"}) + + conn = + conn + |> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"}) + + assert [%{"id" => id}] = json_response(conn, 200) + assert id == to_string(post.id) + end end describe "user relationships" do @@ -1679,7 +1886,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do following = insert(:user) capture_log(fn -> - {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"}) + {:ok, activity} = CommonAPI.post(following, %{"status" => "test #2hu"}) {:ok, [_activity]} = OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") @@ -1992,25 +2199,52 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert %{"error" => "Record not found"} = json_response(conn_res, 404) end - test "muting / unmuting a user", %{conn: conn} do - user = insert(:user) - other_user = insert(:user) + describe "mute/unmute" do + test "with notifications", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) - conn = - conn - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/mute") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/mute") - assert %{"id" => _id, "muting" => true} = json_response(conn, 200) + response = json_response(conn, 200) - user = User.get_cached_by_id(user.id) + assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response + user = User.get_cached_by_id(user.id) - conn = - build_conn() - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/unmute") + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/unmute") + + response = json_response(conn, 200) + assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response + end + + test "without notifications", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"}) - assert %{"id" => _id, "muting" => false} = json_response(conn, 200) + response = json_response(conn, 200) + + assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response + user = User.get_cached_by_id(user.id) + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/unmute") + + response = json_response(conn, 200) + assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response + end end test "subscribing / unsubscribing to a user", %{conn: conn} do @@ -2411,7 +2645,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do insert(:user, %{local: false, nickname: "u@peer1.com"}) insert(:user, %{local: false, nickname: "u@peer2.com"}) - {:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"}) + {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"}) # Stats should count users with missing or nil `info.deactivated` value user = User.get_cached_by_id(user.id) @@ -2504,6 +2738,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> json_response(200) end + test "/pin: returns 400 error when activity is not public", %{conn: conn, user: user} do + {:ok, dm} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"}) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{dm.id}/pin") + + assert json_response(conn, 400) == %{"error" => "Could not pin"} + end + test "unpin status", %{conn: conn, user: user, activity: activity} do {:ok, _} = CommonAPI.pin(activity.id, user) @@ -2523,6 +2768,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> json_response(200) end + test "/unpin: returns 400 error when activity is not exist", %{conn: conn, user: user} do + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/1/unpin") + + assert json_response(conn, 400) == %{"error" => "Could not unpin"} + end + test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"}) @@ -2557,7 +2811,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end test "returns rich-media card", %{conn: conn, user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"}) + {:ok, activity} = CommonAPI.post(user, %{"status" => "https://example.com/ogp"}) card_data = %{ "image" => "http://ia.media-imdb.com/images/rock.jpg", @@ -2589,7 +2843,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do # works with private posts {:ok, activity} = - CommonAPI.post(user, %{"status" => "http://example.com/ogp", "visibility" => "direct"}) + CommonAPI.post(user, %{"status" => "https://example.com/ogp", "visibility" => "direct"}) response_two = conn @@ -2601,7 +2855,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end test "replaces missing description with an empty string", %{conn: conn, user: user} do - {:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp-missing-data"}) + {:ok, activity} = + CommonAPI.post(user, %{"status" => "https://example.com/ogp-missing-data"}) response = conn @@ -2696,6 +2951,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> json_response(200) end + test "cannot mute already muted conversation", %{conn: conn, user: user, activity: activity} do + {:ok, _} = CommonAPI.add_mute(user, activity) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/mute") + + assert json_response(conn, 400) == %{"error" => "conversation is already muted"} + end + test "unmute conversation", %{conn: conn, user: user, activity: activity} do {:ok, _} = CommonAPI.add_mute(user, activity) @@ -2740,7 +3006,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> post("/api/v1/reports", %{ "account_id" => target_user.id, "status_ids" => [activity.id], - "comment" => "bad status!" + "comment" => "bad status!", + "forward" => "false" }) |> json_response(200) end @@ -2773,6 +3040,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment}) |> json_response(400) end + + test "returns error when account is not exist", %{ + conn: conn, + reporter: reporter, + activity: activity + } do + conn = + conn + |> assign(:user, reporter) + |> post("/api/v1/reports", %{"status_ids" => [activity.id], "account_id" => "foo"}) + + assert json_response(conn, 400) == %{"error" => "Account not found"} + end end describe "link headers" do @@ -2844,6 +3124,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do assert Map.has_key?(emoji, "static_url") assert Map.has_key?(emoji, "tags") assert is_list(emoji["tags"]) + assert Map.has_key?(emoji, "category") assert Map.has_key?(emoji, "url") assert Map.has_key?(emoji, "visible_in_picker") end @@ -3131,7 +3412,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user2 = insert(:user) user3 = insert(:user) - {:ok, replied_to} = TwitterAPI.create_status(user1, %{"status" => "cofe"}) + {:ok, replied_to} = CommonAPI.post(user1, %{"status" => "cofe"}) # Reply to status from another user conn1 = @@ -3296,7 +3577,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do |> get("/api/v1/polls/#{object.id}") response = json_response(conn, 200) - id = object.id + id = to_string(object.id) assert %{"id" => ^id, "expired" => false, "multiple" => false} = response end @@ -3396,5 +3677,186 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do total_items == 1 end) end + + test "does not allow choice index to be greater than options count", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = + CommonAPI.post(user, %{ + "status" => "Am I cute?", + "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20} + }) + + object = Object.normalize(activity) + + conn = + conn + |> assign(:user, other_user) + |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]}) + + assert json_response(conn, 422) == %{"error" => "Invalid indices"} + end + + test "returns 404 error when object is not exist", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/polls/1/votes", %{"choices" => [0]}) + + assert json_response(conn, 404) == %{"error" => "Record not found"} + end + + test "returns 404 when poll is private and not available for user", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = + CommonAPI.post(user, %{ + "status" => "Am I cute?", + "poll" => %{"options" => ["Yes", "No"], "expires_in" => 20}, + "visibility" => "private" + }) + + object = Object.normalize(activity) + + conn = + conn + |> assign(:user, other_user) + |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]}) + + assert json_response(conn, 404) == %{"error" => "Record not found"} + end + end + + describe "GET /api/v1/statuses/:id/favourited_by" do + setup do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "test"}) + + conn = + build_conn() + |> assign(:user, user) + + [conn: conn, activity: activity] + end + + test "returns users who have favorited the status", %{conn: conn, activity: activity} do + other_user = insert(:user) + {:ok, _, _} = CommonAPI.favorite(activity.id, other_user) + + response = + conn + |> get("/api/v1/statuses/#{activity.id}/favourited_by") + |> json_response(:ok) + + [%{"id" => id}] = response + + assert id == other_user.id + end + + test "returns empty array when status has not been favorited yet", %{ + conn: conn, + activity: activity + } do + response = + conn + |> get("/api/v1/statuses/#{activity.id}/favourited_by") + |> json_response(:ok) + + assert Enum.empty?(response) + end + end + + describe "GET /api/v1/statuses/:id/reblogged_by" do + setup do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{"status" => "test"}) + + conn = + build_conn() + |> assign(:user, user) + + [conn: conn, activity: activity] + end + + test "returns users who have reblogged the status", %{conn: conn, activity: activity} do + other_user = insert(:user) + {:ok, _, _} = CommonAPI.repeat(activity.id, other_user) + + response = + conn + |> get("/api/v1/statuses/#{activity.id}/reblogged_by") + |> json_response(:ok) + + [%{"id" => id}] = response + + assert id == other_user.id + end + + test "returns empty array when status has not been reblogged yet", %{ + conn: conn, + activity: activity + } do + response = + conn + |> get("/api/v1/statuses/#{activity.id}/reblogged_by") + |> json_response(:ok) + + assert Enum.empty?(response) + end + end + + describe "POST /auth/password, with valid parameters" do + setup %{conn: conn} do + user = insert(:user) + conn = post(conn, "/auth/password?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) + + email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) + notify_email = Pleroma.Config.get([:instance, :notify_email]) + instance_name = Pleroma.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 "POST /auth/password, with invalid parameters" do + setup do + user = insert(:user) + {:ok, user: user} + end + + test "it returns 404 when user is not found", %{conn: conn, user: user} do + conn = post(conn, "/auth/password?email=nonexisting_#{user.email}") + assert conn.status == 404 + refute conn.resp_body + end + + test "it returns 400 when user is not local", %{conn: conn, user: user} do + {:ok, user} = Repo.update(Changeset.change(user, local: false)) + conn = post(conn, "/auth/password?email=#{user.email}") + assert conn.status == 400 + refute conn.resp_body + end end end