Files
vikunja/pkg/modules/avatar/initials/initials_test.go
2025-11-12 22:26:52 +00:00

182 lines
4.8 KiB
Go

// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package initials
import (
"testing"
"code.vikunja.io/api/pkg/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetAvatar(t *testing.T) {
t.Run("generates valid SVG with name", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 1,
Name: "John Doe",
Username: "johndoe",
}
avatar, mimeType, err := provider.GetAvatar(testUser, 128)
require.NoError(t, err)
assert.NotNil(t, avatar)
assert.Equal(t, "image/svg+xml", mimeType)
// Verify it's valid SVG
svgString := string(avatar)
assert.Contains(t, svgString, "<svg")
assert.Contains(t, svgString, "viewBox=\"0 0 100 100\"")
assert.Contains(t, svgString, "width=\"128\"")
assert.Contains(t, svgString, "height=\"128\"")
// Should contain "J" from "John"
assert.Contains(t, svgString, ">J<")
// Should have a background color
assert.Contains(t, svgString, "fill=\"#")
})
t.Run("generates valid SVG with username when name is empty", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 2,
Name: "", // Empty name
Username: "jane_smith",
}
avatar, mimeType, err := provider.GetAvatar(testUser, 64)
require.NoError(t, err)
assert.NotNil(t, avatar)
assert.Equal(t, "image/svg+xml", mimeType)
// Verify it's valid SVG
svgString := string(avatar)
assert.Contains(t, svgString, "<svg")
assert.Contains(t, svgString, "width=\"64\"")
assert.Contains(t, svgString, "height=\"64\"")
// Should contain "J" from "jane_smith"
assert.Contains(t, svgString, ">J<")
})
t.Run("uses consistent colors based on user ID", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 0,
Name: "Alice",
Username: "alice",
}
avatar1, _, err := provider.GetAvatar(testUser, 100)
require.NoError(t, err)
avatar2, _, err := provider.GetAvatar(testUser, 200)
require.NoError(t, err)
// Both should use the same colors (user ID 0 -> index 0)
svg1 := string(avatar1)
svg2 := string(avatar2)
// Should have the first background color (index 0)
assert.Contains(t, svg1, `fill="#e0f8d9"`)
assert.Contains(t, svg2, `fill="#e0f8d9"`)
// Should have the first text color (index 0)
assert.Contains(t, svg1, `fill="#005f00"`)
assert.Contains(t, svg2, `fill="#005f00"`)
})
t.Run("escapes special characters", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 3,
Name: "<script>",
Username: "hacker",
}
avatar, mimeType, err := provider.GetAvatar(testUser, 50)
require.NoError(t, err)
assert.Equal(t, "image/svg+xml", mimeType)
svgString := string(avatar)
// Should escape the < character
assert.NotContains(t, svgString, "><script><")
assert.Contains(t, svgString, "&lt;")
})
t.Run("handles different sizes", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 4,
Name: "Bob",
Username: "bob",
}
testCases := []struct {
size int64
expectedSize string
}{
{32, "32"},
{64, "64"},
{128, "128"},
{256, "256"},
{512, "512"},
}
for _, tc := range testCases {
avatar, mimeType, err := provider.GetAvatar(testUser, tc.size)
require.NoError(t, err)
assert.Equal(t, "image/svg+xml", mimeType)
svgString := string(avatar)
assert.Contains(t, svgString, `width="`+tc.expectedSize+`"`)
assert.Contains(t, svgString, `height="`+tc.expectedSize+`"`)
assert.Contains(t, svgString, ">B<")
}
})
t.Run("returns error for user without name or username", func(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 5,
Name: "",
Username: "",
}
_, _, err := provider.GetAvatar(testUser, 100)
require.Error(t, err)
assert.Contains(t, err.Error(), "no name or username")
})
}
func TestFlushCache(t *testing.T) {
provider := &Provider{}
testUser := &user.User{
ID: 999,
Name: "Test",
Username: "test",
}
// FlushCache should be a no-op and not return an error
err := provider.FlushCache(testUser)
assert.NoError(t, err)
}