gtsocial-umbx

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

bookmarks_test.go (12293B)


      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 bookmarks_test
     19 
     20 import (
     21 	"context"
     22 	"encoding/json"
     23 	"fmt"
     24 	"io/ioutil"
     25 	"net/http"
     26 	"net/http/httptest"
     27 	"strconv"
     28 	"testing"
     29 
     30 	"github.com/stretchr/testify/suite"
     31 	"github.com/superseriousbusiness/gotosocial/internal/api/client/bookmarks"
     32 	"github.com/superseriousbusiness/gotosocial/internal/api/client/statuses"
     33 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     34 	"github.com/superseriousbusiness/gotosocial/internal/config"
     35 	"github.com/superseriousbusiness/gotosocial/internal/db"
     36 	"github.com/superseriousbusiness/gotosocial/internal/email"
     37 	"github.com/superseriousbusiness/gotosocial/internal/federation"
     38 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     39 	"github.com/superseriousbusiness/gotosocial/internal/media"
     40 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     41 	"github.com/superseriousbusiness/gotosocial/internal/processing"
     42 	"github.com/superseriousbusiness/gotosocial/internal/state"
     43 	"github.com/superseriousbusiness/gotosocial/internal/storage"
     44 	"github.com/superseriousbusiness/gotosocial/internal/typeutils"
     45 	"github.com/superseriousbusiness/gotosocial/internal/visibility"
     46 	"github.com/superseriousbusiness/gotosocial/testrig"
     47 )
     48 
     49 type BookmarkTestSuite struct {
     50 	// standard suite interfaces
     51 	suite.Suite
     52 	db           db.DB
     53 	tc           typeutils.TypeConverter
     54 	mediaManager *media.Manager
     55 	federator    federation.Federator
     56 	emailSender  email.Sender
     57 	processor    *processing.Processor
     58 	storage      *storage.Driver
     59 	state        state.State
     60 
     61 	// standard suite models
     62 	testTokens       map[string]*gtsmodel.Token
     63 	testClients      map[string]*gtsmodel.Client
     64 	testApplications map[string]*gtsmodel.Application
     65 	testUsers        map[string]*gtsmodel.User
     66 	testAccounts     map[string]*gtsmodel.Account
     67 	testAttachments  map[string]*gtsmodel.MediaAttachment
     68 	testStatuses     map[string]*gtsmodel.Status
     69 	testFollows      map[string]*gtsmodel.Follow
     70 	testBookmarks    map[string]*gtsmodel.StatusBookmark
     71 
     72 	// module being tested
     73 	statusModule   *statuses.Module
     74 	bookmarkModule *bookmarks.Module
     75 }
     76 
     77 func (suite *BookmarkTestSuite) SetupSuite() {
     78 	suite.testTokens = testrig.NewTestTokens()
     79 	suite.testClients = testrig.NewTestClients()
     80 	suite.testApplications = testrig.NewTestApplications()
     81 	suite.testUsers = testrig.NewTestUsers()
     82 	suite.testAccounts = testrig.NewTestAccounts()
     83 	suite.testAttachments = testrig.NewTestAttachments()
     84 	suite.testStatuses = testrig.NewTestStatuses()
     85 	suite.testFollows = testrig.NewTestFollows()
     86 	suite.testBookmarks = testrig.NewTestBookmarks()
     87 }
     88 
     89 func (suite *BookmarkTestSuite) SetupTest() {
     90 	suite.state.Caches.Init()
     91 	testrig.StartWorkers(&suite.state)
     92 
     93 	testrig.InitTestConfig()
     94 	testrig.InitTestLog()
     95 
     96 	suite.db = testrig.NewTestDB(&suite.state)
     97 	suite.state.DB = suite.db
     98 	suite.storage = testrig.NewInMemoryStorage()
     99 	suite.state.Storage = suite.storage
    100 
    101 	suite.tc = testrig.NewTestTypeConverter(suite.db)
    102 
    103 	testrig.StartTimelines(
    104 		&suite.state,
    105 		visibility.NewFilter(&suite.state),
    106 		suite.tc,
    107 	)
    108 
    109 	testrig.StandardDBSetup(suite.db, nil)
    110 	testrig.StandardStorageSetup(suite.storage, "../../../../testrig/media")
    111 
    112 	suite.mediaManager = testrig.NewTestMediaManager(&suite.state)
    113 	suite.federator = testrig.NewTestFederator(&suite.state, testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../../testrig/media")), suite.mediaManager)
    114 	suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil)
    115 	suite.processor = testrig.NewTestProcessor(&suite.state, suite.federator, suite.emailSender, suite.mediaManager)
    116 	suite.statusModule = statuses.New(suite.processor)
    117 	suite.bookmarkModule = bookmarks.New(suite.processor)
    118 }
    119 
    120 func (suite *BookmarkTestSuite) TearDownTest() {
    121 	testrig.StandardDBTeardown(suite.db)
    122 	testrig.StandardStorageTeardown(suite.storage)
    123 	testrig.StopWorkers(&suite.state)
    124 }
    125 
    126 func (suite *BookmarkTestSuite) getBookmarks(
    127 	account *gtsmodel.Account,
    128 	token *gtsmodel.Token,
    129 	user *gtsmodel.User,
    130 	expectedHTTPStatus int,
    131 	maxID string,
    132 	minID string,
    133 	limit int,
    134 ) ([]*apimodel.Status, string, error) {
    135 	// instantiate recorder + test context
    136 	recorder := httptest.NewRecorder()
    137 	ctx, _ := testrig.CreateGinTestContext(recorder, nil)
    138 	ctx.Set(oauth.SessionAuthorizedAccount, account)
    139 	ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(token))
    140 	ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
    141 	ctx.Set(oauth.SessionAuthorizedUser, user)
    142 
    143 	// create the request URI
    144 	requestPath := bookmarks.BasePath + "?" + bookmarks.LimitKey + "=" + strconv.Itoa(limit)
    145 	if maxID != "" {
    146 		requestPath = requestPath + "&" + bookmarks.MaxIDKey + "=" + maxID
    147 	}
    148 	if minID != "" {
    149 		requestPath = requestPath + "&" + bookmarks.MinIDKey + "=" + minID
    150 	}
    151 	baseURI := config.GetProtocol() + "://" + config.GetHost()
    152 	requestURI := baseURI + "/api/" + requestPath
    153 
    154 	// create the request
    155 	ctx.Request = httptest.NewRequest(http.MethodGet, requestURI, nil)
    156 	ctx.Request.Header.Set("accept", "application/json")
    157 
    158 	// trigger the handler
    159 	suite.bookmarkModule.BookmarksGETHandler(ctx)
    160 
    161 	// read the response
    162 	result := recorder.Result()
    163 	defer result.Body.Close()
    164 
    165 	if resultCode := recorder.Code; expectedHTTPStatus != resultCode {
    166 		return nil, "", fmt.Errorf("expected %d got %d", expectedHTTPStatus, resultCode)
    167 	}
    168 
    169 	b, err := ioutil.ReadAll(result.Body)
    170 	if err != nil {
    171 		return nil, "", err
    172 	}
    173 
    174 	resp := []*apimodel.Status{}
    175 	if err := json.Unmarshal(b, &resp); err != nil {
    176 		return nil, "", err
    177 	}
    178 
    179 	return resp, result.Header.Get("Link"), nil
    180 }
    181 
    182 func (suite *BookmarkTestSuite) TestGetBookmarksSingle() {
    183 	testAccount := suite.testAccounts["local_account_1"]
    184 	testToken := suite.testTokens["local_account_1"]
    185 	testUser := suite.testUsers["local_account_1"]
    186 
    187 	statuses, linkHeader, err := suite.getBookmarks(testAccount, testToken, testUser, http.StatusOK, "", "", 10)
    188 	if err != nil {
    189 		suite.FailNow(err.Error())
    190 	}
    191 
    192 	suite.Len(statuses, 1)
    193 	suite.Equal(`<http://localhost:8080/api/v1/bookmarks?limit=10&max_id=01F8MHD2QCZSZ6WQS2ATVPEYJ9>; rel="next", <http://localhost:8080/api/v1/bookmarks?limit=10&min_id=01F8MHD2QCZSZ6WQS2ATVPEYJ9>; rel="prev"`, linkHeader)
    194 }
    195 
    196 func (suite *BookmarkTestSuite) TestGetBookmarksMultiple() {
    197 	testAccount := suite.testAccounts["local_account_1"]
    198 	testToken := suite.testTokens["local_account_1"]
    199 	testUser := suite.testUsers["local_account_1"]
    200 
    201 	// Add a few extra bookmarks for this account.
    202 	ctx := context.Background()
    203 	for _, b := range []*gtsmodel.StatusBookmark{
    204 		{
    205 			ID:              "01GSZPDQYE9WZ26T501KMM876V", // oldest
    206 			AccountID:       testAccount.ID,
    207 			StatusID:        suite.testStatuses["admin_account_status_2"].ID,
    208 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    209 		},
    210 		{
    211 			ID:              "01GSZPGHY3ACEN11D512V6MR0M",
    212 			AccountID:       testAccount.ID,
    213 			StatusID:        suite.testStatuses["admin_account_status_3"].ID,
    214 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    215 		},
    216 		{
    217 			ID:              "01GSZPGY4ZSHNV0PR3HSBB1DDV", // newest
    218 			AccountID:       testAccount.ID,
    219 			StatusID:        suite.testStatuses["admin_account_status_4"].ID,
    220 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    221 		},
    222 	} {
    223 		if err := suite.db.Put(ctx, b); err != nil {
    224 			suite.FailNow(err.Error())
    225 		}
    226 	}
    227 
    228 	statuses, linkHeader, err := suite.getBookmarks(testAccount, testToken, testUser, http.StatusOK, "", "", 10)
    229 	if err != nil {
    230 		suite.FailNow(err.Error())
    231 	}
    232 
    233 	suite.Len(statuses, 4)
    234 	suite.Equal(`<http://localhost:8080/api/v1/bookmarks?limit=10&max_id=01F8MHD2QCZSZ6WQS2ATVPEYJ9>; rel="next", <http://localhost:8080/api/v1/bookmarks?limit=10&min_id=01GSZPGY4ZSHNV0PR3HSBB1DDV>; rel="prev"`, linkHeader)
    235 }
    236 
    237 func (suite *BookmarkTestSuite) TestGetBookmarksMultiplePaging() {
    238 	testAccount := suite.testAccounts["local_account_1"]
    239 	testToken := suite.testTokens["local_account_1"]
    240 	testUser := suite.testUsers["local_account_1"]
    241 
    242 	// Add a few extra bookmarks for this account.
    243 	ctx := context.Background()
    244 	for _, b := range []*gtsmodel.StatusBookmark{
    245 		{
    246 			ID:              "01GSZPDQYE9WZ26T501KMM876V", // oldest
    247 			AccountID:       testAccount.ID,
    248 			StatusID:        suite.testStatuses["admin_account_status_2"].ID,
    249 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    250 		},
    251 		{
    252 			ID:              "01GSZPGHY3ACEN11D512V6MR0M",
    253 			AccountID:       testAccount.ID,
    254 			StatusID:        suite.testStatuses["admin_account_status_3"].ID,
    255 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    256 		},
    257 		{
    258 			ID:              "01GSZPGY4ZSHNV0PR3HSBB1DDV", // newest
    259 			AccountID:       testAccount.ID,
    260 			StatusID:        suite.testStatuses["admin_account_status_4"].ID,
    261 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    262 		},
    263 	} {
    264 		if err := suite.db.Put(ctx, b); err != nil {
    265 			suite.FailNow(err.Error())
    266 		}
    267 	}
    268 
    269 	statuses, linkHeader, err := suite.getBookmarks(testAccount, testToken, testUser, http.StatusOK, "01GSZPGY4ZSHNV0PR3HSBB1DDV", "", 10)
    270 	if err != nil {
    271 		suite.FailNow(err.Error())
    272 	}
    273 
    274 	suite.Len(statuses, 3)
    275 	suite.Equal(`<http://localhost:8080/api/v1/bookmarks?limit=10&max_id=01F8MHD2QCZSZ6WQS2ATVPEYJ9>; rel="next", <http://localhost:8080/api/v1/bookmarks?limit=10&min_id=01GSZPGHY3ACEN11D512V6MR0M>; rel="prev"`, linkHeader)
    276 }
    277 
    278 func (suite *BookmarkTestSuite) TestGetBookmarksNone() {
    279 	testAccount := suite.testAccounts["local_account_1"]
    280 	testToken := suite.testTokens["local_account_1"]
    281 	testUser := suite.testUsers["local_account_1"]
    282 
    283 	// Remove all bookmarks for this account.
    284 	if err := suite.db.DeleteStatusBookmarks(context.Background(), "", testAccount.ID); err != nil {
    285 		suite.FailNow(err.Error())
    286 	}
    287 
    288 	statuses, linkHeader, err := suite.getBookmarks(testAccount, testToken, testUser, http.StatusOK, "", "", 10)
    289 	if err != nil {
    290 		suite.FailNow(err.Error())
    291 	}
    292 
    293 	suite.Empty(statuses)
    294 	suite.Empty(linkHeader)
    295 }
    296 
    297 func (suite *BookmarkTestSuite) TestGetBookmarksNonexistentStatus() {
    298 	testAccount := suite.testAccounts["local_account_1"]
    299 	testToken := suite.testTokens["local_account_1"]
    300 	testUser := suite.testUsers["local_account_1"]
    301 
    302 	// Add a few extra bookmarks for this account.
    303 	ctx := context.Background()
    304 	for _, b := range []*gtsmodel.StatusBookmark{
    305 		{
    306 			ID:              "01GSZPDQYE9WZ26T501KMM876V", // oldest
    307 			AccountID:       testAccount.ID,
    308 			StatusID:        suite.testStatuses["admin_account_status_2"].ID,
    309 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    310 		},
    311 		{
    312 			ID:              "01GSZPGHY3ACEN11D512V6MR0M",
    313 			AccountID:       testAccount.ID,
    314 			StatusID:        suite.testStatuses["admin_account_status_3"].ID,
    315 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    316 		},
    317 		{
    318 			ID:              "01GSZPGY4ZSHNV0PR3HSBB1DDV", // newest
    319 			AccountID:       testAccount.ID,
    320 			StatusID:        "01GSZQCRX4CXPECWA5M37QNV9F", // <-- THIS ONE DOESN'T EXIST
    321 			TargetAccountID: suite.testAccounts["admin_account"].ID,
    322 		},
    323 	} {
    324 		if err := suite.db.Put(ctx, b); err != nil {
    325 			suite.FailNow(err.Error())
    326 		}
    327 	}
    328 
    329 	statuses, linkHeader, err := suite.getBookmarks(testAccount, testToken, testUser, http.StatusOK, "", "", 10)
    330 	if err != nil {
    331 		suite.FailNow(err.Error())
    332 	}
    333 
    334 	suite.Len(statuses, 3)
    335 	suite.Equal(`<http://localhost:8080/api/v1/bookmarks?limit=10&max_id=01F8MHD2QCZSZ6WQS2ATVPEYJ9>; rel="next", <http://localhost:8080/api/v1/bookmarks?limit=10&min_id=01GSZPGHY3ACEN11D512V6MR0M>; rel="prev"`, linkHeader)
    336 }
    337 
    338 func TestBookmarkTestSuite(t *testing.T) {
    339 	suite.Run(t, new(BookmarkTestSuite))
    340 }