logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

utils_test.exs (16906B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.ActivityPub.UtilsTest do
  5. use Pleroma.DataCase
  6. alias Pleroma.Activity
  7. alias Pleroma.Object
  8. alias Pleroma.Repo
  9. alias Pleroma.User
  10. alias Pleroma.Web.ActivityPub.Utils
  11. alias Pleroma.Web.AdminAPI.AccountView
  12. alias Pleroma.Web.CommonAPI
  13. import Pleroma.Factory
  14. require Pleroma.Constants
  15. describe "fetch the latest Follow" do
  16. test "fetches the latest Follow activity" do
  17. %Activity{data: %{"type" => "Follow"}} = activity = insert(:follow_activity)
  18. follower = User.get_cached_by_ap_id(activity.data["actor"])
  19. followed = User.get_cached_by_ap_id(activity.data["object"])
  20. assert activity == Utils.fetch_latest_follow(follower, followed)
  21. end
  22. end
  23. describe "determine_explicit_mentions()" do
  24. test "works with an object that has mentions" do
  25. object = %{
  26. "tag" => [
  27. %{
  28. "type" => "Mention",
  29. "href" => "https://example.com/~alyssa",
  30. "name" => "Alyssa P. Hacker"
  31. }
  32. ]
  33. }
  34. assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
  35. end
  36. test "works with an object that does not have mentions" do
  37. object = %{
  38. "tag" => [
  39. %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
  40. ]
  41. }
  42. assert Utils.determine_explicit_mentions(object) == []
  43. end
  44. test "works with an object that has mentions and other tags" do
  45. object = %{
  46. "tag" => [
  47. %{
  48. "type" => "Mention",
  49. "href" => "https://example.com/~alyssa",
  50. "name" => "Alyssa P. Hacker"
  51. },
  52. %{"type" => "Hashtag", "href" => "https://example.com/tag/2hu", "name" => "2hu"}
  53. ]
  54. }
  55. assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
  56. end
  57. test "works with an object that has no tags" do
  58. object = %{}
  59. assert Utils.determine_explicit_mentions(object) == []
  60. end
  61. test "works with an object that has only IR tags" do
  62. object = %{"tag" => ["2hu"]}
  63. assert Utils.determine_explicit_mentions(object) == []
  64. end
  65. test "works with an object has tags as map" do
  66. object = %{
  67. "tag" => %{
  68. "type" => "Mention",
  69. "href" => "https://example.com/~alyssa",
  70. "name" => "Alyssa P. Hacker"
  71. }
  72. }
  73. assert Utils.determine_explicit_mentions(object) == ["https://example.com/~alyssa"]
  74. end
  75. end
  76. describe "make_like_data" do
  77. setup do
  78. user = insert(:user)
  79. other_user = insert(:user)
  80. third_user = insert(:user)
  81. [user: user, other_user: other_user, third_user: third_user]
  82. end
  83. test "addresses actor's follower address if the activity is public", %{
  84. user: user,
  85. other_user: other_user,
  86. third_user: third_user
  87. } do
  88. expected_to = Enum.sort([user.ap_id, other_user.follower_address])
  89. expected_cc = Enum.sort(["https://www.w3.org/ns/activitystreams#Public", third_user.ap_id])
  90. {:ok, activity} =
  91. CommonAPI.post(user, %{
  92. status:
  93. "hey @#{other_user.nickname}, @#{third_user.nickname} how about beering together this weekend?"
  94. })
  95. %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
  96. assert Enum.sort(to) == expected_to
  97. assert Enum.sort(cc) == expected_cc
  98. end
  99. test "does not adress actor's follower address if the activity is not public", %{
  100. user: user,
  101. other_user: other_user,
  102. third_user: third_user
  103. } do
  104. expected_to = Enum.sort([user.ap_id])
  105. expected_cc = [third_user.ap_id]
  106. {:ok, activity} =
  107. CommonAPI.post(user, %{
  108. status: "@#{other_user.nickname} @#{third_user.nickname} bought a new swimsuit!",
  109. visibility: "private"
  110. })
  111. %{"to" => to, "cc" => cc} = Utils.make_like_data(other_user, activity, nil)
  112. assert Enum.sort(to) == expected_to
  113. assert Enum.sort(cc) == expected_cc
  114. end
  115. end
  116. test "make_json_ld_header/0" do
  117. assert Utils.make_json_ld_header() == %{
  118. "@context" => [
  119. "https://www.w3.org/ns/activitystreams",
  120. "http://localhost:4001/schemas/litepub-0.1.jsonld",
  121. %{
  122. "@language" => "und"
  123. }
  124. ]
  125. }
  126. end
  127. describe "get_existing_votes" do
  128. test "fetches existing votes" do
  129. user = insert(:user)
  130. other_user = insert(:user)
  131. {:ok, activity} =
  132. CommonAPI.post(user, %{
  133. status: "How do I pronounce LaTeX?",
  134. poll: %{
  135. options: ["laytekh", "lahtekh", "latex"],
  136. expires_in: 20,
  137. multiple: true
  138. }
  139. })
  140. object = Object.normalize(activity)
  141. {:ok, votes, object} = CommonAPI.vote(other_user, object, [0, 1])
  142. assert Enum.sort(Utils.get_existing_votes(other_user.ap_id, object)) == Enum.sort(votes)
  143. end
  144. test "fetches only Create activities" do
  145. user = insert(:user)
  146. other_user = insert(:user)
  147. {:ok, activity} =
  148. CommonAPI.post(user, %{
  149. status: "Are we living in a society?",
  150. poll: %{
  151. options: ["yes", "no"],
  152. expires_in: 20
  153. }
  154. })
  155. object = Object.normalize(activity)
  156. {:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
  157. {:ok, _activity} = CommonAPI.favorite(user, activity.id)
  158. [fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
  159. assert fetched_vote.id == vote.id
  160. end
  161. end
  162. describe "update_follow_state_for_all/2" do
  163. test "updates the state of all Follow activities with the same actor and object" do
  164. user = insert(:user, locked: true)
  165. follower = insert(:user)
  166. {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
  167. {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
  168. data =
  169. follow_activity_two.data
  170. |> Map.put("state", "accept")
  171. cng = Ecto.Changeset.change(follow_activity_two, data: data)
  172. {:ok, follow_activity_two} = Repo.update(cng)
  173. {:ok, follow_activity_two} =
  174. Utils.update_follow_state_for_all(follow_activity_two, "accept")
  175. assert refresh_record(follow_activity).data["state"] == "accept"
  176. assert refresh_record(follow_activity_two).data["state"] == "accept"
  177. end
  178. end
  179. describe "update_follow_state/2" do
  180. test "updates the state of the given follow activity" do
  181. user = insert(:user, locked: true)
  182. follower = insert(:user)
  183. {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user)
  184. {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)
  185. data =
  186. follow_activity_two.data
  187. |> Map.put("state", "accept")
  188. cng = Ecto.Changeset.change(follow_activity_two, data: data)
  189. {:ok, follow_activity_two} = Repo.update(cng)
  190. {:ok, follow_activity_two} = Utils.update_follow_state(follow_activity_two, "reject")
  191. assert refresh_record(follow_activity).data["state"] == "pending"
  192. assert refresh_record(follow_activity_two).data["state"] == "reject"
  193. end
  194. end
  195. describe "update_element_in_object/3" do
  196. test "updates likes" do
  197. user = insert(:user)
  198. activity = insert(:note_activity)
  199. object = Object.normalize(activity)
  200. assert {:ok, updated_object} =
  201. Utils.update_element_in_object(
  202. "like",
  203. [user.ap_id],
  204. object
  205. )
  206. assert updated_object.data["likes"] == [user.ap_id]
  207. assert updated_object.data["like_count"] == 1
  208. end
  209. end
  210. describe "add_like_to_object/2" do
  211. test "add actor to likes" do
  212. user = insert(:user)
  213. user2 = insert(:user)
  214. object = insert(:note)
  215. assert {:ok, updated_object} =
  216. Utils.add_like_to_object(
  217. %Activity{data: %{"actor" => user.ap_id}},
  218. object
  219. )
  220. assert updated_object.data["likes"] == [user.ap_id]
  221. assert updated_object.data["like_count"] == 1
  222. assert {:ok, updated_object2} =
  223. Utils.add_like_to_object(
  224. %Activity{data: %{"actor" => user2.ap_id}},
  225. updated_object
  226. )
  227. assert updated_object2.data["likes"] == [user2.ap_id, user.ap_id]
  228. assert updated_object2.data["like_count"] == 2
  229. end
  230. end
  231. describe "remove_like_from_object/2" do
  232. test "removes ap_id from likes" do
  233. user = insert(:user)
  234. user2 = insert(:user)
  235. object = insert(:note, data: %{"likes" => [user.ap_id, user2.ap_id], "like_count" => 2})
  236. assert {:ok, updated_object} =
  237. Utils.remove_like_from_object(
  238. %Activity{data: %{"actor" => user.ap_id}},
  239. object
  240. )
  241. assert updated_object.data["likes"] == [user2.ap_id]
  242. assert updated_object.data["like_count"] == 1
  243. end
  244. end
  245. describe "get_existing_like/2" do
  246. test "fetches existing like" do
  247. note_activity = insert(:note_activity)
  248. assert object = Object.normalize(note_activity)
  249. user = insert(:user)
  250. refute Utils.get_existing_like(user.ap_id, object)
  251. {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
  252. assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
  253. end
  254. end
  255. describe "get_get_existing_announce/2" do
  256. test "returns nil if announce not found" do
  257. actor = insert(:user)
  258. refute Utils.get_existing_announce(actor.ap_id, %{data: %{"id" => "test"}})
  259. end
  260. test "fetches existing announce" do
  261. note_activity = insert(:note_activity)
  262. assert object = Object.normalize(note_activity)
  263. actor = insert(:user)
  264. {:ok, announce} = CommonAPI.repeat(note_activity.id, actor)
  265. assert Utils.get_existing_announce(actor.ap_id, object) == announce
  266. end
  267. end
  268. describe "fetch_latest_block/2" do
  269. test "fetches last block activities" do
  270. user1 = insert(:user)
  271. user2 = insert(:user)
  272. assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
  273. assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
  274. assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
  275. assert Utils.fetch_latest_block(user1, user2) == activity
  276. end
  277. end
  278. describe "recipient_in_message/3" do
  279. test "returns true when recipient in `to`" do
  280. recipient = insert(:user)
  281. actor = insert(:user)
  282. assert Utils.recipient_in_message(recipient, actor, %{"to" => recipient.ap_id})
  283. assert Utils.recipient_in_message(
  284. recipient,
  285. actor,
  286. %{"to" => [recipient.ap_id], "cc" => ""}
  287. )
  288. end
  289. test "returns true when recipient in `cc`" do
  290. recipient = insert(:user)
  291. actor = insert(:user)
  292. assert Utils.recipient_in_message(recipient, actor, %{"cc" => recipient.ap_id})
  293. assert Utils.recipient_in_message(
  294. recipient,
  295. actor,
  296. %{"cc" => [recipient.ap_id], "to" => ""}
  297. )
  298. end
  299. test "returns true when recipient in `bto`" do
  300. recipient = insert(:user)
  301. actor = insert(:user)
  302. assert Utils.recipient_in_message(recipient, actor, %{"bto" => recipient.ap_id})
  303. assert Utils.recipient_in_message(
  304. recipient,
  305. actor,
  306. %{"bcc" => "", "bto" => [recipient.ap_id]}
  307. )
  308. end
  309. test "returns true when recipient in `bcc`" do
  310. recipient = insert(:user)
  311. actor = insert(:user)
  312. assert Utils.recipient_in_message(recipient, actor, %{"bcc" => recipient.ap_id})
  313. assert Utils.recipient_in_message(
  314. recipient,
  315. actor,
  316. %{"bto" => "", "bcc" => [recipient.ap_id]}
  317. )
  318. end
  319. test "returns true when message without addresses fields" do
  320. recipient = insert(:user)
  321. actor = insert(:user)
  322. assert Utils.recipient_in_message(recipient, actor, %{"bccc" => recipient.ap_id})
  323. assert Utils.recipient_in_message(
  324. recipient,
  325. actor,
  326. %{"btod" => "", "bccc" => [recipient.ap_id]}
  327. )
  328. end
  329. test "returns false" do
  330. recipient = insert(:user)
  331. actor = insert(:user)
  332. refute Utils.recipient_in_message(recipient, actor, %{"to" => "ap_id"})
  333. end
  334. end
  335. describe "lazy_put_activity_defaults/2" do
  336. test "returns map with id and published data" do
  337. note_activity = insert(:note_activity)
  338. object = Object.normalize(note_activity)
  339. res = Utils.lazy_put_activity_defaults(%{"context" => object.data["id"]})
  340. assert res["context"] == object.data["id"]
  341. assert res["context_id"] == object.id
  342. assert res["id"]
  343. assert res["published"]
  344. end
  345. test "returns map with fake id and published data" do
  346. assert %{
  347. "context" => "pleroma:fakecontext",
  348. "context_id" => -1,
  349. "id" => "pleroma:fakeid",
  350. "published" => _
  351. } = Utils.lazy_put_activity_defaults(%{}, true)
  352. end
  353. test "returns activity data with object" do
  354. note_activity = insert(:note_activity)
  355. object = Object.normalize(note_activity)
  356. res =
  357. Utils.lazy_put_activity_defaults(%{
  358. "context" => object.data["id"],
  359. "object" => %{}
  360. })
  361. assert res["context"] == object.data["id"]
  362. assert res["context_id"] == object.id
  363. assert res["id"]
  364. assert res["published"]
  365. assert res["object"]["id"]
  366. assert res["object"]["published"]
  367. assert res["object"]["context"] == object.data["id"]
  368. assert res["object"]["context_id"] == object.id
  369. end
  370. end
  371. describe "make_flag_data" do
  372. test "returns empty map when params is invalid" do
  373. assert Utils.make_flag_data(%{}, %{}) == %{}
  374. end
  375. test "returns map with Flag object" do
  376. reporter = insert(:user)
  377. target_account = insert(:user)
  378. {:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"})
  379. context = Utils.generate_context_id()
  380. content = "foobar"
  381. target_ap_id = target_account.ap_id
  382. activity_ap_id = activity.data["id"]
  383. res =
  384. Utils.make_flag_data(
  385. %{
  386. actor: reporter,
  387. context: context,
  388. account: target_account,
  389. statuses: [%{"id" => activity.data["id"]}],
  390. content: content
  391. },
  392. %{}
  393. )
  394. note_obj = %{
  395. "type" => "Note",
  396. "id" => activity_ap_id,
  397. "content" => content,
  398. "published" => activity.object.data["published"],
  399. "actor" =>
  400. AccountView.render("show.json", %{user: target_account, skip_visibility_check: true})
  401. }
  402. assert %{
  403. "type" => "Flag",
  404. "content" => ^content,
  405. "context" => ^context,
  406. "object" => [^target_ap_id, ^note_obj],
  407. "state" => "open"
  408. } = res
  409. end
  410. end
  411. describe "add_announce_to_object/2" do
  412. test "adds actor to announcement" do
  413. user = insert(:user)
  414. object = insert(:note)
  415. activity =
  416. insert(:note_activity,
  417. data: %{
  418. "actor" => user.ap_id,
  419. "cc" => [Pleroma.Constants.as_public()]
  420. }
  421. )
  422. assert {:ok, updated_object} = Utils.add_announce_to_object(activity, object)
  423. assert updated_object.data["announcements"] == [user.ap_id]
  424. assert updated_object.data["announcement_count"] == 1
  425. end
  426. end
  427. describe "remove_announce_from_object/2" do
  428. test "removes actor from announcements" do
  429. user = insert(:user)
  430. user2 = insert(:user)
  431. object =
  432. insert(:note,
  433. data: %{"announcements" => [user.ap_id, user2.ap_id], "announcement_count" => 2}
  434. )
  435. activity = insert(:note_activity, data: %{"actor" => user.ap_id})
  436. assert {:ok, updated_object} = Utils.remove_announce_from_object(activity, object)
  437. assert updated_object.data["announcements"] == [user2.ap_id]
  438. assert updated_object.data["announcement_count"] == 1
  439. end
  440. end
  441. describe "get_cached_emoji_reactions/1" do
  442. test "returns the data or an emtpy list" do
  443. object = insert(:note)
  444. assert Utils.get_cached_emoji_reactions(object) == []
  445. object = insert(:note, data: %{"reactions" => [["x", ["lain"]]]})
  446. assert Utils.get_cached_emoji_reactions(object) == [["x", ["lain"]]]
  447. object = insert(:note, data: %{"reactions" => %{}})
  448. assert Utils.get_cached_emoji_reactions(object) == []
  449. end
  450. end
  451. end