mirror of
https://github.com/taigrr/colorhash.git
synced 2026-04-01 18:58:45 -07:00
feat: add OKLCH-aware palette generation (#5)
* chore: update deps, fix escape codes, expand tests, add README - Bump Go 1.18 → 1.26, simplecolorpalettes v0.9.5 → v0.9.7 - Fix swapped fg/bg ANSI escape code values in trueColorString - Expand test suite from 2 to 13 tests (determinism, positivity, color assignment, background contrast, stringer palette) - Add README with usage examples * feat: add OKLCH-aware palette generation Add GenerateOKLCHPalette() which creates n evenly-spaced colors in the OKLCH color space at a given lightness and chroma. This produces perceptually uniform palettes where all colors appear equally bright. Uses the new OKLCH support from simplecolorpalettes. Note: go.mod contains a replace directive for local development that must be removed before merge (after simplecolorpalettes is published). * build: update simplecolorpalettes to v0.9.8 (charmtone palette)
This commit is contained in:
144
hash_test.go
144
hash_test.go
@@ -1,12 +1,31 @@
|
||||
package colorhash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image/color"
|
||||
"testing"
|
||||
|
||||
"github.com/taigrr/simplecolorpalettes/simplecolor"
|
||||
)
|
||||
|
||||
func TestHashBytes(t *testing.T) {
|
||||
testBytes := []struct{}{}
|
||||
_ = testBytes
|
||||
// testPalette wraps a slice of colors to satisfy ColorSet.
|
||||
type testPalette []color.Color
|
||||
|
||||
func (p testPalette) ToPalette() color.Palette { return color.Palette(p) }
|
||||
func (p testPalette) Get(i int) color.Color { return p[i] }
|
||||
func (p testPalette) Len() int { return len(p) }
|
||||
|
||||
func newTestPalette() testPalette {
|
||||
return testPalette{
|
||||
simplecolor.FromRGBA(255, 0, 0, 255),
|
||||
simplecolor.FromRGBA(0, 255, 0, 255),
|
||||
simplecolor.FromRGBA(0, 0, 255, 255),
|
||||
simplecolor.FromRGBA(255, 255, 0, 255),
|
||||
simplecolor.FromRGBA(255, 0, 255, 255),
|
||||
simplecolor.FromRGBA(0, 255, 255, 255),
|
||||
simplecolor.FromRGBA(128, 128, 128, 255),
|
||||
simplecolor.FromRGBA(255, 128, 0, 255),
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashString(t *testing.T) {
|
||||
@@ -29,3 +48,122 @@ func TestHashString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashStringDeterministic(t *testing.T) {
|
||||
input := "deterministic-test"
|
||||
h1 := HashString(input)
|
||||
h2 := HashString(input)
|
||||
if h1 != h2 {
|
||||
t.Errorf("HashString is not deterministic: %d != %d", h1, h2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashStringPositive(t *testing.T) {
|
||||
inputs := []string{"", "a", "test", "negative?", "🎨"}
|
||||
for _, s := range inputs {
|
||||
h := HashString(s)
|
||||
if h < 0 {
|
||||
t.Errorf("HashString(%q) returned negative value: %d", s, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashBytes(t *testing.T) {
|
||||
input := []byte("hello colorhash")
|
||||
h := HashBytes(bytes.NewReader(input))
|
||||
expected := HashString("hello colorhash")
|
||||
if h != expected {
|
||||
t.Errorf("HashBytes and HashString diverged for same input: %d != %d", h, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashBytesDeterministic(t *testing.T) {
|
||||
input := []byte("deterministic")
|
||||
h1 := HashBytes(bytes.NewReader(input))
|
||||
h2 := HashBytes(bytes.NewReader(input))
|
||||
if h1 != h2 {
|
||||
t.Errorf("HashBytes is not deterministic: %d != %d", h1, h2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToColor(t *testing.T) {
|
||||
palette := newTestPalette()
|
||||
c := StringToColor(palette, "test")
|
||||
if c == nil {
|
||||
t.Fatal("StringToColor returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBytesToColor(t *testing.T) {
|
||||
palette := newTestPalette()
|
||||
c := BytesToColor(palette, bytes.NewReader([]byte("test")))
|
||||
if c == nil {
|
||||
t.Fatal("BytesToColor returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToColorDeterministic(t *testing.T) {
|
||||
palette := newTestPalette()
|
||||
c1 := StringToColor(palette, "consistent")
|
||||
c2 := StringToColor(palette, "consistent")
|
||||
r1, g1, b1, a1 := c1.RGBA()
|
||||
r2, g2, b2, a2 := c2.RGBA()
|
||||
if r1 != r2 || g1 != g2 || b1 != b2 || a1 != a2 {
|
||||
t.Error("StringToColor is not deterministic")
|
||||
}
|
||||
}
|
||||
|
||||
func TestColorString(t *testing.T) {
|
||||
result := Red("error")
|
||||
if result == "" {
|
||||
t.Fatal("ColorString returned empty string")
|
||||
}
|
||||
if result == "error" {
|
||||
t.Fatal("ColorString did not wrap with escape codes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBackgroundColor(t *testing.T) {
|
||||
// White text should get black background
|
||||
white := simplecolor.FromRGBA(255, 255, 255, 0)
|
||||
bg := GetBackgroundColor(white)
|
||||
r, g, b, _ := bg.RGBA()
|
||||
if r != 0 || g != 0 || b != 0 {
|
||||
t.Errorf("expected black background for white, got (%d,%d,%d)", r, g, b)
|
||||
}
|
||||
|
||||
// Black text should get white background
|
||||
black := simplecolor.FromRGBA(0, 0, 0, 0)
|
||||
bg2 := GetBackgroundColor(black)
|
||||
r2, g2, b2, _ := bg2.RGBA()
|
||||
if r2 == 0 && g2 == 0 && b2 == 0 {
|
||||
t.Error("expected white background for black, got black")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringerPalette(t *testing.T) {
|
||||
palette := newTestPalette()
|
||||
sp := createStringerPalette(false, false, palette)
|
||||
if len(sp) == 0 {
|
||||
t.Fatal("createStringerPalette returned empty palette")
|
||||
}
|
||||
result := sp.GetString("test")
|
||||
if result == "" {
|
||||
t.Fatal("GetString returned empty string")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDifferentInputsDifferentColors(t *testing.T) {
|
||||
palette := newTestPalette()
|
||||
type rgba struct{ r, g, b, a uint32 }
|
||||
colors := make(map[rgba]bool)
|
||||
inputs := []string{"alice", "bob", "charlie", "dave", "eve", "frank", "grace", "heidi"}
|
||||
for _, s := range inputs {
|
||||
c := StringToColor(palette, s)
|
||||
r, g, b, a := c.RGBA()
|
||||
colors[rgba{r, g, b, a}] = true
|
||||
}
|
||||
if len(colors) < 2 {
|
||||
t.Errorf("expected multiple distinct colors, got %d", len(colors))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user