2019-09-26 08:38:45 +02:00
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Activity
alias Pleroma.ActivityExpiration
alias Pleroma.Config
2019-10-09 05:51:14 +02:00
alias Pleroma.Conversation.Participation
2019-09-26 08:38:45 +02:00
alias Pleroma.Object
2019-09-27 08:35:45 +02:00
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
2019-09-26 08:38:45 +02:00
alias Pleroma.User
2019-09-27 08:35:45 +02:00
alias Pleroma.Web.ActivityPub.ActivityPub
2019-09-26 08:38:45 +02:00
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
2019-10-19 14:46:14 +02:00
import ExUnit.CaptureLog
2019-09-26 08:38:45 +02:00
describe " posting statuses " do
setup do
user = insert ( :user )
conn =
build_conn ( )
|> assign ( :user , user )
[ conn : conn ]
end
test " posting a status " , %{ conn : conn } do
idempotency_key = " Pikachu rocks! "
conn_one =
conn
|> put_req_header ( " idempotency-key " , idempotency_key )
|> post ( " /api/v1/statuses " , %{
" status " = > " cofe " ,
" spoiler_text " = > " 2hu " ,
" sensitive " = > " false "
} )
{ :ok , ttl } = Cachex . ttl ( :idempotency_cache , idempotency_key )
# Six hours
assert ttl > :timer . seconds ( 6 * 60 * 60 - 1 )
assert %{ " content " = > " cofe " , " id " = > id , " spoiler_text " = > " 2hu " , " sensitive " = > false } =
json_response ( conn_one , 200 )
assert Activity . get_by_id ( id )
conn_two =
conn
|> put_req_header ( " idempotency-key " , idempotency_key )
|> post ( " /api/v1/statuses " , %{
" status " = > " cofe " ,
" spoiler_text " = > " 2hu " ,
" sensitive " = > " false "
} )
assert %{ " id " = > second_id } = json_response ( conn_two , 200 )
assert id == second_id
conn_three =
conn
|> post ( " /api/v1/statuses " , %{
" status " = > " cofe " ,
" spoiler_text " = > " 2hu " ,
" sensitive " = > " false "
} )
assert %{ " id " = > third_id } = json_response ( conn_three , 200 )
refute id == third_id
# An activity that will expire:
# 2 hours
expires_in = 120 * 60
conn_four =
conn
|> post ( " api/v1/statuses " , %{
" status " = > " oolong " ,
" expires_in " = > expires_in
} )
assert fourth_response = %{ " id " = > fourth_id } = json_response ( conn_four , 200 )
assert activity = Activity . get_by_id ( fourth_id )
assert expiration = ActivityExpiration . get_by_activity_id ( fourth_id )
estimated_expires_at =
NaiveDateTime . utc_now ( )
|> NaiveDateTime . add ( expires_in )
|> NaiveDateTime . truncate ( :second )
# This assert will fail if the test takes longer than a minute. I sure hope it never does:
assert abs ( NaiveDateTime . diff ( expiration . scheduled_at , estimated_expires_at , :second ) ) < 60
assert fourth_response [ " pleroma " ] [ " expires_at " ] ==
NaiveDateTime . to_iso8601 ( expiration . scheduled_at )
end
2019-09-28 01:21:28 +02:00
test " posting an undefined status with an attachment " , %{ conn : conn } do
2019-09-28 00:56:20 +02:00
user = insert ( :user )
file = % Plug.Upload {
content_type : " image/jpg " ,
path : Path . absname ( " test/fixtures/image.jpg " ) ,
filename : " an_image.jpg "
}
{ :ok , upload } = ActivityPub . upload ( file , actor : user . ap_id )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
2019-09-28 01:21:28 +02:00
" media_ids " = > [ to_string ( upload . id ) ]
2019-09-28 00:56:20 +02:00
} )
assert json_response ( conn , 200 )
end
2019-09-26 08:38:45 +02:00
test " replying to a status " , %{ conn : conn } do
user = insert ( :user )
{ :ok , replied_to } = CommonAPI . post ( user , %{ " status " = > " cofe " } )
conn =
conn
|> post ( " /api/v1/statuses " , %{ " status " = > " xD " , " in_reply_to_id " = > replied_to . id } )
assert %{ " content " = > " xD " , " id " = > id } = json_response ( conn , 200 )
activity = Activity . get_by_id ( id )
assert activity . data [ " context " ] == replied_to . data [ " context " ]
assert Activity . get_in_reply_to_activity ( activity ) . id == replied_to . id
end
test " replying to a direct message with visibility other than direct " , %{ conn : conn } do
user = insert ( :user )
{ :ok , replied_to } = CommonAPI . post ( user , %{ " status " = > " suya.. " , " visibility " = > " direct " } )
Enum . each ( [ " public " , " private " , " unlisted " ] , fn visibility ->
conn =
conn
|> post ( " /api/v1/statuses " , %{
" status " = > " @ #{ user . nickname } hey " ,
" in_reply_to_id " = > replied_to . id ,
" visibility " = > visibility
} )
assert json_response ( conn , 422 ) == %{ " error " = > " The message visibility must be direct " }
end )
end
test " posting a status with an invalid in_reply_to_id " , %{ conn : conn } do
conn =
conn
|> post ( " /api/v1/statuses " , %{ " status " = > " xD " , " in_reply_to_id " = > " " } )
assert %{ " content " = > " xD " , " id " = > id } = json_response ( conn , 200 )
assert Activity . get_by_id ( id )
end
test " posting a sensitive status " , %{ conn : conn } do
conn =
conn
|> post ( " /api/v1/statuses " , %{ " status " = > " cofe " , " sensitive " = > true } )
assert %{ " content " = > " cofe " , " id " = > id , " sensitive " = > true } = json_response ( conn , 200 )
assert Activity . get_by_id ( id )
end
test " posting a fake status " , %{ conn : conn } do
real_conn =
conn
|> post ( " /api/v1/statuses " , %{
" status " = >
" \" Tenshi Eating a Corndog \" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it "
} )
real_status = json_response ( real_conn , 200 )
assert real_status
assert Object . get_by_ap_id ( real_status [ " uri " ] )
real_status =
real_status
|> Map . put ( " id " , nil )
|> Map . put ( " url " , nil )
|> Map . put ( " uri " , nil )
|> Map . put ( " created_at " , nil )
|> Kernel . put_in ( [ " pleroma " , " conversation_id " ] , nil )
fake_conn =
conn
|> post ( " /api/v1/statuses " , %{
" status " = >
" \" Tenshi Eating a Corndog \" is a much discussed concept on /jp/. The significance of it is disputed, so I will focus on one core concept: the symbolism behind it " ,
" preview " = > true
} )
fake_status = json_response ( fake_conn , 200 )
assert fake_status
refute Object . get_by_ap_id ( fake_status [ " uri " ] )
fake_status =
fake_status
|> Map . put ( " id " , nil )
|> Map . put ( " url " , nil )
|> Map . put ( " uri " , nil )
|> Map . put ( " created_at " , nil )
|> Kernel . put_in ( [ " pleroma " , " conversation_id " ] , nil )
assert real_status == fake_status
end
test " posting a status with OGP link preview " , %{ conn : conn } do
Tesla.Mock . mock ( fn env -> apply ( HttpRequestMock , :request , [ env ] ) end )
Config . put ( [ :rich_media , :enabled ] , true )
conn =
conn
|> post ( " /api/v1/statuses " , %{
" status " = > " https://example.com/ogp "
} )
assert %{ " id " = > id , " card " = > %{ " title " = > " The Rock " } } = json_response ( conn , 200 )
assert Activity . get_by_id ( id )
end
test " posting a direct status " , %{ conn : conn } do
user2 = insert ( :user )
content = " direct cofe @ #{ user2 . nickname } "
conn =
conn
|> post ( " api/v1/statuses " , %{ " status " = > content , " visibility " = > " direct " } )
assert %{ " id " = > id } = response = json_response ( conn , 200 )
assert response [ " visibility " ] == " direct "
assert response [ " pleroma " ] [ " direct_conversation_id " ]
assert activity = Activity . get_by_id ( id )
assert activity . recipients == [ user2 . ap_id , conn . assigns [ :user ] . ap_id ]
assert activity . data [ " to " ] == [ user2 . ap_id ]
assert activity . data [ " cc " ] == [ ]
end
end
2019-09-27 08:35:45 +02:00
describe " posting scheduled statuses " do
test " creates a scheduled activity " , %{ conn : conn } do
user = insert ( :user )
scheduled_at = NaiveDateTime . add ( NaiveDateTime . utc_now ( ) , :timer . minutes ( 120 ) , :millisecond )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " scheduled " ,
" scheduled_at " = > scheduled_at
} )
assert %{ " scheduled_at " = > expected_scheduled_at } = json_response ( conn , 200 )
assert expected_scheduled_at == CommonAPI.Utils . to_masto_date ( scheduled_at )
assert [ ] == Repo . all ( Activity )
end
test " creates a scheduled activity with a media attachment " , %{ conn : conn } do
user = insert ( :user )
scheduled_at = NaiveDateTime . add ( NaiveDateTime . utc_now ( ) , :timer . minutes ( 120 ) , :millisecond )
file = % Plug.Upload {
content_type : " image/jpg " ,
path : Path . absname ( " test/fixtures/image.jpg " ) ,
filename : " an_image.jpg "
}
{ :ok , upload } = ActivityPub . upload ( file , actor : user . ap_id )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" media_ids " = > [ to_string ( upload . id ) ] ,
" status " = > " scheduled " ,
" scheduled_at " = > scheduled_at
} )
assert %{ " media_attachments " = > [ media_attachment ] } = json_response ( conn , 200 )
assert %{ " type " = > " image " } = media_attachment
end
test " skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now " ,
%{ conn : conn } do
user = insert ( :user )
scheduled_at =
NaiveDateTime . add ( NaiveDateTime . utc_now ( ) , :timer . minutes ( 5 ) - 1 , :millisecond )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " not scheduled " ,
" scheduled_at " = > scheduled_at
} )
assert %{ " content " = > " not scheduled " } = json_response ( conn , 200 )
assert [ ] == Repo . all ( ScheduledActivity )
end
test " returns error when daily user limit is exceeded " , %{ conn : conn } do
user = insert ( :user )
today =
NaiveDateTime . utc_now ( )
|> NaiveDateTime . add ( :timer . minutes ( 6 ) , :millisecond )
|> NaiveDateTime . to_iso8601 ( )
attrs = %{ params : %{ } , scheduled_at : today }
{ :ok , _ } = ScheduledActivity . create ( user , attrs )
{ :ok , _ } = ScheduledActivity . create ( user , attrs )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{ " status " = > " scheduled " , " scheduled_at " = > today } )
assert %{ " error " = > " daily limit exceeded " } == json_response ( conn , 422 )
end
test " returns error when total user limit is exceeded " , %{ conn : conn } do
user = insert ( :user )
today =
NaiveDateTime . utc_now ( )
|> NaiveDateTime . add ( :timer . minutes ( 6 ) , :millisecond )
|> NaiveDateTime . to_iso8601 ( )
tomorrow =
NaiveDateTime . utc_now ( )
|> NaiveDateTime . add ( :timer . hours ( 36 ) , :millisecond )
|> NaiveDateTime . to_iso8601 ( )
attrs = %{ params : %{ } , scheduled_at : today }
{ :ok , _ } = ScheduledActivity . create ( user , attrs )
{ :ok , _ } = ScheduledActivity . create ( user , attrs )
{ :ok , _ } = ScheduledActivity . create ( user , %{ params : %{ } , scheduled_at : tomorrow } )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{ " status " = > " scheduled " , " scheduled_at " = > tomorrow } )
assert %{ " error " = > " total limit exceeded " } == json_response ( conn , 422 )
end
end
2019-09-26 08:38:45 +02:00
describe " posting polls " do
test " posting a poll " , %{ conn : conn } do
user = insert ( :user )
time = NaiveDateTime . utc_now ( )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " Who is the # bestgrill? " ,
" poll " = > %{ " options " = > [ " Rei " , " Asuka " , " Misato " ] , " expires_in " = > 420 }
} )
response = json_response ( conn , 200 )
assert Enum . all? ( response [ " poll " ] [ " options " ] , fn %{ " title " = > title } ->
title in [ " Rei " , " Asuka " , " Misato " ]
end )
assert NaiveDateTime . diff ( NaiveDateTime . from_iso8601! ( response [ " poll " ] [ " expires_at " ] ) , time ) in 420 . . 430
refute response [ " poll " ] [ " expred " ]
end
test " option limit is enforced " , %{ conn : conn } do
user = insert ( :user )
limit = Config . get ( [ :instance , :poll_limits , :max_options ] )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " desu~ " ,
" poll " = > %{ " options " = > Enum . map ( 0 . . limit , fn _ -> " desu " end ) , " expires_in " = > 1 }
} )
%{ " error " = > error } = json_response ( conn , 422 )
assert error == " Poll can't contain more than #{ limit } options "
end
test " option character limit is enforced " , %{ conn : conn } do
user = insert ( :user )
limit = Config . get ( [ :instance , :poll_limits , :max_option_chars ] )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " ... " ,
" poll " = > %{
" options " = > [ Enum . reduce ( 0 . . limit , " " , fn _ , acc -> acc <> " . " end ) ] ,
" expires_in " = > 1
}
} )
%{ " error " = > error } = json_response ( conn , 422 )
assert error == " Poll options cannot be longer than #{ limit } characters each "
end
test " minimal date limit is enforced " , %{ conn : conn } do
user = insert ( :user )
limit = Config . get ( [ :instance , :poll_limits , :min_expiration ] )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " imagine arbitrary limits " ,
" poll " = > %{
" options " = > [ " this post was made by pleroma gang " ] ,
" expires_in " = > limit - 1
}
} )
%{ " error " = > error } = json_response ( conn , 422 )
assert error == " Expiration date is too soon "
end
test " maximum date limit is enforced " , %{ conn : conn } do
user = insert ( :user )
limit = Config . get ( [ :instance , :poll_limits , :max_expiration ] )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses " , %{
" status " = > " imagine arbitrary limits " ,
" poll " = > %{
" options " = > [ " this post was made by pleroma gang " ] ,
" expires_in " = > limit + 1
}
} )
%{ " error " = > error } = json_response ( conn , 422 )
assert error == " Expiration date is too far in the future "
end
end
test " get a status " , %{ conn : conn } do
activity = insert ( :note_activity )
conn =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } " )
assert %{ " id " = > id } = json_response ( conn , 200 )
assert id == to_string ( activity . id )
end
2019-10-09 05:51:14 +02:00
test " get a direct status " , %{ conn : conn } do
user = insert ( :user )
other_user = insert ( :user )
{ :ok , activity } =
CommonAPI . post ( user , %{ " status " = > " @ #{ other_user . nickname } " , " visibility " = > " direct " } )
conn =
conn
|> assign ( :user , user )
|> get ( " /api/v1/statuses/ #{ activity . id } " )
[ participation ] = Participation . for_user ( user )
res = json_response ( conn , 200 )
assert res [ " pleroma " ] [ " direct_conversation_id " ] == participation . id
end
2019-09-26 08:38:45 +02:00
test " get statuses by IDs " , %{ conn : conn } do
%{ id : id1 } = insert ( :note_activity )
%{ id : id2 } = insert ( :note_activity )
query_string = " ids[]= #{ id1 } &ids[]= #{ id2 } "
conn = get ( conn , " /api/v1/statuses/? #{ query_string } " )
assert [ %{ " id " = > ^ id1 } , %{ " id " = > ^ id2 } ] = Enum . sort_by ( json_response ( conn , :ok ) , & &1 [ " id " ] )
end
describe " deleting a status " do
test " when you created it " , %{ conn : conn } do
activity = insert ( :note_activity )
author = User . get_cached_by_ap_id ( activity . data [ " actor " ] )
conn =
conn
|> assign ( :user , author )
|> delete ( " /api/v1/statuses/ #{ activity . id } " )
assert %{ } = json_response ( conn , 200 )
refute Activity . get_by_id ( activity . id )
end
test " when you didn't create it " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> delete ( " /api/v1/statuses/ #{ activity . id } " )
assert %{ " error " = > _ } = json_response ( conn , 403 )
assert Activity . get_by_id ( activity . id ) == activity
end
test " when you're an admin or moderator " , %{ conn : conn } do
activity1 = insert ( :note_activity )
activity2 = insert ( :note_activity )
admin = insert ( :user , info : %{ is_admin : true } )
moderator = insert ( :user , info : %{ is_moderator : true } )
res_conn =
conn
|> assign ( :user , admin )
|> delete ( " /api/v1/statuses/ #{ activity1 . id } " )
assert %{ } = json_response ( res_conn , 200 )
res_conn =
conn
|> assign ( :user , moderator )
|> delete ( " /api/v1/statuses/ #{ activity2 . id } " )
assert %{ } = json_response ( res_conn , 200 )
refute Activity . get_by_id ( activity1 . id )
refute Activity . get_by_id ( activity2 . id )
end
end
describe " reblogging " do
test " reblogs and returns the reblogged status " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /reblog " )
assert %{
" reblog " = > %{ " id " = > id , " reblogged " = > true , " reblogs_count " = > 1 } ,
" reblogged " = > true
} = json_response ( conn , 200 )
assert to_string ( activity . id ) == id
end
2019-10-01 19:08:25 +02:00
test " reblogs privately and returns the reblogged status " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /reblog " , %{ " visibility " = > " private " } )
assert %{
2019-10-01 21:40:35 +02:00
" reblog " = > %{ " id " = > id , " reblogged " = > true , " reblogs_count " = > 1 } ,
2019-10-01 19:08:25 +02:00
" reblogged " = > true ,
" visibility " = > " private "
} = json_response ( conn , 200 )
assert to_string ( activity . id ) == id
end
2019-09-26 08:38:45 +02:00
test " reblogged status for another user " , %{ conn : conn } do
activity = insert ( :note_activity )
user1 = insert ( :user )
user2 = insert ( :user )
user3 = insert ( :user )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( user2 , activity . id )
2019-09-26 08:38:45 +02:00
{ :ok , _bookmark } = Pleroma.Bookmark . create ( user2 . id , activity . id )
{ :ok , reblog_activity1 , _object } = CommonAPI . repeat ( activity . id , user1 )
{ :ok , _ , _object } = CommonAPI . repeat ( activity . id , user2 )
conn_res =
conn
|> assign ( :user , user3 )
|> get ( " /api/v1/statuses/ #{ reblog_activity1 . id } " )
assert %{
" reblog " = > %{ " id " = > id , " reblogged " = > false , " reblogs_count " = > 2 } ,
" reblogged " = > false ,
" favourited " = > false ,
" bookmarked " = > false
} = json_response ( conn_res , 200 )
conn_res =
conn
|> assign ( :user , user2 )
|> get ( " /api/v1/statuses/ #{ reblog_activity1 . id } " )
assert %{
" reblog " = > %{ " id " = > id , " reblogged " = > true , " reblogs_count " = > 2 } ,
" reblogged " = > true ,
" favourited " = > true ,
" bookmarked " = > true
} = json_response ( conn_res , 200 )
assert to_string ( activity . id ) == id
end
test " returns 400 error when activity is not exist " , %{ conn : conn } do
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/foo/reblog " )
assert json_response ( conn , 400 ) == %{ " error " = > " Could not repeat " }
end
end
describe " unreblogging " do
test " unreblogs and returns the unreblogged status " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
{ :ok , _ , _ } = CommonAPI . repeat ( activity . id , user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /unreblog " )
assert %{ " id " = > id , " reblogged " = > false , " reblogs_count " = > 0 } = json_response ( conn , 200 )
assert to_string ( activity . id ) == id
end
test " returns 400 error when activity is not exist " , %{ conn : conn } do
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/foo/unreblog " )
assert json_response ( conn , 400 ) == %{ " error " = > " Could not unrepeat " }
end
end
describe " favoriting " do
test " favs a status and returns it " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /favourite " )
assert %{ " id " = > id , " favourites_count " = > 1 , " favourited " = > true } =
json_response ( conn , 200 )
assert to_string ( activity . id ) == id
end
test " returns 400 error for a wrong id " , %{ conn : conn } do
user = insert ( :user )
2019-10-19 14:46:14 +02:00
assert capture_log ( fn ->
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/1/favourite " )
2019-09-26 08:38:45 +02:00
2019-10-19 14:46:14 +02:00
assert json_response ( conn , 400 ) == %{ " error " = > " Could not favorite " }
end ) =~ " [error] "
2019-09-26 08:38:45 +02:00
end
end
describe " unfavoriting " do
test " unfavorites a status and returns it " , %{ conn : conn } do
activity = insert ( :note_activity )
user = insert ( :user )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( user , activity . id )
2019-09-26 08:38:45 +02:00
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /unfavourite " )
assert %{ " id " = > id , " favourites_count " = > 0 , " favourited " = > false } =
json_response ( conn , 200 )
assert to_string ( activity . id ) == id
end
test " returns 400 error for a wrong id " , %{ conn : conn } do
user = insert ( :user )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/1/unfavourite " )
assert json_response ( conn , 400 ) == %{ " error " = > " Could not unfavorite " }
end
end
describe " pinned statuses " do
setup do
user = insert ( :user )
{ :ok , activity } = CommonAPI . post ( user , %{ " status " = > " HI!!! " } )
[ user : user , activity : activity ]
end
clear_config ( [ :instance , :max_pinned_statuses ] ) do
Config . put ( [ :instance , :max_pinned_statuses ] , 1 )
end
test " pin status " , %{ conn : conn , user : user , activity : activity } do
id_str = to_string ( activity . id )
assert %{ " id " = > ^ id_str , " pinned " = > true } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /pin " )
|> json_response ( 200 )
assert [ %{ " id " = > ^ id_str , " pinned " = > true } ] =
conn
|> assign ( :user , user )
|> get ( " /api/v1/accounts/ #{ user . id } /statuses?pinned=true " )
|> json_response ( 200 )
end
test " /pin: returns 400 error when activity is not public " , %{ conn : conn , user : user } do
{ :ok , dm } = CommonAPI . post ( user , %{ " status " = > " test " , " visibility " = > " direct " } )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ dm . id } /pin " )
assert json_response ( conn , 400 ) == %{ " error " = > " Could not pin " }
end
test " unpin status " , %{ conn : conn , user : user , activity : activity } do
{ :ok , _ } = CommonAPI . pin ( activity . id , user )
id_str = to_string ( activity . id )
user = refresh_record ( user )
assert %{ " id " = > ^ id_str , " pinned " = > false } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /unpin " )
|> json_response ( 200 )
assert [ ] =
conn
|> assign ( :user , user )
|> get ( " /api/v1/accounts/ #{ user . id } /statuses?pinned=true " )
|> json_response ( 200 )
end
test " /unpin: returns 400 error when activity is not exist " , %{ conn : conn , user : user } do
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/1/unpin " )
assert json_response ( conn , 400 ) == %{ " error " = > " Could not unpin " }
end
test " max pinned statuses " , %{ conn : conn , user : user , activity : activity_one } do
{ :ok , activity_two } = CommonAPI . post ( user , %{ " status " = > " HI!!! " } )
id_str_one = to_string ( activity_one . id )
assert %{ " id " = > ^ id_str_one , " pinned " = > true } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ id_str_one } /pin " )
|> json_response ( 200 )
user = refresh_record ( user )
assert %{ " error " = > " You have already pinned the maximum number of statuses " } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity_two . id } /pin " )
|> json_response ( 400 )
end
end
describe " cards " do
setup do
Config . put ( [ :rich_media , :enabled ] , true )
user = insert ( :user )
%{ user : user }
end
test " returns rich-media card " , %{ conn : conn , user : user } do
Tesla.Mock . mock ( fn env -> apply ( HttpRequestMock , :request , [ env ] ) end )
{ :ok , activity } = CommonAPI . post ( user , %{ " status " = > " https://example.com/ogp " } )
card_data = %{
" image " = > " http://ia.media-imdb.com/images/rock.jpg " ,
" provider_name " = > " example.com " ,
" provider_url " = > " https://example.com " ,
" title " = > " The Rock " ,
" type " = > " link " ,
" url " = > " https://example.com/ogp " ,
" description " = >
" Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer. " ,
" pleroma " = > %{
" opengraph " = > %{
" image " = > " http://ia.media-imdb.com/images/rock.jpg " ,
" title " = > " The Rock " ,
" type " = > " video.movie " ,
" url " = > " https://example.com/ogp " ,
" description " = >
" Directed by Michael Bay. With Sean Connery, Nicolas Cage, Ed Harris, John Spencer. "
}
}
}
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /card " )
|> json_response ( 200 )
assert response == card_data
# works with private posts
{ :ok , activity } =
CommonAPI . post ( user , %{ " status " = > " https://example.com/ogp " , " visibility " = > " direct " } )
response_two =
conn
|> assign ( :user , user )
|> get ( " /api/v1/statuses/ #{ activity . id } /card " )
|> json_response ( 200 )
assert response_two == card_data
end
test " replaces missing description with an empty string " , %{ conn : conn , user : user } do
Tesla.Mock . mock ( fn env -> apply ( HttpRequestMock , :request , [ env ] ) end )
{ :ok , activity } =
CommonAPI . post ( user , %{ " status " = > " https://example.com/ogp-missing-data " } )
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /card " )
|> json_response ( :ok )
assert response == %{
" type " = > " link " ,
" title " = > " Pleroma " ,
" description " = > " " ,
" image " = > nil ,
" provider_name " = > " example.com " ,
" provider_url " = > " https://example.com " ,
" url " = > " https://example.com/ogp-missing-data " ,
" pleroma " = > %{
" opengraph " = > %{
" title " = > " Pleroma " ,
" type " = > " website " ,
" url " = > " https://example.com/ogp-missing-data "
}
}
}
end
end
test " bookmarks " do
user = insert ( :user )
for_user = insert ( :user )
{ :ok , activity1 } =
CommonAPI . post ( user , %{
" status " = > " heweoo? "
} )
{ :ok , activity2 } =
CommonAPI . post ( user , %{
" status " = > " heweoo! "
} )
response1 =
build_conn ( )
|> assign ( :user , for_user )
|> post ( " /api/v1/statuses/ #{ activity1 . id } /bookmark " )
assert json_response ( response1 , 200 ) [ " bookmarked " ] == true
response2 =
build_conn ( )
|> assign ( :user , for_user )
|> post ( " /api/v1/statuses/ #{ activity2 . id } /bookmark " )
assert json_response ( response2 , 200 ) [ " bookmarked " ] == true
bookmarks =
build_conn ( )
|> assign ( :user , for_user )
|> get ( " /api/v1/bookmarks " )
assert [ json_response ( response2 , 200 ) , json_response ( response1 , 200 ) ] ==
json_response ( bookmarks , 200 )
response1 =
build_conn ( )
|> assign ( :user , for_user )
|> post ( " /api/v1/statuses/ #{ activity1 . id } /unbookmark " )
assert json_response ( response1 , 200 ) [ " bookmarked " ] == false
bookmarks =
build_conn ( )
|> assign ( :user , for_user )
|> get ( " /api/v1/bookmarks " )
assert [ json_response ( response2 , 200 ) ] == json_response ( bookmarks , 200 )
end
describe " conversation muting " do
setup do
post_user = insert ( :user )
user = insert ( :user )
{ :ok , activity } = CommonAPI . post ( post_user , %{ " status " = > " HIE " } )
[ user : user , activity : activity ]
end
test " mute conversation " , %{ conn : conn , user : user , activity : activity } do
id_str = to_string ( activity . id )
assert %{ " id " = > ^ id_str , " muted " = > true } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /mute " )
|> json_response ( 200 )
end
test " cannot mute already muted conversation " , %{ conn : conn , user : user , activity : activity } do
{ :ok , _ } = CommonAPI . add_mute ( user , activity )
conn =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /mute " )
assert json_response ( conn , 400 ) == %{ " error " = > " conversation is already muted " }
end
test " unmute conversation " , %{ conn : conn , user : user , activity : activity } do
{ :ok , _ } = CommonAPI . add_mute ( user , activity )
id_str = to_string ( activity . id )
user = refresh_record ( user )
assert %{ " id " = > ^ id_str , " muted " = > false } =
conn
|> assign ( :user , user )
|> post ( " /api/v1/statuses/ #{ activity . id } /unmute " )
|> json_response ( 200 )
end
end
test " Repeated posts that are replies incorrectly have in_reply_to_id null " , %{ conn : conn } do
user1 = insert ( :user )
user2 = insert ( :user )
user3 = insert ( :user )
{ :ok , replied_to } = CommonAPI . post ( user1 , %{ " status " = > " cofe " } )
# Reply to status from another user
conn1 =
conn
|> assign ( :user , user2 )
|> post ( " /api/v1/statuses " , %{ " status " = > " xD " , " in_reply_to_id " = > replied_to . id } )
assert %{ " content " = > " xD " , " id " = > id } = json_response ( conn1 , 200 )
activity = Activity . get_by_id_with_object ( id )
assert Object . normalize ( activity ) . data [ " inReplyTo " ] == Object . normalize ( replied_to ) . data [ " id " ]
assert Activity . get_in_reply_to_activity ( activity ) . id == replied_to . id
# Reblog from the third user
conn2 =
conn
|> assign ( :user , user3 )
|> post ( " /api/v1/statuses/ #{ activity . id } /reblog " )
assert %{ " reblog " = > %{ " id " = > id , " reblogged " = > true , " reblogs_count " = > 1 } } =
json_response ( conn2 , 200 )
assert to_string ( activity . id ) == id
# Getting third user status
conn3 =
conn
|> assign ( :user , user3 )
|> get ( " api/v1/timelines/home " )
[ reblogged_activity ] = json_response ( conn3 , 200 )
assert reblogged_activity [ " reblog " ] [ " in_reply_to_id " ] == replied_to . id
replied_to_user = User . get_by_ap_id ( replied_to . data [ " actor " ] )
assert reblogged_activity [ " reblog " ] [ " in_reply_to_account_id " ] == replied_to_user . id
end
describe " GET /api/v1/statuses/:id/favourited_by " do
setup do
user = insert ( :user )
{ :ok , activity } = CommonAPI . post ( user , %{ " status " = > " test " } )
conn =
build_conn ( )
|> assign ( :user , user )
[ conn : conn , activity : activity , user : user ]
end
test " returns users who have favorited the status " , %{ conn : conn , activity : activity } do
other_user = insert ( :user )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( other_user , activity . id )
2019-09-26 08:38:45 +02:00
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( :ok )
[ %{ " id " = > id } ] = response
assert id == other_user . id
end
test " returns empty array when status has not been favorited yet " , %{
conn : conn ,
activity : activity
} do
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( :ok )
assert Enum . empty? ( response )
end
test " does not return users who have favorited the status but are blocked " , %{
conn : %{ assigns : %{ user : user } } = conn ,
activity : activity
} do
other_user = insert ( :user )
{ :ok , user } = User . block ( user , other_user )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( other_user , activity . id )
2019-09-26 08:38:45 +02:00
response =
conn
|> assign ( :user , user )
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( :ok )
assert Enum . empty? ( response )
end
test " does not fail on an unauthenticated request " , %{ conn : conn , activity : activity } do
other_user = insert ( :user )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( other_user , activity . id )
2019-09-26 08:38:45 +02:00
response =
conn
|> assign ( :user , nil )
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( :ok )
[ %{ " id " = > id } ] = response
assert id == other_user . id
end
test " requires authentification for private posts " , %{ conn : conn , user : user } do
other_user = insert ( :user )
{ :ok , activity } =
CommonAPI . post ( user , %{
" status " = > " @ #{ other_user . nickname } wanna get some # cofe together? " ,
" visibility " = > " direct "
} )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( other_user , activity . id )
2019-09-26 08:38:45 +02:00
conn
|> assign ( :user , nil )
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( 404 )
response =
build_conn ( )
|> assign ( :user , other_user )
|> get ( " /api/v1/statuses/ #{ activity . id } /favourited_by " )
|> json_response ( 200 )
[ %{ " id " = > id } ] = response
assert id == other_user . id
end
end
describe " GET /api/v1/statuses/:id/reblogged_by " do
setup do
user = insert ( :user )
{ :ok , activity } = CommonAPI . post ( user , %{ " status " = > " test " } )
conn =
build_conn ( )
|> assign ( :user , user )
[ conn : conn , activity : activity , user : user ]
end
test " returns users who have reblogged the status " , %{ conn : conn , activity : activity } do
other_user = insert ( :user )
{ :ok , _ , _ } = CommonAPI . repeat ( activity . id , other_user )
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( :ok )
[ %{ " id " = > id } ] = response
assert id == other_user . id
end
test " returns empty array when status has not been reblogged yet " , %{
conn : conn ,
activity : activity
} do
response =
conn
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( :ok )
assert Enum . empty? ( response )
end
test " does not return users who have reblogged the status but are blocked " , %{
conn : %{ assigns : %{ user : user } } = conn ,
activity : activity
} do
other_user = insert ( :user )
{ :ok , user } = User . block ( user , other_user )
{ :ok , _ , _ } = CommonAPI . repeat ( activity . id , other_user )
response =
conn
2019-10-01 21:40:35 +02:00
|> assign ( :user , user )
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( :ok )
assert Enum . empty? ( response )
end
test " does not return users who have reblogged the status privately " , %{
conn : %{ assigns : %{ user : user } } = conn ,
activity : activity
} do
other_user = insert ( :user )
{ :ok , _ , _ } = CommonAPI . repeat ( activity . id , other_user , %{ " visibility " = > " private " } )
response =
conn
2019-09-26 08:38:45 +02:00
|> assign ( :user , user )
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( :ok )
assert Enum . empty? ( response )
end
test " does not fail on an unauthenticated request " , %{ conn : conn , activity : activity } do
other_user = insert ( :user )
{ :ok , _ , _ } = CommonAPI . repeat ( activity . id , other_user )
response =
conn
|> assign ( :user , nil )
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( :ok )
[ %{ " id " = > id } ] = response
assert id == other_user . id
end
test " requires authentification for private posts " , %{ conn : conn , user : user } do
other_user = insert ( :user )
{ :ok , activity } =
CommonAPI . post ( user , %{
" status " = > " @ #{ other_user . nickname } wanna get some # cofe together? " ,
" visibility " = > " direct "
} )
conn
|> assign ( :user , nil )
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( 404 )
response =
build_conn ( )
|> assign ( :user , other_user )
|> get ( " /api/v1/statuses/ #{ activity . id } /reblogged_by " )
|> json_response ( 200 )
assert [ ] == response
end
end
2019-09-26 09:28:35 +02:00
test " context " do
user = insert ( :user )
{ :ok , %{ id : id1 } } = CommonAPI . post ( user , %{ " status " = > " 1 " } )
{ :ok , %{ id : id2 } } = CommonAPI . post ( user , %{ " status " = > " 2 " , " in_reply_to_status_id " = > id1 } )
{ :ok , %{ id : id3 } } = CommonAPI . post ( user , %{ " status " = > " 3 " , " in_reply_to_status_id " = > id2 } )
{ :ok , %{ id : id4 } } = CommonAPI . post ( user , %{ " status " = > " 4 " , " in_reply_to_status_id " = > id3 } )
{ :ok , %{ id : id5 } } = CommonAPI . post ( user , %{ " status " = > " 5 " , " in_reply_to_status_id " = > id4 } )
response =
build_conn ( )
|> assign ( :user , nil )
|> get ( " /api/v1/statuses/ #{ id3 } /context " )
|> json_response ( :ok )
assert %{
" ancestors " = > [ %{ " id " = > ^ id1 } , %{ " id " = > ^ id2 } ] ,
" descendants " = > [ %{ " id " = > ^ id4 } , %{ " id " = > ^ id5 } ]
} = response
end
2019-10-02 13:27:01 +02:00
test " returns the favorites of a user " , %{ conn : conn } do
user = insert ( :user )
other_user = insert ( :user )
{ :ok , _ } = CommonAPI . post ( other_user , %{ " status " = > " bla " } )
{ :ok , activity } = CommonAPI . post ( other_user , %{ " status " = > " traps are happy " } )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( user , activity . id )
2019-10-02 13:27:01 +02:00
first_conn =
conn
|> assign ( :user , user )
|> get ( " /api/v1/favourites " )
assert [ status ] = json_response ( first_conn , 200 )
assert status [ " id " ] == to_string ( activity . id )
assert [ { " link " , _link_header } ] =
Enum . filter ( first_conn . resp_headers , fn element -> match? ( { " link " , _ } , element ) end )
# Honours query params
{ :ok , second_activity } =
CommonAPI . post ( other_user , %{
" status " = >
" Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful. "
} )
2019-10-16 16:16:39 +02:00
{ :ok , _ } = CommonAPI . favorite ( user , second_activity . id )
2019-10-02 13:27:01 +02:00
last_like = status [ " id " ]
second_conn =
conn
|> assign ( :user , user )
|> get ( " /api/v1/favourites?since_id= #{ last_like } " )
assert [ second_status ] = json_response ( second_conn , 200 )
assert second_status [ " id " ] == to_string ( second_activity . id )
third_conn =
conn
|> assign ( :user , user )
|> get ( " /api/v1/favourites?limit=0 " )
assert [ ] = json_response ( third_conn , 200 )
end
2019-09-26 08:38:45 +02:00
end