2021-05-08 14:25:55 +02:00
/ *
GoToSocial
2023-01-05 12:43:00 +01:00
Copyright ( C ) 2021 - 2023 GoToSocial Authors admin @ gotosocial . org
2021-05-08 14:25:55 +02:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2023-01-02 13:10:50 +01:00
package accounts_test
2021-05-08 14:25:55 +02:00
import (
2021-09-11 13:19:06 +02:00
"context"
2021-09-10 14:36:10 +02:00
"encoding/json"
2021-05-08 14:25:55 +02:00
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/suite"
2023-01-02 13:10:50 +01:00
"github.com/superseriousbusiness/gotosocial/internal/api/client/accounts"
2021-09-10 14:36:10 +02:00
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
2021-05-08 14:25:55 +02:00
"github.com/superseriousbusiness/gotosocial/testrig"
)
type AccountUpdateTestSuite struct {
AccountStandardTestSuite
}
2021-09-11 13:19:06 +02:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandler ( ) {
// set up the request
2023-03-06 10:30:19 +01:00
// we're updating the note and profile fields of zork
2021-09-11 13:19:06 +02:00
newBio := "this is my new bio read it and weep"
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
2023-03-06 10:30:19 +01:00
"note" : newBio ,
"fields_attributes[0][name]" : "pronouns" ,
"fields_attributes[0][value]" : "they/them" ,
2021-09-11 13:19:06 +02:00
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-09-11 13:19:06 +02:00
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . Equal ( "<p>this is my new bio read it and weep</p>" , apimodelAccount . Note )
2023-03-06 10:30:19 +01:00
suite . Equal ( "they/them" , apimodelAccount . Fields [ 0 ] . Value )
2022-05-07 17:55:27 +02:00
suite . Equal ( newBio , apimodelAccount . Source . Note )
2021-09-11 13:19:06 +02:00
}
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerUnlockLock ( ) {
// set up the first request
requestBody1 , w1 , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"locked" : "false" ,
} )
if err != nil {
panic ( err )
}
bodyBytes1 := requestBody1 . Bytes ( )
recorder1 := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx1 := suite . newContext ( recorder1 , http . MethodPatch , bodyBytes1 , accounts . UpdateCredentialsPath , w1 . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx1 )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder1 . Code )
// 2. we should have no error message in the result body
result1 := recorder1 . Result ( )
defer result1 . Body . Close ( )
// check the response
b1 , err := ioutil . ReadAll ( result1 . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-09-11 13:19:06 +02:00
// unmarshal the returned account
apimodelAccount1 := & apimodel . Account { }
err = json . Unmarshal ( b1 , apimodelAccount1 )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . False ( apimodelAccount1 . Locked )
// set up the first request
requestBody2 , w2 , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"locked" : "true" ,
} )
if err != nil {
panic ( err )
}
bodyBytes2 := requestBody2 . Bytes ( )
recorder2 := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx2 := suite . newContext ( recorder2 , http . MethodPatch , bodyBytes2 , accounts . UpdateCredentialsPath , w2 . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx2 )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder1 . Code )
// 2. we should have no error message in the result body
result2 := recorder2 . Result ( )
defer result2 . Body . Close ( )
// check the response
b2 , err := ioutil . ReadAll ( result2 . Body )
suite . NoError ( err )
// unmarshal the returned account
apimodelAccount2 := & apimodel . Account { }
err = json . Unmarshal ( b2 , apimodelAccount2 )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . True ( apimodelAccount2 . Locked )
}
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerGetAccountFirst ( ) {
// get the account first to make sure it's in the database cache -- when the account is updated via
// the PATCH handler, it should invalidate the cache and not return the old version
_ , err := suite . db . GetAccountByID ( context . Background ( ) , suite . testAccounts [ "local_account_1" ] . ID )
suite . NoError ( err )
// set up the request
// we're updating the note of zork
newBio := "this is my new bio read it and weep"
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"note" : newBio ,
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-09-11 13:19:06 +02:00
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . Equal ( "<p>this is my new bio read it and weep</p>" , apimodelAccount . Note )
2022-05-07 17:55:27 +02:00
suite . Equal ( newBio , apimodelAccount . Source . Note )
2021-09-11 13:19:06 +02:00
}
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerTwoFields ( ) {
// set up the request
// we're updating the note of zork, and setting locked to true
2022-09-26 11:56:01 +02:00
newBio := "this is my new bio read it and weep :rainbow:"
2021-09-11 13:19:06 +02:00
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"note" : newBio ,
"locked" : "true" ,
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-09-11 13:19:06 +02:00
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
2022-09-26 11:56:01 +02:00
suite . Equal ( "<p>this is my new bio read it and weep :rainbow:</p>" , apimodelAccount . Note )
2022-05-07 17:55:27 +02:00
suite . Equal ( newBio , apimodelAccount . Source . Note )
2021-09-11 13:19:06 +02:00
suite . True ( apimodelAccount . Locked )
2022-09-26 11:56:01 +02:00
suite . NotEmpty ( apimodelAccount . Emojis )
suite . Equal ( apimodelAccount . Emojis [ 0 ] . Shortcode , "rainbow" )
// check the account in the database
dbZork , err := suite . db . GetAccountByID ( context . Background ( ) , apimodelAccount . ID )
suite . NoError ( err )
suite . Equal ( newBio , dbZork . NoteRaw )
suite . Equal ( "<p>this is my new bio read it and weep :rainbow:</p>" , dbZork . Note )
suite . True ( * dbZork . Locked )
suite . NotEmpty ( dbZork . EmojiIDs )
2021-09-11 13:19:06 +02:00
}
2023-02-16 14:20:23 +01:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerDiscoverable ( ) {
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"discoverable" : "false" ,
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
// call the handler
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
suite . NoError ( err )
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . False ( apimodelAccount . Discoverable )
// check the account in the database
dbZork , err := suite . db . GetAccountByID ( context . Background ( ) , apimodelAccount . ID )
suite . NoError ( err )
suite . False ( * dbZork . Discoverable )
}
2021-09-11 13:19:06 +02:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerWithMedia ( ) {
2021-09-10 14:36:10 +02:00
// set up the request
// we're updating the header image, the display name, and the locked status of zork
// we're removing the note/bio
requestBody , w , err := testrig . CreateMultipartFormData (
"header" , "../../../../testrig/media/test-jpeg.jpg" ,
map [ string ] string {
"display_name" : "updated zork display name!!!" ,
"note" : "" ,
"locked" : "true" ,
} )
2021-05-08 14:25:55 +02:00
if err != nil {
panic ( err )
}
2021-09-11 13:19:06 +02:00
bodyBytes := requestBody . Bytes ( )
2021-05-08 14:25:55 +02:00
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2021-05-08 14:25:55 +02:00
2021-09-10 14:36:10 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-05-08 14:25:55 +02:00
// 1. we should have OK because our request was valid
2021-09-10 14:36:10 +02:00
suite . Equal ( http . StatusOK , recorder . Code )
2021-05-08 14:25:55 +02:00
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
2021-09-10 14:36:10 +02:00
// check the response
2021-05-08 14:25:55 +02:00
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-05-08 14:25:55 +02:00
2021-09-10 14:36:10 +02:00
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . Equal ( "updated zork display name!!!" , apimodelAccount . DisplayName )
suite . True ( apimodelAccount . Locked )
suite . Empty ( apimodelAccount . Note )
2022-05-07 17:55:27 +02:00
suite . Empty ( apimodelAccount . Source . Note )
2021-09-10 14:36:10 +02:00
// header values...
// should be set
suite . NotEmpty ( apimodelAccount . Header )
suite . NotEmpty ( apimodelAccount . HeaderStatic )
// should be different from the values set before
2023-01-11 12:13:13 +01:00
suite . NotEqual ( "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg" , apimodelAccount . Header )
suite . NotEqual ( "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg" , apimodelAccount . HeaderStatic )
2021-05-08 14:25:55 +02:00
}
2021-09-11 13:19:06 +02:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerEmptyForm ( ) {
// set up the request
bodyBytes := [ ] byte { }
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , "" )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusBadRequest , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
suite . Equal ( ` { "error":"Bad Request: empty form submitted"} ` , string ( b ) )
2021-09-11 13:19:06 +02:00
}
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerUpdateSource ( ) {
// set up the request
// we're updating the language of zork
newLanguage := "de"
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
"source[privacy]" : string ( apimodel . VisibilityPrivate ) ,
"source[language]" : "de" ,
"source[sensitive]" : "true" ,
"locked" : "true" ,
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2021-09-11 13:19:06 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2021-09-11 13:19:06 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
2022-06-08 20:38:03 +02:00
suite . NoError ( err )
2021-09-11 13:19:06 +02:00
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
suite . Equal ( newLanguage , apimodelAccount . Source . Language )
suite . EqualValues ( apimodel . VisibilityPrivate , apimodelAccount . Source . Privacy )
suite . True ( apimodelAccount . Source . Sensitive )
suite . True ( apimodelAccount . Locked )
}
2023-03-02 12:06:40 +01:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerUpdateStatusContentTypeOK ( ) {
2022-08-06 12:09:21 +02:00
// set up the request
// we're updating the language of zork
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
2023-03-02 12:06:40 +01:00
"source[status_content_type]" : "text/markdown" ,
2022-08-06 12:09:21 +02:00
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2022-08-06 12:09:21 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2022-08-06 12:09:21 +02:00
// 1. we should have OK because our request was valid
suite . Equal ( http . StatusOK , recorder . Code )
// 2. we should have no error message in the result body
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
suite . NoError ( err )
// unmarshal the returned account
apimodelAccount := & apimodel . Account { }
err = json . Unmarshal ( b , apimodelAccount )
suite . NoError ( err )
// check the returned api model account
// fields should be updated
2023-03-02 12:06:40 +01:00
suite . Equal ( "text/markdown" , apimodelAccount . Source . StatusContentType )
2022-08-06 12:09:21 +02:00
dbAccount , err := suite . db . GetAccountByID ( context . Background ( ) , suite . testAccounts [ "local_account_1" ] . ID )
if err != nil {
suite . FailNow ( err . Error ( ) )
}
2023-03-02 12:06:40 +01:00
suite . Equal ( dbAccount . StatusContentType , "text/markdown" )
2022-08-06 12:09:21 +02:00
}
2023-03-02 12:06:40 +01:00
func ( suite * AccountUpdateTestSuite ) TestAccountUpdateCredentialsPATCHHandlerUpdateStatusContentTypeBad ( ) {
2022-08-06 12:09:21 +02:00
// set up the request
// we're updating the language of zork
requestBody , w , err := testrig . CreateMultipartFormData (
"" , "" ,
map [ string ] string {
2023-03-02 12:06:40 +01:00
"source[status_content_type]" : "peepeepoopoo" ,
2022-08-06 12:09:21 +02:00
} )
if err != nil {
panic ( err )
}
bodyBytes := requestBody . Bytes ( )
recorder := httptest . NewRecorder ( )
2023-01-02 13:10:50 +01:00
ctx := suite . newContext ( recorder , http . MethodPatch , bodyBytes , accounts . UpdateCredentialsPath , w . FormDataContentType ( ) )
2022-08-06 12:09:21 +02:00
// call the handler
2023-01-02 13:10:50 +01:00
suite . accountsModule . AccountUpdateCredentialsPATCHHandler ( ctx )
2022-08-06 12:09:21 +02:00
suite . Equal ( http . StatusBadRequest , recorder . Code )
result := recorder . Result ( )
defer result . Body . Close ( )
// check the response
b , err := ioutil . ReadAll ( result . Body )
suite . NoError ( err )
2023-03-02 12:06:40 +01:00
suite . Equal ( ` { "error":"Bad Request: status content type 'peepeepoopoo' was not recognized, valid options are 'text/plain', 'text/markdown'"} ` , string ( b ) )
2022-08-06 12:09:21 +02:00
}
2021-05-08 14:25:55 +02:00
func TestAccountUpdateTestSuite ( t * testing . T ) {
suite . Run ( t , new ( AccountUpdateTestSuite ) )
}