statuses_test.go (10560B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package accounts_test 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "net/http" 25 "net/http/httptest" 26 "testing" 27 28 "github.com/gin-gonic/gin" 29 "github.com/stretchr/testify/suite" 30 "github.com/superseriousbusiness/gotosocial/internal/api/client/accounts" 31 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 32 "github.com/superseriousbusiness/gotosocial/internal/oauth" 33 ) 34 35 type AccountStatusesTestSuite struct { 36 AccountStandardTestSuite 37 } 38 39 func (suite *AccountStatusesTestSuite) TestGetStatusesPublicOnly() { 40 // set up the request 41 // we're getting statuses of admin 42 targetAccount := suite.testAccounts["admin_account"] 43 recorder := httptest.NewRecorder() 44 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?limit=20&only_media=false&only_public=true", targetAccount.ID), "") 45 ctx.Params = gin.Params{ 46 gin.Param{ 47 Key: accounts.IDKey, 48 Value: targetAccount.ID, 49 }, 50 } 51 52 // call the handler 53 suite.accountsModule.AccountStatusesGETHandler(ctx) 54 55 // 1. we should have OK because our request was valid 56 suite.Equal(http.StatusOK, recorder.Code) 57 58 // 2. we should have no error message in the result body 59 result := recorder.Result() 60 defer result.Body.Close() 61 62 // check the response 63 b, err := ioutil.ReadAll(result.Body) 64 suite.NoError(err) 65 66 // unmarshal the returned statuses 67 apimodelStatuses := []*apimodel.Status{} 68 err = json.Unmarshal(b, &apimodelStatuses) 69 suite.NoError(err) 70 suite.NotEmpty(apimodelStatuses) 71 72 for _, s := range apimodelStatuses { 73 suite.Equal(apimodel.VisibilityPublic, s.Visibility) 74 } 75 76 suite.Equal(`<http://localhost:8080/api/v1/accounts/01F8MH17FWEB39HZJ76B6VXSKF/statuses?limit=20&max_id=01F8MH75CBF9JFX4ZAD54N0W0R&exclude_replies=false&exclude_reblogs=false&pinned=false&only_media=false&only_public=true>; rel="next", <http://localhost:8080/api/v1/accounts/01F8MH17FWEB39HZJ76B6VXSKF/statuses?limit=20&min_id=01G36SF3V6Y6V5BF9P4R7PQG7G&exclude_replies=false&exclude_reblogs=false&pinned=false&only_media=false&only_public=true>; rel="prev"`, result.Header.Get("link")) 77 } 78 79 func (suite *AccountStatusesTestSuite) TestGetStatusesPublicOnlyMediaOnly() { 80 // set up the request 81 // we're getting statuses of admin 82 targetAccount := suite.testAccounts["admin_account"] 83 recorder := httptest.NewRecorder() 84 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?limit=20&only_media=true&only_public=true", targetAccount.ID), "") 85 ctx.Params = gin.Params{ 86 gin.Param{ 87 Key: accounts.IDKey, 88 Value: targetAccount.ID, 89 }, 90 } 91 92 // call the handler 93 suite.accountsModule.AccountStatusesGETHandler(ctx) 94 95 // 1. we should have OK because our request was valid 96 suite.Equal(http.StatusOK, recorder.Code) 97 98 // 2. we should have no error message in the result body 99 result := recorder.Result() 100 defer result.Body.Close() 101 102 // check the response 103 b, err := ioutil.ReadAll(result.Body) 104 suite.NoError(err) 105 106 // unmarshal the returned statuses 107 apimodelStatuses := []*apimodel.Status{} 108 err = json.Unmarshal(b, &apimodelStatuses) 109 suite.NoError(err) 110 suite.NotEmpty(apimodelStatuses) 111 112 for _, s := range apimodelStatuses { 113 suite.NotEmpty(s.MediaAttachments) 114 suite.Equal(apimodel.VisibilityPublic, s.Visibility) 115 } 116 117 suite.Equal(`<http://localhost:8080/api/v1/accounts/01F8MH17FWEB39HZJ76B6VXSKF/statuses?limit=20&max_id=01F8MH75CBF9JFX4ZAD54N0W0R&exclude_replies=false&exclude_reblogs=false&pinned=false&only_media=true&only_public=true>; rel="next", <http://localhost:8080/api/v1/accounts/01F8MH17FWEB39HZJ76B6VXSKF/statuses?limit=20&min_id=01F8MH75CBF9JFX4ZAD54N0W0R&exclude_replies=false&exclude_reblogs=false&pinned=false&only_media=true&only_public=true>; rel="prev"`, result.Header.Get("link")) 118 } 119 120 func (suite *AccountStatusesTestSuite) TestGetStatusesPinnedOnlyPublicPins() { 121 // admin has a couple statuses pinned 122 // we're getting pinned statuses of admin, as local account 1 123 targetAccount := suite.testAccounts["admin_account"] 124 recorder := httptest.NewRecorder() 125 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?pinned=true", targetAccount.ID), "") 126 ctx.Params = gin.Params{ 127 gin.Param{ 128 Key: accounts.IDKey, 129 Value: targetAccount.ID, 130 }, 131 } 132 133 // call the handler 134 suite.accountsModule.AccountStatusesGETHandler(ctx) 135 136 // 1. we should have OK because our request was valid 137 suite.Equal(http.StatusOK, recorder.Code) 138 139 // 2. we should have no error message in the result body 140 result := recorder.Result() 141 defer result.Body.Close() 142 143 // check the response 144 b, err := ioutil.ReadAll(result.Body) 145 suite.NoError(err) 146 147 // unmarshal the returned statuses 148 apimodelStatuses := []*apimodel.Status{} 149 err = json.Unmarshal(b, &apimodelStatuses) 150 suite.NoError(err) 151 suite.Len(apimodelStatuses, 2) 152 suite.Empty(result.Header.Get("link")) 153 154 for _, s := range apimodelStatuses { 155 // Requesting account doesn't own these 156 // statuses, so pinned should be false. 157 suite.False(s.Pinned) 158 } 159 } 160 161 func (suite *AccountStatusesTestSuite) TestGetStatusesPinnedOnlyNotFollowing() { 162 // local account 2 has a followers-only status pinned 163 // we're getting pinned statuses of local account 2 with an account that doesn't follow it 164 targetAccount := suite.testAccounts["local_account_2"] 165 recorder := httptest.NewRecorder() 166 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?pinned=true", targetAccount.ID), "") 167 ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["admin_account"]) 168 ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(suite.testTokens["admin_account"])) 169 ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"]) 170 ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["admin_account"]) 171 ctx.Params = gin.Params{ 172 gin.Param{ 173 Key: accounts.IDKey, 174 Value: targetAccount.ID, 175 }, 176 } 177 178 // call the handler 179 suite.accountsModule.AccountStatusesGETHandler(ctx) 180 181 // 1. we should have OK because our request was valid 182 suite.Equal(http.StatusOK, recorder.Code) 183 184 // 2. we should have no error message in the result body 185 result := recorder.Result() 186 defer result.Body.Close() 187 188 // check the response 189 b, err := ioutil.ReadAll(result.Body) 190 suite.NoError(err) 191 192 // unmarshal the returned statuses 193 apimodelStatuses := []*apimodel.Status{} 194 err = json.Unmarshal(b, &apimodelStatuses) 195 suite.NoError(err) 196 suite.Empty(apimodelStatuses) 197 suite.Empty(result.Header.Get("link")) 198 } 199 200 func (suite *AccountStatusesTestSuite) TestGetStatusesPinnedOnlyFollowing() { 201 // local account 2 has a followers-only status pinned 202 // we're getting pinned statuses of local account 2 with an account that *DOES* follow it 203 targetAccount := suite.testAccounts["local_account_2"] 204 recorder := httptest.NewRecorder() 205 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?pinned=true", targetAccount.ID), "") 206 ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"]) 207 ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(suite.testTokens["local_account_1"])) 208 ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"]) 209 ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"]) 210 ctx.Params = gin.Params{ 211 gin.Param{ 212 Key: accounts.IDKey, 213 Value: targetAccount.ID, 214 }, 215 } 216 217 // call the handler 218 suite.accountsModule.AccountStatusesGETHandler(ctx) 219 220 // 1. we should have OK because our request was valid 221 suite.Equal(http.StatusOK, recorder.Code) 222 223 // 2. we should have no error message in the result body 224 result := recorder.Result() 225 defer result.Body.Close() 226 227 // check the response 228 b, err := ioutil.ReadAll(result.Body) 229 suite.NoError(err) 230 231 // unmarshal the returned statuses 232 apimodelStatuses := []*apimodel.Status{} 233 err = json.Unmarshal(b, &apimodelStatuses) 234 suite.NoError(err) 235 suite.Len(apimodelStatuses, 1) 236 suite.Empty(result.Header.Get("link")) 237 238 for _, s := range apimodelStatuses { 239 // Requesting account doesn't own these 240 // statuses, so pinned should be false. 241 suite.False(s.Pinned) 242 } 243 } 244 245 func (suite *AccountStatusesTestSuite) TestGetStatusesPinnedOnlyGetOwn() { 246 // local account 2 has a followers-only status pinned 247 // we're getting pinned statuses of local account 2 with local account 2! 248 targetAccount := suite.testAccounts["local_account_2"] 249 recorder := httptest.NewRecorder() 250 ctx := suite.newContext(recorder, http.MethodGet, nil, fmt.Sprintf("/api/v1/accounts/%s/statuses?pinned=true", targetAccount.ID), "") 251 ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_2"]) 252 ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(suite.testTokens["local_account_2"])) 253 ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"]) 254 ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_2"]) 255 ctx.Params = gin.Params{ 256 gin.Param{ 257 Key: accounts.IDKey, 258 Value: targetAccount.ID, 259 }, 260 } 261 262 // call the handler 263 suite.accountsModule.AccountStatusesGETHandler(ctx) 264 265 // 1. we should have OK because our request was valid 266 suite.Equal(http.StatusOK, recorder.Code) 267 268 // 2. we should have no error message in the result body 269 result := recorder.Result() 270 defer result.Body.Close() 271 272 // check the response 273 b, err := ioutil.ReadAll(result.Body) 274 suite.NoError(err) 275 276 // unmarshal the returned statuses 277 apimodelStatuses := []*apimodel.Status{} 278 err = json.Unmarshal(b, &apimodelStatuses) 279 suite.NoError(err) 280 suite.Len(apimodelStatuses, 1) 281 suite.Empty(result.Header.Get("link")) 282 283 for _, s := range apimodelStatuses { 284 // Requesting account owns pinned statuses. 285 suite.True(s.Pinned) 286 } 287 } 288 289 func TestAccountStatusesTestSuite(t *testing.T) { 290 suite.Run(t, new(AccountStatusesTestSuite)) 291 }