Files
MujicaUI/files/file_explorer_test.go
T

231 lines
6.2 KiB
Go

package files
import (
"fmt"
"path"
"runtime"
"strings"
"testing"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/core"
)
// 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) {
core.Use(c, core.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) {
core.Use(c, core.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) {
core.Use(c, core.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)
}
}