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.

202 lines
6.8KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.ObjectTest do
  5. use Pleroma.DataCase
  6. import ExUnit.CaptureLog
  7. import Pleroma.Factory
  8. import Tesla.Mock
  9. alias Pleroma.Activity
  10. alias Pleroma.Object
  11. alias Pleroma.Repo
  12. alias Pleroma.Web.CommonAPI
  13. setup do
  14. mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
  15. :ok
  16. end
  17. test "returns an object by it's AP id" do
  18. object = insert(:note)
  19. found_object = Object.get_by_ap_id(object.data["id"])
  20. assert object == found_object
  21. end
  22. describe "generic changeset" do
  23. test "it ensures uniqueness of the id" do
  24. object = insert(:note)
  25. cs = Object.change(%Object{}, %{data: %{id: object.data["id"]}})
  26. assert cs.valid?
  27. {:error, _result} = Repo.insert(cs)
  28. end
  29. end
  30. describe "deletion function" do
  31. test "deletes an object" do
  32. object = insert(:note)
  33. found_object = Object.get_by_ap_id(object.data["id"])
  34. assert object == found_object
  35. Object.delete(found_object)
  36. found_object = Object.get_by_ap_id(object.data["id"])
  37. refute object == found_object
  38. assert found_object.data["type"] == "Tombstone"
  39. end
  40. test "ensures cache is cleared for the object" do
  41. object = insert(:note)
  42. cached_object = Object.get_cached_by_ap_id(object.data["id"])
  43. assert object == cached_object
  44. Cachex.put(:web_resp_cache, URI.parse(object.data["id"]).path, "cofe")
  45. Object.delete(cached_object)
  46. {:ok, nil} = Cachex.get(:object_cache, "object:#{object.data["id"]}")
  47. {:ok, nil} = Cachex.get(:web_resp_cache, URI.parse(object.data["id"]).path)
  48. cached_object = Object.get_cached_by_ap_id(object.data["id"])
  49. refute object == cached_object
  50. assert cached_object.data["type"] == "Tombstone"
  51. end
  52. end
  53. describe "normalizer" do
  54. test "fetches unknown objects by default" do
  55. %Object{} =
  56. object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367")
  57. assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
  58. end
  59. test "fetches unknown objects when fetch_remote is explicitly true" do
  60. %Object{} =
  61. object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367", true)
  62. assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
  63. end
  64. test "does not fetch unknown objects when fetch_remote is false" do
  65. assert is_nil(
  66. Object.normalize("http://mastodon.example.org/@admin/99541947525187367", false)
  67. )
  68. end
  69. end
  70. describe "get_by_id_and_maybe_refetch" do
  71. setup do
  72. mock(fn
  73. %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
  74. %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
  75. env ->
  76. apply(HttpRequestMock, :request, [env])
  77. end)
  78. mock_modified = fn resp ->
  79. mock(fn
  80. %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
  81. resp
  82. env ->
  83. apply(HttpRequestMock, :request, [env])
  84. end)
  85. end
  86. on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
  87. [mock_modified: mock_modified]
  88. end
  89. test "refetches if the time since the last refetch is greater than the interval", %{
  90. mock_modified: mock_modified
  91. } do
  92. %Object{} =
  93. object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
  94. assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  95. assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  96. mock_modified.(%Tesla.Env{
  97. status: 200,
  98. body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
  99. })
  100. updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
  101. assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
  102. assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
  103. end
  104. test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
  105. %Object{} =
  106. object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
  107. assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  108. assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  109. assert capture_log(fn ->
  110. mock_modified.(%Tesla.Env{status: 404, body: ""})
  111. updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
  112. assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  113. assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  114. end) =~
  115. "[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
  116. end
  117. test "does not refetch if the time since the last refetch is greater than the interval", %{
  118. mock_modified: mock_modified
  119. } do
  120. %Object{} =
  121. object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
  122. assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  123. assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  124. mock_modified.(%Tesla.Env{
  125. status: 200,
  126. body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
  127. })
  128. updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
  129. assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  130. assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  131. end
  132. test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
  133. %Object{} =
  134. object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
  135. assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
  136. assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
  137. user = insert(:user)
  138. activity = Activity.get_create_by_object_ap_id(object.data["id"])
  139. {:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
  140. assert object.data["like_count"] == 1
  141. mock_modified.(%Tesla.Env{
  142. status: 200,
  143. body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
  144. })
  145. updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
  146. assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
  147. assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
  148. assert updated_object.data["like_count"] == 1
  149. end
  150. end
  151. end