gtsocial-umbx

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

search_test.go (11200B)


      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"
     24 	"net/http"
     25 	"net/http/httptest"
     26 	"net/url"
     27 	"strconv"
     28 	"strings"
     29 	"testing"
     30 
     31 	"github.com/stretchr/testify/suite"
     32 	"github.com/superseriousbusiness/gotosocial/internal/api/client/accounts"
     33 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     34 	apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
     35 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     36 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     37 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     38 	"github.com/superseriousbusiness/gotosocial/testrig"
     39 )
     40 
     41 type AccountSearchTestSuite struct {
     42 	AccountStandardTestSuite
     43 }
     44 
     45 func (suite *AccountSearchTestSuite) getSearch(
     46 	requestingAccount *gtsmodel.Account,
     47 	token *gtsmodel.Token,
     48 	user *gtsmodel.User,
     49 	limit *int,
     50 	offset *int,
     51 	query string,
     52 	resolve *bool,
     53 	following *bool,
     54 	expectedHTTPStatus int,
     55 	expectedBody string,
     56 ) ([]*apimodel.Account, error) {
     57 	var (
     58 		recorder   = httptest.NewRecorder()
     59 		ctx, _     = testrig.CreateGinTestContext(recorder, nil)
     60 		requestURL = testrig.URLMustParse("/api" + accounts.BasePath + "/search")
     61 		queryParts []string
     62 	)
     63 
     64 	// Put the request together.
     65 	if limit != nil {
     66 		queryParts = append(queryParts, apiutil.LimitKey+"="+strconv.Itoa(*limit))
     67 	}
     68 
     69 	if offset != nil {
     70 		queryParts = append(queryParts, apiutil.SearchOffsetKey+"="+strconv.Itoa(*offset))
     71 	}
     72 
     73 	queryParts = append(queryParts, apiutil.SearchQueryKey+"="+url.QueryEscape(query))
     74 
     75 	if resolve != nil {
     76 		queryParts = append(queryParts, apiutil.SearchResolveKey+"="+strconv.FormatBool(*resolve))
     77 	}
     78 
     79 	if following != nil {
     80 		queryParts = append(queryParts, apiutil.SearchFollowingKey+"="+strconv.FormatBool(*following))
     81 	}
     82 
     83 	requestURL.RawQuery = strings.Join(queryParts, "&")
     84 	ctx.Request = httptest.NewRequest(http.MethodGet, requestURL.String(), nil)
     85 	ctx.Set(oauth.SessionAuthorizedAccount, requestingAccount)
     86 	ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(token))
     87 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
     88 	ctx.Set(oauth.SessionAuthorizedUser, user)
     89 
     90 	// Trigger the function being tested.
     91 	suite.accountsModule.AccountSearchGETHandler(ctx)
     92 
     93 	// Read the result.
     94 	result := recorder.Result()
     95 	defer result.Body.Close()
     96 
     97 	b, err := io.ReadAll(result.Body)
     98 	if err != nil {
     99 		suite.FailNow(err.Error())
    100 	}
    101 
    102 	errs := gtserror.MultiError{}
    103 
    104 	// Check expected code + body.
    105 	if resultCode := recorder.Code; expectedHTTPStatus != resultCode {
    106 		errs = append(errs, fmt.Sprintf("expected %d got %d", expectedHTTPStatus, resultCode))
    107 	}
    108 
    109 	// If we got an expected body, return early.
    110 	if expectedBody != "" && string(b) != expectedBody {
    111 		errs = append(errs, fmt.Sprintf("expected %s got %s", expectedBody, string(b)))
    112 	}
    113 
    114 	if err := errs.Combine(); err != nil {
    115 		suite.FailNow("", "%v (body %s)", err, string(b))
    116 	}
    117 
    118 	accounts := []*apimodel.Account{}
    119 	if err := json.Unmarshal(b, &accounts); err != nil {
    120 		suite.FailNow(err.Error())
    121 	}
    122 
    123 	return accounts, nil
    124 }
    125 
    126 func (suite *AccountSearchTestSuite) TestSearchZorkOK() {
    127 	var (
    128 		requestingAccount        = suite.testAccounts["local_account_1"]
    129 		token                    = suite.testTokens["local_account_1"]
    130 		user                     = suite.testUsers["local_account_1"]
    131 		limit              *int  = nil
    132 		offset             *int  = nil
    133 		resolve            *bool = nil
    134 		query                    = "zork"
    135 		following          *bool = nil
    136 		expectedHTTPStatus       = http.StatusOK
    137 		expectedBody             = ""
    138 	)
    139 
    140 	accounts, err := suite.getSearch(
    141 		requestingAccount,
    142 		token,
    143 		user,
    144 		limit,
    145 		offset,
    146 		query,
    147 		resolve,
    148 		following,
    149 		expectedHTTPStatus,
    150 		expectedBody,
    151 	)
    152 
    153 	if err != nil {
    154 		suite.FailNow(err.Error())
    155 	}
    156 
    157 	if l := len(accounts); l != 1 {
    158 		suite.FailNow("", "expected length %d got %d", 1, l)
    159 	}
    160 }
    161 
    162 func (suite *AccountSearchTestSuite) TestSearchZorkExactOK() {
    163 	var (
    164 		requestingAccount        = suite.testAccounts["local_account_1"]
    165 		token                    = suite.testTokens["local_account_1"]
    166 		user                     = suite.testUsers["local_account_1"]
    167 		limit              *int  = nil
    168 		offset             *int  = nil
    169 		resolve            *bool = nil
    170 		query                    = "@the_mighty_zork"
    171 		following          *bool = nil
    172 		expectedHTTPStatus       = http.StatusOK
    173 		expectedBody             = ""
    174 	)
    175 
    176 	accounts, err := suite.getSearch(
    177 		requestingAccount,
    178 		token,
    179 		user,
    180 		limit,
    181 		offset,
    182 		query,
    183 		resolve,
    184 		following,
    185 		expectedHTTPStatus,
    186 		expectedBody,
    187 	)
    188 
    189 	if err != nil {
    190 		suite.FailNow(err.Error())
    191 	}
    192 
    193 	if l := len(accounts); l != 1 {
    194 		suite.FailNow("", "expected length %d got %d", 1, l)
    195 	}
    196 }
    197 
    198 func (suite *AccountSearchTestSuite) TestSearchZorkWithDomainOK() {
    199 	var (
    200 		requestingAccount        = suite.testAccounts["local_account_1"]
    201 		token                    = suite.testTokens["local_account_1"]
    202 		user                     = suite.testUsers["local_account_1"]
    203 		limit              *int  = nil
    204 		offset             *int  = nil
    205 		resolve            *bool = nil
    206 		query                    = "@the_mighty_zork@localhost:8080"
    207 		following          *bool = nil
    208 		expectedHTTPStatus       = http.StatusOK
    209 		expectedBody             = ""
    210 	)
    211 
    212 	accounts, err := suite.getSearch(
    213 		requestingAccount,
    214 		token,
    215 		user,
    216 		limit,
    217 		offset,
    218 		query,
    219 		resolve,
    220 		following,
    221 		expectedHTTPStatus,
    222 		expectedBody,
    223 	)
    224 
    225 	if err != nil {
    226 		suite.FailNow(err.Error())
    227 	}
    228 
    229 	if l := len(accounts); l != 1 {
    230 		suite.FailNow("", "expected length %d got %d", 1, l)
    231 	}
    232 }
    233 
    234 func (suite *AccountSearchTestSuite) TestSearchFossSatanNotFollowing() {
    235 	var (
    236 		requestingAccount        = suite.testAccounts["local_account_1"]
    237 		token                    = suite.testTokens["local_account_1"]
    238 		user                     = suite.testUsers["local_account_1"]
    239 		limit              *int  = nil
    240 		offset             *int  = nil
    241 		resolve            *bool = nil
    242 		query                    = "foss_satan"
    243 		following          *bool = func() *bool { i := false; return &i }()
    244 		expectedHTTPStatus       = http.StatusOK
    245 		expectedBody             = ""
    246 	)
    247 
    248 	accounts, err := suite.getSearch(
    249 		requestingAccount,
    250 		token,
    251 		user,
    252 		limit,
    253 		offset,
    254 		query,
    255 		resolve,
    256 		following,
    257 		expectedHTTPStatus,
    258 		expectedBody,
    259 	)
    260 
    261 	if err != nil {
    262 		suite.FailNow(err.Error())
    263 	}
    264 
    265 	if l := len(accounts); l != 1 {
    266 		suite.FailNow("", "expected length %d got %d", 1, l)
    267 	}
    268 }
    269 
    270 func (suite *AccountSearchTestSuite) TestSearchFossSatanFollowing() {
    271 	var (
    272 		requestingAccount        = suite.testAccounts["local_account_1"]
    273 		token                    = suite.testTokens["local_account_1"]
    274 		user                     = suite.testUsers["local_account_1"]
    275 		limit              *int  = nil
    276 		offset             *int  = nil
    277 		resolve            *bool = nil
    278 		query                    = "foss_satan"
    279 		following          *bool = func() *bool { i := true; return &i }()
    280 		expectedHTTPStatus       = http.StatusOK
    281 		expectedBody             = ""
    282 	)
    283 
    284 	accounts, err := suite.getSearch(
    285 		requestingAccount,
    286 		token,
    287 		user,
    288 		limit,
    289 		offset,
    290 		query,
    291 		resolve,
    292 		following,
    293 		expectedHTTPStatus,
    294 		expectedBody,
    295 	)
    296 
    297 	if err != nil {
    298 		suite.FailNow(err.Error())
    299 	}
    300 
    301 	if l := len(accounts); l != 0 {
    302 		suite.FailNow("", "expected length %d got %d", 0, l)
    303 	}
    304 }
    305 
    306 func (suite *AccountSearchTestSuite) TestSearchBonkersQuery() {
    307 	var (
    308 		requestingAccount        = suite.testAccounts["local_account_1"]
    309 		token                    = suite.testTokens["local_account_1"]
    310 		user                     = suite.testUsers["local_account_1"]
    311 		limit              *int  = nil
    312 		offset             *int  = nil
    313 		resolve            *bool = nil
    314 		query                    = "aaaaa@aaaaaaaaa@aaaaa **** this won't@ return anything!@!!"
    315 		following          *bool = nil
    316 		expectedHTTPStatus       = http.StatusOK
    317 		expectedBody             = ""
    318 	)
    319 
    320 	accounts, err := suite.getSearch(
    321 		requestingAccount,
    322 		token,
    323 		user,
    324 		limit,
    325 		offset,
    326 		query,
    327 		resolve,
    328 		following,
    329 		expectedHTTPStatus,
    330 		expectedBody,
    331 	)
    332 
    333 	if err != nil {
    334 		suite.FailNow(err.Error())
    335 	}
    336 
    337 	if l := len(accounts); l != 0 {
    338 		suite.FailNow("", "expected length %d got %d", 0, l)
    339 	}
    340 }
    341 
    342 func (suite *AccountSearchTestSuite) TestSearchAFollowing() {
    343 	var (
    344 		requestingAccount        = suite.testAccounts["local_account_1"]
    345 		token                    = suite.testTokens["local_account_1"]
    346 		user                     = suite.testUsers["local_account_1"]
    347 		limit              *int  = nil
    348 		offset             *int  = nil
    349 		resolve            *bool = nil
    350 		query                    = "a"
    351 		following          *bool = nil
    352 		expectedHTTPStatus       = http.StatusOK
    353 		expectedBody             = ""
    354 	)
    355 
    356 	accounts, err := suite.getSearch(
    357 		requestingAccount,
    358 		token,
    359 		user,
    360 		limit,
    361 		offset,
    362 		query,
    363 		resolve,
    364 		following,
    365 		expectedHTTPStatus,
    366 		expectedBody,
    367 	)
    368 
    369 	if err != nil {
    370 		suite.FailNow(err.Error())
    371 	}
    372 
    373 	if l := len(accounts); l != 5 {
    374 		suite.FailNow("", "expected length %d got %d", 5, l)
    375 	}
    376 
    377 	usernames := make([]string, 0, 5)
    378 	for _, account := range accounts {
    379 		usernames = append(usernames, account.Username)
    380 	}
    381 
    382 	suite.EqualValues([]string{"her_fuckin_maj", "foss_satan", "1happyturtle", "the_mighty_zork", "admin"}, usernames)
    383 }
    384 
    385 func (suite *AccountSearchTestSuite) TestSearchANotFollowing() {
    386 	var (
    387 		requestingAccount        = suite.testAccounts["local_account_1"]
    388 		token                    = suite.testTokens["local_account_1"]
    389 		user                     = suite.testUsers["local_account_1"]
    390 		limit              *int  = nil
    391 		offset             *int  = nil
    392 		resolve            *bool = nil
    393 		query                    = "a"
    394 		following          *bool = func() *bool { i := true; return &i }()
    395 		expectedHTTPStatus       = http.StatusOK
    396 		expectedBody             = ""
    397 	)
    398 
    399 	accounts, err := suite.getSearch(
    400 		requestingAccount,
    401 		token,
    402 		user,
    403 		limit,
    404 		offset,
    405 		query,
    406 		resolve,
    407 		following,
    408 		expectedHTTPStatus,
    409 		expectedBody,
    410 	)
    411 
    412 	if err != nil {
    413 		suite.FailNow(err.Error())
    414 	}
    415 
    416 	if l := len(accounts); l != 2 {
    417 		suite.FailNow("", "expected length %d got %d", 2, l)
    418 	}
    419 
    420 	usernames := make([]string, 0, 2)
    421 	for _, account := range accounts {
    422 		usernames = append(usernames, account.Username)
    423 	}
    424 
    425 	suite.EqualValues([]string{"1happyturtle", "admin"}, usernames)
    426 }
    427 
    428 func TestAccountSearchTestSuite(t *testing.T) {
    429 	suite.Run(t, new(AccountSearchTestSuite))
    430 }