okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
3b601a9
main
1// Terminal color reply parsing and contrast across palettes cannot be 2// exercised by daemon E2E: they need a terminal that answers OSC queries, and 3// the e2e harness has no PTY. 4package tui 5 6import ( 7"math" 8"testing" 9) 10 11func hexColor (t * testing.T ,h string )rgb { 12c := parseColors ("\x1b]10;rgb:" + h [1 :3 ]+ "/" + h [3 :5 ]+ "/" + h [5 :7 ]+ "\x07" ).fg 13if c == nil { 14t .Fatalf ("could not parse %s" ,h ) 15 } 16return * c 17} 18 19func TestParseColorReplies (t * testing.T ) { 20c := parseColors ("\x1b]10;rgb:cdcd/d6d6/f4f4\x1b\\\x1b]11;rgb:1e/1e/2e\x07\x1b]4;4;rgb:8989/b4b4/fafa\x1b\\\x1b]4;5;rgb:f5f5/c2c2/e7e7\x1b\\\x1b[?62;22c" ) 21if _ ,blue := c .palette [ansiBlue ];c .fg == nil || c .bg == nil || ! blue || len (c .palette )!= 2 { 22t .Fatalf ("missing colors: %+v" ,c ) 23 } 24if got := c .fg .hex ();got != "#cdd6f4" { 25t .Fatalf ("fg %s" ,got ) 26 } 27if got := c .bg .hex ();got != "#1e1e2e" { 28t .Fatalf ("bg %s" ,got ) 29 } 30if got := parseColors ("\x1b[?62;22c" );got .fg != nil || got .bg != nil { 31t .Fatal ("a terminal that only answers device attributes reports no colors" ) 32 } 33} 34 35func TestInkHitsItsContrastTargets (t * testing.T ) { 36themes := map [string ][2 ]string { 37"mocha" : {"#cdd6f4" ,"#1e1e2e" }, 38"latte" : {"#4c4f69" ,"#eff1f5" }, 39"black" : {"#ffffff" ,"#000000" }, 40 } 41for name ,theme := range themes { 42fg ,bg := hexColor (t ,theme [0 ]),hexColor (t ,theme [1 ]) 43mixed ,ok := mixInk (termColors {fg :& fg ,bg :& bg }) 44if ! ok { 45t .Fatal ("colors were reported" ) 46 } 47for _ ,step := range []struct { 48hex string 49target float64 50 }{{mixed .code ,codeLc }, {mixed .secondary ,secondaryLc }, {mixed .decor ,decorLc }} { 51if got := apca (hexColor (t ,step .hex ),bg );math .Abs (got - step .target )> 1.5 { 52t .Errorf ("%s: %s has Lc %.1f, want %v" ,name ,step .hex ,got ,step .target ) 53 } 54 } 55 } 56soft ,bg := hexColor (t ,"#b3bbd7" ),hexColor (t ,"#1e1e2e" ) 57if mixed ,_ := mixInk (termColors {fg :& soft ,bg :& bg });mixed .code != soft .hex () { 58t .Fatalf ("text already under a target keeps its color, got %s" ,mixed .code ) 59 } 60black := hexColor (t ,"#000000" ) 61if _ ,ok := mixInk (termColors {fg :& black ,bg :& bg });ok { 62t .Fatal ("a text color barely apart from the background is not trusted" ) 63 } 64if _ ,ok := mixInk (termColors {});ok { 65t .Fatal ("no reply leaves the palette fallbacks in place" ) 66 } 67} 68 69func TestLanguageColorsReachTheirContrastOnEveryTheme (t * testing.T ) { 70colors := []string {"#00ADD8" ,"#3572A5" ,"#000080" ,"#f1e05a" ,"#555555" ,"#ffaff3" } 71for _ ,hex := range languageHues { 72colors = append (colors ,hex ) 73 } 74for _ ,bgHex := range []string {"#1e1e2e" ,"#eff1f5" ,"#000000" ,"#ffffff" } { 75bg := hexColor (t ,bgHex ) 76for _ ,hex := range colors { 77c := hexColor (t ,hex ) 78got := legible (c ,bg ,languageLc ) 79if lc := apca (got ,bg );lc < languageLc - 1 { 80t .Errorf ("%s on %s became %s with Lc %.1f, want %d" ,hex ,bgHex ,got .hex (),lc ,languageLc ) 81 } 82if apca (c ,bg )>= languageLc && got != c { 83t .Errorf ("%s is legible on %s and should stay, got %s" ,hex ,bgHex ,got .hex ()) 84 } 85 } 86 } 87}