1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.ObjectTest do
7 import ExUnit.CaptureLog
10 alias Pleroma.Activity
13 alias Pleroma.Web.CommonAPI
16 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
20 test "returns an object by it's AP id" do
21 object = insert(:note)
22 found_object = Object.get_by_ap_id(object.data["id"])
24 assert object == found_object
27 describe "generic changeset" do
28 test "it ensures uniqueness of the id" do
29 object = insert(:note)
30 cs = Object.change(%Object{}, %{data: %{id: object.data["id"]}})
33 {:error, _result} = Repo.insert(cs)
37 describe "deletion function" do
38 test "deletes an object" do
39 object = insert(:note)
40 found_object = Object.get_by_ap_id(object.data["id"])
42 assert object == found_object
44 Object.delete(found_object)
46 found_object = Object.get_by_ap_id(object.data["id"])
48 refute object == found_object
50 assert found_object.data["type"] == "Tombstone"
53 test "ensures cache is cleared for the object" do
54 object = insert(:note)
55 cached_object = Object.get_cached_by_ap_id(object.data["id"])
57 assert object == cached_object
59 Cachex.put(:web_resp_cache, URI.parse(object.data["id"]).path, "cofe")
61 Object.delete(cached_object)
63 {:ok, nil} = Cachex.get(:object_cache, "object:#{object.data["id"]}")
64 {:ok, nil} = Cachex.get(:web_resp_cache, URI.parse(object.data["id"]).path)
66 cached_object = Object.get_cached_by_ap_id(object.data["id"])
68 refute object == cached_object
70 assert cached_object.data["type"] == "Tombstone"
74 describe "normalizer" do
75 test "fetches unknown objects by default" do
77 object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367")
79 assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
82 test "fetches unknown objects when fetch_remote is explicitly true" do
84 object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367", true)
86 assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
89 test "does not fetch unknown objects when fetch_remote is false" do
91 Object.normalize("http://mastodon.example.org/@admin/99541947525187367", false)
96 describe "get_by_id_and_maybe_refetch" do
99 %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
100 %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/poll_original.json")}
103 apply(HttpRequestMock, :request, [env])
106 mock_modified = fn resp ->
108 %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
112 apply(HttpRequestMock, :request, [env])
116 on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
118 [mock_modified: mock_modified]
121 test "refetches if the time since the last refetch is greater than the interval", %{
122 mock_modified: mock_modified
125 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
127 Object.set_cache(object)
129 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
130 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
132 mock_modified.(%Tesla.Env{
134 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
137 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
138 object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
139 assert updated_object == object_in_cache
140 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
141 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
144 test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
146 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
148 Object.set_cache(object)
150 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
151 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
153 assert capture_log(fn ->
154 mock_modified.(%Tesla.Env{status: 404, body: ""})
156 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
157 object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
158 assert updated_object == object_in_cache
159 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
160 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
162 "[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
165 test "does not refetch if the time since the last refetch is greater than the interval", %{
166 mock_modified: mock_modified
169 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
171 Object.set_cache(object)
173 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
174 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
176 mock_modified.(%Tesla.Env{
178 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
181 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
182 object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
183 assert updated_object == object_in_cache
184 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
185 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
188 test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
190 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
192 Object.set_cache(object)
194 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
195 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
198 activity = Activity.get_create_by_object_ap_id(object.data["id"])
199 {:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
201 assert object.data["like_count"] == 1
203 mock_modified.(%Tesla.Env{
205 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
208 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
209 object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
210 assert updated_object == object_in_cache
211 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
212 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
214 assert updated_object.data["like_count"] == 1