Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
186 lines
4.9 KiB
Go
186 lines
4.9 KiB
Go
package gallery
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"testing/fstest"
|
|
"time"
|
|
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/CrychicUI/icon"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/CrychicUI/sound"
|
|
"github.com/egoist/mygo/ui"
|
|
)
|
|
|
|
func pingDemo(c *ui.Context, log func(string)) {
|
|
if ui.Button(c, "Ping").Clicked() {
|
|
log("pinged")
|
|
}
|
|
}
|
|
|
|
var pingEntry = Entry{ID: 1, Name: "PingBox", Category: "layout", Summary: "Answers a ping.", Demo: pingDemo}
|
|
|
|
// withEntry registers pingEntry for one test.
|
|
func withEntry(t *testing.T) {
|
|
t.Helper()
|
|
old, oldCode := entries, codes["pingDemo"]
|
|
entries, codes["pingDemo"] = []Entry{pingEntry}, "func pingDemo() {}\n"
|
|
t.Cleanup(func() { entries, codes["pingDemo"] = old, oldCode })
|
|
}
|
|
|
|
func open(path string) (*App, *ui.Tester) {
|
|
a := New(path)
|
|
return a, ui.NewTester(a.View, 1280, 820)
|
|
}
|
|
|
|
func TestHome(t *testing.T) {
|
|
withEntry(t)
|
|
a, tt := open("/")
|
|
for _, s := range []string{"Components", "Categories", "Sound cues", "Layout", "Geo", "1 components"} {
|
|
if !tt.HasText(s) {
|
|
t.Errorf("home lacks %q", s)
|
|
}
|
|
}
|
|
if s := a.Snapshot(); !s.Built || s.Page != "/" {
|
|
t.Errorf("snapshot %+v", s)
|
|
}
|
|
if err := tt.Click("Layout"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tt.Advance(time.Second)
|
|
if a.Snapshot().Page != "/c/layout" || !tt.HasText("PingBox") {
|
|
t.Errorf("page %q, texts %q", a.Snapshot().Page, tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestComponentPage(t *testing.T) {
|
|
withEntry(t)
|
|
a, tt := open(pingEntry.Path())
|
|
for _, s := range []string{"PingBox", "Answers a ping.", "0001 · layout", "Code"} {
|
|
if !tt.HasText(s) {
|
|
t.Errorf("page lacks %q", s)
|
|
}
|
|
}
|
|
if got := a.codes[pingEntry.Path()].Buffer.String(); got != codes["pingDemo"] {
|
|
t.Errorf("code = %q", got)
|
|
}
|
|
if err := tt.Click("Ping"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !tt.HasText("PingBox: pinged") {
|
|
t.Errorf("log strip lacks the event: %q", tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestNotFound(t *testing.T) {
|
|
withEntry(t)
|
|
for _, p := range []string{"/c/nope", "/c/layout/nope", "/x"} {
|
|
if _, tt := open(p); !tt.HasText("Not found") {
|
|
t.Errorf("%s: no Not found", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSearch(t *testing.T) {
|
|
withEntry(t)
|
|
a, tt := open("/")
|
|
a.query = "ping"
|
|
tt.Frame()
|
|
if !tt.HasText("1 results") {
|
|
t.Fatalf("texts %q", tt.Texts())
|
|
}
|
|
if err := tt.Click("PingBox"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tt.Advance(time.Second)
|
|
if a.query != "" || a.Snapshot().Page != pingEntry.Path() {
|
|
t.Errorf("query %q, page %q", a.query, a.Snapshot().Page)
|
|
}
|
|
}
|
|
|
|
func TestAppearance(t *testing.T) {
|
|
_, tt := open("/")
|
|
px := func() ui.Color { p := tt.Image().RGBAAt(1200, 400); return ui.Color{R: p.R, G: p.G, B: p.B, A: 255} }
|
|
if err := tt.Click("Dark"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tt.Advance(time.Second)
|
|
if got, want := px(), ui.DarkTheme().Background; got.R != want.R || got.G != want.G || got.B != want.B {
|
|
t.Errorf("dark background %v, want %v", got, want)
|
|
}
|
|
if err := tt.Click("Light"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tt.Advance(time.Second)
|
|
if got, want := px(), ui.LightTheme().Background; got.R != want.R || got.G != want.G || got.B != want.B {
|
|
t.Errorf("light background %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSoundSwitch(t *testing.T) {
|
|
t.Cleanup(func() { sound.SetEnabled(false) })
|
|
_, tt := open("/")
|
|
if err := tt.Click("Sound"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !sound.Enabled() {
|
|
t.Fatal("switch did not enable sound")
|
|
}
|
|
if err := tt.Click("Sound"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if sound.Enabled() {
|
|
t.Error("switch did not mute sound")
|
|
}
|
|
}
|
|
|
|
func TestCueStrip(t *testing.T) {
|
|
sound.Play(sound.Success)
|
|
if _, tt := open("/"); !strings.Contains(strings.Join(tt.Texts(), " "), "success") {
|
|
t.Errorf("cue strip lacks success: %q", tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestSources(t *testing.T) {
|
|
raw := "func demoR() string {\n\treturn `a\n}\nb`\n}"
|
|
got := sources(fstest.MapFS{"demos_x.go": {Data: []byte(
|
|
"package gallery\r\n\r\n// A doc.\r\nfunc demoA(c int) {\r\n\tx()\r\n}\r\n\r\nfunc demoB() { x() }\r\n\r\n" +
|
|
"func (e Entry) M() {\r\n}\r\n\r\n" + strings.ReplaceAll(raw, "\n", "\r\n") + "\r\n")}})
|
|
want := map[string]string{"demoA": "func demoA(c int) {\n\tx()\n}", "demoB": "func demoB() { x() }", "demoR": raw}
|
|
if len(got) != len(want) {
|
|
t.Errorf("sources = %q", got)
|
|
}
|
|
for k, v := range want {
|
|
if got[k] != v {
|
|
t.Errorf("%s = %q, want %q", k, got[k], v)
|
|
}
|
|
}
|
|
defer func() {
|
|
if recover() == nil {
|
|
t.Error("broken file did not panic")
|
|
}
|
|
}()
|
|
sources(fstest.MapFS{"demos_y.go": {Data: []byte("package gallery\nfunc demoB() {\n")}})
|
|
}
|
|
|
|
func TestSlug(t *testing.T) {
|
|
for in, want := range map[string]string{"Stack": "stack", "KPIGrid": "kpi-grid", "Base64Tool": "base64-tool"} {
|
|
if got := (Entry{Name: in}).Slug(); got != want {
|
|
t.Errorf("slug(%s) = %s, want %s", in, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCategories(t *testing.T) {
|
|
seen := map[string]bool{}
|
|
for _, k := range Categories {
|
|
icon.Must(k.Icon)
|
|
if seen[k.Key] {
|
|
t.Errorf("category %s twice", k.Key)
|
|
}
|
|
seen[k.Key] = true
|
|
}
|
|
if len(Categories) != 38 {
|
|
t.Errorf("categories = %d, want 38", len(Categories))
|
|
}
|
|
}
|