Add gallery core and command: routes, sidebar, search, code panel, browser hook
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
727de5f110
commit
ff50f9b35a
10 files changed
+750
-2
No files matched your search
@@ -0,0 +1,185 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user