Merge develop
[akkoma] / test / web / feed / user_controller_test.exs
index 41cc9e07ee24021aed7fdb258c99c9bf6bcff0be..9a5610baa9bd78ae47cbfe3ef8e232e81dad7030 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.Feed.UserControllerTest do
@@ -8,222 +8,195 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
   import Pleroma.Factory
   import SweetXml
 
+  alias Pleroma.Config
   alias Pleroma.Object
   alias Pleroma.User
+  alias Pleroma.Web.CommonAPI
 
-  clear_config([:feed])
-
-  test "gets a feed", %{conn: conn} do
-    Pleroma.Config.put(
-      [:feed, :post_title],
-      %{max_length: 10, omission: "..."}
-    )
-
-    activity = insert(:note_activity)
-
-    note =
-      insert(:note,
-        data: %{
-          "content" => "This is :moominmamma: note ",
-          "attachment" => [
-            %{
-              "url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}]
-            }
-          ],
-          "inReplyTo" => activity.data["id"]
-        }
-      )
+  setup do: clear_config([:instance, :federating], true)
 
-    note_activity = insert(:note_activity, note: note)
-    user = User.get_cached_by_ap_id(note_activity.data["actor"])
+  describe "feed" do
+    setup do: clear_config([:feed])
 
-    note2 =
-      insert(:note,
-        user: user,
-        data: %{"content" => "42 This is :moominmamma: note ", "inReplyTo" => activity.data["id"]}
+    test "gets an atom feed", %{conn: conn} do
+      Config.put(
+        [:feed, :post_title],
+        %{max_length: 10, omission: "..."}
       )
 
-    _note_activity2 = insert(:note_activity, note: note2)
-    object = Object.normalize(note_activity)
+      activity = insert(:note_activity)
+
+      note =
+        insert(:note,
+          data: %{
+            "content" => "This is :moominmamma: note ",
+            "attachment" => [
+              %{
+                "url" => [
+                  %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
+                ]
+              }
+            ],
+            "inReplyTo" => activity.data["id"]
+          }
+        )
+
+      note_activity = insert(:note_activity, note: note)
+      user = User.get_cached_by_ap_id(note_activity.data["actor"])
 
-    resp =
-      conn
-      |> put_req_header("content-type", "application/atom+xml")
-      |> get(user_feed_path(conn, :feed, user.nickname))
-      |> response(200)
+      note2 =
+        insert(:note,
+          user: user,
+          data: %{
+            "content" => "42 This is :moominmamma: note ",
+            "inReplyTo" => activity.data["id"]
+          }
+        )
 
-    activity_titles =
-      resp
-      |> SweetXml.parse()
-      |> SweetXml.xpath(~x"//entry/title/text()"l)
+      note_activity2 = insert(:note_activity, note: note2)
+      object = Object.normalize(note_activity)
 
-    assert activity_titles == ['42 This...', 'This is...']
-    assert resp =~ object.data["content"]
-  end
-
-  test "returns 404 for a missing feed", %{conn: conn} do
-    conn =
-      conn
-      |> put_req_header("content-type", "application/atom+xml")
-      |> get(user_feed_path(conn, :feed, "nonexisting"))
+      resp =
+        conn
+        |> put_req_header("accept", "application/atom+xml")
+        |> get(user_feed_path(conn, :feed, user.nickname))
+        |> response(200)
 
-    assert response(conn, 404)
-  end
+      activity_titles =
+        resp
+        |> SweetXml.parse()
+        |> SweetXml.xpath(~x"//entry/title/text()"l)
 
-  describe "feed_redirect" do
-    test "undefined format. it redirects to feed", %{conn: conn} do
-      note_activity = insert(:note_activity)
-      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+      assert activity_titles == ['42 This...', 'This is...']
+      assert resp =~ object.data["content"]
 
-      response =
+      resp =
         conn
-        |> put_req_header("accept", "application/xml")
-        |> get("/users/#{user.nickname}")
-        |> response(302)
+        |> put_req_header("accept", "application/atom+xml")
+        |> get("/users/#{user.nickname}/feed", %{"max_id" => note_activity2.id})
+        |> response(200)
 
-      assert response ==
-               "<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{
-                 user.nickname
-               }/feed.atom\">redirected</a>.</body></html>"
+      activity_titles =
+        resp
+        |> SweetXml.parse()
+        |> SweetXml.xpath(~x"//entry/title/text()"l)
+
+      assert activity_titles == ['This is...']
     end
 
-    test "undefined format. it returns error when user not found", %{conn: conn} do
-      response =
+    test "gets a rss feed", %{conn: conn} do
+      Pleroma.Config.put(
+        [:feed, :post_title],
+        %{max_length: 10, omission: "..."}
+      )
+
+      activity = insert(:note_activity)
+
+      note =
+        insert(:note,
+          data: %{
+            "content" => "This is :moominmamma: note ",
+            "attachment" => [
+              %{
+                "url" => [
+                  %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
+                ]
+              }
+            ],
+            "inReplyTo" => activity.data["id"]
+          }
+        )
+
+      note_activity = insert(:note_activity, note: note)
+      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+      note2 =
+        insert(:note,
+          user: user,
+          data: %{
+            "content" => "42 This is :moominmamma: note ",
+            "inReplyTo" => activity.data["id"]
+          }
+        )
+
+      note_activity2 = insert(:note_activity, note: note2)
+      object = Object.normalize(note_activity)
+
+      resp =
         conn
-        |> put_req_header("accept", "application/xml")
-        |> get(user_feed_path(conn, :feed, "jimm"))
-        |> response(404)
+        |> put_req_header("accept", "application/rss+xml")
+        |> get("/users/#{user.nickname}/feed.rss")
+        |> response(200)
 
-      assert response == ~S({"error":"Not found"})
-    end
+      activity_titles =
+        resp
+        |> SweetXml.parse()
+        |> SweetXml.xpath(~x"//item/title/text()"l)
 
-    test "activity+json format. it redirects on actual feed of user", %{conn: conn} do
-      note_activity = insert(:note_activity)
-      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+      assert activity_titles == ['42 This...', 'This is...']
+      assert resp =~ object.data["content"]
 
-      response =
+      resp =
         conn
-        |> put_req_header("accept", "application/activity+json")
-        |> get("/users/#{user.nickname}")
-        |> json_response(200)
-
-      assert response["endpoints"] == %{
-               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
-               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
-               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
-               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
-               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
-             }
-
-      assert response["@context"] == [
-               "https://www.w3.org/ns/activitystreams",
-               "http://localhost:4001/schemas/litepub-0.1.jsonld",
-               %{"@language" => "und"}
-             ]
-
-      assert Map.take(response, [
-               "followers",
-               "following",
-               "id",
-               "inbox",
-               "manuallyApprovesFollowers",
-               "name",
-               "outbox",
-               "preferredUsername",
-               "summary",
-               "tag",
-               "type",
-               "url"
-             ]) == %{
-               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
-               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
-               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
-               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
-               "manuallyApprovesFollowers" => false,
-               "name" => user.name,
-               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
-               "preferredUsername" => user.nickname,
-               "summary" => user.bio,
-               "tag" => [],
-               "type" => "Person",
-               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
-             }
+        |> put_req_header("accept", "application/rss+xml")
+        |> get("/users/#{user.nickname}/feed.rss", %{"max_id" => note_activity2.id})
+        |> response(200)
+
+      activity_titles =
+        resp
+        |> SweetXml.parse()
+        |> SweetXml.xpath(~x"//item/title/text()"l)
+
+      assert activity_titles == ['This is...']
     end
 
-    test "activity+json format. it returns error whe use not found", %{conn: conn} do
-      response =
+    test "returns 404 for a missing feed", %{conn: conn} do
+      conn =
         conn
-        |> put_req_header("accept", "application/activity+json")
-        |> get("/users/jimm")
-        |> json_response(404)
+        |> put_req_header("accept", "application/atom+xml")
+        |> get(user_feed_path(conn, :feed, "nonexisting"))
 
-      assert response == "Not found"
+      assert response(conn, 404)
     end
 
-    test "json format. it redirects on actual feed of user", %{conn: conn} do
-      note_activity = insert(:note_activity)
-      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+    test "returns feed with public and unlisted activities", %{conn: conn} do
+      user = insert(:user)
 
-      response =
+      {:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
+      {:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
+      {:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
+      {:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
+
+      resp =
         conn
-        |> put_req_header("accept", "application/json")
-        |> get("/users/#{user.nickname}")
-        |> json_response(200)
-
-      assert response["endpoints"] == %{
-               "oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
-               "oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
-               "oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
-               "sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
-               "uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
-             }
-
-      assert response["@context"] == [
-               "https://www.w3.org/ns/activitystreams",
-               "http://localhost:4001/schemas/litepub-0.1.jsonld",
-               %{"@language" => "und"}
-             ]
-
-      assert Map.take(response, [
-               "followers",
-               "following",
-               "id",
-               "inbox",
-               "manuallyApprovesFollowers",
-               "name",
-               "outbox",
-               "preferredUsername",
-               "summary",
-               "tag",
-               "type",
-               "url"
-             ]) == %{
-               "followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
-               "following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
-               "id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
-               "inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
-               "manuallyApprovesFollowers" => false,
-               "name" => user.name,
-               "outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
-               "preferredUsername" => user.nickname,
-               "summary" => user.bio,
-               "tag" => [],
-               "type" => "Person",
-               "url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
-             }
+        |> put_req_header("accept", "application/atom+xml")
+        |> get(user_feed_path(conn, :feed, user.nickname))
+        |> response(200)
+
+      activity_titles =
+        resp
+        |> SweetXml.parse()
+        |> SweetXml.xpath(~x"//entry/title/text()"l)
+        |> Enum.sort()
+
+      assert activity_titles == ['public', 'unlisted']
     end
 
-    test "json format. it returns error whe use not found", %{conn: conn} do
-      response =
-        conn
-        |> put_req_header("accept", "application/json")
-        |> get("/users/jimm")
-        |> json_response(404)
+    test "returns 404 when the user is remote", %{conn: conn} do
+      user = insert(:user, local: false)
+
+      {:ok, _} = CommonAPI.post(user, %{status: "test"})
 
-      assert response == "Not found"
+      assert conn
+             |> put_req_header("accept", "application/atom+xml")
+             |> get(user_feed_path(conn, :feed, user.nickname))
+             |> response(404)
     end
+  end
 
-    test "html format. it redirects on actual feed of user", %{conn: conn} do
+  # Note: see ActivityPubControllerTest for JSON format tests
+  describe "feed_redirect" do
+    test "with html format, it redirects to user feed", %{conn: conn} do
       note_activity = insert(:note_activity)
       user = User.get_cached_by_ap_id(note_activity.data["actor"])
 
@@ -239,7 +212,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
                ).resp_body
     end
 
-    test "html format. it returns error when user not found", %{conn: conn} do
+    test "with html format, it returns error when user is not found", %{conn: conn} do
       response =
         conn
         |> get("/users/jimm")
@@ -247,5 +220,46 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
 
       assert response == %{"error" => "Not found"}
     end
+
+    test "with non-html / non-json format, it redirects to user feed in atom format", %{
+      conn: conn
+    } do
+      note_activity = insert(:note_activity)
+      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+      conn =
+        conn
+        |> put_req_header("accept", "application/xml")
+        |> get("/users/#{user.nickname}")
+
+      assert conn.status == 302
+      assert redirected_to(conn) == "#{Pleroma.Web.base_url()}/users/#{user.nickname}/feed.atom"
+    end
+
+    test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
+      response =
+        conn
+        |> put_req_header("accept", "application/xml")
+        |> get(user_feed_path(conn, :feed, "jimm"))
+        |> response(404)
+
+      assert response == ~S({"error":"Not found"})
+    end
+  end
+
+  describe "private instance" do
+    setup do: clear_config([:instance, :public])
+
+    test "returns 404 for user feed", %{conn: conn} do
+      Config.put([:instance, :public], false)
+      user = insert(:user)
+
+      {:ok, _} = CommonAPI.post(user, %{status: "test"})
+
+      assert conn
+             |> put_req_header("accept", "application/atom+xml")
+             |> get(user_feed_path(conn, :feed, user.nickname))
+             |> response(404)
+    end
   end
 end