activity_view_test.exs (12799B)
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.Web.TwitterAPI.ActivityViewTest do 6 use Pleroma.DataCase 7 8 alias Pleroma.Activity 9 alias Pleroma.Object 10 alias Pleroma.Repo 11 alias Pleroma.User 12 alias Pleroma.Web.ActivityPub.ActivityPub 13 alias Pleroma.Web.CommonAPI 14 alias Pleroma.Web.CommonAPI.Utils 15 alias Pleroma.Web.TwitterAPI.ActivityView 16 alias Pleroma.Web.TwitterAPI.UserView 17 18 import Pleroma.Factory 19 import Tesla.Mock 20 21 setup do 22 mock(fn env -> apply(HttpRequestMock, :request, [env]) end) 23 :ok 24 end 25 26 import Mock 27 28 test "returns a temporary ap_id based user for activities missing db users" do 29 user = insert(:user) 30 31 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"}) 32 33 Repo.delete(user) 34 Cachex.clear(:user_cache) 35 36 %{"user" => tw_user} = ActivityView.render("activity.json", activity: activity) 37 38 assert tw_user["screen_name"] == "erroruser@example.com" 39 assert tw_user["name"] == user.ap_id 40 assert tw_user["statusnet_profile_url"] == user.ap_id 41 end 42 43 test "tries to get a user by nickname if fetching by ap_id doesn't work" do 44 user = insert(:user) 45 46 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"}) 47 48 {:ok, user} = 49 user 50 |> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"}) 51 |> Repo.update() 52 53 Cachex.clear(:user_cache) 54 55 result = ActivityView.render("activity.json", activity: activity) 56 assert result["user"]["id"] == user.id 57 end 58 59 test "tells if the message is muted for some reason" do 60 user = insert(:user) 61 other_user = insert(:user) 62 63 {:ok, user} = User.mute(user, other_user) 64 65 {:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"}) 66 status = ActivityView.render("activity.json", %{activity: activity}) 67 68 assert status["muted"] == false 69 70 status = ActivityView.render("activity.json", %{activity: activity, for: user}) 71 72 assert status["muted"] == true 73 end 74 75 test "a create activity with a html status" do 76 text = """ 77 #Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg 78 """ 79 80 {:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text}) 81 82 result = ActivityView.render("activity.json", activity: activity) 83 84 assert result["statusnet_html"] == 85 "<a class=\"hashtag\" data-tag=\"bike\" href=\"http://localhost:4001/tag/bike\" rel=\"tag\">#Bike</a> log - Commute Tuesday<br /><a href=\"https://pla.bike/posts/20181211/\">https://pla.bike/posts/20181211/</a><br /><a class=\"hashtag\" data-tag=\"cycling\" href=\"http://localhost:4001/tag/cycling\" rel=\"tag\">#cycling</a> <a class=\"hashtag\" data-tag=\"chscycling\" href=\"http://localhost:4001/tag/chscycling\" rel=\"tag\">#CHScycling</a> <a class=\"hashtag\" data-tag=\"commute\" href=\"http://localhost:4001/tag/commute\" rel=\"tag\">#commute</a><br />MVIMG_20181211_054020.jpg" 86 87 assert result["text"] == 88 "#Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg" 89 end 90 91 test "a create activity with a summary containing emoji" do 92 {:ok, activity} = 93 CommonAPI.post(insert(:user), %{ 94 "spoiler_text" => ":firefox: meow", 95 "status" => "." 96 }) 97 98 result = ActivityView.render("activity.json", activity: activity) 99 100 expected = ":firefox: meow" 101 102 expected_html = 103 "<img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"http://localhost:4001/emoji/Firefox.gif\" /> meow" 104 105 assert result["summary"] == expected 106 assert result["summary_html"] == expected_html 107 end 108 109 test "a create activity with a summary containing invalid HTML" do 110 {:ok, activity} = 111 CommonAPI.post(insert(:user), %{ 112 "spoiler_text" => "<span style=\"color: magenta; font-size: 32px;\">meow</span>", 113 "status" => "." 114 }) 115 116 result = ActivityView.render("activity.json", activity: activity) 117 118 expected = "meow" 119 120 assert result["summary"] == expected 121 assert result["summary_html"] == expected 122 end 123 124 test "a create activity with a note" do 125 user = insert(:user) 126 other_user = insert(:user, %{nickname: "shp"}) 127 128 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"}) 129 object = Object.normalize(activity) 130 131 result = ActivityView.render("activity.json", activity: activity) 132 133 convo_id = Utils.context_to_conversation_id(object.data["context"]) 134 135 expected = %{ 136 "activity_type" => "post", 137 "attachments" => [], 138 "attentions" => [ 139 UserView.render("show.json", %{user: other_user}) 140 ], 141 "created_at" => object.data["published"] |> Utils.date_to_asctime(), 142 "external_url" => object.data["id"], 143 "fave_num" => 0, 144 "favorited" => false, 145 "id" => activity.id, 146 "in_reply_to_status_id" => nil, 147 "in_reply_to_screen_name" => nil, 148 "in_reply_to_user_id" => nil, 149 "in_reply_to_profileurl" => nil, 150 "in_reply_to_ostatus_uri" => nil, 151 "is_local" => true, 152 "is_post_verb" => true, 153 "possibly_sensitive" => false, 154 "repeat_num" => 0, 155 "repeated" => false, 156 "pinned" => false, 157 "statusnet_conversation_id" => convo_id, 158 "summary" => "", 159 "summary_html" => "", 160 "statusnet_html" => 161 "Hey <span class=\"h-card\"><a data-user=\"#{other_user.id}\" class=\"u-url mention\" href=\"#{ 162 other_user.ap_id 163 }\">@<span>shp</span></a></span>!", 164 "tags" => [], 165 "text" => "Hey @shp!", 166 "uri" => object.data["id"], 167 "user" => UserView.render("show.json", %{user: user}), 168 "visibility" => "direct", 169 "card" => nil, 170 "muted" => false 171 } 172 173 assert result == expected 174 end 175 176 test "a list of activities" do 177 user = insert(:user) 178 other_user = insert(:user, %{nickname: "shp"}) 179 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 180 object = Object.normalize(activity) 181 182 convo_id = Utils.context_to_conversation_id(object.data["context"]) 183 184 mocks = [ 185 { 186 Utils, 187 [:passthrough], 188 [context_to_conversation_id: fn _ -> false end] 189 }, 190 { 191 User, 192 [:passthrough], 193 [get_cached_by_ap_id: fn _ -> nil end] 194 } 195 ] 196 197 with_mocks mocks do 198 [result] = ActivityView.render("index.json", activities: [activity]) 199 200 assert result["statusnet_conversation_id"] == convo_id 201 assert result["user"] 202 refute called(Utils.context_to_conversation_id(:_)) 203 refute called(User.get_cached_by_ap_id(user.ap_id)) 204 refute called(User.get_cached_by_ap_id(other_user.ap_id)) 205 end 206 end 207 208 test "an activity that is a reply" do 209 user = insert(:user) 210 other_user = insert(:user, %{nickname: "shp"}) 211 212 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 213 214 {:ok, answer} = 215 CommonAPI.post(other_user, %{"status" => "Hi!", "in_reply_to_status_id" => activity.id}) 216 217 result = ActivityView.render("activity.json", %{activity: answer}) 218 219 assert result["in_reply_to_status_id"] == activity.id 220 end 221 222 test "a like activity" do 223 user = insert(:user) 224 other_user = insert(:user, %{nickname: "shp"}) 225 226 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 227 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user) 228 229 result = ActivityView.render("activity.json", activity: like) 230 activity = Pleroma.Activity.get_by_ap_id(activity.data["id"]) 231 232 expected = %{ 233 "activity_type" => "like", 234 "created_at" => like.data["published"] |> Utils.date_to_asctime(), 235 "external_url" => like.data["id"], 236 "id" => like.id, 237 "in_reply_to_status_id" => activity.id, 238 "is_local" => true, 239 "is_post_verb" => false, 240 "favorited_status" => ActivityView.render("activity.json", activity: activity), 241 "statusnet_html" => "shp favorited a status.", 242 "text" => "shp favorited a status.", 243 "uri" => "tag:#{like.data["id"]}:objectType=Favourite", 244 "user" => UserView.render("show.json", user: other_user) 245 } 246 247 assert result == expected 248 end 249 250 test "a like activity for deleted post" do 251 user = insert(:user) 252 other_user = insert(:user, %{nickname: "shp"}) 253 254 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 255 {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user) 256 CommonAPI.delete(activity.id, user) 257 258 result = ActivityView.render("activity.json", activity: like) 259 260 expected = %{ 261 "activity_type" => "like", 262 "created_at" => like.data["published"] |> Utils.date_to_asctime(), 263 "external_url" => like.data["id"], 264 "id" => like.id, 265 "in_reply_to_status_id" => nil, 266 "is_local" => true, 267 "is_post_verb" => false, 268 "favorited_status" => nil, 269 "statusnet_html" => "shp favorited a status.", 270 "text" => "shp favorited a status.", 271 "uri" => "tag:#{like.data["id"]}:objectType=Favourite", 272 "user" => UserView.render("show.json", user: other_user) 273 } 274 275 assert result == expected 276 end 277 278 test "an announce activity" do 279 user = insert(:user) 280 other_user = insert(:user, %{nickname: "shp"}) 281 282 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 283 {:ok, announce, object} = CommonAPI.repeat(activity.id, other_user) 284 285 convo_id = Utils.context_to_conversation_id(object.data["context"]) 286 287 activity = Activity.get_by_id(activity.id) 288 289 result = ActivityView.render("activity.json", activity: announce) 290 291 expected = %{ 292 "activity_type" => "repeat", 293 "created_at" => announce.data["published"] |> Utils.date_to_asctime(), 294 "external_url" => announce.data["id"], 295 "id" => announce.id, 296 "is_local" => true, 297 "is_post_verb" => false, 298 "statusnet_html" => "shp repeated a status.", 299 "text" => "shp repeated a status.", 300 "uri" => "tag:#{announce.data["id"]}:objectType=note", 301 "user" => UserView.render("show.json", user: other_user), 302 "retweeted_status" => ActivityView.render("activity.json", activity: activity), 303 "statusnet_conversation_id" => convo_id 304 } 305 306 assert result == expected 307 end 308 309 test "A follow activity" do 310 user = insert(:user) 311 other_user = insert(:user, %{nickname: "shp"}) 312 313 {:ok, follower} = User.follow(user, other_user) 314 {:ok, follow} = ActivityPub.follow(follower, other_user) 315 316 result = ActivityView.render("activity.json", activity: follow) 317 318 expected = %{ 319 "activity_type" => "follow", 320 "attentions" => [], 321 "created_at" => follow.data["published"] |> Utils.date_to_asctime(), 322 "external_url" => follow.data["id"], 323 "id" => follow.id, 324 "in_reply_to_status_id" => nil, 325 "is_local" => true, 326 "is_post_verb" => false, 327 "statusnet_html" => "#{user.nickname} started following shp", 328 "text" => "#{user.nickname} started following shp", 329 "user" => UserView.render("show.json", user: user) 330 } 331 332 assert result == expected 333 end 334 335 test "a delete activity" do 336 user = insert(:user) 337 338 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) 339 {:ok, delete} = CommonAPI.delete(activity.id, user) 340 341 result = ActivityView.render("activity.json", activity: delete) 342 343 expected = %{ 344 "activity_type" => "delete", 345 "attentions" => [], 346 "created_at" => delete.data["published"] |> Utils.date_to_asctime(), 347 "external_url" => delete.data["id"], 348 "id" => delete.id, 349 "in_reply_to_status_id" => nil, 350 "is_local" => true, 351 "is_post_verb" => false, 352 "statusnet_html" => "deleted notice {{tag", 353 "text" => "deleted notice {{tag", 354 "uri" => Object.normalize(delete).data["id"], 355 "user" => UserView.render("show.json", user: user) 356 } 357 358 assert result == expected 359 end 360 361 test "a peertube video" do 362 {:ok, object} = 363 Pleroma.Object.Fetcher.fetch_object_from_id( 364 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" 365 ) 366 367 %Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"]) 368 369 result = ActivityView.render("activity.json", activity: activity) 370 371 assert length(result["attachments"]) == 1 372 assert result["summary"] == "Friday Night" 373 end 374 375 test "special characters are not escaped in text field for status created" do 376 text = "<3 is on the way" 377 378 {:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text}) 379 380 result = ActivityView.render("activity.json", activity: activity) 381 382 assert result["text"] == text 383 end 384 end