logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/

poll_controller_test.exs (8534B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
  5. use Oban.Testing, repo: Pleroma.Repo
  6. use Pleroma.Web.ConnCase, async: true
  7. alias Pleroma.Object
  8. alias Pleroma.Web.CommonAPI
  9. import Pleroma.Factory
  10. describe "GET /api/v1/polls/:id" do
  11. setup do: oauth_access(["read:statuses"])
  12. test "returns poll entity for object id", %{user: user, conn: conn} do
  13. {:ok, activity} =
  14. CommonAPI.post(user, %{
  15. status: "Pleroma does",
  16. poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20}
  17. })
  18. object = Object.normalize(activity, fetch: false)
  19. conn = get(conn, "/api/v1/polls/#{object.id}")
  20. response = json_response_and_validate_schema(conn, 200)
  21. id = to_string(object.id)
  22. assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
  23. # Local activities should not generate an Oban job to refresh
  24. assert activity.local
  25. refute_enqueued(
  26. worker: Pleroma.Workers.PollWorker,
  27. args: %{"op" => "refresh", "activity_id" => activity.id}
  28. )
  29. end
  30. test "creates an oban job to refresh poll if activity is remote", %{conn: conn} do
  31. user = insert(:user, local: false)
  32. question = insert(:question, user: user)
  33. activity = insert(:question_activity, question: question, local: false)
  34. # Ensure this is not represented as a local activity
  35. refute activity.local
  36. object = Object.normalize(activity, fetch: false)
  37. get(conn, "/api/v1/polls/#{object.id}")
  38. |> json_response_and_validate_schema(200)
  39. assert_enqueued(
  40. worker: Pleroma.Workers.PollWorker,
  41. args: %{"op" => "refresh", "activity_id" => activity.id}
  42. )
  43. end
  44. test "does not expose polls for private statuses", %{conn: conn} do
  45. other_user = insert(:user)
  46. {:ok, activity} =
  47. CommonAPI.post(other_user, %{
  48. status: "Pleroma does",
  49. poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20},
  50. visibility: "private"
  51. })
  52. object = Object.normalize(activity, fetch: false)
  53. conn = get(conn, "/api/v1/polls/#{object.id}")
  54. assert json_response_and_validate_schema(conn, 404)
  55. end
  56. end
  57. test "own_votes" do
  58. %{conn: conn} = oauth_access(["write:statuses", "read:statuses"])
  59. other_user = insert(:user)
  60. {:ok, activity} =
  61. CommonAPI.post(other_user, %{
  62. status: "A very delicious sandwich",
  63. poll: %{
  64. options: ["Lettuce", "Grilled Bacon", "Tomato"],
  65. expires_in: 20,
  66. multiple: true
  67. }
  68. })
  69. object = Object.normalize(activity, fetch: false)
  70. conn
  71. |> put_req_header("content-type", "application/json")
  72. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 2]})
  73. |> json_response_and_validate_schema(200)
  74. object = Object.get_by_id(object.id)
  75. assert [
  76. %{
  77. "name" => "Lettuce",
  78. "replies" => %{"totalItems" => 1, "type" => "Collection"},
  79. "type" => "Note"
  80. },
  81. %{
  82. "name" => "Grilled Bacon",
  83. "replies" => %{"totalItems" => 0, "type" => "Collection"},
  84. "type" => "Note"
  85. },
  86. %{
  87. "name" => "Tomato",
  88. "replies" => %{"totalItems" => 1, "type" => "Collection"},
  89. "type" => "Note"
  90. }
  91. ] == object.data["anyOf"]
  92. assert %{"replies" => %{"totalItems" => 0}} =
  93. Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == "Grilled Bacon" end)
  94. Enum.each(["Lettuce", "Tomato"], fn title ->
  95. %{"replies" => %{"totalItems" => total_items}} =
  96. Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == title end)
  97. assert total_items == 1
  98. end)
  99. assert %{
  100. "own_votes" => own_votes,
  101. "voted" => true
  102. } =
  103. conn
  104. |> get("/api/v1/polls/#{object.id}")
  105. |> json_response_and_validate_schema(200)
  106. assert 0 in own_votes
  107. assert 2 in own_votes
  108. # for non authenticated user
  109. response =
  110. build_conn()
  111. |> get("/api/v1/polls/#{object.id}")
  112. |> json_response_and_validate_schema(200)
  113. refute Map.has_key?(response, "own_votes")
  114. refute Map.has_key?(response, "voted")
  115. end
  116. describe "POST /api/v1/polls/:id/votes" do
  117. setup do: oauth_access(["write:statuses"])
  118. test "votes are added to the poll", %{conn: conn} do
  119. other_user = insert(:user)
  120. {:ok, activity} =
  121. CommonAPI.post(other_user, %{
  122. status: "A very delicious sandwich",
  123. poll: %{
  124. options: ["Lettuce", "Grilled Bacon", "Tomato"],
  125. expires_in: 20,
  126. multiple: true
  127. }
  128. })
  129. object = Object.normalize(activity, fetch: false)
  130. conn
  131. |> put_req_header("content-type", "application/json")
  132. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
  133. |> json_response_and_validate_schema(200)
  134. object = Object.get_by_id(object.id)
  135. assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
  136. total_items == 1
  137. end)
  138. end
  139. test "author can't vote", %{user: user, conn: conn} do
  140. {:ok, activity} =
  141. CommonAPI.post(user, %{
  142. status: "Am I cute?",
  143. poll: %{options: ["Yes", "No"], expires_in: 20}
  144. })
  145. object = Object.normalize(activity, fetch: false)
  146. assert conn
  147. |> put_req_header("content-type", "application/json")
  148. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
  149. |> json_response_and_validate_schema(422) == %{"error" => "Poll's author can't vote"}
  150. object = Object.get_by_id(object.id)
  151. refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
  152. end
  153. test "does not allow multiple choices on a single-choice question", %{conn: conn} do
  154. other_user = insert(:user)
  155. {:ok, activity} =
  156. CommonAPI.post(other_user, %{
  157. status: "The glass is",
  158. poll: %{options: ["half empty", "half full"], expires_in: 20}
  159. })
  160. object = Object.normalize(activity, fetch: false)
  161. assert conn
  162. |> put_req_header("content-type", "application/json")
  163. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
  164. |> json_response_and_validate_schema(422) == %{"error" => "Too many choices"}
  165. object = Object.get_by_id(object.id)
  166. refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
  167. total_items == 1
  168. end)
  169. end
  170. test "does not allow choice index to be greater than options count", %{conn: conn} do
  171. other_user = insert(:user)
  172. {:ok, activity} =
  173. CommonAPI.post(other_user, %{
  174. status: "Am I cute?",
  175. poll: %{options: ["Yes", "No"], expires_in: 20}
  176. })
  177. object = Object.normalize(activity, fetch: false)
  178. conn =
  179. conn
  180. |> put_req_header("content-type", "application/json")
  181. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
  182. assert json_response_and_validate_schema(conn, 422) == %{"error" => "Invalid indices"}
  183. end
  184. test "returns 404 error when object is not exist", %{conn: conn} do
  185. conn =
  186. conn
  187. |> put_req_header("content-type", "application/json")
  188. |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
  189. assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
  190. end
  191. test "returns 404 when poll is private and not available for user", %{conn: conn} do
  192. other_user = insert(:user)
  193. {:ok, activity} =
  194. CommonAPI.post(other_user, %{
  195. status: "Am I cute?",
  196. poll: %{options: ["Yes", "No"], expires_in: 20},
  197. visibility: "private"
  198. })
  199. object = Object.normalize(activity, fetch: false)
  200. conn =
  201. conn
  202. |> put_req_header("content-type", "application/json")
  203. |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
  204. assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
  205. end
  206. end
  207. end