Merge branch 'develop' into feature/moderation-log-filters
[akkoma] / test / object_test.exs
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
5 defmodule Pleroma.ObjectTest do
6 use Pleroma.DataCase
7 import ExUnit.CaptureLog
8 import Pleroma.Factory
9 import Tesla.Mock
10 alias Pleroma.Activity
11 alias Pleroma.Object
12 alias Pleroma.Repo
13 alias Pleroma.Web.CommonAPI
14
15 setup do
16 mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
17 :ok
18 end
19
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"])
23
24 assert object == found_object
25 end
26
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"]}})
31 assert cs.valid?
32
33 {:error, _result} = Repo.insert(cs)
34 end
35 end
36
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"])
41
42 assert object == found_object
43
44 Object.delete(found_object)
45
46 found_object = Object.get_by_ap_id(object.data["id"])
47
48 refute object == found_object
49
50 assert found_object.data["type"] == "Tombstone"
51 end
52
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"])
56
57 assert object == cached_object
58
59 Cachex.put(:web_resp_cache, URI.parse(object.data["id"]).path, "cofe")
60
61 Object.delete(cached_object)
62
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)
65
66 cached_object = Object.get_cached_by_ap_id(object.data["id"])
67
68 refute object == cached_object
69
70 assert cached_object.data["type"] == "Tombstone"
71 end
72 end
73
74 describe "normalizer" do
75 test "fetches unknown objects by default" do
76 %Object{} =
77 object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367")
78
79 assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
80 end
81
82 test "fetches unknown objects when fetch_remote is explicitly true" do
83 %Object{} =
84 object = Object.normalize("http://mastodon.example.org/@admin/99541947525187367", true)
85
86 assert object.data["url"] == "http://mastodon.example.org/@admin/99541947525187367"
87 end
88
89 test "does not fetch unknown objects when fetch_remote is false" do
90 assert is_nil(
91 Object.normalize("http://mastodon.example.org/@admin/99541947525187367", false)
92 )
93 end
94 end
95
96 describe "get_by_id_and_maybe_refetch" do
97 setup do
98 mock(fn
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")}
101
102 env ->
103 apply(HttpRequestMock, :request, [env])
104 end)
105
106 mock_modified = fn resp ->
107 mock(fn
108 %{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
109 resp
110
111 env ->
112 apply(HttpRequestMock, :request, [env])
113 end)
114 end
115
116 on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
117
118 [mock_modified: mock_modified]
119 end
120
121 test "refetches if the time since the last refetch is greater than the interval", %{
122 mock_modified: mock_modified
123 } do
124 %Object{} =
125 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
126
127 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
128 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
129
130 mock_modified.(%Tesla.Env{
131 status: 200,
132 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
133 })
134
135 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
136 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
137 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
138 end
139
140 test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
141 %Object{} =
142 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
143
144 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
145 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
146
147 assert capture_log(fn ->
148 mock_modified.(%Tesla.Env{status: 404, body: ""})
149
150 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
151 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
152 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
153 end) =~
154 "[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
155 end
156
157 test "does not refetch if the time since the last refetch is greater than the interval", %{
158 mock_modified: mock_modified
159 } do
160 %Object{} =
161 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
162
163 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
164 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
165
166 mock_modified.(%Tesla.Env{
167 status: 200,
168 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
169 })
170
171 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
172 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
173 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
174 end
175
176 test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
177 %Object{} =
178 object = Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d")
179
180 assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
181 assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
182
183 user = insert(:user)
184 activity = Activity.get_create_by_object_ap_id(object.data["id"])
185 {:ok, _activity, object} = CommonAPI.favorite(activity.id, user)
186
187 assert object.data["like_count"] == 1
188
189 mock_modified.(%Tesla.Env{
190 status: 200,
191 body: File.read!("test/fixtures/tesla_mock/poll_modified.json")
192 })
193
194 updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
195 assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
196 assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
197
198 assert updated_object.data["like_count"] == 1
199 end
200 end
201 end