alias Ecto.Changeset
alias Pleroma.Activity
- alias Pleroma.ActivityExpiration
alias Pleroma.Config
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.MastodonAPI.FilterView
alias Pleroma.Web.OAuth.App
alias Pleroma.Web.OAuth.Token
- alias Pleroma.Web.OStatus
alias Pleroma.Web.Push
- import Pleroma.Factory
+
import ExUnit.CaptureLog
- import Tesla.Mock
+ import Pleroma.Factory
import Swoosh.TestAssertions
+ import Tesla.Mock
@image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
clear_config([:instance, :public])
clear_config([:rich_media, :enabled])
- test "the home timeline", %{conn: conn} do
- user = insert(:user)
- following = insert(:user)
-
- {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/timelines/home")
-
- assert Enum.empty?(json_response(conn, 200))
-
- {:ok, user} = User.follow(user, following)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> get("/api/v1/timelines/home")
-
- assert [%{"content" => "test"}] = json_response(conn, 200)
- end
-
- test "the public timeline", %{conn: conn} do
- following = insert(:user)
-
- capture_log(fn ->
- {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
-
- {:ok, [_activity]} =
- OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
-
- conn =
- conn
- |> get("/api/v1/timelines/public", %{"local" => "False"})
-
- assert length(json_response(conn, 200)) == 2
-
- conn =
- build_conn()
- |> get("/api/v1/timelines/public", %{"local" => "True"})
-
- assert [%{"content" => "test"}] = json_response(conn, 200)
-
- conn =
- build_conn()
- |> get("/api/v1/timelines/public", %{"local" => "1"})
-
- assert [%{"content" => "test"}] = json_response(conn, 200)
- end)
- end
-
- test "the public timeline when public is set to false", %{conn: conn} do
- Config.put([:instance, :public], false)
-
- assert conn
- |> get("/api/v1/timelines/public", %{"local" => "False"})
- |> json_response(403) == %{"error" => "This resource requires authentication."}
- end
-
- test "the public timeline includes only public statuses for an authenticated user" do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
-
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "private"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "unlisted"})
- {:ok, _activity} = CommonAPI.post(user, %{"status" => "test", "visibility" => "direct"})
-
- res_conn = get(conn, "/api/v1/timelines/public")
- assert length(json_response(res_conn, 200)) == 1
- end
-
- describe "posting statuses" do
- setup do
- user = insert(:user)
-
- conn =
- build_conn()
- |> assign(:user, user)
-
- [conn: conn]
- end
-
- test "posting a status", %{conn: conn} do
- idempotency_key = "Pikachu rocks!"
-
- conn_one =
- conn
- |> put_req_header("idempotency-key", idempotency_key)
- |> post("/api/v1/statuses", %{
- "status" => "cofe",
- "spoiler_text" => "2hu",
- "sensitive" => "false"
- })
-
- {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key)
- # Six hours
- assert ttl > :timer.seconds(6 * 60 * 60 - 1)
-
- assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
- json_response(conn_one, 200)
-
- assert Activity.get_by_id(id)
-
- 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} = json_response(conn_two, 200)
- assert id == second_id
-
- 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
-
- # An activity that will expire:
- # 2 hours
- expires_in = 120 * 60
-
- conn_four =
- conn
- |> post("api/v1/statuses", %{
- "status" => "oolong",
- "expires_in" => expires_in
- })
-
- assert fourth_response = %{"id" => fourth_id} = json_response(conn_four, 200)
- assert activity = Activity.get_by_id(fourth_id)
- assert expiration = ActivityExpiration.get_by_activity_id(fourth_id)
-
- estimated_expires_at =
- NaiveDateTime.utc_now()
- |> NaiveDateTime.add(expires_in)
- |> NaiveDateTime.truncate(:second)
-
- # This assert will fail if the test takes longer than a minute. I sure hope it never does:
- assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60
-
- assert fourth_response["pleroma"]["expires_at"] ==
- NaiveDateTime.to_iso8601(expiration.scheduled_at)
- 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"
- })
-
- 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
- |> 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
- 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)
- 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} = response = json_response(conn, 200)
- assert response["visibility"] == "direct"
- assert response["pleroma"]["direct_conversation_id"]
- 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
- test "posting a poll", %{conn: conn} do
- user = insert(:user)
- time = NaiveDateTime.utc_now()
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses", %{
- "status" => "Who is the #bestgrill?",
- "poll" => %{"options" => ["Rei", "Asuka", "Misato"], "expires_in" => 420}
- })
-
- response = json_response(conn, 200)
-
- assert Enum.all?(response["poll"]["options"], fn %{"title" => title} ->
- title in ["Rei", "Asuka", "Misato"]
- end)
-
- assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430
- refute response["poll"]["expred"]
- end
-
- test "option limit is enforced", %{conn: conn} do
- user = insert(:user)
- limit = Config.get([:instance, :poll_limits, :max_options])
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses", %{
- "status" => "desu~",
- "poll" => %{"options" => Enum.map(0..limit, fn _ -> "desu" end), "expires_in" => 1}
- })
-
- %{"error" => error} = json_response(conn, 422)
- assert error == "Poll can't contain more than #{limit} options"
- end
-
- test "option character limit is enforced", %{conn: conn} do
- user = insert(:user)
- limit = Config.get([:instance, :poll_limits, :max_option_chars])
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses", %{
- "status" => "...",
- "poll" => %{
- "options" => [Enum.reduce(0..limit, "", fn _, acc -> acc <> "." end)],
- "expires_in" => 1
- }
- })
-
- %{"error" => error} = json_response(conn, 422)
- assert error == "Poll options cannot be longer than #{limit} characters each"
- end
-
- test "minimal date limit is enforced", %{conn: conn} do
- user = insert(:user)
- limit = Config.get([:instance, :poll_limits, :min_expiration])
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses", %{
- "status" => "imagine arbitrary limits",
- "poll" => %{
- "options" => ["this post was made by pleroma gang"],
- "expires_in" => limit - 1
- }
- })
-
- %{"error" => error} = json_response(conn, 422)
- assert error == "Expiration date is too soon"
- end
-
- test "maximum date limit is enforced", %{conn: conn} do
- user = insert(:user)
- limit = Config.get([:instance, :poll_limits, :max_expiration])
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses", %{
- "status" => "imagine arbitrary limits",
- "poll" => %{
- "options" => ["this post was made by pleroma gang"],
- "expires_in" => limit + 1
- }
- })
-
- %{"error" => error} = json_response(conn, 422)
- assert error == "Expiration date is too far in the future"
- end
- end
-
- test "direct timeline", %{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"
- })
-
- {: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/v1/timelines/direct")
-
- [status] = json_response(res_conn, 200)
-
- assert %{"visibility" => "direct"} = status
- assert status["url"] != direct.data["id"]
-
- # User should be able to see their own direct message
- res_conn =
- build_conn()
- |> assign(:user, user_one)
- |> get("api/v1/timelines/direct")
-
- [status] = json_response(res_conn, 200)
-
- assert %{"visibility" => "direct"} = status
-
- # Both should be visible here
- res_conn =
- conn
- |> assign(:user, user_two)
- |> get("api/v1/timelines/home")
-
- [_s1, _s2] = json_response(res_conn, 200)
-
- # Test pagination
- Enum.each(1..20, fn _ ->
- {:ok, _} =
- CommonAPI.post(user_one, %{
- "status" => "Hi @#{user_two.nickname}!",
- "visibility" => "direct"
- })
- end)
-
- res_conn =
- conn
- |> assign(:user, user_two)
- |> get("api/v1/timelines/direct")
-
- statuses = json_response(res_conn, 200)
- assert length(statuses) == 20
-
- res_conn =
- conn
- |> assign(:user, user_two)
- |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
-
- [status] = json_response(res_conn, 200)
-
- assert status["url"] != direct.data["id"]
- end
-
test "Conversations", %{conn: conn} do
user_one = insert(:user)
user_two = insert(:user)
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
end
- test "doesn't include DMs from blocked users", %{conn: conn} do
- blocker = insert(:user)
- blocked = insert(:user)
- user = insert(:user)
- {:ok, blocker} = User.block(blocker, blocked)
-
- {:ok, _blocked_direct} =
- CommonAPI.post(blocked, %{
- "status" => "Hi @#{blocker.nickname}!",
- "visibility" => "direct"
- })
-
- {:ok, direct} =
- CommonAPI.post(user, %{
- "status" => "Hi @#{blocker.nickname}!",
- "visibility" => "direct"
- })
-
- res_conn =
- conn
- |> assign(:user, user)
- |> get("api/v1/timelines/direct")
-
- [status] = json_response(res_conn, 200)
- assert status["id"] == direct.id
- end
-
- test "verify_credentials", %{conn: conn} do
+ test "verify_credentials", %{conn: conn} do
user = insert(:user)
conn =
"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)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/apps", %{
- client_name: app_attrs.client_name,
- redirect_uris: app_attrs.redirect_uris
- })
-
- [app] = Repo.all(App)
-
- expected = %{
- "name" => app.client_name,
- "website" => app.website,
- "client_id" => app.client_id,
- "client_secret" => app.client_secret,
- "id" => app.id |> to_string(),
- "redirect_uri" => app.redirect_uris,
- "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
- }
-
- assert expected == json_response(conn, 200)
- end
-
- test "get a status", %{conn: conn} do
- activity = insert(:note_activity)
-
- conn =
- conn
- |> get("/api/v1/statuses/#{activity.id}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(activity.id)
- end
-
- test "get statuses by IDs", %{conn: conn} do
- %{id: id1} = insert(:note_activity)
- %{id: id2} = insert(:note_activity)
-
- query_string = "ids[]=#{id1}&ids[]=#{id2}"
- conn = get(conn, "/api/v1/statuses/?#{query_string}")
-
- assert [%{"id" => ^id1}, %{"id" => ^id2}] = Enum.sort_by(json_response(conn, :ok), & &1["id"])
- end
-
- describe "deleting a status" do
- test "when you created it", %{conn: conn} do
- activity = insert(:note_activity)
- author = User.get_cached_by_ap_id(activity.data["actor"])
-
- conn =
- conn
- |> assign(:user, author)
- |> delete("/api/v1/statuses/#{activity.id}")
-
- assert %{} = json_response(conn, 200)
-
- refute Activity.get_by_id(activity.id)
- end
-
- test "when you didn't create it", %{conn: conn} do
- activity = insert(:note_activity)
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> delete("/api/v1/statuses/#{activity.id}")
-
- assert %{"error" => _} = json_response(conn, 403)
-
- assert Activity.get_by_id(activity.id) == activity
- end
-
- test "when you're an admin or moderator", %{conn: conn} do
- activity1 = insert(:note_activity)
- activity2 = insert(:note_activity)
- admin = insert(:user, info: %{is_admin: true})
- moderator = insert(:user, info: %{is_moderator: true})
-
- res_conn =
- conn
- |> assign(:user, admin)
- |> delete("/api/v1/statuses/#{activity1.id}")
-
- assert %{} = json_response(res_conn, 200)
-
- res_conn =
- conn
- |> assign(:user, moderator)
- |> delete("/api/v1/statuses/#{activity2.id}")
-
- assert %{} = json_response(res_conn, 200)
-
- refute Activity.get_by_id(activity1.id)
- refute Activity.get_by_id(activity2.id)
- end
- end
-
- describe "filters" do
- test "creating a filter", %{conn: conn} do
- user = insert(:user)
-
- filter = %Pleroma.Filter{
- phrase: "knights",
- context: ["home"]
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
-
- assert response = json_response(conn, 200)
- assert response["phrase"] == filter.phrase
- assert response["context"] == filter.context
- assert response["irreversible"] == false
- assert response["id"] != nil
- assert response["id"] != ""
- end
-
- test "fetching a list of filters", %{conn: conn} do
- user = insert(:user)
-
- query_one = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 1,
- phrase: "knights",
- context: ["home"]
- }
-
- query_two = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 2,
- phrase: "who",
- context: ["home"]
- }
-
- {:ok, filter_one} = Pleroma.Filter.create(query_one)
- {:ok, filter_two} = Pleroma.Filter.create(query_two)
-
- response =
- conn
- |> assign(:user, user)
- |> get("/api/v1/filters")
- |> json_response(200)
-
- assert response ==
- render_json(
- FilterView,
- "filters.json",
- filters: [filter_two, filter_one]
- )
- end
-
- test "get a filter", %{conn: conn} do
- user = insert(:user)
-
- query = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 2,
- phrase: "knight",
- context: ["home"]
- }
-
- {:ok, filter} = Pleroma.Filter.create(query)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/filters/#{filter.filter_id}")
-
- assert _response = json_response(conn, 200)
- end
-
- test "update a filter", %{conn: conn} do
- user = insert(:user)
-
- query = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 2,
- phrase: "knight",
- context: ["home"]
- }
-
- {:ok, _filter} = Pleroma.Filter.create(query)
-
- new = %Pleroma.Filter{
- phrase: "nii",
- context: ["home"]
- }
-
- conn =
- conn
- |> assign(:user, user)
- |> put("/api/v1/filters/#{query.filter_id}", %{
- phrase: new.phrase,
- context: new.context
- })
-
- assert response = json_response(conn, 200)
- assert response["phrase"] == new.phrase
- assert response["context"] == new.context
- end
-
- test "delete a filter", %{conn: conn} do
- user = insert(:user)
-
- query = %Pleroma.Filter{
- user_id: user.id,
- filter_id: 2,
- phrase: "knight",
- context: ["home"]
- }
-
- {:ok, filter} = Pleroma.Filter.create(query)
-
- conn =
- conn
- |> assign(:user, user)
- |> delete("/api/v1/filters/#{filter.filter_id}")
-
- assert response = json_response(conn, 200)
- assert response == %{}
- end
- end
-
- describe "list timelines" do
- test "list timeline", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
- {: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)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/timelines/list/#{list.id}")
-
- assert [%{"id" => id}] = json_response(conn, 200)
-
- assert id == to_string(activity_two.id)
- end
-
- 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} = CommonAPI.post(other_user, %{"status" => "Marisa is cute."})
-
- {:ok, _activity_two} =
- CommonAPI.post(other_user, %{
- "status" => "Marisa is cute.",
- "visibility" => "private"
- })
-
- {:ok, list} = Pleroma.List.create("name", user)
- {:ok, list} = Pleroma.List.follow(list, other_user)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/timelines/list/#{list.id}")
-
- assert [%{"id" => id}] = json_response(conn, 200)
-
- assert id == to_string(activity_one.id)
- end
- end
-
- describe "notifications" do
- test "list of notifications", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
-
- {:ok, [_notification]} = Notification.create_notifications(activity)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/notifications")
-
- expected_response =
- "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
- user.ap_id
- }\">@<span>#{user.nickname}</span></a></span>"
-
- assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
- assert response == expected_response
- end
-
- test "getting a single notification", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
-
- {:ok, [notification]} = Notification.create_notifications(activity)
-
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/notifications/#{notification.id}")
-
- expected_response =
- "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
- user.ap_id
- }\">@<span>#{user.nickname}</span></a></span>"
-
- assert %{"status" => %{"content" => response}} = json_response(conn, 200)
- assert response == expected_response
- end
-
- test "dismissing a single notification", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
-
- {:ok, [notification]} = Notification.create_notifications(activity)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/notifications/dismiss", %{"id" => notification.id})
-
- assert %{} = json_response(conn, 200)
- end
-
- test "clearing all notifications", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
-
- {:ok, [_notification]} = Notification.create_notifications(activity)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/notifications/clear")
-
- assert %{} = json_response(conn, 200)
-
- conn =
- build_conn()
- |> assign(:user, user)
- |> get("/api/v1/notifications")
-
- assert all = json_response(conn, 200)
- assert all == []
- end
-
- test "paginates notifications using min_id, since_id, max_id, and limit", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity3} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity4} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
-
- notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
- notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
- notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
- notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
-
- conn =
- conn
- |> assign(:user, user)
-
- # min_id
- conn_res =
- conn
- |> get("/api/v1/notifications?limit=2&min_id=#{notification1_id}")
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
-
- # since_id
- conn_res =
- conn
- |> get("/api/v1/notifications?limit=2&since_id=#{notification1_id}")
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
-
- # max_id
- conn_res =
- conn
- |> get("/api/v1/notifications?limit=2&max_id=#{notification4_id}")
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
- end
-
- test "filters notifications using exclude_types", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, mention_activity} = CommonAPI.post(other_user, %{"status" => "hey @#{user.nickname}"})
- {:ok, create_activity} = CommonAPI.post(user, %{"status" => "hey"})
- {:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, other_user)
- {:ok, reblog_activity, _} = CommonAPI.repeat(create_activity.id, other_user)
- {:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
-
- mention_notification_id =
- Repo.get_by(Notification, activity_id: mention_activity.id).id |> to_string()
-
- favorite_notification_id =
- Repo.get_by(Notification, activity_id: favorite_activity.id).id |> to_string()
-
- reblog_notification_id =
- Repo.get_by(Notification, activity_id: reblog_activity.id).id |> to_string()
-
- follow_notification_id =
- Repo.get_by(Notification, activity_id: follow_activity.id).id |> to_string()
-
- conn =
- conn
- |> assign(:user, user)
-
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["mention", "favourite", "reblog"]})
-
- assert [%{"id" => ^follow_notification_id}] = json_response(conn_res, 200)
-
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["favourite", "reblog", "follow"]})
-
- assert [%{"id" => ^mention_notification_id}] = json_response(conn_res, 200)
-
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["reblog", "follow", "mention"]})
-
- assert [%{"id" => ^favorite_notification_id}] = json_response(conn_res, 200)
-
- conn_res =
- get(conn, "/api/v1/notifications", %{exclude_types: ["follow", "mention", "favourite"]})
-
- assert [%{"id" => ^reblog_notification_id}] = json_response(conn_res, 200)
- end
-
- test "destroy multiple", %{conn: conn} do
- user = insert(:user)
- other_user = insert(:user)
-
- {:ok, activity1} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity2} = CommonAPI.post(other_user, %{"status" => "hi @#{user.nickname}"})
- {:ok, activity3} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
- {:ok, activity4} = CommonAPI.post(user, %{"status" => "hi @#{other_user.nickname}"})
-
- notification1_id = Repo.get_by(Notification, activity_id: activity1.id).id |> to_string()
- notification2_id = Repo.get_by(Notification, activity_id: activity2.id).id |> to_string()
- notification3_id = Repo.get_by(Notification, activity_id: activity3.id).id |> to_string()
- notification4_id = Repo.get_by(Notification, activity_id: activity4.id).id |> to_string()
-
- conn =
- conn
- |> assign(:user, user)
-
- conn_res =
- conn
- |> get("/api/v1/notifications")
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification2_id}, %{"id" => ^notification1_id}] = result
-
- conn2 =
- conn
- |> assign(:user, other_user)
-
- conn_res =
- conn2
- |> get("/api/v1/notifications")
-
- result = json_response(conn_res, 200)
- assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result
-
- conn_destroy =
- conn
- |> delete("/api/v1/notifications/destroy_multiple", %{
- "ids" => [notification1_id, notification2_id]
- })
-
- assert json_response(conn_destroy, 200) == %{}
-
- conn_res =
- conn2
- |> get("/api/v1/notifications")
-
- 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
- test "reblogs and returns the reblogged status", %{conn: conn} do
- activity = insert(:note_activity)
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/reblog")
-
- assert %{
- "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
- "reblogged" => true
- } = json_response(conn, 200)
-
- assert to_string(activity.id) == id
- end
-
- test "reblogged status for another user", %{conn: conn} do
- activity = insert(:note_activity)
- user1 = insert(:user)
- user2 = insert(:user)
- user3 = insert(:user)
- CommonAPI.favorite(activity.id, user2)
- {:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
- {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
- {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
-
- conn_res =
- conn
- |> assign(:user, user3)
- |> get("/api/v1/statuses/#{reblog_activity1.id}")
-
- assert %{
- "reblog" => %{"id" => id, "reblogged" => false, "reblogs_count" => 2},
- "reblogged" => false,
- "favourited" => false,
- "bookmarked" => false
- } = json_response(conn_res, 200)
-
- conn_res =
- conn
- |> assign(:user, user2)
- |> get("/api/v1/statuses/#{reblog_activity1.id}")
-
- assert %{
- "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 2},
- "reblogged" => true,
- "favourited" => true,
- "bookmarked" => true
- } = json_response(conn_res, 200)
-
- 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")
+ %{
+ "href" => _,
+ "mediaType" => _,
+ "type" => _
+ }
+ ]
+ } = user.avatar
- assert json_response(conn, 400) == %{"error" => "Could not repeat"}
- end
+ assert %{"url" => _} = json_response(conn, 200)
end
- describe "unreblogging" do
- test "unreblogs and returns the unreblogged status", %{conn: conn} do
- activity = insert(:note_activity)
- user = insert(:user)
+ test "user avatar can be reset", %{conn: conn} do
+ user = insert(:user)
- {:ok, _, _} = CommonAPI.repeat(activity.id, user)
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/unreblog")
+ user = User.get_cached_by_id(user.id)
- assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200)
+ assert user.avatar == nil
- assert to_string(activity.id) == id
- end
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
- test "returns 400 error when activity is not exist", %{conn: conn} do
- user = insert(:user)
+ test "can set profile banner", %{conn: conn} do
+ user = insert(:user)
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/foo/unreblog")
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
- assert json_response(conn, 400) == %{"error" => "Could not unrepeat"}
- end
+ user = refresh_record(user)
+ assert user.info.banner["type"] == "Image"
+
+ assert %{"url" => _} = json_response(conn, 200)
end
- describe "favoriting" do
- test "favs a status and returns it", %{conn: conn} do
- activity = insert(:note_activity)
- user = insert(:user)
+ test "can reset profile banner", %{conn: conn} do
+ user = insert(:user)
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/favourite")
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
- assert %{"id" => id, "favourites_count" => 1, "favourited" => true} =
- json_response(conn, 200)
+ user = refresh_record(user)
+ assert user.info.banner == %{}
- assert to_string(activity.id) == id
- end
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
- test "returns 400 error for a wrong id", %{conn: conn} do
- user = insert(:user)
+ test "background image can be set", %{conn: conn} do
+ user = insert(:user)
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/1/favourite")
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
- assert json_response(conn, 400) == %{"error" => "Could not favorite"}
- end
+ user = refresh_record(user)
+ assert user.info.background["type"] == "Image"
+ assert %{"url" => _} = json_response(conn, 200)
end
- describe "unfavoriting" do
- test "unfavorites a status and returns it", %{conn: conn} do
- activity = insert(:note_activity)
- user = insert(:user)
+ test "background image can be reset", %{conn: conn} do
+ user = insert(:user)
- {:ok, _, _} = CommonAPI.favorite(activity.id, user)
+ conn =
+ conn
+ |> assign(:user, user)
+ |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/unfavourite")
+ user = refresh_record(user)
+ assert user.info.background == %{}
+ assert %{"url" => nil} = json_response(conn, 200)
+ end
- assert %{"id" => id, "favourites_count" => 0, "favourited" => false} =
- json_response(conn, 200)
+ test "creates an oauth app", %{conn: conn} do
+ user = insert(:user)
+ app_attrs = build(:oauth_app)
- assert to_string(activity.id) == id
- end
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/apps", %{
+ client_name: app_attrs.client_name,
+ redirect_uris: app_attrs.redirect_uris
+ })
- test "returns 400 error for a wrong id", %{conn: conn} do
- user = insert(:user)
+ [app] = Repo.all(App)
- conn =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/1/unfavourite")
+ expected = %{
+ "name" => app.client_name,
+ "website" => app.website,
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret,
+ "id" => app.id |> to_string(),
+ "redirect_uri" => app.redirect_uris,
+ "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
+ }
- assert json_response(conn, 400) == %{"error" => "Could not unfavorite"}
- end
+ assert expected == json_response(conn, 200)
end
describe "user timelines" do
assert url =~ "an_image"
end
- test "hashtag timeline", %{conn: conn} do
- following = insert(:user)
-
- capture_log(fn ->
- {:ok, activity} = CommonAPI.post(following, %{"status" => "test #2hu"})
-
- {:ok, [_activity]} =
- OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
-
- nconn =
- conn
- |> get("/api/v1/timelines/tag/2hu")
-
- assert [%{"id" => id}] = json_response(nconn, 200)
-
- assert id == to_string(activity.id)
-
- # works for different capitalization too
- nconn =
- conn
- |> get("/api/v1/timelines/tag/2HU")
-
- assert [%{"id" => id}] = json_response(nconn, 200)
-
- assert id == to_string(activity.id)
- end)
- end
-
- test "multi-hashtag timeline", %{conn: conn} do
- user = insert(:user)
-
- {:ok, activity_test} = CommonAPI.post(user, %{"status" => "#test"})
- {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test #test1"})
- {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"})
-
- any_test =
- conn
- |> get("/api/v1/timelines/tag/test", %{"any" => ["test1"]})
-
- [status_none, status_test1, status_test] = json_response(any_test, 200)
-
- assert to_string(activity_test.id) == status_test["id"]
- assert to_string(activity_test1.id) == status_test1["id"]
- assert to_string(activity_none.id) == status_none["id"]
-
- restricted_test =
- conn
- |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]})
-
- assert [status_test1] == json_response(restricted_test, 200)
-
- all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]})
-
- assert [status_none] == json_response(all_test, 200)
- end
-
test "getting followers", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
"stats" => _,
"thumbnail" => _,
"languages" => _,
- "registrations" => _,
- "poll_limits" => _
- } = result
-
- assert email == from_config_email
- end
-
- test "get instance stats", %{conn: conn} do
- user = insert(:user, %{local: true})
-
- user2 = insert(:user, %{local: true})
- {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
-
- insert(:user, %{local: false, nickname: "u@peer1.com"})
- insert(:user, %{local: false, nickname: "u@peer2.com"})
-
- {: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)
- info_change = Changeset.change(user.info, %{deactivated: nil})
-
- {:ok, _user} =
- user
- |> Changeset.change()
- |> Changeset.put_embed(:info, info_change)
- |> User.update_and_set_cache()
-
- Pleroma.Stats.force_update()
-
- conn = get(conn, "/api/v1/instance")
-
- assert result = json_response(conn, 200)
-
- stats = result["stats"]
-
- assert stats
- assert stats["user_count"] == 1
- assert stats["status_count"] == 1
- assert stats["domain_count"] == 2
- end
-
- test "get peers", %{conn: conn} do
- insert(:user, %{local: false, nickname: "u@peer1.com"})
- insert(:user, %{local: false, nickname: "u@peer2.com"})
-
- Pleroma.Stats.force_update()
-
- conn = get(conn, "/api/v1/instance/peers")
-
- assert result = json_response(conn, 200)
-
- assert ["peer1.com", "peer2.com"] == Enum.sort(result)
- end
-
- test "put settings", %{conn: conn} do
- user = insert(:user)
-
- conn =
- conn
- |> assign(:user, user)
- |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
-
- assert _result = json_response(conn, 200)
-
- user = User.get_cached_by_ap_id(user.ap_id)
- assert user.info.settings == %{"programming" => "socks"}
- end
-
- describe "pinned statuses" do
- setup do
- user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
-
- [user: user, activity: activity]
- end
-
- clear_config([:instance, :max_pinned_statuses]) do
- Config.put([:instance, :max_pinned_statuses], 1)
- end
-
- test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
- {:ok, _} = CommonAPI.pin(activity.id, user)
-
- result =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
-
- id_str = to_string(activity.id)
-
- assert [%{"id" => ^id_str, "pinned" => true}] = result
- end
-
- test "pin status", %{conn: conn, user: user, activity: activity} do
- id_str = to_string(activity.id)
-
- assert %{"id" => ^id_str, "pinned" => true} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/pin")
- |> json_response(200)
-
- assert [%{"id" => ^id_str, "pinned" => true}] =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> 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)
-
- id_str = to_string(activity.id)
- user = refresh_record(user)
-
- assert %{"id" => ^id_str, "pinned" => false} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/unpin")
- |> json_response(200)
-
- assert [] =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
- |> json_response(200)
- end
+ "registrations" => _,
+ "poll_limits" => _
+ } = result
- 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 email == from_config_email
+ end
- assert json_response(conn, 400) == %{"error" => "Could not unpin"}
- end
+ test "get instance stats", %{conn: conn} do
+ user = insert(:user, %{local: true})
- test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
- {:ok, activity_two} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ user2 = insert(:user, %{local: true})
+ {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
- id_str_one = to_string(activity_one.id)
+ insert(:user, %{local: false, nickname: "u@peer1.com"})
+ insert(:user, %{local: false, nickname: "u@peer2.com"})
- assert %{"id" => ^id_str_one, "pinned" => true} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{id_str_one}/pin")
- |> json_response(200)
+ {:ok, _} = CommonAPI.post(user, %{"status" => "cofe"})
- user = refresh_record(user)
+ # Stats should count users with missing or nil `info.deactivated` value
- assert %{"error" => "You have already pinned the maximum number of statuses"} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity_two.id}/pin")
- |> json_response(400)
- end
- end
+ {:ok, _user} =
+ user.id
+ |> User.get_cached_by_id()
+ |> User.update_info(&Changeset.change(&1, %{deactivated: nil}))
- describe "cards" do
- setup do
- Config.put([:rich_media, :enabled], true)
+ Pleroma.Stats.force_update()
- user = insert(:user)
- %{user: user}
- end
-
- test "returns rich-media card", %{conn: conn, user: user} do
- {:ok, activity} = CommonAPI.post(user, %{"status" => "https://example.com/ogp"})
-
- card_data = %{
- "image" => "http://ia.media-imdb.com/images/rock.jpg",
- "provider_name" => "example.com",
- "provider_url" => "https://example.com",
- "title" => "The Rock",
- "type" => "link",
- "url" => "https://example.com/ogp",
- "description" =>
- "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer.",
- "pleroma" => %{
- "opengraph" => %{
- "image" => "http://ia.media-imdb.com/images/rock.jpg",
- "title" => "The Rock",
- "type" => "video.movie",
- "url" => "https://example.com/ogp",
- "description" =>
- "Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer."
- }
- }
- }
+ conn = get(conn, "/api/v1/instance")
- response =
- conn
- |> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(200)
+ assert result = json_response(conn, 200)
- assert response == card_data
+ stats = result["stats"]
- # works with private posts
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "https://example.com/ogp", "visibility" => "direct"})
+ assert stats
+ assert stats["user_count"] == 1
+ assert stats["status_count"] == 1
+ assert stats["domain_count"] == 2
+ end
- response_two =
- conn
- |> assign(:user, user)
- |> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(200)
+ test "get peers", %{conn: conn} do
+ insert(:user, %{local: false, nickname: "u@peer1.com"})
+ insert(:user, %{local: false, nickname: "u@peer2.com"})
- assert response_two == card_data
- end
+ Pleroma.Stats.force_update()
- test "replaces missing description with an empty string", %{conn: conn, user: user} do
- {:ok, activity} =
- CommonAPI.post(user, %{"status" => "https://example.com/ogp-missing-data"})
+ conn = get(conn, "/api/v1/instance/peers")
- response =
- conn
- |> get("/api/v1/statuses/#{activity.id}/card")
- |> json_response(:ok)
+ assert result = json_response(conn, 200)
- assert response == %{
- "type" => "link",
- "title" => "Pleroma",
- "description" => "",
- "image" => nil,
- "provider_name" => "example.com",
- "provider_url" => "https://example.com",
- "url" => "https://example.com/ogp-missing-data",
- "pleroma" => %{
- "opengraph" => %{
- "title" => "Pleroma",
- "type" => "website",
- "url" => "https://example.com/ogp-missing-data"
- }
- }
- }
- end
+ assert ["peer1.com", "peer2.com"] == Enum.sort(result)
end
- test "bookmarks" do
+ test "put settings", %{conn: conn} do
user = insert(:user)
- for_user = insert(:user)
-
- {:ok, activity1} =
- CommonAPI.post(user, %{
- "status" => "heweoo?"
- })
-
- {:ok, activity2} =
- CommonAPI.post(user, %{
- "status" => "heweoo!"
- })
- response1 =
- build_conn()
- |> assign(:user, for_user)
- |> post("/api/v1/statuses/#{activity1.id}/bookmark")
-
- assert json_response(response1, 200)["bookmarked"] == true
-
- response2 =
- build_conn()
- |> assign(:user, for_user)
- |> post("/api/v1/statuses/#{activity2.id}/bookmark")
-
- assert json_response(response2, 200)["bookmarked"] == true
-
- bookmarks =
- build_conn()
- |> assign(:user, for_user)
- |> get("/api/v1/bookmarks")
-
- assert [json_response(response2, 200), json_response(response1, 200)] ==
- json_response(bookmarks, 200)
-
- response1 =
- build_conn()
- |> assign(:user, for_user)
- |> post("/api/v1/statuses/#{activity1.id}/unbookmark")
-
- assert json_response(response1, 200)["bookmarked"] == false
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
- bookmarks =
- build_conn()
- |> assign(:user, for_user)
- |> get("/api/v1/bookmarks")
+ assert _result = json_response(conn, 200)
- assert [json_response(response2, 200)] == json_response(bookmarks, 200)
+ user = User.get_cached_by_ap_id(user.ap_id)
+ assert user.info.settings == %{"programming" => "socks"}
end
- describe "conversation muting" do
+ describe "pinned statuses" do
setup do
- post_user = insert(:user)
user = insert(:user)
-
- {:ok, activity} = CommonAPI.post(post_user, %{"status" => "HIE"})
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
[user: user, activity: activity]
end
- test "mute conversation", %{conn: conn, user: user, activity: activity} do
- id_str = to_string(activity.id)
-
- assert %{"id" => ^id_str, "muted" => true} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/mute")
- |> json_response(200)
- end
-
- test "cannot mute already muted conversation", %{conn: conn, user: user, activity: activity} do
- {:ok, _} = CommonAPI.add_mute(user, activity)
+ test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
+ {:ok, _} = CommonAPI.pin(activity.id, user)
- conn =
+ result =
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)
+ |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
+ |> json_response(200)
id_str = to_string(activity.id)
- user = refresh_record(user)
- assert %{"id" => ^id_str, "muted" => false} =
- conn
- |> assign(:user, user)
- |> post("/api/v1/statuses/#{activity.id}/unmute")
- |> json_response(200)
+ assert [%{"id" => ^id_str, "pinned" => true}] = result
end
end
end
end
- test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{conn: conn} do
- user1 = insert(:user)
- user2 = insert(:user)
- user3 = insert(:user)
-
- {:ok, replied_to} = CommonAPI.post(user1, %{"status" => "cofe"})
-
- # Reply to status from another user
- conn1 =
- conn
- |> assign(:user, user2)
- |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
-
- assert %{"content" => "xD", "id" => id} = json_response(conn1, 200)
-
- activity = Activity.get_by_id_with_object(id)
-
- assert Object.normalize(activity).data["inReplyTo"] == Object.normalize(replied_to).data["id"]
- assert Activity.get_in_reply_to_activity(activity).id == replied_to.id
-
- # Reblog from the third user
- conn2 =
- conn
- |> assign(:user, user3)
- |> post("/api/v1/statuses/#{activity.id}/reblog")
-
- assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} =
- json_response(conn2, 200)
-
- assert to_string(activity.id) == id
-
- # Getting third user status
- conn3 =
- conn
- |> assign(:user, user3)
- |> get("api/v1/timelines/home")
-
- [reblogged_activity] = json_response(conn3, 200)
-
- assert reblogged_activity["reblog"]["in_reply_to_id"] == replied_to.id
-
- replied_to_user = User.get_by_ap_id(replied_to.data["actor"])
- assert reblogged_activity["reblog"]["in_reply_to_account_id"] == replied_to_user.id
- end
-
describe "create account by app" do
test "Account registration via Application", %{conn: conn} do
conn =
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, user: user]
- 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
-
- test "does not return users who have favorited the status but are blocked", %{
- conn: %{assigns: %{user: user}} = conn,
- activity: activity
- } do
- other_user = insert(:user)
- {:ok, user} = User.block(user, other_user)
-
- {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
-
- response =
- conn
- |> assign(:user, user)
- |> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
-
- assert Enum.empty?(response)
- end
-
- test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do
- other_user = insert(:user)
- {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
-
- response =
- conn
- |> assign(:user, nil)
- |> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(:ok)
-
- [%{"id" => id}] = response
- assert id == other_user.id
- end
-
- test "requires authentification for private posts", %{conn: conn, user: user} do
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} wanna get some #cofe together?",
- "visibility" => "direct"
- })
-
- {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
-
- conn
- |> assign(:user, nil)
- |> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(404)
-
- response =
- build_conn()
- |> assign(:user, other_user)
- |> get("/api/v1/statuses/#{activity.id}/favourited_by")
- |> json_response(200)
-
- [%{"id" => id}] = response
- assert id == other_user.id
- 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, user: user]
- 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
-
- test "does not return users who have reblogged the status but are blocked", %{
- conn: %{assigns: %{user: user}} = conn,
- activity: activity
- } do
- other_user = insert(:user)
- {:ok, user} = User.block(user, other_user)
-
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
-
- response =
- conn
- |> assign(:user, user)
- |> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
-
- assert Enum.empty?(response)
- end
-
- test "does not fail on an unauthenticated request", %{conn: conn, activity: activity} do
- other_user = insert(:user)
- {:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
-
- response =
- conn
- |> assign(:user, nil)
- |> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(:ok)
-
- [%{"id" => id}] = response
- assert id == other_user.id
- end
-
- test "requires authentification for private posts", %{conn: conn, user: user} do
- other_user = insert(:user)
-
- {:ok, activity} =
- CommonAPI.post(user, %{
- "status" => "@#{other_user.nickname} wanna get some #cofe together?",
- "visibility" => "direct"
- })
-
- conn
- |> assign(:user, nil)
- |> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(404)
-
- response =
- build_conn()
- |> assign(:user, other_user)
- |> get("/api/v1/statuses/#{activity.id}/reblogged_by")
- |> json_response(200)
-
- assert [] == response
- end
- end
-
describe "POST /auth/password, with valid parameters" do
setup %{conn: conn} do
user = insert(:user)
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
setup do
- user = insert(:user)
- info_change = User.Info.confirmation_changeset(user.info, need_confirmation: true)
-
{:ok, user} =
- user
- |> Changeset.change()
- |> Changeset.put_embed(:info, info_change)
+ insert(:user)
+ |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
|> Repo.update()
assert user.info.confirmation_pending