activity_representer_test.exs (11506B)
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.OStatus.ActivityRepresenterTest do 6 use Pleroma.DataCase 7 8 alias Pleroma.Activity 9 alias Pleroma.Object 10 alias Pleroma.User 11 alias Pleroma.Web.ActivityPub.ActivityPub 12 alias Pleroma.Web.OStatus 13 alias Pleroma.Web.OStatus.ActivityRepresenter 14 15 import Pleroma.Factory 16 import Tesla.Mock 17 18 setup do 19 mock(fn env -> apply(HttpRequestMock, :request, [env]) end) 20 :ok 21 end 22 23 test "an external note activity" do 24 incoming = File.read!("test/fixtures/mastodon-note-cw.xml") 25 {:ok, [activity]} = OStatus.handle_incoming(incoming) 26 27 user = User.get_cached_by_ap_id(activity.data["actor"]) 28 29 tuple = ActivityRepresenter.to_simple_form(activity, user) 30 31 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 32 33 assert String.contains?( 34 res, 35 ~s{<link type="text/html" href="https://mastodon.social/users/lambadalambda/updates/2314748" rel="alternate"/>} 36 ) 37 end 38 39 test "a note activity" do 40 note_activity = insert(:note_activity) 41 object_data = Object.normalize(note_activity).data 42 43 user = User.get_cached_by_ap_id(note_activity.data["actor"]) 44 45 expected = """ 46 <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> 47 <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> 48 <id>#{object_data["id"]}</id> 49 <title>New note by #{user.nickname}</title> 50 <content type="html">#{object_data["content"]}</content> 51 <published>#{object_data["published"]}</published> 52 <updated>#{object_data["published"]}</updated> 53 <ostatus:conversation ref="#{note_activity.data["context"]}">#{note_activity.data["context"]}</ostatus:conversation> 54 <link ref="#{note_activity.data["context"]}" rel="ostatus:conversation" /> 55 <summary>#{object_data["summary"]}</summary> 56 <link type="application/atom+xml" href="#{object_data["id"]}" rel="self" /> 57 <link type="text/html" href="#{object_data["id"]}" rel="alternate" /> 58 <category term="2hu"/> 59 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> 60 <link name="2hu" rel="emoji" href="corndog.png" /> 61 """ 62 63 tuple = ActivityRepresenter.to_simple_form(note_activity, user) 64 65 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 66 67 assert clean(res) == clean(expected) 68 end 69 70 test "a reply note" do 71 user = insert(:user) 72 note_object = insert(:note) 73 _note = insert(:note_activity, %{note: note_object}) 74 object = insert(:note, %{data: %{"inReplyTo" => note_object.data["id"]}}) 75 answer = insert(:note_activity, %{note: object}) 76 77 Repo.update!( 78 Object.change(note_object, %{data: Map.put(note_object.data, "external_url", "someurl")}) 79 ) 80 81 expected = """ 82 <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> 83 <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> 84 <id>#{object.data["id"]}</id> 85 <title>New note by #{user.nickname}</title> 86 <content type="html">#{object.data["content"]}</content> 87 <published>#{object.data["published"]}</published> 88 <updated>#{object.data["published"]}</updated> 89 <ostatus:conversation ref="#{answer.data["context"]}">#{answer.data["context"]}</ostatus:conversation> 90 <link ref="#{answer.data["context"]}" rel="ostatus:conversation" /> 91 <summary>2hu</summary> 92 <link type="application/atom+xml" href="#{object.data["id"]}" rel="self" /> 93 <link type="text/html" href="#{object.data["id"]}" rel="alternate" /> 94 <category term="2hu"/> 95 <thr:in-reply-to ref="#{note_object.data["id"]}" href="someurl" /> 96 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> 97 <link name="2hu" rel="emoji" href="corndog.png" /> 98 """ 99 100 tuple = ActivityRepresenter.to_simple_form(answer, user) 101 102 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 103 104 assert clean(res) == clean(expected) 105 end 106 107 test "an announce activity" do 108 note = insert(:note_activity) 109 user = insert(:user) 110 object = Object.normalize(note) 111 112 {:ok, announce, _object} = ActivityPub.announce(user, object) 113 114 announce = Activity.get_by_id(announce.id) 115 116 note_user = User.get_cached_by_ap_id(note.data["actor"]) 117 note = Activity.get_by_id(note.id) 118 119 note_xml = 120 ActivityRepresenter.to_simple_form(note, note_user, true) 121 |> :xmerl.export_simple_content(:xmerl_xml) 122 |> to_string 123 124 expected = """ 125 <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> 126 <activity:verb>http://activitystrea.ms/schema/1.0/share</activity:verb> 127 <id>#{announce.data["id"]}</id> 128 <title>#{user.nickname} repeated a notice</title> 129 <content type="html">RT #{object.data["content"]}</content> 130 <published>#{announce.data["published"]}</published> 131 <updated>#{announce.data["published"]}</updated> 132 <ostatus:conversation ref="#{announce.data["context"]}">#{announce.data["context"]}</ostatus:conversation> 133 <link ref="#{announce.data["context"]}" rel="ostatus:conversation" /> 134 <link rel="self" type="application/atom+xml" href="#{announce.data["id"]}"/> 135 <activity:object> 136 #{note_xml} 137 </activity:object> 138 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="#{ 139 note.data["actor"] 140 }"/> 141 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> 142 """ 143 144 announce_xml = 145 ActivityRepresenter.to_simple_form(announce, user) 146 |> :xmerl.export_simple_content(:xmerl_xml) 147 |> to_string 148 149 assert clean(expected) == clean(announce_xml) 150 end 151 152 test "a like activity" do 153 note = insert(:note) 154 user = insert(:user) 155 {:ok, like, _note} = ActivityPub.like(user, note) 156 157 tuple = ActivityRepresenter.to_simple_form(like, user) 158 refute is_nil(tuple) 159 160 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 161 162 expected = """ 163 <activity:verb>http://activitystrea.ms/schema/1.0/favorite</activity:verb> 164 <id>#{like.data["id"]}</id> 165 <title>New favorite by #{user.nickname}</title> 166 <content type="html">#{user.nickname} favorited something</content> 167 <published>#{like.data["published"]}</published> 168 <updated>#{like.data["published"]}</updated> 169 <activity:object> 170 <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type> 171 <id>#{note.data["id"]}</id> 172 </activity:object> 173 <ostatus:conversation ref="#{like.data["context"]}">#{like.data["context"]}</ostatus:conversation> 174 <link ref="#{like.data["context"]}" rel="ostatus:conversation" /> 175 <link rel="self" type="application/atom+xml" href="#{like.data["id"]}"/> 176 <thr:in-reply-to ref="#{note.data["id"]}" /> 177 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="#{ 178 note.data["actor"] 179 }"/> 180 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/> 181 """ 182 183 assert clean(res) == clean(expected) 184 end 185 186 test "a follow activity" do 187 follower = insert(:user) 188 followed = insert(:user) 189 190 {:ok, activity} = 191 ActivityPub.insert(%{ 192 "type" => "Follow", 193 "actor" => follower.ap_id, 194 "object" => followed.ap_id, 195 "to" => [followed.ap_id] 196 }) 197 198 tuple = ActivityRepresenter.to_simple_form(activity, follower) 199 200 refute is_nil(tuple) 201 202 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 203 204 expected = """ 205 <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> 206 <activity:verb>http://activitystrea.ms/schema/1.0/follow</activity:verb> 207 <id>#{activity.data["id"]}</id> 208 <title>#{follower.nickname} started following #{activity.data["object"]}</title> 209 <content type="html"> #{follower.nickname} started following #{activity.data["object"]}</content> 210 <published>#{activity.data["published"]}</published> 211 <updated>#{activity.data["published"]}</updated> 212 <activity:object> 213 <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> 214 <id>#{activity.data["object"]}</id> 215 <uri>#{activity.data["object"]}</uri> 216 </activity:object> 217 <link rel="self" type="application/atom+xml" href="#{activity.data["id"]}"/> 218 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="#{ 219 activity.data["object"] 220 }"/> 221 """ 222 223 assert clean(res) == clean(expected) 224 end 225 226 test "an unfollow activity" do 227 follower = insert(:user) 228 followed = insert(:user) 229 {:ok, _activity} = ActivityPub.follow(follower, followed) 230 {:ok, activity} = ActivityPub.unfollow(follower, followed) 231 232 tuple = ActivityRepresenter.to_simple_form(activity, follower) 233 234 refute is_nil(tuple) 235 236 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 237 238 expected = """ 239 <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> 240 <activity:verb>http://activitystrea.ms/schema/1.0/unfollow</activity:verb> 241 <id>#{activity.data["id"]}</id> 242 <title>#{follower.nickname} stopped following #{followed.ap_id}</title> 243 <content type="html"> #{follower.nickname} stopped following #{followed.ap_id}</content> 244 <published>#{activity.data["published"]}</published> 245 <updated>#{activity.data["published"]}</updated> 246 <activity:object> 247 <activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type> 248 <id>#{followed.ap_id}</id> 249 <uri>#{followed.ap_id}</uri> 250 </activity:object> 251 <link rel="self" type="application/atom+xml" href="#{activity.data["id"]}"/> 252 <link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/person" href="#{ 253 followed.ap_id 254 }"/> 255 """ 256 257 assert clean(res) == clean(expected) 258 end 259 260 test "a delete" do 261 user = insert(:user) 262 263 activity = %Activity{ 264 data: %{ 265 "id" => "ap_id", 266 "type" => "Delete", 267 "actor" => user.ap_id, 268 "object" => "some_id", 269 "published" => "2017-06-18T12:00:18+00:00" 270 } 271 } 272 273 tuple = ActivityRepresenter.to_simple_form(activity, nil) 274 275 refute is_nil(tuple) 276 277 res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary() 278 279 expected = """ 280 <activity:object-type>http://activitystrea.ms/schema/1.0/activity</activity:object-type> 281 <activity:verb>http://activitystrea.ms/schema/1.0/delete</activity:verb> 282 <id>#{activity.data["object"]}</id> 283 <title>An object was deleted</title> 284 <content type="html">An object was deleted</content> 285 <published>#{activity.data["published"]}</published> 286 <updated>#{activity.data["published"]}</updated> 287 """ 288 289 assert clean(res) == clean(expected) 290 end 291 292 test "an unknown activity" do 293 tuple = ActivityRepresenter.to_simple_form(%Activity{}, nil) 294 assert is_nil(tuple) 295 end 296 297 defp clean(string) do 298 String.replace(string, ~r/\s/, "") 299 end 300 end