forgejo/tests/integration/repo_topic_test.go
Gergely Nagy 06b808fa2c
[GITEA] Fix the topic search paging
When searching for repository topics, either via the API, or via
Explore, paging did not work correctly, because it only applied when the
`page` parameter was non-zero. Paging should have applied when the page
size is greater than zero, which is what this patch does.

As a result, both the API, and the Explore endpoint will return paged
results (30 by default). As such, when managing topics on the frontend,
the offered completions will also be limited to a pageful of results,
based on what the user has already typed.

This drastically reduces the amount of traffic, and also the number of
the topics to choose from, and thus, the rendering time too.

The topics will be returned by popularity, with most used topics first.
A single page will contain `[api].DEFAULT_PAGING_NUM` (30 by default)
items that match the query. That's plenty to choose from.

Fixes #132.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit 64d4ff41db)
2024-01-15 16:51:45 +00:00

81 lines
2.8 KiB
Go

// Copyright 2022 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"net/http"
"net/url"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestTopicSearch(t *testing.T) {
defer tests.PrepareTestEnv(t)()
searchURL, _ := url.Parse("/explore/topics/search")
var topics struct {
TopicNames []*api.TopicResponse `json:"topics"`
}
query := url.Values{"page": []string{"1"}, "limit": []string{"4"}}
searchURL.RawQuery = query.Encode()
res := MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 4)
assert.EqualValues(t, "6", res.Header().Get("x-total-count"))
query.Add("q", "topic")
searchURL.RawQuery = query.Encode()
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 2)
query.Set("q", "database")
searchURL.RawQuery = query.Encode()
res = MakeRequest(t, NewRequest(t, "GET", searchURL.String()), http.StatusOK)
DecodeJSON(t, res, &topics)
if assert.Len(t, topics.TopicNames, 1) {
assert.EqualValues(t, 2, topics.TopicNames[0].ID)
assert.EqualValues(t, "database", topics.TopicNames[0].Name)
assert.EqualValues(t, 1, topics.TopicNames[0].RepoCount)
}
}
func TestTopicSearchPaging(t *testing.T) {
defer tests.PrepareTestEnv(t)()
var topics struct {
TopicNames []*api.TopicResponse `json:"topics"`
}
// Add 20 unique topics to user2/repo2, and 20 unique ones to user2/repo3
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
token2 := getUserToken(t, user2.Name, auth_model.AccessTokenScopeWriteRepository)
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
for i := 0; i < 20; i++ {
req := NewRequestf(t, "PUT", "/api/v1/repos/%s/%s/topics/paging-topic-%d", user2.Name, repo2.Name, i).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusNoContent)
req = NewRequestf(t, "PUT", "/api/v1/repos/%s/%s/topics/paging-topic-%d", user2.Name, repo3.Name, i+30).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusNoContent)
}
res := MakeRequest(t, NewRequest(t, "GET", "/explore/topics/search"), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Len(t, topics.TopicNames, 30)
res = MakeRequest(t, NewRequest(t, "GET", "/explore/topics/search?page=2"), http.StatusOK)
DecodeJSON(t, res, &topics)
assert.Greater(t, len(topics.TopicNames), 0)
}