logo

pleroma

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

poll_controller_test.exs (7614B)


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