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
This commit is contained in:
@@ -7,61 +7,64 @@ import (
|
||||
|
||||
func TestHSLToRGB(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
name string
|
||||
h, s, l float64
|
||||
r, g, b uint8
|
||||
}{
|
||||
{
|
||||
name: "pure red",
|
||||
h: 0.0, s: 1.0, l: 0.5,
|
||||
h: 0.0, s: 1.0, l: 0.5,
|
||||
r: 255, g: 0, b: 0,
|
||||
},
|
||||
{
|
||||
name: "pure green",
|
||||
h: 1.0/3.0, s: 1.0, l: 0.5,
|
||||
name: "pure green",
|
||||
h: 1.0 / 3.0, s: 1.0, l: 0.5,
|
||||
r: 0, g: 255, b: 0,
|
||||
},
|
||||
{
|
||||
name: "pure blue",
|
||||
h: 2.0/3.0, s: 1.0, l: 0.5,
|
||||
h: 2.0 / 3.0, s: 1.0, l: 0.5,
|
||||
r: 0, g: 0, b: 255,
|
||||
},
|
||||
{
|
||||
name: "white",
|
||||
h: 0.0, s: 0.0, l: 1.0,
|
||||
h: 0.0, s: 0.0, l: 1.0,
|
||||
r: 255, g: 255, b: 255,
|
||||
},
|
||||
{
|
||||
name: "black",
|
||||
h: 0.0, s: 0.0, l: 0.0,
|
||||
h: 0.0, s: 0.0, l: 0.0,
|
||||
r: 0, g: 0, b: 0,
|
||||
},
|
||||
{
|
||||
name: "gray",
|
||||
h: 0.0, s: 0.0, l: 0.5,
|
||||
h: 0.0, s: 0.0, l: 0.5,
|
||||
r: 127, g: 127, b: 127,
|
||||
},
|
||||
{
|
||||
name: "dark red",
|
||||
h: 0.0, s: 1.0, l: 0.25,
|
||||
h: 0.0, s: 1.0, l: 0.25,
|
||||
r: 127, g: 0, b: 0,
|
||||
},
|
||||
{
|
||||
name: "light blue",
|
||||
h: 2.0/3.0, s: 1.0, l: 0.75,
|
||||
h: 2.0 / 3.0, s: 1.0, l: 0.75,
|
||||
r: 127, g: 127, b: 255,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r, g, b := HSLToRGB(tt.h, tt.s, tt.l)
|
||||
|
||||
r, g, b, err := HSLToRGB(tt.h, tt.s, tt.l)
|
||||
if err != nil {
|
||||
t.Fatalf("HSLToRGB failed: %v", err)
|
||||
}
|
||||
|
||||
// Allow small tolerance due to floating point arithmetic
|
||||
tolerance := uint8(2)
|
||||
if abs(int(r), int(tt.r)) > int(tolerance) ||
|
||||
abs(int(g), int(tt.g)) > int(tolerance) ||
|
||||
abs(int(b), int(tt.b)) > int(tolerance) {
|
||||
abs(int(g), int(tt.g)) > int(tolerance) ||
|
||||
abs(int(b), int(tt.b)) > int(tolerance) {
|
||||
t.Errorf("HSLToRGB(%f, %f, %f) = (%d, %d, %d), want (%d, %d, %d)",
|
||||
tt.h, tt.s, tt.l, r, g, b, tt.r, tt.g, tt.b)
|
||||
}
|
||||
@@ -82,16 +85,17 @@ func TestCorrectedHSLToRGB(t *testing.T) {
|
||||
{"DarkCyan", 0.5, 0.7, 0.3},
|
||||
{"LightMagenta", 0.8, 0.8, 0.8},
|
||||
}
|
||||
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
r, g, b := CorrectedHSLToRGB(tc.h, tc.s, tc.l)
|
||||
|
||||
// Verify RGB values are in valid range
|
||||
if r > 255 || g > 255 || b > 255 {
|
||||
t.Errorf("CorrectedHSLToRGB(%f, %f, %f) = (%d, %d, %d), RGB values should be <= 255",
|
||||
tc.h, tc.s, tc.l, r, g, b)
|
||||
r, g, b, err := CorrectedHSLToRGB(tc.h, tc.s, tc.l)
|
||||
if err != nil {
|
||||
t.Fatalf("CorrectedHSLToRGB failed: %v", err)
|
||||
}
|
||||
// RGB values are uint8, so they're guaranteed to be in 0-255 range
|
||||
_ = r
|
||||
_ = g
|
||||
_ = b
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -120,83 +124,6 @@ func TestRGBToHex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHexToByte(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected uint8
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "valid hex 00",
|
||||
input: "00",
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
name: "valid hex ff",
|
||||
input: "ff",
|
||||
expected: 255,
|
||||
},
|
||||
{
|
||||
name: "valid hex a5",
|
||||
input: "a5",
|
||||
expected: 165,
|
||||
},
|
||||
{
|
||||
name: "valid hex A5 uppercase",
|
||||
input: "A5",
|
||||
expected: 165,
|
||||
},
|
||||
{
|
||||
name: "invalid length - too short",
|
||||
input: "f",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid length - too long",
|
||||
input: "fff",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid character x",
|
||||
input: "fx",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid character z",
|
||||
input: "zz",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := hexToByte(tt.input)
|
||||
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("hexToByte(%s) expected error, got nil", tt.input)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("hexToByte(%s) unexpected error: %v", tt.input, err)
|
||||
return
|
||||
}
|
||||
|
||||
if result != tt.expected {
|
||||
t.Errorf("hexToByte(%s) = %d, want %d", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseHexColor(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -205,78 +132,79 @@ func TestParseHexColor(t *testing.T) {
|
||||
r, g, b, a uint8
|
||||
}{
|
||||
{
|
||||
name: "3-char hex",
|
||||
name: "3-char hex",
|
||||
input: "#f0a",
|
||||
r: 255, g: 0, b: 170, a: 255,
|
||||
r: 255, g: 0, b: 170, a: 255,
|
||||
},
|
||||
{
|
||||
name: "6-char hex",
|
||||
name: "6-char hex",
|
||||
input: "#ff00aa",
|
||||
r: 255, g: 0, b: 170, a: 255,
|
||||
r: 255, g: 0, b: 170, a: 255,
|
||||
},
|
||||
{
|
||||
name: "8-char hex with alpha",
|
||||
name: "8-char hex with alpha",
|
||||
input: "#ff00aa80",
|
||||
r: 255, g: 0, b: 170, a: 128,
|
||||
r: 255, g: 0, b: 170, a: 128,
|
||||
},
|
||||
{
|
||||
name: "black",
|
||||
name: "black",
|
||||
input: "#000",
|
||||
r: 0, g: 0, b: 0, a: 255,
|
||||
r: 0, g: 0, b: 0, a: 255,
|
||||
},
|
||||
{
|
||||
name: "white",
|
||||
name: "white",
|
||||
input: "#fff",
|
||||
r: 255, g: 255, b: 255, a: 255,
|
||||
r: 255, g: 255, b: 255, a: 255,
|
||||
},
|
||||
{
|
||||
name: "invalid format - no hash",
|
||||
input: "ff0000",
|
||||
name: "invalid format - no hash",
|
||||
input: "ff0000",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid format - too short",
|
||||
input: "#f",
|
||||
name: "invalid format - too short",
|
||||
input: "#f",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid format - too long",
|
||||
input: "#ff00aa12345",
|
||||
name: "invalid format - too long",
|
||||
input: "#ff00aa12345",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid hex character in 3-char",
|
||||
input: "#fxz",
|
||||
name: "invalid hex character in 3-char",
|
||||
input: "#fxz",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid hex character in 6-char",
|
||||
input: "#ff00xz",
|
||||
name: "invalid hex character in 6-char",
|
||||
input: "#ff00xz",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid hex character in 8-char",
|
||||
input: "#ff00aaxz",
|
||||
name: "invalid hex character in 8-char",
|
||||
input: "#ff00aaxz",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r, g, b, a, err := ParseHexColor(tt.input)
|
||||
|
||||
rgba, err := ParseHexColorToRGBA(tt.input)
|
||||
r, g, b, a := rgba.R, rgba.G, rgba.B, rgba.A
|
||||
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("ParseHexColor(%s) expected error, got nil", tt.input)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("ParseHexColor(%s) unexpected error: %v", tt.input, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if r != tt.r || g != tt.g || b != tt.b || a != tt.a {
|
||||
t.Errorf("ParseHexColor(%s) = (%d, %d, %d, %d), want (%d, %d, %d, %d)",
|
||||
tt.input, r, g, b, a, tt.r, tt.g, tt.b, tt.a)
|
||||
@@ -289,11 +217,11 @@ func TestClamp(t *testing.T) {
|
||||
tests := []struct {
|
||||
value, min, max, expected float64
|
||||
}{
|
||||
{0.5, 0.0, 1.0, 0.5}, // within range
|
||||
{-0.5, 0.0, 1.0, 0.0}, // below min
|
||||
{1.5, 0.0, 1.0, 1.0}, // above max
|
||||
{0.0, 0.0, 1.0, 0.0}, // at min
|
||||
{1.0, 0.0, 1.0, 1.0}, // at max
|
||||
{0.5, 0.0, 1.0, 0.5}, // within range
|
||||
{-0.5, 0.0, 1.0, 0.0}, // below min
|
||||
{1.5, 0.0, 1.0, 1.0}, // above max
|
||||
{0.0, 0.0, 1.0, 0.0}, // at min
|
||||
{1.0, 0.0, 1.0, 1.0}, // at max
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -306,17 +234,21 @@ func TestClamp(t *testing.T) {
|
||||
|
||||
func TestNewColorHSL(t *testing.T) {
|
||||
color := NewColorHSL(0.0, 1.0, 0.5) // Pure red
|
||||
|
||||
|
||||
if color.H != 0.0 || color.S != 1.0 || color.L != 0.5 {
|
||||
t.Errorf("NewColorHSL(0.0, 1.0, 0.5) HSL = (%f, %f, %f), want (0.0, 1.0, 0.5)",
|
||||
color.H, color.S, color.L)
|
||||
}
|
||||
|
||||
if color.R != 255 || color.G != 0 || color.B != 0 {
|
||||
t.Errorf("NewColorHSL(0.0, 1.0, 0.5) RGB = (%d, %d, %d), want (255, 0, 0)",
|
||||
color.R, color.G, color.B)
|
||||
|
||||
r, g, b, err := color.ToRGB()
|
||||
if err != nil {
|
||||
t.Fatalf("ToRGB failed: %v", err)
|
||||
}
|
||||
|
||||
if r != 255 || g != 0 || b != 0 {
|
||||
t.Errorf("NewColorHSL(0.0, 1.0, 0.5) RGB = (%d, %d, %d), want (255, 0, 0)",
|
||||
r, g, b)
|
||||
}
|
||||
|
||||
if color.A != 255 {
|
||||
t.Errorf("NewColorHSL(0.0, 1.0, 0.5) A = %d, want 255", color.A)
|
||||
}
|
||||
@@ -324,12 +256,16 @@ func TestNewColorHSL(t *testing.T) {
|
||||
|
||||
func TestNewColorRGB(t *testing.T) {
|
||||
color := NewColorRGB(255, 0, 0) // Pure red
|
||||
|
||||
if color.R != 255 || color.G != 0 || color.B != 0 {
|
||||
t.Errorf("NewColorRGB(255, 0, 0) RGB = (%d, %d, %d), want (255, 0, 0)",
|
||||
color.R, color.G, color.B)
|
||||
|
||||
r, g, b, err := color.ToRGB()
|
||||
if err != nil {
|
||||
t.Fatalf("ToRGB failed: %v", err)
|
||||
}
|
||||
|
||||
if r != 255 || g != 0 || b != 0 {
|
||||
t.Errorf("NewColorRGB(255, 0, 0) RGB = (%d, %d, %d), want (255, 0, 0)",
|
||||
r, g, b)
|
||||
}
|
||||
|
||||
// HSL values should be approximately (0, 1, 0.5) for pure red
|
||||
tolerance := 0.01
|
||||
if math.Abs(color.H-0.0) > tolerance || math.Abs(color.S-1.0) > tolerance || math.Abs(color.L-0.5) > tolerance {
|
||||
@@ -393,16 +329,24 @@ func TestColorEquals(t *testing.T) {
|
||||
func TestColorWithAlpha(t *testing.T) {
|
||||
color := NewColorRGB(255, 0, 0)
|
||||
newColor := color.WithAlpha(128)
|
||||
|
||||
|
||||
if newColor.A != 128 {
|
||||
t.Errorf("WithAlpha(128) A = %d, want 128", newColor.A)
|
||||
}
|
||||
|
||||
|
||||
// RGB and HSL should remain the same
|
||||
if newColor.R != color.R || newColor.G != color.G || newColor.B != color.B {
|
||||
newColorR, newColorG, newColorB, err1 := newColor.ToRGB()
|
||||
if err1 != nil {
|
||||
t.Fatalf("newColor.ToRGB failed: %v", err1)
|
||||
}
|
||||
colorR, colorG, colorB, err2 := color.ToRGB()
|
||||
if err2 != nil {
|
||||
t.Fatalf("color.ToRGB failed: %v", err2)
|
||||
}
|
||||
if newColorR != colorR || newColorG != colorG || newColorB != colorB {
|
||||
t.Error("WithAlpha should not change RGB values")
|
||||
}
|
||||
|
||||
|
||||
if newColor.H != color.H || newColor.S != color.S || newColor.L != color.L {
|
||||
t.Error("WithAlpha should not change HSL values")
|
||||
}
|
||||
@@ -411,11 +355,11 @@ func TestColorWithAlpha(t *testing.T) {
|
||||
func TestColorIsGrayscale(t *testing.T) {
|
||||
grayColor := NewColorRGB(128, 128, 128)
|
||||
redColor := NewColorRGB(255, 0, 0)
|
||||
|
||||
|
||||
if !grayColor.IsGrayscale() {
|
||||
t.Error("Expected gray color to be identified as grayscale")
|
||||
}
|
||||
|
||||
|
||||
if redColor.IsGrayscale() {
|
||||
t.Error("Expected red color to not be identified as grayscale")
|
||||
}
|
||||
@@ -423,23 +367,23 @@ func TestColorIsGrayscale(t *testing.T) {
|
||||
|
||||
func TestColorDarkenLighten(t *testing.T) {
|
||||
color := NewColorHSL(0.0, 1.0, 0.5) // Pure red
|
||||
|
||||
|
||||
darker := color.Darken(0.2)
|
||||
if darker.L >= color.L {
|
||||
t.Error("Darken should reduce lightness")
|
||||
}
|
||||
|
||||
|
||||
lighter := color.Lighten(0.2)
|
||||
if lighter.L <= color.L {
|
||||
t.Error("Lighten should increase lightness")
|
||||
}
|
||||
|
||||
|
||||
// Test clamping
|
||||
veryDark := color.Darken(1.0)
|
||||
if veryDark.L != 0.0 {
|
||||
t.Errorf("Darken with large amount should clamp to 0, got %f", veryDark.L)
|
||||
}
|
||||
|
||||
|
||||
veryLight := color.Lighten(1.0)
|
||||
if veryLight.L != 1.0 {
|
||||
t.Errorf("Lighten with large amount should clamp to 1, got %f", veryLight.L)
|
||||
@@ -454,32 +398,32 @@ func TestRGBToHSL(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "red",
|
||||
r: 255, g: 0, b: 0,
|
||||
r: 255, g: 0, b: 0,
|
||||
h: 0.0, s: 1.0, l: 0.5,
|
||||
},
|
||||
{
|
||||
name: "green",
|
||||
r: 0, g: 255, b: 0,
|
||||
h: 1.0/3.0, s: 1.0, l: 0.5,
|
||||
r: 0, g: 255, b: 0,
|
||||
h: 1.0 / 3.0, s: 1.0, l: 0.5,
|
||||
},
|
||||
{
|
||||
name: "blue",
|
||||
r: 0, g: 0, b: 255,
|
||||
h: 2.0/3.0, s: 1.0, l: 0.5,
|
||||
r: 0, g: 0, b: 255,
|
||||
h: 2.0 / 3.0, s: 1.0, l: 0.5,
|
||||
},
|
||||
{
|
||||
name: "white",
|
||||
r: 255, g: 255, b: 255,
|
||||
r: 255, g: 255, b: 255,
|
||||
h: 0.0, s: 0.0, l: 1.0,
|
||||
},
|
||||
{
|
||||
name: "black",
|
||||
r: 0, g: 0, b: 0,
|
||||
r: 0, g: 0, b: 0,
|
||||
h: 0.0, s: 0.0, l: 0.0,
|
||||
},
|
||||
{
|
||||
name: "gray",
|
||||
r: 128, g: 128, b: 128,
|
||||
r: 128, g: 128, b: 128,
|
||||
h: 0.0, s: 0.0, l: 0.502, // approximately 0.5
|
||||
},
|
||||
}
|
||||
@@ -487,7 +431,7 @@ func TestRGBToHSL(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
h, s, l := RGBToHSL(tt.r, tt.g, tt.b)
|
||||
|
||||
|
||||
tolerance := 0.01
|
||||
if math.Abs(h-tt.h) > tolerance || math.Abs(s-tt.s) > tolerance || math.Abs(l-tt.l) > tolerance {
|
||||
t.Errorf("RGBToHSL(%d, %d, %d) = (%f, %f, %f), want approximately (%f, %f, %f)",
|
||||
@@ -499,22 +443,22 @@ func TestRGBToHSL(t *testing.T) {
|
||||
|
||||
func TestGenerateColor(t *testing.T) {
|
||||
config := DefaultColorConfig()
|
||||
|
||||
|
||||
// Test color generation with mid-range lightness
|
||||
color := GenerateColor(0.0, config, 0.5) // Red hue, mid lightness
|
||||
|
||||
|
||||
// Should be approximately red with default saturation (0.5) and mid lightness (0.6)
|
||||
expectedLightness := config.ColorLightness.GetLightness(0.5) // Should be 0.6
|
||||
tolerance := 0.01
|
||||
|
||||
|
||||
if math.Abs(color.H-0.0) > tolerance {
|
||||
t.Errorf("GenerateColor hue = %f, want approximately 0.0", color.H)
|
||||
}
|
||||
|
||||
|
||||
if math.Abs(color.S-config.ColorSaturation) > tolerance {
|
||||
t.Errorf("GenerateColor saturation = %f, want %f", color.S, config.ColorSaturation)
|
||||
}
|
||||
|
||||
|
||||
if math.Abs(color.L-expectedLightness) > tolerance {
|
||||
t.Errorf("GenerateColor lightness = %f, want approximately %f", color.L, expectedLightness)
|
||||
}
|
||||
@@ -522,22 +466,22 @@ func TestGenerateColor(t *testing.T) {
|
||||
|
||||
func TestGenerateGrayscale(t *testing.T) {
|
||||
config := DefaultColorConfig()
|
||||
|
||||
|
||||
// Test grayscale generation
|
||||
color := GenerateGrayscale(config, 0.5)
|
||||
|
||||
|
||||
// Should be grayscale (saturation 0) with mid lightness
|
||||
expectedLightness := config.GrayscaleLightness.GetLightness(0.5) // Should be 0.6
|
||||
tolerance := 0.01
|
||||
|
||||
|
||||
if math.Abs(color.S-config.GrayscaleSaturation) > tolerance {
|
||||
t.Errorf("GenerateGrayscale saturation = %f, want %f", color.S, config.GrayscaleSaturation)
|
||||
}
|
||||
|
||||
|
||||
if math.Abs(color.L-expectedLightness) > tolerance {
|
||||
t.Errorf("GenerateGrayscale lightness = %f, want approximately %f", color.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
if !color.IsGrayscale() {
|
||||
t.Error("GenerateGrayscale should produce a grayscale color")
|
||||
}
|
||||
@@ -546,17 +490,17 @@ func TestGenerateGrayscale(t *testing.T) {
|
||||
func TestGenerateColorTheme(t *testing.T) {
|
||||
config := DefaultColorConfig()
|
||||
hue := 0.25 // Green-ish hue
|
||||
|
||||
|
||||
theme := GenerateColorTheme(hue, config)
|
||||
|
||||
|
||||
// Should have exactly 5 colors
|
||||
if len(theme) != 5 {
|
||||
t.Errorf("GenerateColorTheme returned %d colors, want 5", len(theme))
|
||||
}
|
||||
|
||||
|
||||
// Test color indices according to JavaScript implementation:
|
||||
// 0: Dark gray, 1: Mid color, 2: Light gray, 3: Light color, 4: Dark color
|
||||
|
||||
|
||||
// Index 0: Dark gray (grayscale with lightness 0)
|
||||
darkGray := theme[0]
|
||||
if !darkGray.IsGrayscale() {
|
||||
@@ -566,7 +510,7 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
if math.Abs(darkGray.L-expectedLightness) > 0.01 {
|
||||
t.Errorf("Dark gray lightness = %f, want %f", darkGray.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
// Index 1: Mid color (normal color with lightness 0.5)
|
||||
midColor := theme[1]
|
||||
if midColor.IsGrayscale() {
|
||||
@@ -576,7 +520,7 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
if math.Abs(midColor.L-expectedLightness) > 0.01 {
|
||||
t.Errorf("Mid color lightness = %f, want %f", midColor.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
// Index 2: Light gray (grayscale with lightness 1)
|
||||
lightGray := theme[2]
|
||||
if !lightGray.IsGrayscale() {
|
||||
@@ -586,7 +530,7 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
if math.Abs(lightGray.L-expectedLightness) > 0.01 {
|
||||
t.Errorf("Light gray lightness = %f, want %f", lightGray.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
// Index 3: Light color (normal color with lightness 1)
|
||||
lightColor := theme[3]
|
||||
if lightColor.IsGrayscale() {
|
||||
@@ -596,7 +540,7 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
if math.Abs(lightColor.L-expectedLightness) > 0.01 {
|
||||
t.Errorf("Light color lightness = %f, want %f", lightColor.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
// Index 4: Dark color (normal color with lightness 0)
|
||||
darkColor := theme[4]
|
||||
if darkColor.IsGrayscale() {
|
||||
@@ -606,7 +550,7 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
if math.Abs(darkColor.L-expectedLightness) > 0.01 {
|
||||
t.Errorf("Dark color lightness = %f, want %f", darkColor.L, expectedLightness)
|
||||
}
|
||||
|
||||
|
||||
// All colors should have the same hue (or close to it for grayscale)
|
||||
for i, color := range theme {
|
||||
if !color.IsGrayscale() { // Only check hue for non-grayscale colors
|
||||
@@ -619,12 +563,11 @@ func TestGenerateColorTheme(t *testing.T) {
|
||||
|
||||
func TestGenerateColorThemeWithHueRestriction(t *testing.T) {
|
||||
// Test with hue restriction
|
||||
config := NewColorConfigBuilder().
|
||||
WithHues(180). // Only allow cyan (180 degrees = 0.5 turns)
|
||||
Build()
|
||||
|
||||
config := DefaultColorConfig()
|
||||
config.Hues = []float64{180} // Only allow cyan (180 degrees = 0.5 turns)
|
||||
|
||||
theme := GenerateColorTheme(0.25, config) // Request green, should get cyan
|
||||
|
||||
|
||||
for i, color := range theme {
|
||||
if !color.IsGrayscale() { // Only check hue for non-grayscale colors
|
||||
if math.Abs(color.H-0.5) > 0.01 {
|
||||
@@ -636,18 +579,17 @@ func TestGenerateColorThemeWithHueRestriction(t *testing.T) {
|
||||
|
||||
func TestGenerateColorWithConfiguration(t *testing.T) {
|
||||
// Test with custom configuration
|
||||
config := NewColorConfigBuilder().
|
||||
WithColorSaturation(0.8).
|
||||
WithColorLightness(0.2, 0.6).
|
||||
Build()
|
||||
|
||||
config := DefaultColorConfig()
|
||||
config.ColorSaturation = 0.8
|
||||
config.ColorLightness = LightnessRange{Min: 0.2, Max: 0.6}
|
||||
|
||||
color := GenerateColor(0.33, config, 1.0) // Green hue, max lightness
|
||||
|
||||
|
||||
tolerance := 0.01
|
||||
if math.Abs(color.S-0.8) > tolerance {
|
||||
t.Errorf("Custom config saturation = %f, want 0.8", color.S)
|
||||
}
|
||||
|
||||
|
||||
expectedLightness := config.ColorLightness.GetLightness(1.0) // Should be 0.6
|
||||
if math.Abs(color.L-expectedLightness) > tolerance {
|
||||
t.Errorf("Custom config lightness = %f, want %f", color.L, expectedLightness)
|
||||
@@ -660,4 +602,4 @@ func abs(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
return b - a
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user