mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-28 21:50:29 +01:00
Implemented #29798 This feature implements list badges, create new badges, view badge, edit badge and assign badge to users. - List all badges  - Create new badges  - View badge   - Edit badge  - Add user to badge 
186 lines
6.3 KiB
Go
186 lines
6.3 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package user_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/util"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestBadge(t *testing.T) {
|
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
|
|
t.Run("GetBadgeNotExist", testGetBadgeNotExist)
|
|
t.Run("CreateBadgeAlreadyExists", testCreateBadgeAlreadyExists)
|
|
t.Run("GetBadgeUsers", testGetBadgeUsers)
|
|
t.Run("AddAndRemoveUserBadges", testAddAndRemoveUserBadges)
|
|
t.Run("SearchBadgesOrderingAndKeyword", testSearchBadgesOrderingAndKeyword)
|
|
}
|
|
|
|
func testGetBadgeNotExist(t *testing.T) {
|
|
badge, err := user_model.GetBadge(t.Context(), "does-not-exist")
|
|
assert.Nil(t, badge)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, util.ErrNotExist)
|
|
}
|
|
|
|
func testCreateBadgeAlreadyExists(t *testing.T) {
|
|
badge := &user_model.Badge{
|
|
Slug: "duplicate-badge-slug",
|
|
Description: "First",
|
|
}
|
|
assert.NoError(t, user_model.CreateBadge(t.Context(), badge))
|
|
|
|
err := user_model.CreateBadge(t.Context(), &user_model.Badge{
|
|
Slug: "duplicate-badge-slug",
|
|
Description: "Second",
|
|
})
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, util.ErrAlreadyExist)
|
|
}
|
|
|
|
func testGetBadgeUsers(t *testing.T) {
|
|
// Create a test badge
|
|
badge := &user_model.Badge{
|
|
Slug: "test-badge-users",
|
|
Description: "Test Badge",
|
|
ImageURL: "test.png",
|
|
}
|
|
assert.NoError(t, user_model.CreateBadge(t.Context(), badge))
|
|
|
|
// Create test users and assign badges
|
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
|
|
assert.NoError(t, user_model.AddUserBadge(t.Context(), user1, badge))
|
|
assert.NoError(t, user_model.AddUserBadge(t.Context(), user2, badge))
|
|
defer func() {
|
|
assert.NoError(t, user_model.RemoveUserBadge(t.Context(), user1, badge))
|
|
assert.NoError(t, user_model.RemoveUserBadge(t.Context(), user2, badge))
|
|
}()
|
|
|
|
// Test getting users with pagination
|
|
opts := &user_model.GetBadgeUsersOptions{
|
|
BadgeSlug: badge.Slug,
|
|
ListOptions: db.ListOptions{
|
|
Page: 1,
|
|
PageSize: 1,
|
|
},
|
|
}
|
|
|
|
users, count, err := user_model.GetBadgeUsers(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 2, count)
|
|
assert.Len(t, users, 1)
|
|
|
|
// Test second page
|
|
opts.Page = 2
|
|
users, count, err = user_model.GetBadgeUsers(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 2, count)
|
|
assert.Len(t, users, 1)
|
|
|
|
// Test with non-existent badge
|
|
opts.BadgeSlug = "non-existent"
|
|
users, count, err = user_model.GetBadgeUsers(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 0, count)
|
|
assert.Empty(t, users)
|
|
}
|
|
|
|
func testAddAndRemoveUserBadges(t *testing.T) {
|
|
badge1 := unittest.AssertExistsAndLoadBean(t, &user_model.Badge{ID: 1})
|
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
|
|
// Add a badge to user and verify that it is returned in the list
|
|
assert.NoError(t, user_model.AddUserBadge(t.Context(), user1, badge1))
|
|
badges, count, err := user_model.GetUserBadges(t.Context(), user1)
|
|
assert.Equal(t, int64(1), count)
|
|
assert.Equal(t, badge1.Slug, badges[0].Slug)
|
|
assert.NoError(t, err)
|
|
|
|
// Confirm that it is impossible to duplicate the same badge
|
|
err = user_model.AddUserBadge(t.Context(), user1, badge1)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, util.ErrAlreadyExist)
|
|
|
|
// Nothing happened to the existing badge
|
|
badges, count, err = user_model.GetUserBadges(t.Context(), user1)
|
|
assert.Equal(t, int64(1), count)
|
|
assert.Equal(t, badge1.Slug, badges[0].Slug)
|
|
assert.NoError(t, err)
|
|
|
|
// Remove a badge from user and verify that it is no longer in the list
|
|
assert.NoError(t, user_model.RemoveUserBadge(t.Context(), user1, badge1))
|
|
_, count, err = user_model.GetUserBadges(t.Context(), user1)
|
|
assert.Equal(t, int64(0), count)
|
|
assert.NoError(t, err)
|
|
|
|
// Removing empty or missing badge selections should be a no-op.
|
|
assert.NoError(t, user_model.RemoveUserBadges(t.Context(), user1, nil))
|
|
assert.NoError(t, user_model.RemoveUserBadges(t.Context(), user1, []*user_model.Badge{{Slug: "does-not-exist"}}))
|
|
}
|
|
|
|
func testSearchBadgesOrderingAndKeyword(t *testing.T) {
|
|
createdBadges := []*user_model.Badge{
|
|
{Slug: "badge-sort-b", Description: "Badge Sort B"},
|
|
{Slug: "badge-sort-c", Description: "Badge Sort C"},
|
|
{Slug: "badge-sort-a", Description: "Badge Sort A"},
|
|
{Slug: "badge-sort-case", Description: "MiXeDCaSeKeyword"},
|
|
}
|
|
for _, badge := range createdBadges {
|
|
assert.NoError(t, user_model.CreateBadge(t.Context(), badge))
|
|
}
|
|
|
|
opts := &user_model.SearchBadgeOptions{
|
|
ListOptions: db.ListOptions{ListAll: true},
|
|
Keyword: "badge-sort-",
|
|
OrderBy: db.SearchOrderBy("`badge`.id ASC"),
|
|
}
|
|
|
|
oldestFirst, count, err := user_model.SearchBadges(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 4, count)
|
|
assert.Equal(t, []string{"badge-sort-b", "badge-sort-c", "badge-sort-a", "badge-sort-case"}, collectBadgeSlugs(oldestFirst))
|
|
|
|
opts.OrderBy = db.SearchOrderBy("`badge`.id DESC")
|
|
newestFirst, count, err := user_model.SearchBadges(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 4, count)
|
|
assert.Equal(t, []string{"badge-sort-case", "badge-sort-a", "badge-sort-c", "badge-sort-b"}, collectBadgeSlugs(newestFirst))
|
|
|
|
opts.OrderBy = db.SearchOrderBy("`badge`.slug ASC")
|
|
alpha, count, err := user_model.SearchBadges(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 4, count)
|
|
assert.Equal(t, []string{"badge-sort-a", "badge-sort-b", "badge-sort-c", "badge-sort-case"}, collectBadgeSlugs(alpha))
|
|
|
|
opts.OrderBy = db.SearchOrderBy("`badge`.slug DESC")
|
|
reverseAlpha, count, err := user_model.SearchBadges(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 4, count)
|
|
assert.Equal(t, []string{"badge-sort-case", "badge-sort-c", "badge-sort-b", "badge-sort-a"}, collectBadgeSlugs(reverseAlpha))
|
|
|
|
opts.Keyword = "mixedcasekeyword"
|
|
opts.OrderBy = db.SearchOrderBy("`badge`.slug ASC")
|
|
caseInsensitive, count, err := user_model.SearchBadges(t.Context(), opts)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, 1, count)
|
|
assert.Equal(t, []string{"badge-sort-case"}, collectBadgeSlugs(caseInsensitive))
|
|
}
|
|
|
|
func collectBadgeSlugs(badges []*user_model.Badge) []string {
|
|
slugs := make([]string, 0, len(badges))
|
|
for _, badge := range badges {
|
|
slugs = append(slugs, badge.Slug)
|
|
}
|
|
return slugs
|
|
}
|