Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.4KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.Feed.UserControllerTest do
  5. use Pleroma.Web.ConnCase
  6. import Pleroma.Factory
  7. import SweetXml
  8. alias Pleroma.Object
  9. alias Pleroma.User
  10. alias Pleroma.Web.CommonAPI
  11. alias Pleroma.Web.Feed.FeedView
  12. setup do: clear_config([:static_fe, :enabled], false)
  13. describe "feed" do
  14. setup do: clear_config([:feed])
  15. setup do
  16. clear_config(
  17. [:feed, :post_title],
  18. %{max_length: 15, omission: "..."}
  19. )
  20. activity = insert(:note_activity)
  21. note =
  22. insert(:note,
  23. data: %{
  24. "content" => "This & this is :moominmamma: note ",
  25. "source" => "This & this is :moominmamma: note ",
  26. "attachment" => [
  27. %{
  28. "url" => [
  29. %{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
  30. ]
  31. }
  32. ],
  33. "inReplyTo" => activity.data["id"],
  34. "context" => "2hu & as",
  35. "summary" => "2hu & as"
  36. }
  37. )
  38. note_activity = insert(:note_activity, note: note)
  39. user = User.get_cached_by_ap_id(note_activity.data["actor"])
  40. note2 =
  41. insert(:note,
  42. user: user,
  43. data: %{
  44. "content" => "42 & This is :moominmamma: note ",
  45. "inReplyTo" => activity.data["id"]
  46. }
  47. )
  48. note_activity2 = insert(:note_activity, note: note2)
  49. object = Object.normalize(note_activity, fetch: false)
  50. [user: user, object: object, max_id: note_activity2.id]
  51. end
  52. test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_id} do
  53. resp =
  54. conn
  55. |> put_req_header("accept", "application/atom+xml")
  56. |> get(user_feed_path(conn, :feed, user.nickname))
  57. |> response(200)
  58. activity_titles =
  59. resp
  60. |> SweetXml.parse()
  61. |> SweetXml.xpath(~x"//entry/title/text()"l)
  62. assert activity_titles == ['42 &amp; Thi...', 'This &amp; t...']
  63. assert resp =~ FeedView.escape(object.data["content"])
  64. assert resp =~ FeedView.escape(object.data["summary"])
  65. assert resp =~ FeedView.escape(object.data["context"])
  66. resp =
  67. conn
  68. |> put_req_header("accept", "application/atom+xml")
  69. |> get("/users/#{user.nickname}/feed", %{"max_id" => max_id})
  70. |> response(200)
  71. activity_titles =
  72. resp
  73. |> SweetXml.parse()
  74. |> SweetXml.xpath(~x"//entry/title/text()"l)
  75. assert activity_titles == ['This &amp; t...']
  76. end
  77. test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id} do
  78. resp =
  79. conn
  80. |> put_req_header("accept", "application/rss+xml")
  81. |> get("/users/#{user.nickname}/feed.rss")
  82. |> response(200)
  83. activity_titles =
  84. resp
  85. |> SweetXml.parse()
  86. |> SweetXml.xpath(~x"//item/title/text()"l)
  87. assert activity_titles == ['42 &amp; Thi...', 'This &amp; t...']
  88. assert resp =~ FeedView.escape(object.data["content"])
  89. assert resp =~ FeedView.escape(object.data["summary"])
  90. assert resp =~ FeedView.escape(object.data["context"])
  91. resp =
  92. conn
  93. |> put_req_header("accept", "application/rss+xml")
  94. |> get("/users/#{user.nickname}/feed.rss", %{"max_id" => max_id})
  95. |> response(200)
  96. activity_titles =
  97. resp
  98. |> SweetXml.parse()
  99. |> SweetXml.xpath(~x"//item/title/text()"l)
  100. assert activity_titles == ['This &amp; t...']
  101. end
  102. test "returns 404 for a missing feed", %{conn: conn} do
  103. conn =
  104. conn
  105. |> put_req_header("accept", "application/atom+xml")
  106. |> get(user_feed_path(conn, :feed, "nonexisting"))
  107. assert response(conn, 404)
  108. end
  109. test "returns feed with public and unlisted activities", %{conn: conn} do
  110. user = insert(:user)
  111. {:ok, _} = CommonAPI.post(user, %{status: "public", visibility: "public"})
  112. {:ok, _} = CommonAPI.post(user, %{status: "direct", visibility: "direct"})
  113. {:ok, _} = CommonAPI.post(user, %{status: "unlisted", visibility: "unlisted"})
  114. {:ok, _} = CommonAPI.post(user, %{status: "private", visibility: "private"})
  115. resp =
  116. conn
  117. |> put_req_header("accept", "application/atom+xml")
  118. |> get(user_feed_path(conn, :feed, user.nickname))
  119. |> response(200)
  120. activity_titles =
  121. resp
  122. |> SweetXml.parse()
  123. |> SweetXml.xpath(~x"//entry/title/text()"l)
  124. |> Enum.sort()
  125. assert activity_titles == ['public', 'unlisted']
  126. end
  127. test "returns 404 when the user is remote", %{conn: conn} do
  128. user = insert(:user, local: false)
  129. {:ok, _} = CommonAPI.post(user, %{status: "test"})
  130. assert conn
  131. |> put_req_header("accept", "application/atom+xml")
  132. |> get(user_feed_path(conn, :feed, user.nickname))
  133. |> response(404)
  134. end
  135. test "does not require authentication on non-federating instances", %{conn: conn} do
  136. clear_config([:instance, :federating], false)
  137. user = insert(:user)
  138. conn
  139. |> put_req_header("accept", "application/rss+xml")
  140. |> get("/users/#{user.nickname}/feed.rss")
  141. |> response(200)
  142. end
  143. end
  144. # Note: see ActivityPubControllerTest for JSON format tests
  145. describe "feed_redirect" do
  146. test "with html format, it redirects to user feed", %{conn: conn} do
  147. note_activity = insert(:note_activity)
  148. user = User.get_cached_by_ap_id(note_activity.data["actor"])
  149. response =
  150. conn
  151. |> get("/users/#{user.nickname}")
  152. |> response(200)
  153. assert response ==
  154. Pleroma.Web.Fallback.RedirectController.redirector_with_meta(
  155. conn,
  156. %{user: user}
  157. ).resp_body
  158. end
  159. test "with html format, it returns error when user is not found", %{conn: conn} do
  160. response =
  161. conn
  162. |> get("/users/jimm")
  163. |> json_response(404)
  164. assert response == %{"error" => "Not found"}
  165. end
  166. test "with non-html / non-json format, it redirects to user feed in atom format", %{
  167. conn: conn
  168. } do
  169. note_activity = insert(:note_activity)
  170. user = User.get_cached_by_ap_id(note_activity.data["actor"])
  171. conn =
  172. conn
  173. |> put_req_header("accept", "application/xml")
  174. |> get("/users/#{user.nickname}")
  175. assert conn.status == 302
  176. assert redirected_to(conn) ==
  177. "#{Pleroma.Web.Endpoint.url()}/users/#{user.nickname}/feed.atom"
  178. end
  179. test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
  180. response =
  181. conn
  182. |> put_req_header("accept", "application/xml")
  183. |> get(user_feed_path(conn, :feed, "jimm"))
  184. |> response(404)
  185. assert response == ~S({"error":"Not found"})
  186. end
  187. end
  188. describe "private instance" do
  189. setup do: clear_config([:instance, :public])
  190. test "returns 404 for user feed", %{conn: conn} do
  191. clear_config([:instance, :public], false)
  192. user = insert(:user)
  193. {:ok, _} = CommonAPI.post(user, %{status: "test"})
  194. assert conn
  195. |> put_req_header("accept", "application/atom+xml")
  196. |> get(user_feed_path(conn, :feed, user.nickname))
  197. |> response(404)
  198. end
  199. end
  200. end