gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

statusboost_test.go (9593B)


      1 /*
      2    GoToSocial
      3    Copyright (C) GoToSocial Authors admin@gotosocial.org
      4    This program is free software: you can redistribute it and/or modify
      5    it under the terms of the GNU Affero General Public License as published by
      6    the Free Software Foundation, either version 3 of the License, or
      7    (at your option) any later version.
      8    This program is distributed in the hope that it will be useful,
      9    but WITHOUT ANY WARRANTY; without even the implied warranty of
     10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11    GNU Affero General Public License for more details.
     12    You should have received a copy of the GNU Affero General Public License
     13    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     14 */
     15 
     16 package statuses_test
     17 
     18 import (
     19 	"context"
     20 	"encoding/json"
     21 	"fmt"
     22 	"io/ioutil"
     23 	"net/http"
     24 	"net/http/httptest"
     25 	"strings"
     26 	"testing"
     27 
     28 	"github.com/gin-gonic/gin"
     29 	"github.com/stretchr/testify/suite"
     30 	"github.com/superseriousbusiness/gotosocial/internal/api/client/statuses"
     31 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     32 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     33 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     34 	"github.com/superseriousbusiness/gotosocial/testrig"
     35 )
     36 
     37 type StatusBoostTestSuite struct {
     38 	StatusStandardTestSuite
     39 }
     40 
     41 func (suite *StatusBoostTestSuite) TestPostBoost() {
     42 	t := suite.testTokens["local_account_1"]
     43 	oauthToken := oauth.DBTokenToToken(t)
     44 
     45 	targetStatus := suite.testStatuses["admin_account_status_1"]
     46 
     47 	// setup
     48 	recorder := httptest.NewRecorder()
     49 	ctx, _ := testrig.CreateGinTestContext(recorder, nil)
     50 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
     51 	ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
     52 	ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"])
     53 	ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"])
     54 	ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
     55 	ctx.Request.Header.Set("accept", "application/json")
     56 
     57 	// normally the router would populate these params from the path values,
     58 	// but because we're calling the function directly, we need to set them manually.
     59 	ctx.Params = gin.Params{
     60 		gin.Param{
     61 			Key:   statuses.IDKey,
     62 			Value: targetStatus.ID,
     63 		},
     64 	}
     65 
     66 	suite.statusModule.StatusBoostPOSTHandler(ctx)
     67 
     68 	// check response
     69 	suite.EqualValues(http.StatusOK, recorder.Code)
     70 
     71 	result := recorder.Result()
     72 	defer result.Body.Close()
     73 	b, err := ioutil.ReadAll(result.Body)
     74 	suite.NoError(err)
     75 
     76 	statusReply := &apimodel.Status{}
     77 	err = json.Unmarshal(b, statusReply)
     78 	suite.NoError(err)
     79 
     80 	suite.False(statusReply.Sensitive)
     81 	suite.Equal(apimodel.VisibilityPublic, statusReply.Visibility)
     82 
     83 	suite.Equal(targetStatus.ContentWarning, statusReply.SpoilerText)
     84 	suite.Equal(targetStatus.Content, statusReply.Content)
     85 	suite.Equal("the_mighty_zork", statusReply.Account.Username)
     86 	suite.Len(statusReply.MediaAttachments, 0)
     87 	suite.Len(statusReply.Mentions, 0)
     88 	suite.Len(statusReply.Emojis, 0)
     89 	suite.Len(statusReply.Tags, 0)
     90 
     91 	suite.NotNil(statusReply.Application)
     92 	suite.Equal("really cool gts application", statusReply.Application.Name)
     93 
     94 	suite.NotNil(statusReply.Reblog)
     95 	suite.Equal(1, statusReply.Reblog.ReblogsCount)
     96 	suite.Equal(1, statusReply.Reblog.FavouritesCount)
     97 	suite.Equal(targetStatus.Content, statusReply.Reblog.Content)
     98 	suite.Equal(targetStatus.ContentWarning, statusReply.Reblog.SpoilerText)
     99 	suite.Equal(targetStatus.AccountID, statusReply.Reblog.Account.ID)
    100 	suite.Len(statusReply.Reblog.MediaAttachments, 1)
    101 	suite.Len(statusReply.Reblog.Tags, 1)
    102 	suite.Len(statusReply.Reblog.Emojis, 1)
    103 	suite.Equal("superseriousbusiness", statusReply.Reblog.Application.Name)
    104 }
    105 
    106 func (suite *StatusBoostTestSuite) TestPostBoostOwnFollowersOnly() {
    107 	t := suite.testTokens["local_account_1"]
    108 	oauthToken := oauth.DBTokenToToken(t)
    109 
    110 	testStatus := suite.testStatuses["local_account_1_status_5"]
    111 	testAccount := suite.testAccounts["local_account_1"]
    112 	testUser := suite.testUsers["local_account_1"]
    113 
    114 	recorder := httptest.NewRecorder()
    115 	ctx, _ := testrig.CreateGinTestContext(recorder, nil)
    116 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
    117 	ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
    118 	ctx.Set(oauth.SessionAuthorizedUser, testUser)
    119 	ctx.Set(oauth.SessionAuthorizedAccount, testAccount)
    120 	ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", testStatus.ID, 1)), nil)
    121 	ctx.Request.Header.Set("accept", "application/json")
    122 
    123 	ctx.Params = gin.Params{
    124 		gin.Param{
    125 			Key:   statuses.IDKey,
    126 			Value: testStatus.ID,
    127 		},
    128 	}
    129 
    130 	suite.statusModule.StatusBoostPOSTHandler(ctx)
    131 
    132 	// check response
    133 	suite.EqualValues(http.StatusOK, recorder.Code)
    134 
    135 	result := recorder.Result()
    136 	defer result.Body.Close()
    137 	b, err := ioutil.ReadAll(result.Body)
    138 	suite.NoError(err)
    139 
    140 	responseStatus := &apimodel.Status{}
    141 	err = json.Unmarshal(b, responseStatus)
    142 	suite.NoError(err)
    143 
    144 	suite.False(responseStatus.Sensitive)
    145 	suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Visibility)
    146 
    147 	suite.Equal(testStatus.ContentWarning, responseStatus.SpoilerText)
    148 	suite.Equal(testStatus.Content, responseStatus.Content)
    149 	suite.Equal("the_mighty_zork", responseStatus.Account.Username)
    150 	suite.Len(responseStatus.MediaAttachments, 0)
    151 	suite.Len(responseStatus.Mentions, 0)
    152 	suite.Len(responseStatus.Emojis, 0)
    153 	suite.Len(responseStatus.Tags, 0)
    154 
    155 	suite.NotNil(responseStatus.Application)
    156 	suite.Equal("really cool gts application", responseStatus.Application.Name)
    157 
    158 	suite.NotNil(responseStatus.Reblog)
    159 	suite.Equal(1, responseStatus.Reblog.ReblogsCount)
    160 	suite.Equal(0, responseStatus.Reblog.FavouritesCount)
    161 	suite.Equal(testStatus.Content, responseStatus.Reblog.Content)
    162 	suite.Equal(testStatus.ContentWarning, responseStatus.Reblog.SpoilerText)
    163 	suite.Equal(testStatus.AccountID, responseStatus.Reblog.Account.ID)
    164 	suite.Equal(suite.tc.VisToAPIVis(context.Background(), testStatus.Visibility), responseStatus.Reblog.Visibility)
    165 	suite.Empty(responseStatus.Reblog.MediaAttachments)
    166 	suite.Empty(responseStatus.Reblog.Tags)
    167 	suite.Empty(responseStatus.Reblog.Emojis)
    168 	suite.Equal("really cool gts application", responseStatus.Reblog.Application.Name)
    169 }
    170 
    171 // try to boost a status that's not boostable / visible to us
    172 func (suite *StatusBoostTestSuite) TestPostUnboostable() {
    173 	t := suite.testTokens["local_account_1"]
    174 	oauthToken := oauth.DBTokenToToken(t)
    175 
    176 	targetStatus := suite.testStatuses["local_account_2_status_4"]
    177 
    178 	// setup
    179 	recorder := httptest.NewRecorder()
    180 	ctx, _ := testrig.CreateGinTestContext(recorder, nil)
    181 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
    182 	ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
    183 	ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"])
    184 	ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"])
    185 	ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
    186 	ctx.Request.Header.Set("accept", "application/json")
    187 
    188 	// normally the router would populate these params from the path values,
    189 	// but because we're calling the function directly, we need to set them manually.
    190 	ctx.Params = gin.Params{
    191 		gin.Param{
    192 			Key:   statuses.IDKey,
    193 			Value: targetStatus.ID,
    194 		},
    195 	}
    196 
    197 	suite.statusModule.StatusBoostPOSTHandler(ctx)
    198 
    199 	// check response
    200 	suite.Equal(http.StatusNotFound, recorder.Code) // we 404 unboostable statuses
    201 
    202 	result := recorder.Result()
    203 	defer result.Body.Close()
    204 	b, err := ioutil.ReadAll(result.Body)
    205 	suite.NoError(err)
    206 	suite.Equal(`{"error":"Not Found"}`, string(b))
    207 }
    208 
    209 // try to boost a status that's not visible to the user
    210 func (suite *StatusBoostTestSuite) TestPostNotVisible() {
    211 	// stop local_account_2 following zork
    212 	err := suite.db.DeleteByID(context.Background(), suite.testFollows["local_account_2_local_account_1"].ID, &gtsmodel.Follow{})
    213 	suite.NoError(err)
    214 
    215 	t := suite.testTokens["local_account_2"]
    216 	oauthToken := oauth.DBTokenToToken(t)
    217 
    218 	targetStatus := suite.testStatuses["local_account_1_status_3"] // this is a mutual only status and these accounts aren't mutuals
    219 
    220 	// setup
    221 	recorder := httptest.NewRecorder()
    222 	ctx, _ := testrig.CreateGinTestContext(recorder, nil)
    223 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
    224 	ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
    225 	ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_2"])
    226 	ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_2"])
    227 	ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080%s", strings.Replace(statuses.ReblogPath, ":id", targetStatus.ID, 1)), nil) // the endpoint we're hitting
    228 	ctx.Request.Header.Set("accept", "application/json")
    229 
    230 	// normally the router would populate these params from the path values,
    231 	// but because we're calling the function directly, we need to set them manually.
    232 	ctx.Params = gin.Params{
    233 		gin.Param{
    234 			Key:   statuses.IDKey,
    235 			Value: targetStatus.ID,
    236 		},
    237 	}
    238 
    239 	suite.statusModule.StatusBoostPOSTHandler(ctx)
    240 
    241 	// check response
    242 	suite.Equal(http.StatusNotFound, recorder.Code) // we 404 statuses that aren't visible
    243 }
    244 
    245 func TestStatusBoostTestSuite(t *testing.T) {
    246 	suite.Run(t, new(StatusBoostTestSuite))
    247 }