Files
go-jdenticon/jdenticon/config_test.go
Kevin McIntyre d9e84812ff Initial release: Go Jdenticon library v0.1.0
- Core library with SVG and PNG generation
- CLI tool with generate and batch commands
- Cross-platform path handling for Windows compatibility
- Comprehensive test suite with integration tests
2026-01-03 23:41:48 -05:00

463 lines
11 KiB
Go

package jdenticon
import (
"errors"
"strings"
"testing"
)
// TestIsValidHexColor tests the hex color validation helper function.
func TestIsValidHexColor(t *testing.T) {
tests := []struct {
name string
color string
expected bool
}{
// Valid cases
{
name: "empty string (transparent)",
color: "",
expected: true,
},
{
name: "valid 3-digit lowercase",
color: "#fff",
expected: true,
},
{
name: "valid 3-digit uppercase",
color: "#FFF",
expected: true,
},
{
name: "valid 3-digit mixed case",
color: "#Fa3",
expected: true,
},
{
name: "valid 6-digit lowercase",
color: "#ffffff",
expected: true,
},
{
name: "valid 6-digit uppercase",
color: "#FFFFFF",
expected: true,
},
{
name: "valid 6-digit mixed case",
color: "#Ff00Aa",
expected: true,
},
{
name: "valid with numbers",
color: "#123456",
expected: true,
},
{
name: "valid 3-digit with numbers",
color: "#123",
expected: true,
},
// Invalid cases
{
name: "missing hash prefix",
color: "ffffff",
expected: false,
},
{
name: "too short",
color: "#ff",
expected: false,
},
{
name: "too long",
color: "#fffffff",
expected: false,
},
{
name: "invalid hex characters",
color: "#gggggg",
expected: false,
},
{
name: "invalid hex characters in 3-digit",
color: "#ggg",
expected: false,
},
{
name: "just hash",
color: "#",
expected: false,
},
{
name: "double hash",
color: "##ffffff",
expected: false,
},
{
name: "color name",
color: "red",
expected: false,
},
{
name: "color name with hash",
color: "#red",
expected: false,
},
{
name: "4-digit hex",
color: "#1234",
expected: false,
},
{
name: "5-digit hex",
color: "#12345",
expected: false,
},
{
name: "7-digit hex",
color: "#1234567",
expected: false,
},
{
name: "8-digit hex (RGBA)",
color: "#12345678",
expected: false,
},
{
name: "with spaces",
color: "# ffffff",
expected: false,
},
{
name: "with special characters",
color: "#ffffff!",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isValidHexColor(tt.color)
if result != tt.expected {
t.Errorf("isValidHexColor(%q) = %v, expected %v", tt.color, result, tt.expected)
}
})
}
}
// TestWithBackgroundColor tests the WithBackgroundColor config option.
func TestWithBackgroundColor(t *testing.T) {
tests := []struct {
name string
color string
expectError bool
expectedError string
}{
// Valid cases
{
name: "empty string (transparent)",
color: "",
expectError: false,
},
{
name: "valid 3-digit hex",
color: "#fff",
expectError: false,
},
{
name: "valid 6-digit hex",
color: "#ffffff",
expectError: false,
},
{
name: "valid mixed case",
color: "#FfAa00",
expectError: false,
},
{
name: "valid with numbers",
color: "#123456",
expectError: false,
},
// Invalid cases
{
name: "missing hash",
color: "ffffff",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "invalid hex characters",
color: "#gggggg",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "too short",
color: "#ff",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "too long",
color: "#fffffff",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "color name",
color: "red",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "4-digit hex",
color: "#1234",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "8-digit hex (RGBA)",
color: "#12345678",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
option := WithBackgroundColor(tt.color)
config := DefaultConfig()
err := option(&config)
if tt.expectError {
if err == nil {
t.Errorf("WithBackgroundColor(%q) expected error but got none", tt.color)
return
}
// Check that it's the right error type
var invalidInput *ErrInvalidInput
if !errors.As(err, &invalidInput) {
t.Errorf("WithBackgroundColor(%q) error type = %T, expected *ErrInvalidInput", tt.color, err)
return
}
// Check error message contains expected text
if tt.expectedError != "" {
if !strings.Contains(err.Error(), tt.expectedError) {
t.Errorf("WithBackgroundColor(%q) error = %q, expected to contain %q", tt.color, err.Error(), tt.expectedError)
}
}
// Check field name
if invalidInput.Field != "background_color" {
t.Errorf("WithBackgroundColor(%q) error field = %q, expected %q", tt.color, invalidInput.Field, "background_color")
}
// Check value is captured
if invalidInput.Value != tt.color {
t.Errorf("WithBackgroundColor(%q) error value = %q, expected %q", tt.color, invalidInput.Value, tt.color)
}
} else {
if err != nil {
t.Errorf("WithBackgroundColor(%q) unexpected error: %v", tt.color, err)
return
}
// Check that the color was set
if config.BackgroundColor != tt.color {
t.Errorf("WithBackgroundColor(%q) config.BackgroundColor = %q, expected %q", tt.color, config.BackgroundColor, tt.color)
}
}
})
}
}
// TestConfigValidateBackgroundColor tests that Config.Validate() validates background colors.
func TestConfigValidateBackgroundColor(t *testing.T) {
tests := []struct {
name string
color string
expectError bool
expectedError string
}{
{
name: "valid empty color",
color: "",
expectError: false,
},
{
name: "valid 3-digit hex",
color: "#fff",
expectError: false,
},
{
name: "valid 6-digit hex",
color: "#ffffff",
expectError: false,
},
{
name: "invalid color",
color: "invalid-color",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
{
name: "missing hash",
color: "ffffff",
expectError: true,
expectedError: "must be a valid hex color in #RGB or #RRGGBB format",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig()
config.BackgroundColor = tt.color
err := config.Validate()
if tt.expectError {
if err == nil {
t.Errorf("Config.Validate() with BackgroundColor=%q expected error but got none", tt.color)
return
}
// Check that it's the right error type
var invalidInput *ErrInvalidInput
if !errors.As(err, &invalidInput) {
t.Errorf("Config.Validate() with BackgroundColor=%q error type = %T, expected *ErrInvalidInput", tt.color, err)
return
}
// Check error message contains expected text
if tt.expectedError != "" {
if !strings.Contains(err.Error(), tt.expectedError) {
t.Errorf("Config.Validate() with BackgroundColor=%q error = %q, expected to contain %q", tt.color, err.Error(), tt.expectedError)
}
}
} else {
if err != nil {
t.Errorf("Config.Validate() with BackgroundColor=%q unexpected error: %v", tt.color, err)
}
}
})
}
}
// TestToEngineColorConfigBackgroundColor tests that toEngineColorConfig handles background colors.
// Since validation is handled by Config.Validate(), this test focuses on the successful conversion path.
func TestToEngineColorConfigBackgroundColor(t *testing.T) {
tests := []struct {
name string
color string
expectError bool
expectedError string
}{
{
name: "valid empty color",
color: "",
expectError: false,
},
{
name: "valid 3-digit hex",
color: "#fff",
expectError: false,
},
{
name: "valid 6-digit hex",
color: "#ffffff",
expectError: false,
},
{
name: "invalid color caught by Validate()",
color: "invalid-color",
expectError: true,
expectedError: "invalid configuration",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config := DefaultConfig()
// Directly set the background color to bypass WithBackgroundColor validation
config.BackgroundColor = tt.color
_, err := config.toEngineColorConfig()
if tt.expectError {
if err == nil {
t.Errorf("toEngineColorConfig() with BackgroundColor=%q expected error but got none", tt.color)
return
}
// Check error message contains expected text (from c.Validate() call)
if tt.expectedError != "" {
if !strings.Contains(err.Error(), tt.expectedError) {
t.Errorf("toEngineColorConfig() with BackgroundColor=%q error = %q, expected to contain %q", tt.color, err.Error(), tt.expectedError)
}
}
} else {
if err != nil {
t.Errorf("toEngineColorConfig() with BackgroundColor=%q unexpected error: %v", tt.color, err)
}
}
})
}
}
// TestConfigureFunctionWithBackgroundColor tests the Configure function with background color options.
func TestConfigureFunctionWithBackgroundColor(t *testing.T) {
tests := []struct {
name string
color string
expectError bool
expectedError string
}{
{
name: "valid color through Configure",
color: "#ffffff",
expectError: false,
},
{
name: "invalid color through Configure",
color: "invalid",
expectError: true,
expectedError: "configuration option failed",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config, err := Configure(WithBackgroundColor(tt.color))
if tt.expectError {
if err == nil {
t.Errorf("Configure(WithBackgroundColor(%q)) expected error but got none", tt.color)
return
}
if tt.expectedError != "" {
if !strings.Contains(err.Error(), tt.expectedError) {
t.Errorf("Configure(WithBackgroundColor(%q)) error = %q, expected to contain %q", tt.color, err.Error(), tt.expectedError)
}
}
} else {
if err != nil {
t.Errorf("Configure(WithBackgroundColor(%q)) unexpected error: %v", tt.color, err)
return
}
if config.BackgroundColor != tt.color {
t.Errorf("Configure(WithBackgroundColor(%q)) config.BackgroundColor = %q, expected %q", tt.color, config.BackgroundColor, tt.color)
}
}
})
}
}