WIP components (as built)
This commit is contained in:
96 files changed
+6468
-16
No files matched your search
@@ -0,0 +1,228 @@
|
||||
package mujica
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
)
|
||||
|
||||
// fileFS maps folders to entry names, with trailing directory slashes.
|
||||
var fileFS = map[string][]string{
|
||||
"/court": {"chronicles/", "decrees/", "seal.go", "notes.md"},
|
||||
"/court/chronicles": {"first.md", "second.md"},
|
||||
"/court/decrees": {"old/", "42.pdf"},
|
||||
"/court/decrees/old": {"7.pdf"},
|
||||
}
|
||||
|
||||
func fileFSOptions() FileExplorerOptions {
|
||||
return FileExplorerOptions{
|
||||
Roots: []string{"/court"},
|
||||
Folders: func(dir string) []string {
|
||||
var out []string
|
||||
for _, n := range fileFS[dir] {
|
||||
if strings.HasSuffix(n, "/") {
|
||||
out = append(out, path.Join(dir, strings.TrimSuffix(n, "/")))
|
||||
}
|
||||
}
|
||||
return out
|
||||
},
|
||||
Entries: func(dir string) []FileEntry {
|
||||
var out []FileEntry
|
||||
for _, n := range fileFS[dir] {
|
||||
name := strings.TrimSuffix(n, "/")
|
||||
out = append(out, FileEntry{Path: path.Join(dir, name), Name: name, Dir: name != n, Size: 2048})
|
||||
}
|
||||
return out
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type explorerProbe struct {
|
||||
s FileExplorerState
|
||||
opts FileExplorerOptions
|
||||
nav int
|
||||
opened []string
|
||||
}
|
||||
|
||||
func (p *explorerProbe) view(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
r := FileExplorer(c, &p.s, p.opts)
|
||||
r.Element.Height(380)
|
||||
if r.Navigated {
|
||||
p.nav++
|
||||
}
|
||||
if r.Opened != nil {
|
||||
p.opened = append(p.opened, r.Opened.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerOpenFolderAndHistory(t *testing.T) {
|
||||
p := &explorerProbe{opts: fileFSOptions()}
|
||||
tt := ui.NewTester(p.view, 720, 400)
|
||||
if p.s.Current != "/court" || !tt.HasText("seal.go") {
|
||||
t.Fatalf("start %q", p.s.Current)
|
||||
}
|
||||
rows := 0
|
||||
for _, s := range tt.Texts() {
|
||||
if s == "decrees" {
|
||||
rows++
|
||||
}
|
||||
}
|
||||
if rows != 2 {
|
||||
t.Fatalf("decrees shows %d times, want tree and list", rows)
|
||||
}
|
||||
// The list's decrees row is the one above seal.go.
|
||||
seal, _ := tt.Find("seal.go")
|
||||
tt.ClickAt(seal.X, seal.Y+seal.H/2-36)
|
||||
tt.ClickAt(seal.X, seal.Y+seal.H/2-36)
|
||||
if p.s.Current != "/court/decrees" || !tt.HasText("42.pdf") || p.nav != 1 {
|
||||
t.Fatalf("open folder: current %q nav %d", p.s.Current, p.nav)
|
||||
}
|
||||
if err := tt.Click("Back"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.s.Current != "/court" {
|
||||
t.Fatalf("back to %q", p.s.Current)
|
||||
}
|
||||
_ = tt.Click("Forward")
|
||||
if p.s.Current != "/court/decrees" {
|
||||
t.Fatalf("forward to %q", p.s.Current)
|
||||
}
|
||||
_ = tt.Click("Enclosing folder")
|
||||
if p.s.Current != "/court" {
|
||||
t.Fatalf("up to %q", p.s.Current)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerTreeAndOpenFile(t *testing.T) {
|
||||
p := &explorerProbe{opts: fileFSOptions()}
|
||||
tt := ui.NewTester(p.view, 720, 400)
|
||||
p.s.Navigate("/court/decrees/old")
|
||||
tt.Frame()
|
||||
if !tt.HasText("old") || !tt.HasText("7.pdf") {
|
||||
t.Fatalf("tree did not open the ancestors: %q", tt.Texts())
|
||||
}
|
||||
if sel, _ := p.s.tree.Selected(); sel != "/court/decrees/old" {
|
||||
t.Fatalf("tree chose %q", sel)
|
||||
}
|
||||
r, _ := tt.Find("7.pdf")
|
||||
tt.ClickAt(r.X, r.Y+r.H/2)
|
||||
tt.ClickAt(r.X, r.Y+r.H/2)
|
||||
if len(p.opened) != 1 || p.opened[0] != "/court/decrees/old/7.pdf" {
|
||||
t.Fatalf("opened %v", p.opened)
|
||||
}
|
||||
if got := p.s.Selected(); len(got) != 1 {
|
||||
t.Fatalf("selection %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerShortcutsAndDisabled(t *testing.T) {
|
||||
p := &explorerProbe{opts: fileFSOptions()}
|
||||
tt := ui.NewTester(p.view, 720, 400)
|
||||
p.s.Navigate("/court/chronicles")
|
||||
tt.Frame()
|
||||
tt.Key(0, ui.KeyTab)
|
||||
back, up := ui.Modifiers(ui.Alt), ui.Modifiers(ui.Alt)
|
||||
bk, uk := ui.KeyLeft, ui.KeyUp
|
||||
if runtime.GOOS == "darwin" {
|
||||
back, up, bk = ui.Super, ui.Super, ui.KeyBracketLeft
|
||||
}
|
||||
tt.Key(back, bk)
|
||||
if p.s.Current != "/court" {
|
||||
t.Fatalf("back shortcut gave %q", p.s.Current)
|
||||
}
|
||||
p.s.Navigate("/court/decrees/old")
|
||||
tt.Frame()
|
||||
tt.Key(up, uk)
|
||||
if p.s.Current != "/court/decrees" {
|
||||
t.Fatalf("up shortcut gave %q", p.s.Current)
|
||||
}
|
||||
p.opts.Disabled = true
|
||||
tt.Frame()
|
||||
_ = tt.Click("Back")
|
||||
if p.s.Current != "/court/decrees" {
|
||||
t.Fatal("disabled explorer moved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerSnapshot(t *testing.T) {
|
||||
snapshot(t, "file_explorer", 640, 300, func(c *ui.Context) {
|
||||
p := ui.Local(c.Root(), "snap", func() *explorerProbe {
|
||||
p := &explorerProbe{opts: fileFSOptions()}
|
||||
p.s.Navigate("/court/decrees")
|
||||
return p
|
||||
})
|
||||
ui.Column(c).Padding(12).Children(func() {
|
||||
FileExplorer(c, &(*p).s, (*p).opts).Element.Height(276)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestFileExplorerDisablingBeforeDeliveredKey(t *testing.T) {
|
||||
p := &explorerProbe{opts: fileFSOptions()}
|
||||
tt := ui.NewTester(p.view, 720, 400)
|
||||
if err := tt.Click("seal.go"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
before := p.s.Selected()
|
||||
p.opts.Disabled = true
|
||||
tt.Key(0, ui.KeyDown)
|
||||
after := p.s.Selected()
|
||||
if len(after) != len(before) || after[0] != before[0] {
|
||||
t.Fatalf("disabled selection %v, want %v", after, before)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerPrunesRemovedSelection(t *testing.T) {
|
||||
entries := []FileEntry{{Path: "/court/a.txt", Name: "a.txt"}, {Path: "/court/b.txt", Name: "b.txt"}}
|
||||
var s FileExplorerState
|
||||
opts := FileExplorerOptions{Roots: []string{"/court"}, Folders: func(string) []string { return nil }, Entries: func(string) []FileEntry { return entries }}
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
FileExplorer(c, &s, opts).Element.Height(380)
|
||||
}, 720, 400)
|
||||
if err := tt.Click("b.txt"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
entries = entries[:1]
|
||||
tt.Frame()
|
||||
if got := s.Selected(); len(got) != 0 {
|
||||
t.Fatalf("removed selection %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExplorerLargeAndRevision(t *testing.T) {
|
||||
entries := make([]FileEntry, 100000)
|
||||
for i := range entries {
|
||||
name := fmt.Sprintf("f-%d.txt", i)
|
||||
entries[i] = FileEntry{Path: "/court/" + name, Name: name}
|
||||
}
|
||||
var s FileExplorerState
|
||||
opts := FileExplorerOptions{Roots: []string{"/court"}, Folders: func(string) []string { return nil }, Entries: func(string) []FileEntry { return entries }}
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
Use(c, Settings{})
|
||||
FileExplorer(c, &s, opts).Element.Height(380)
|
||||
}, 720, 400)
|
||||
n := 0
|
||||
for _, text := range tt.Texts() {
|
||||
if strings.HasPrefix(text, "f-") {
|
||||
n++
|
||||
}
|
||||
}
|
||||
if n == 0 || n > 60 {
|
||||
t.Fatalf("built %d file labels", n)
|
||||
}
|
||||
if err := tt.Click("f-0.txt"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
entries[0].Path = "/court/replaced.txt"
|
||||
opts.Revision++
|
||||
tt.Frame()
|
||||
if got := s.Selected(); len(got) != 0 {
|
||||
t.Fatalf("replaced selection %v", got)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user