1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
6 use Pleroma.Web.ConnCase, async: true
9 alias Pleroma.Web.CommonAPI
11 import Pleroma.Factory
13 describe "GET /api/v1/polls/:id" do
14 setup do: oauth_access(["read:statuses"])
16 test "returns poll entity for object id", %{user: user, conn: conn} do
18 CommonAPI.post(user, %{
19 status: "Pleroma does",
20 poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20}
23 object = Object.normalize(activity, fetch: false)
25 conn = get(conn, "/api/v1/polls/#{object.id}")
27 response = json_response_and_validate_schema(conn, 200)
28 id = to_string(object.id)
29 assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
32 test "does not expose polls for private statuses", %{conn: conn} do
33 other_user = insert(:user)
36 CommonAPI.post(other_user, %{
37 status: "Pleroma does",
38 poll: %{options: ["what Mastodon't", "n't what Mastodoes"], expires_in: 20},
42 object = Object.normalize(activity, fetch: false)
44 conn = get(conn, "/api/v1/polls/#{object.id}")
46 assert json_response_and_validate_schema(conn, 404)
51 %{conn: conn} = oauth_access(["write:statuses", "read:statuses"])
53 other_user = insert(:user)
56 CommonAPI.post(other_user, %{
57 status: "A very delicious sandwich",
59 options: ["Lettuce", "Grilled Bacon", "Tomato"],
65 object = Object.normalize(activity, fetch: false)
68 |> put_req_header("content-type", "application/json")
69 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 2]})
70 |> json_response_and_validate_schema(200)
72 object = Object.get_by_id(object.id)
77 "replies" => %{"totalItems" => 1, "type" => "Collection"},
81 "name" => "Grilled Bacon",
82 "replies" => %{"totalItems" => 0, "type" => "Collection"},
87 "replies" => %{"totalItems" => 1, "type" => "Collection"},
90 ] == object.data["anyOf"]
92 assert %{"replies" => %{"totalItems" => 0}} =
93 Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == "Grilled Bacon" end)
95 Enum.each(["Lettuce", "Tomato"], fn title ->
96 %{"replies" => %{"totalItems" => total_items}} =
97 Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == title end)
99 assert total_items == 1
103 "own_votes" => own_votes,
107 |> get("/api/v1/polls/#{object.id}")
108 |> json_response_and_validate_schema(200)
110 assert 0 in own_votes
111 assert 2 in own_votes
112 # for non authenticated user
115 |> get("/api/v1/polls/#{object.id}")
116 |> json_response_and_validate_schema(200)
118 refute Map.has_key?(response, "own_votes")
119 refute Map.has_key?(response, "voted")
122 describe "POST /api/v1/polls/:id/votes" do
123 setup do: oauth_access(["write:statuses"])
125 test "votes are added to the poll", %{conn: conn} do
126 other_user = insert(:user)
129 CommonAPI.post(other_user, %{
130 status: "A very delicious sandwich",
132 options: ["Lettuce", "Grilled Bacon", "Tomato"],
138 object = Object.normalize(activity, fetch: false)
141 |> put_req_header("content-type", "application/json")
142 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
143 |> json_response_and_validate_schema(200)
145 object = Object.get_by_id(object.id)
147 assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
152 test "author can't vote", %{user: user, conn: conn} do
154 CommonAPI.post(user, %{
155 status: "Am I cute?",
156 poll: %{options: ["Yes", "No"], expires_in: 20}
159 object = Object.normalize(activity, fetch: false)
162 |> put_req_header("content-type", "application/json")
163 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [1]})
164 |> json_response_and_validate_schema(422) == %{"error" => "Poll's author can't vote"}
166 object = Object.get_by_id(object.id)
168 refute Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 1
171 test "does not allow multiple choices on a single-choice question", %{conn: conn} do
172 other_user = insert(:user)
175 CommonAPI.post(other_user, %{
176 status: "The glass is",
177 poll: %{options: ["half empty", "half full"], expires_in: 20}
180 object = Object.normalize(activity, fetch: false)
183 |> put_req_header("content-type", "application/json")
184 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1]})
185 |> json_response_and_validate_schema(422) == %{"error" => "Too many choices"}
187 object = Object.get_by_id(object.id)
189 refute Enum.any?(object.data["oneOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
194 test "does not allow choice index to be greater than options count", %{conn: conn} do
195 other_user = insert(:user)
198 CommonAPI.post(other_user, %{
199 status: "Am I cute?",
200 poll: %{options: ["Yes", "No"], expires_in: 20}
203 object = Object.normalize(activity, fetch: false)
207 |> put_req_header("content-type", "application/json")
208 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [2]})
210 assert json_response_and_validate_schema(conn, 422) == %{"error" => "Invalid indices"}
213 test "returns 404 error when object is not exist", %{conn: conn} do
216 |> put_req_header("content-type", "application/json")
217 |> post("/api/v1/polls/1/votes", %{"choices" => [0]})
219 assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}
222 test "returns 404 when poll is private and not available for user", %{conn: conn} do
223 other_user = insert(:user)
226 CommonAPI.post(other_user, %{
227 status: "Am I cute?",
228 poll: %{options: ["Yes", "No"], expires_in: 20},
229 visibility: "private"
232 object = Object.normalize(activity, fetch: false)
236 |> put_req_header("content-type", "application/json")
237 |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0]})
239 assert json_response_and_validate_schema(conn, 404) == %{"error" => "Record not found"}