little refactor and tests
authorAlexander Strizhakov <alex.strizhakov@gmail.com>
Mon, 25 Jan 2021 16:46:36 +0000 (19:46 +0300)
committerAlexander Strizhakov <alex.strizhakov@gmail.com>
Mon, 25 Jan 2021 16:46:36 +0000 (19:46 +0300)
for voted & own_votes fields in polls

lib/pleroma/web/mastodon_api/views/poll_view.ex
test/pleroma/web/mastodon_api/controllers/poll_controller_test.exs
test/pleroma/web/mastodon_api/views/poll_view_test.exs

index 94bc1c13992dfba57b37c88d958a13ec8487dac3..de536c8fb6959a6c5f31abdeaf2a16210f4d88f6 100644 (file)
@@ -10,9 +10,8 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
   def render("show.json", %{object: object, multiple: multiple, options: options} = params) do
     {end_time, expired} = end_time_and_expired(object)
     {options, votes_count} = options_and_votes_count(options)
-    {voted, own_votes} = voted_and_own_votes(params, options)
 
-    %{
+    poll = %{
       # Mastodon uses separate ids for polls, but an object can't have
       # more than one poll embedded so object id is fine
       id: to_string(object.id),
@@ -22,10 +21,16 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
       votes_count: votes_count,
       voters_count: voters_count(object),
       options: options,
-      voted: voted,
-      own_votes: own_votes,
       emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
     }
+
+    if params[:for] do
+      # if a user is not authenticated Mastodon doesn't include `voted` & `own_votes` keys in response
+      {voted, own_votes} = voted_and_own_votes(params, options)
+      Map.merge(poll, %{voted: voted, own_votes: own_votes})
+    else
+      poll
+    end
   end
 
   def render("show.json", %{object: object} = params) do
@@ -70,21 +75,25 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
   defp voters_count(_), do: 0
 
   defp voted_and_own_votes(%{object: object} = params, options) do
-    options = options |> Enum.map(fn x -> Map.get(x, :title) end)
-
     if params[:for] do
       existing_votes =
         Pleroma.Web.ActivityPub.Utils.get_existing_votes(params[:for].ap_id, object)
 
-      own_votes =
-        for vote <- existing_votes do
-          data = Map.get(vote, :object) |> Map.get(:data)
-
-          Enum.find_index(options, fn x -> x == data["name"] end)
-        end || []
-
       voted = existing_votes != [] or params[:for].ap_id == object.data["actor"]
 
+      own_votes =
+        if voted do
+          titles = Enum.map(options, & &1[:title])
+
+          Enum.reduce(existing_votes, [], fn vote, acc ->
+            data = vote |> Map.get(:object) |> Map.get(:data)
+            index = Enum.find_index(titles, &(&1 == data["name"]))
+            [index | acc]
+          end)
+        else
+          []
+        end
+
       {voted, own_votes}
     else
       {false, []}
index 95df48ab07eca75c2f022a748cdce4c1e9687b6a..da0a631a93de7d657c2b046133b09e319b4a53e7 100644 (file)
@@ -47,6 +47,78 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
     end
   end
 
+  test "own_votes" do
+    %{conn: conn} = oauth_access(["write:statuses", "read:statuses"])
+
+    other_user = insert(:user)
+
+    {:ok, activity} =
+      CommonAPI.post(other_user, %{
+        status: "A very delicious sandwich",
+        poll: %{
+          options: ["Lettuce", "Grilled Bacon", "Tomato"],
+          expires_in: 20,
+          multiple: true
+        }
+      })
+
+    object = Object.normalize(activity, fetch: false)
+
+    conn
+    |> put_req_header("content-type", "application/json")
+    |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 2]})
+    |> json_response_and_validate_schema(200)
+
+    object = Object.get_by_id(object.id)
+
+    assert [
+             %{
+               "name" => "Lettuce",
+               "replies" => %{"totalItems" => 1, "type" => "Collection"},
+               "type" => "Note"
+             },
+             %{
+               "name" => "Grilled Bacon",
+               "replies" => %{"totalItems" => 0, "type" => "Collection"},
+               "type" => "Note"
+             },
+             %{
+               "name" => "Tomato",
+               "replies" => %{"totalItems" => 1, "type" => "Collection"},
+               "type" => "Note"
+             }
+           ] == object.data["anyOf"]
+
+    assert %{"replies" => %{"totalItems" => 0}} =
+             Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == "Grilled Bacon" end)
+
+    Enum.each(["Lettuce", "Tomato"], fn title ->
+      %{"replies" => %{"totalItems" => total_items}} =
+        Enum.find(object.data["anyOf"], fn %{"name" => name} -> name == title end)
+
+      assert total_items == 1
+    end)
+
+    assert %{
+             "own_votes" => own_votes,
+             "voted" => true
+           } =
+             conn
+             |> get("/api/v1/polls/#{object.id}")
+             |> json_response_and_validate_schema(200)
+
+    assert 0 in own_votes
+    assert 2 in own_votes
+    # for non authenticated user
+    response =
+      build_conn()
+      |> get("/api/v1/polls/#{object.id}")
+      |> json_response_and_validate_schema(200)
+
+    refute Map.has_key?(response, "own_votes")
+    refute Map.has_key?(response, "voted")
+  end
+
   describe "POST /api/v1/polls/:id/votes" do
     setup do: oauth_access(["write:statuses"])
 
@@ -65,12 +137,11 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
 
       object = Object.normalize(activity, fetch: false)
 
-      conn =
-        conn
-        |> put_req_header("content-type", "application/json")
-        |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
+      conn
+      |> put_req_header("content-type", "application/json")
+      |> post("/api/v1/polls/#{object.id}/votes", %{"choices" => [0, 1, 2]})
+      |> json_response_and_validate_schema(200)
 
-      assert json_response_and_validate_schema(conn, 200)
       object = Object.get_by_id(object.id)
 
       assert Enum.all?(object.data["anyOf"], fn %{"replies" => %{"totalItems" => total_items}} ->
index f087d50e8a4b3c2d3a9ef1d52790871269d79f6b..224b26cb91db1593dd1c16e3c778fc8ece10b4df 100644 (file)
@@ -42,10 +42,8 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
         %{title: "yes", votes_count: 0},
         %{title: "why are you even asking?", votes_count: 0}
       ],
-      voted: false,
       votes_count: 0,
-      voters_count: 0,
-      own_votes: []
+      voters_count: 0
     }
 
     result = PollView.render("show.json", %{object: object})
@@ -124,10 +122,9 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do
 
     result = PollView.render("show.json", %{object: object, for: other_user})
 
-    _own_votes = result[:own_votes]
-
     assert result[:voted] == true
-    assert own_votes = [1, 2]
+    assert 1 in result[:own_votes]
+    assert 2 in result[:own_votes]
     assert Enum.at(result[:options], 1)[:votes_count] == 1
     assert Enum.at(result[:options], 2)[:votes_count] == 1
   end