From df33164b0823636d76db7b79e3e1e46e007e360a Mon Sep 17 00:00:00 2001 From: noe Date: Sun, 6 Apr 2025 17:28:26 -0700 Subject: [PATCH] catch mid colors outside of WCAG AA --- auth/authmiddleware/must_test.go | 2 +- auth/authmiddleware/session.go | 2 +- auth/authmiddleware/util_test.go | 4 +- auth/authmiddleware/validation_test.go | 2 +- auth/discordauth.go | 1 + default.nix | 2 +- discord/discord_client.go | 3 +- go.mod | 1 - go.sum | 2 - interactions/interactions_test.go | 2 +- interactions/utils_test.go | 2 +- interactions/verify_test.go | 2 +- justfile | 2 +- presentation/role.go | 10 ++--- presentation/role_test.go | 4 +- roleypoly/fiber.go | 3 -- static/images/x.svg | 4 ++ static/main.css | 5 ++- templates/components/role.html | 2 +- templates/components/role_test.go | 15 ++----- templates/layouts/main.html | 2 +- templates/testing/templates.go | 14 +++++++ templates/testing/templates_test.go | 7 ++++ templates/tests/picker.html | 6 +-- testing/testing.go | 8 ++-- types/fixtures/role.go | 20 ++++++++-- utils/colors.go | 54 +++++++++++++++++++------- utils/colors_test.go | 50 ++++++++++-------------- 28 files changed, 135 insertions(+), 96 deletions(-) create mode 100644 static/images/x.svg create mode 100644 templates/testing/templates.go create mode 100644 templates/testing/templates_test.go diff --git a/auth/authmiddleware/must_test.go b/auth/authmiddleware/must_test.go index 20122d3..b678cb8 100644 --- a/auth/authmiddleware/must_test.go +++ b/auth/authmiddleware/must_test.go @@ -3,7 +3,7 @@ package authmiddleware_test import ( "testing" - "git.sapphic.engineer/roleypoly/v4/authmiddleware" + "git.sapphic.engineer/roleypoly/v4/auth/authmiddleware" "git.sapphic.engineer/roleypoly/v4/discord/clientmock" "git.sapphic.engineer/roleypoly/v4/types" "git.sapphic.engineer/roleypoly/v4/types/fixtures" diff --git a/auth/authmiddleware/session.go b/auth/authmiddleware/session.go index 34325bd..ec3e9b9 100644 --- a/auth/authmiddleware/session.go +++ b/auth/authmiddleware/session.go @@ -1,11 +1,11 @@ package authmiddleware import ( + "encoding/json" "log" "time" "git.sapphic.engineer/roleypoly/v4/types" - "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/session" ) diff --git a/auth/authmiddleware/util_test.go b/auth/authmiddleware/util_test.go index b77099b..79e8dcb 100644 --- a/auth/authmiddleware/util_test.go +++ b/auth/authmiddleware/util_test.go @@ -2,16 +2,16 @@ package authmiddleware_test import ( "bytes" + "encoding/json" "errors" "net/http" "testing" - "git.sapphic.engineer/roleypoly/v4/authmiddleware" + "git.sapphic.engineer/roleypoly/v4/auth/authmiddleware" "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/discord/clientmock" "git.sapphic.engineer/roleypoly/v4/roleypoly" "git.sapphic.engineer/roleypoly/v4/types" - "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/session" "github.com/stretchr/testify/assert" diff --git a/auth/authmiddleware/validation_test.go b/auth/authmiddleware/validation_test.go index 20aaa7f..7ccbe20 100644 --- a/auth/authmiddleware/validation_test.go +++ b/auth/authmiddleware/validation_test.go @@ -3,7 +3,7 @@ package authmiddleware_test import ( "testing" - "git.sapphic.engineer/roleypoly/v4/authmiddleware" + "git.sapphic.engineer/roleypoly/v4/auth/authmiddleware" "git.sapphic.engineer/roleypoly/v4/discord/clientmock" "git.sapphic.engineer/roleypoly/v4/types/fixtures" "github.com/stretchr/testify/assert" diff --git a/auth/discordauth.go b/auth/discordauth.go index e69de29..8832b06 100644 --- a/auth/discordauth.go +++ b/auth/discordauth.go @@ -0,0 +1 @@ +package auth diff --git a/default.nix b/default.nix index 1ff83fa..5e3cbbb 100644 --- a/default.nix +++ b/default.nix @@ -1,6 +1,6 @@ { pkgs ? import {}, - vendorHash ? "sha256-ilEuRNE61UN22Jm6Yyv80S6VdRa1mB6J/Pde1x/DgEk=", + vendorHash ? "sha256-19z+/CD45jtKSCOooCQaVX4YvMFSp+aDaUIXlLMPLkA=", }: rec { default = roleypoly; diff --git a/discord/discord_client.go b/discord/discord_client.go index 7eb7c8b..2bdd6e0 100644 --- a/discord/discord_client.go +++ b/discord/discord_client.go @@ -1,13 +1,12 @@ package discord import ( + "encoding/json" "errors" "fmt" "net/http" "net/url" "time" - - "github.com/goccy/go-json" ) const DiscordBaseUrl = "https://discord.com/api/v10" diff --git a/go.mod b/go.mod index 287f903..c0a23cd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module git.sapphic.engineer/roleypoly/v4 go 1.24.1 require ( - github.com/goccy/go-json v0.10.5 github.com/gofiber/fiber/v3 v3.0.0-beta.4 github.com/gofiber/template/html/v2 v2.1.3 github.com/stretchr/testify v1.10.0 diff --git a/go.sum b/go.sum index 8543bfb..0325c88 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofiber/fiber/v3 v3.0.0-beta.4 h1:KzDSavvhG7m81NIsmnu5l3ZDbVS4feCidl4xlIfu6V0= github.com/gofiber/fiber/v3 v3.0.0-beta.4/go.mod h1:/WFUoHRkZEsGHyy2+fYcdqi109IVOFbVwxv1n1RU+kk= github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg= diff --git a/interactions/interactions_test.go b/interactions/interactions_test.go index 0aac146..5f8af60 100644 --- a/interactions/interactions_test.go +++ b/interactions/interactions_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/ed25519" "encoding/hex" + "encoding/json" "net/http" "testing" @@ -11,7 +12,6 @@ import ( "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/interactions" "git.sapphic.engineer/roleypoly/v4/roleypoly" - "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/session" "github.com/stretchr/testify/assert" diff --git a/interactions/utils_test.go b/interactions/utils_test.go index 4a5e03e..a9c9cd8 100644 --- a/interactions/utils_test.go +++ b/interactions/utils_test.go @@ -5,6 +5,7 @@ import ( "crypto" "crypto/ed25519" "encoding/hex" + "encoding/json" "net/http" "testing" "time" @@ -13,7 +14,6 @@ import ( "git.sapphic.engineer/roleypoly/v4/discord/clientmock" "git.sapphic.engineer/roleypoly/v4/interactions" "git.sapphic.engineer/roleypoly/v4/types/fixtures" - "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" "github.com/stretchr/testify/assert" ) diff --git a/interactions/verify_test.go b/interactions/verify_test.go index 940015b..9a29f4d 100644 --- a/interactions/verify_test.go +++ b/interactions/verify_test.go @@ -3,9 +3,9 @@ package interactions_test import ( "crypto/ed25519" "encoding/hex" + "encoding/json" "testing" - "github.com/goccy/go-json" "github.com/stretchr/testify/assert" ) diff --git a/justfile b/justfile index 268eea8..d8d2885 100644 --- a/justfile +++ b/justfile @@ -18,7 +18,7 @@ fmt: go fmt ./... prettier: - prettier -w -c **/*.{css,html,json,md} + prettier -w -c "**/*.{css,json,md}" tidy: go mod tidy diff --git a/presentation/role.go b/presentation/role.go index 9769d5c..2ce89ae 100644 --- a/presentation/role.go +++ b/presentation/role.go @@ -40,9 +40,8 @@ func Role(category *types.Category, role *types.Role, selected bool) Presentable } type PresentableRoleColors struct { - Main string - Alt string - IsDark bool + Main string + Alt string } func GetColors(roleColor uint32) PresentableRoleColors { @@ -52,8 +51,7 @@ func GetColors(roleColor uint32) PresentableRoleColors { altR, altG, altB := utils.AltColor(r, g, b) return PresentableRoleColors{ - Main: utils.RgbToString(r, g, b), - Alt: utils.RgbToString(altR, altG, altB), - IsDark: utils.IsDarkColor(r, g, b), + Main: utils.RgbToString(r, g, b), + Alt: utils.RgbToString(altR, altG, altB), } } diff --git a/presentation/role_test.go b/presentation/role_test.go index fdc1c14..5f00843 100644 --- a/presentation/role_test.go +++ b/presentation/role_test.go @@ -14,7 +14,6 @@ func TestRole(t *testing.T) { assert.Equal(t, fixtures.RoleWithDarkColor.Name, r.Name) assert.Equal(t, presentation.InputCheckbox, r.InputType) assert.Equal(t, "#a20000", r.Colors.Main) - assert.True(t, r.Colors.IsDark) assert.True(t, r.Selected) r = presentation.Role(&fixtures.CategorySingle, &fixtures.RoleWithDarkColor, false) @@ -22,12 +21,11 @@ func TestRole(t *testing.T) { assert.False(t, r.Selected) r = presentation.Role(&fixtures.CategorySingle, &fixtures.RoleWithLightColor, true) - assert.False(t, r.Colors.IsDark) assert.True(t, r.Selected) } func TestGetColors(t *testing.T) { c := presentation.GetColors(0xa20000) assert.Equal(t, "#a20000", c.Main) - assert.True(t, c.IsDark) + assert.Equal(t, "#ffd8d8", c.Alt) } diff --git a/roleypoly/fiber.go b/roleypoly/fiber.go index 669ee6e..88d3bb7 100644 --- a/roleypoly/fiber.go +++ b/roleypoly/fiber.go @@ -6,7 +6,6 @@ import ( "strings" "time" - "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/csrf" "github.com/gofiber/fiber/v3/middleware/session" @@ -26,8 +25,6 @@ func CreateFiberApp() *fiber.App { viewEngine := html.NewFileSystem(http.FS(templates.FS), ".html") app := fiber.New(fiber.Config{ - JSONEncoder: json.Marshal, - JSONDecoder: json.Unmarshal, Views: viewEngine, ViewsLayout: "layouts/main", }) diff --git a/static/images/x.svg b/static/images/x.svg new file mode 100644 index 0000000..5d1a758 --- /dev/null +++ b/static/images/x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/main.css b/static/main.css index b3ace6b..aa897c0 100644 --- a/static/main.css +++ b/static/main.css @@ -41,8 +41,8 @@ body { border: 2px solid var(--role-color); border-radius: 3px; user-select: none; - padding: 0.217rem; /* this is silly number pls ignore :3 (^noe) */ - gap: 0.215rem; + padding: 0.369rem; /* this is silly number pls ignore :3 (^noe) */ + gap: 0.269rem; cursor: pointer; transition: all 0.35s ease-in-out; @@ -84,6 +84,7 @@ body { label { cursor: pointer; + font-weight: 600; } &:has(input:checked) { diff --git a/templates/components/role.html b/templates/components/role.html index f65b1db..7e2f5bd 100644 --- a/templates/components/role.html +++ b/templates/components/role.html @@ -2,7 +2,7 @@
diff --git a/templates/components/role_test.go b/templates/components/role_test.go index 897c9c1..779a0fd 100644 --- a/templates/components/role_test.go +++ b/templates/components/role_test.go @@ -35,9 +35,9 @@ func TestRole(t *testing.T) { assert.Contains(t, html, "--role-color: #a20000;", "role color is set") assert.Contains(t, html, `type="checkbox"`, "multi has input type=checkbox") assert.Contains(t, html, fmt.Sprintf("--contrast-color: %s;", utils.RgbToString(utils.AltColor(162, 0, 0))), "contrast color is set") - assert.Contains(t, html, fmt.Sprintf(`id="%s"`, roleInputID(c, r)), "input has ID attr") - assert.Contains(t, html, fmt.Sprintf(`for="%s"`, roleInputID(c, r)), "label has for attr") - assert.NotContains(t, html, fmt.Sprintf(`name="%s"`, roleInputName(c)), "multi has no name attr") + assert.Contains(t, html, fmt.Sprintf(`id="%s"`, utils.RoleInputID(c, r)), "input has ID attr") + assert.Contains(t, html, fmt.Sprintf(`for="%s"`, utils.RoleInputID(c, r)), "label has for attr") + assert.NotContains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c)), "multi has no name attr") // TODO: selected? c = &fixtures.CategorySingle @@ -45,14 +45,7 @@ func TestRole(t *testing.T) { html = renderRole(t, c, r, true) assert.Contains(t, html, `type="radio"`, "single has input type=radio") assert.Contains(t, html, fmt.Sprintf("--contrast-color: %s;", utils.RgbToString(utils.AltColor(0xff, 0xaa, 0x88))), "contrast color") - assert.Contains(t, html, fmt.Sprintf(`name="%s"`, roleInputName(c)), "single has name attr") + assert.Contains(t, html, fmt.Sprintf(`name="%s"`, utils.RoleInputName(c)), "single has name attr") } // TODO: these can probably be string utils that are injected as functions into template -func roleInputID(c *types.Category, r *types.Role) string { - return fmt.Sprintf("category-%s_role-%s", c.ID, r.ID) -} - -func roleInputName(c *types.Category) string { - return fmt.Sprintf("category_group_%s", c.ID) -} diff --git a/templates/layouts/main.html b/templates/layouts/main.html index 06f98da..0617048 100644 --- a/templates/layouts/main.html +++ b/templates/layouts/main.html @@ -5,7 +5,7 @@ {{ .HeadTitle }} diff --git a/templates/testing/templates.go b/templates/testing/templates.go new file mode 100644 index 0000000..823d4a7 --- /dev/null +++ b/templates/testing/templates.go @@ -0,0 +1,14 @@ +// Package testing provides test helpers that support fiber templates +package testing + +import ( + "html/template" + + "git.sapphic.engineer/roleypoly/v4/templates" +) + +var ( + Templates = template.Must(template.ParseFS(templates.FS, "*.html")).Funcs(template.FuncMap{ + "embed": func() {}, + }) +) diff --git a/templates/testing/templates_test.go b/templates/testing/templates_test.go new file mode 100644 index 0000000..4568c0f --- /dev/null +++ b/templates/testing/templates_test.go @@ -0,0 +1,7 @@ +package testing_test + +// func Test(t *testing.T) { + +// } + +// TODO: test the template tester diff --git a/templates/tests/picker.html b/templates/tests/picker.html index 01599fb..16575b0 100644 --- a/templates/tests/picker.html +++ b/templates/tests/picker.html @@ -7,10 +7,10 @@
{{ template "components/role" .TestRole }} {{ template "components/role" - .TestRole2 }} + .TestRole2 }} {{ template "components/role" .TestRole3 }}
- {{ template "components/role" .TestRole3 }} {{ template "components/role" - .TestRole4 }} + {{ template "components/role" .TestRole4 }} {{ template "components/role" + .TestRole5 }} {{ template "components/role" .TestRole6 }}
diff --git a/testing/testing.go b/testing/testing.go index dcd59f2..b6514c7 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -40,9 +40,11 @@ func (t *TestingController) TestTemplate(c fiber.Ctx) error { cat2 := fixtures.Category(fixtures.CategorySingle) return c.Render("tests/"+which, fiber.Map{ "TestRole": presentation.Role(cat1, &fixtures.RoleWithDarkColor, false), - "TestRole2": presentation.Role(cat1, &fixtures.RoleWithLightColor, true), - "TestRole3": presentation.Role(cat2, &fixtures.RoleWithDarkColor, false), - "TestRole4": presentation.Role(cat2, &fixtures.RoleWithLightColor, true), + "TestRole2": presentation.Role(cat1, &fixtures.RoleWithDarkMediumColor, false), + "TestRole3": presentation.Role(cat1, &fixtures.RoleWithLightColor, true), + "TestRole4": presentation.Role(cat1, &fixtures.RoleWithDarkColor, false), + "TestRole5": presentation.Role(cat2, &fixtures.RoleWithLightColor, true), + "TestRole6": presentation.Role(cat1, &fixtures.RoleWithLightMediumColor, false), }, "layouts/main") } diff --git a/types/fixtures/role.go b/types/fixtures/role.go index 9abbe30..9f3b592 100644 --- a/types/fixtures/role.go +++ b/types/fixtures/role.go @@ -5,17 +5,31 @@ import "git.sapphic.engineer/roleypoly/v4/types" var ( RoleWithDarkColor = types.Role{ ID: "dark-color", - Name: "role with dark color", + Name: "dark", Color: 0xa20000, Permissions: 0, Position: 10, } + RoleWithDarkMediumColor = types.Role{ + ID: "dark-medium-color", + Name: "dark medium", + Color: 0xeb5e4b, + Permissions: 0, + Position: 11, + } + RoleWithLightMediumColor = types.Role{ + ID: "light-medium-color", + Name: "light medium", + Color: 0xfa8373, + Permissions: 0, + Position: 11, + } RoleWithLightColor = types.Role{ ID: "light-color", - Name: "role with light color", + Name: "light", Color: 0xffaa88, Permissions: 0, - Position: 10, + Position: 12, } RoleWithoutColor = types.Role{ ID: "without-color", diff --git a/utils/colors.go b/utils/colors.go index da0ea16..a2bc97f 100644 --- a/utils/colors.go +++ b/utils/colors.go @@ -2,6 +2,7 @@ package utils import ( "fmt" + "log" "math" ) @@ -11,11 +12,10 @@ const ( Pblue float64 = 0.114 ) -func IsDarkColor(r, g, b uint8) bool { - lum := Luminance(r, g, b) - - return lum <= 130 -} +var ( + DarkAltFallback = []uint8{0x1c, 0x10, 0x10} + LightAltFallback = []uint8{0xf2, 0xef, 0xef} +) func IntToRgb(color uint32) (uint8, uint8, uint8) { b := color % 256 @@ -30,11 +30,30 @@ func RgbToString(r, g, b uint8) string { } func AltColor(r, g, b uint8) (uint8, uint8, uint8) { + l1 := Luminance(r, g, b) + isDark := l1 <= 0.5098 + brightnessAmount := -0.6 - if IsDarkColor(r, g, b) { + if isDark { // color is dark brightnessAmount = 0.85 } - return Brighten(r, g, b, brightnessAmount) + + r2, g2, b2 := Brighten(r, g, b, brightnessAmount) + + l2 := Luminance(r2, g2, b2) + ratio := WCAGRatio(l1, l2) + + log.Printf("isDark=%v, ratio: %f, l1(%f)=%s, l2(%f)=%s", isDark, ratio, l1, RgbToString(r, g, b), l2, RgbToString(r2, g2, b2)) + + if ratio >= 3 { + return r2, g2, b2 + } + + if isDark { + return LightAltFallback[0], LightAltFallback[1], LightAltFallback[2] + } else { + return DarkAltFallback[0], DarkAltFallback[1], DarkAltFallback[3] + } } func Brighten(r, g, b uint8, amount float64) (uint8, uint8, uint8) { @@ -53,18 +72,23 @@ func multiply(i uint8, amount float64) uint8 { ) } +func sRGB(c uint8) float64 { + cf := float64(c) / 255 + if cf <= 0.03928 { + return cf / 12.92 + } else { + return math.Pow((cf+0.055)/1.055, 2.4) + } +} + func Luminance(r, g, b uint8) float64 { - rC := Pred * math.Pow(float64(r), 2) - gC := Pgreen * math.Pow(float64(g), 2) - bC := Pblue * math.Pow(float64(b), 2) + rC := Pred * math.Pow(sRGB(r), 2) + gC := Pgreen * math.Pow(sRGB(g), 2) + bC := Pblue * math.Pow(sRGB(b), 2) return math.Sqrt(rC + gC + bC) } func WCAGRatio(l1, l2 float64) float64 { - if l1 < l2 { - return (l1 + 0.05) / (l2 + 0.05) - } else { - return (l2 + 0.05) / (l1 + 0.05) - } + return (math.Max(l1, l2) + 0.05) / (math.Min(l1, l2) + 0.05) } diff --git a/utils/colors_test.go b/utils/colors_test.go index b76fd78..0eb2d49 100644 --- a/utils/colors_test.go +++ b/utils/colors_test.go @@ -8,8 +8,7 @@ import ( ) const ( - WCAGAAA float64 = 0.14285714285714285 - WCAGAA float64 = 0.25 + WCAGAA float64 = 3 ) func TestIntToRgb(t *testing.T) { @@ -19,38 +18,20 @@ func TestIntToRgb(t *testing.T) { assert.Equal(t, uint8(0x56), b, "blue") } -func TestIsDarkColor(t *testing.T) { - isDark := utils.IsDarkColor(0, 0, 0) - assert.True(t, isDark) - - isLight := utils.IsDarkColor(255, 255, 255) - assert.False(t, isLight) - - isQuestionable := utils.IsDarkColor(0x88, 0x88, 0x88) - assert.False(t, isQuestionable) - - isReallyQuestionable := utils.IsDarkColor(0x00, 0x88, 0x00) - assert.True(t, isReallyQuestionable) -} - func TestBrighten(t *testing.T) { r, g, b := utils.Brighten(0, 0, 0, 0.1) assert.Equal(t, uint8(0x19), r) assert.Equal(t, uint8(0x19), g) assert.Equal(t, uint8(0x19), b) - // assert.LessOrEqual(t, WCAGAA, utils.WCAGRatio( - // utils.Luminance(0, 0, 0), - // utils.Luminance(r, g, b), - // )) r, g, b = utils.Brighten(0x88, 0x88, 0x88, -0.1) assert.Equal(t, uint8(0x88-0x19-1), r) assert.Equal(t, uint8(0x88-0x19-1), g) assert.Equal(t, uint8(0x88-0x19-1), b) - // assert.LessOrEqual(t, WCAGAA, utils.WCAGRatio( - // utils.Luminance(0x88, 0x88, 0x88), - // utils.Luminance(r, g, b), - // )) + assert.GreaterOrEqual(t, utils.WCAGRatio( + utils.Luminance(0x88, 0x88, 0x88), + utils.Luminance(r, g, b), + ), WCAGAA) } func TestRgbToString(t *testing.T) { @@ -59,12 +40,21 @@ func TestRgbToString(t *testing.T) { func TestAltColor(t *testing.T) { r, g, b := utils.AltColor(0xa2, 0xc2, 0x42) - assert.Equal(t, uint8(0x09), r, "red") - assert.Equal(t, uint8(0x29), g, "green") - assert.Equal(t, uint8(0x00), b, "blue") + assert.Equal(t, uint8(0xf2), r, "red") + assert.Equal(t, uint8(0xef), g, "green") + assert.Equal(t, uint8(0xef), b, "blue") + assert.GreaterOrEqual(t, utils.WCAGRatio( + utils.Luminance(0xa2, 0xc2, 0x42), + utils.Luminance(r, g, b), + ), WCAGAA) r, g, b = utils.AltColor(0xa2, 0x15, 0x18) - assert.Equal(t, uint8(0xff), r, "red") - assert.Equal(t, uint8(0xed), g, "green") - assert.Equal(t, uint8(0xf0), b, "blue") + assert.Equal(t, uint8(0xff), r, "red2") + assert.Equal(t, uint8(0xed), g, "green2") + assert.Equal(t, uint8(0xf0), b, "blue2") + assert.GreaterOrEqual(t, utils.WCAGRatio( + utils.Luminance(0xa2, 0x15, 0x18), + utils.Luminance(r, g, b), + ), WCAGAA) + }