alias Pleroma.Activity
alias Pleroma.ActivityExpiration
alias Pleroma.Config
+ alias Pleroma.Conversation.Participation
alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.ScheduledActivity
+ alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
+ clear_config([:instance, :federating])
+ clear_config([:instance, :allow_relay])
+
describe "posting statuses" do
setup do
user = insert(:user)
[conn: conn]
end
+ test "posting a status does not increment reblog_count when relaying", %{conn: conn} do
+ Pleroma.Config.put([:instance, :federating], true)
+ Pleroma.Config.get([:instance, :allow_relay], true)
+ user = insert(:user)
+
+ response =
+ conn
+ |> assign(:user, user)
+ |> post("api/v1/statuses", %{
+ "content_type" => "text/plain",
+ "source" => "Pleroma FE",
+ "status" => "Hello world",
+ "visibility" => "public"
+ })
+ |> json_response(200)
+
+ assert response["reblogs_count"] == 0
+ ObanHelpers.perform_all()
+
+ response =
+ conn
+ |> assign(:user, user)
+ |> get("api/v1/statuses/#{response["id"]}", %{})
+ |> json_response(200)
+
+ assert response["reblogs_count"] == 0
+ end
+
test "posting a status", %{conn: conn} do
idempotency_key = "Pikachu rocks!"
NaiveDateTime.to_iso8601(expiration.scheduled_at)
end
+ test "posting an undefined status with an attachment", %{conn: conn} do
+ user = insert(:user)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{
+ "media_ids" => [to_string(upload.id)]
+ })
+
+ assert json_response(conn, 200)
+ end
+
test "replying to a status", %{conn: conn} do
user = insert(:user)
{:ok, replied_to} = CommonAPI.post(user, %{"status" => "cofe"})
end
end
+ describe "posting scheduled statuses" do
+ test "creates a scheduled activity", %{conn: conn} do
+ user = insert(:user)
+ scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{
+ "status" => "scheduled",
+ "scheduled_at" => scheduled_at
+ })
+
+ assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
+ assert expected_scheduled_at == CommonAPI.Utils.to_masto_date(scheduled_at)
+ assert [] == Repo.all(Activity)
+ end
+
+ test "creates a scheduled activity with a media attachment", %{conn: conn} do
+ user = insert(:user)
+ scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{
+ "media_ids" => [to_string(upload.id)],
+ "status" => "scheduled",
+ "scheduled_at" => scheduled_at
+ })
+
+ assert %{"media_attachments" => [media_attachment]} = json_response(conn, 200)
+ assert %{"type" => "image"} = media_attachment
+ end
+
+ test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
+ %{conn: conn} do
+ user = insert(:user)
+
+ scheduled_at =
+ NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{
+ "status" => "not scheduled",
+ "scheduled_at" => scheduled_at
+ })
+
+ assert %{"content" => "not scheduled"} = json_response(conn, 200)
+ assert [] == Repo.all(ScheduledActivity)
+ end
+
+ test "returns error when daily user limit is exceeded", %{conn: conn} do
+ user = insert(:user)
+
+ today =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+
+ attrs = %{params: %{}, scheduled_at: today}
+ {:ok, _} = ScheduledActivity.create(user, attrs)
+ {:ok, _} = ScheduledActivity.create(user, attrs)
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => today})
+
+ assert %{"error" => "daily limit exceeded"} == json_response(conn, 422)
+ end
+
+ test "returns error when total user limit is exceeded", %{conn: conn} do
+ user = insert(:user)
+
+ today =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+
+ tomorrow =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.hours(36), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+
+ attrs = %{params: %{}, scheduled_at: today}
+ {:ok, _} = ScheduledActivity.create(user, attrs)
+ {:ok, _} = ScheduledActivity.create(user, attrs)
+ {:ok, _} = ScheduledActivity.create(user, %{params: %{}, scheduled_at: tomorrow})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses", %{"status" => "scheduled", "scheduled_at" => tomorrow})
+
+ assert %{"error" => "total limit exceeded"} == json_response(conn, 422)
+ end
+ end
+
describe "posting polls" do
test "posting a poll", %{conn: conn} do
user = insert(:user)
assert id == to_string(activity.id)
end
+ test "get a direct status", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{"status" => "@#{other_user.nickname}", "visibility" => "direct"})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/statuses/#{activity.id}")
+
+ [participation] = Participation.for_user(user)
+
+ res = json_response(conn, 200)
+ assert res["pleroma"]["direct_conversation_id"] == participation.id
+ end
+
test "get statuses by IDs", %{conn: conn} do
%{id: id1} = insert(:note_activity)
%{id: id2} = insert(:note_activity)
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})
+ admin = insert(:user, is_admin: true)
+ moderator = insert(:user, is_moderator: true)
res_conn =
conn
assert to_string(activity.id) == id
end
+ test "reblogs privately 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", %{"visibility" => "private"})
+
+ assert %{
+ "reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1},
+ "reblogged" => true,
+ "visibility" => "private"
+ } = 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)
activity: activity
} do
other_user = insert(:user)
- {:ok, user} = User.block(user, other_user)
+ {:ok, _user_relationship} = User.block(user, other_user)
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
activity: activity
} do
other_user = insert(:user)
- {:ok, user} = User.block(user, other_user)
+ {:ok, _user_relationship} = User.block(user, other_user)
{:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
assert Enum.empty?(response)
end
+ test "does not return users who have reblogged the status privately", %{
+ conn: %{assigns: %{user: user}} = conn,
+ activity: activity
+ } do
+ other_user = insert(:user)
+
+ {:ok, _, _} = CommonAPI.repeat(activity.id, other_user, %{"visibility" => "private"})
+
+ 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)
"descendants" => [%{"id" => ^id4}, %{"id" => ^id5}]
} = response
end
+
+ test "returns the favorites of a user", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
+
+ {:ok, _, _} = CommonAPI.favorite(activity.id, user)
+
+ first_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites")
+
+ assert [status] = json_response(first_conn, 200)
+ assert status["id"] == to_string(activity.id)
+
+ assert [{"link", _link_header}] =
+ Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
+
+ # Honours query params
+ {:ok, second_activity} =
+ CommonAPI.post(other_user, %{
+ "status" =>
+ "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
+ })
+
+ {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
+
+ last_like = status["id"]
+
+ second_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites?since_id=#{last_like}")
+
+ assert [second_status] = json_response(second_conn, 200)
+ assert second_status["id"] == to_string(second_activity.id)
+
+ third_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites?limit=0")
+
+ assert [] = json_response(third_conn, 200)
+ end
end