github.com/elves/elvish@v0.15.0/pkg/cli/addons/location/location_test.go (about) 1 package location 2 3 import ( 4 "errors" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "testing" 10 11 "github.com/elves/elvish/pkg/cli" 12 . "github.com/elves/elvish/pkg/cli/clitest" 13 "github.com/elves/elvish/pkg/cli/term" 14 "github.com/elves/elvish/pkg/store" 15 "github.com/elves/elvish/pkg/testutil" 16 "github.com/elves/elvish/pkg/ui" 17 ) 18 19 type testStore struct { 20 storedDirs []store.Dir 21 dirsError error 22 chdir func(dir string) error 23 wd string 24 } 25 26 func (ts testStore) Dirs(blacklist map[string]struct{}) ([]store.Dir, error) { 27 dirs := []store.Dir{} 28 for _, dir := range ts.storedDirs { 29 if _, ok := blacklist[dir.Path]; ok { 30 continue 31 } 32 dirs = append(dirs, dir) 33 } 34 return dirs, ts.dirsError 35 } 36 37 func (ts testStore) Chdir(dir string) error { 38 if ts.chdir == nil { 39 return nil 40 } 41 return ts.chdir(dir) 42 } 43 44 func (ts testStore) Getwd() (string, error) { 45 return ts.wd, nil 46 } 47 48 func TestStart_NoStore(t *testing.T) { 49 f := Setup() 50 defer f.Stop() 51 52 Start(f.App, Config{}) 53 54 f.TestTTYNotes(t, "no dir history store") 55 } 56 57 func TestStart_StoreError(t *testing.T) { 58 f := Setup() 59 defer f.Stop() 60 61 Start(f.App, Config{Store: testStore{dirsError: errors.New("ERROR")}}) 62 63 f.TestTTYNotes(t, "db error: ERROR") 64 } 65 66 func TestStart_Hidden(t *testing.T) { 67 f := Setup() 68 defer f.Stop() 69 70 dirs := []store.Dir{ 71 {Path: fix("/usr/bin"), Score: 200}, 72 {Path: fix("/usr"), Score: 100}, 73 {Path: fix("/tmp"), Score: 50}, 74 } 75 Start(f.App, Config{ 76 Store: testStore{storedDirs: dirs}, 77 IterateHidden: func(f func(string)) { f(fix("/usr")) }, 78 }) 79 // Test UI. 80 wantBuf := listingBuf( 81 "", 82 "200 "+fix("/usr/bin"), "<- selected", 83 " 50 "+fix("/tmp")) 84 f.TTY.TestBuffer(t, wantBuf) 85 } 86 87 func TestStart_Pinned(t *testing.T) { 88 f := Setup() 89 defer f.Stop() 90 91 dirs := []store.Dir{ 92 {Path: fix("/usr/bin"), Score: 200}, 93 {Path: fix("/usr"), Score: 100}, 94 {Path: fix("/tmp"), Score: 50}, 95 } 96 Start(f.App, Config{ 97 Store: testStore{storedDirs: dirs}, 98 IteratePinned: func(f func(string)) { f(fix("/home")); f(fix("/usr")) }, 99 }) 100 // Test UI. 101 wantBuf := listingBuf( 102 "", 103 " * "+fix("/home"), "<- selected", 104 " * "+fix("/usr"), 105 "200 "+fix("/usr/bin"), 106 " 50 "+fix("/tmp")) 107 f.TTY.TestBuffer(t, wantBuf) 108 } 109 110 func TestStart_HideWd(t *testing.T) { 111 f := Setup() 112 defer f.Stop() 113 114 dirs := []store.Dir{ 115 {Path: fix("/home"), Score: 200}, 116 {Path: fix("/tmp"), Score: 50}, 117 } 118 Start(f.App, Config{Store: testStore{storedDirs: dirs, wd: fix("/home")}}) 119 // Test UI. 120 wantBuf := listingBuf( 121 "", 122 " 50 "+fix("/tmp"), "<- selected") 123 f.TTY.TestBuffer(t, wantBuf) 124 } 125 126 func TestStart_Workspace(t *testing.T) { 127 f := Setup() 128 defer f.Stop() 129 130 chdir := "" 131 dirs := []store.Dir{ 132 {Path: fix("home/src"), Score: 200}, 133 {Path: fix("ws1/src"), Score: 150}, 134 {Path: fix("ws2/bin"), Score: 100}, 135 {Path: fix("/tmp"), Score: 50}, 136 } 137 Start(f.App, Config{ 138 Store: testStore{ 139 storedDirs: dirs, 140 wd: fix("/home/elf/bin"), 141 chdir: func(dir string) error { 142 chdir = dir 143 return nil 144 }, 145 }, 146 IterateWorkspaces: func(f func(kind, pattern string) bool) { 147 if runtime.GOOS == "windows" { 148 // Invalid patterns are ignored. 149 f("ws1", `C:\\usr\\[^\\+`) 150 f("home", `C:\\home\\[^\\]+`) 151 f("ws2", `C:\\tmp\[^\]+`) 152 } else { 153 // Invalid patterns are ignored. 154 f("ws1", "/usr/[^/+") 155 f("home", "/home/[^/]+") 156 f("ws2", "/tmp/[^/]+") 157 } 158 }, 159 }) 160 161 wantBuf := listingBuf( 162 "", 163 "200 "+fix("home/src"), "<- selected", 164 " 50 "+fix("/tmp")) 165 f.TTY.TestBuffer(t, wantBuf) 166 167 f.TTY.Inject(term.K(ui.Enter)) 168 f.TestTTY(t /* nothing */) 169 wantChdir := fix("/home/elf/src") 170 if chdir != wantChdir { 171 t.Errorf("got chdir %q, want %q", chdir, wantChdir) 172 } 173 } 174 175 func TestStart_OK(t *testing.T) { 176 home, cleanupHome := testutil.InTempHome() 177 defer cleanupHome() 178 f := Setup() 179 defer f.Stop() 180 181 errChdir := errors.New("mock chdir error") 182 chdirCh := make(chan string, 100) 183 dirs := []store.Dir{ 184 {Path: filepath.Join(home, "go"), Score: 200}, 185 {Path: home, Score: 100}, 186 {Path: fix("/tmp/foo/bar/lorem/ipsum"), Score: 50}, 187 } 188 Start(f.App, Config{Store: testStore{ 189 storedDirs: dirs, 190 chdir: func(dir string) error { chdirCh <- dir; return errChdir }, 191 }}) 192 193 // Test UI. 194 wantBuf := listingBuf( 195 "", 196 "200 "+filepath.Join("~", "go"), "<- selected", 197 "100 ~", 198 " 50 "+fix("/tmp/foo/bar/lorem/ipsum")) 199 f.TTY.TestBuffer(t, wantBuf) 200 201 // Test filtering. 202 f.TTY.Inject(term.K('f'), term.K(os.PathSeparator), term.K('l')) 203 204 wantBuf = listingBuf( 205 "f"+string(os.PathSeparator)+"l", 206 " 50 "+fix("/tmp/foo/bar/lorem/ipsum"), "<- selected") 207 f.TTY.TestBuffer(t, wantBuf) 208 209 // Test accepting. 210 f.TTY.Inject(term.K(ui.Enter)) 211 // There should be no change to codearea after accepting. 212 f.TestTTY(t /* nothing */) 213 // Error from Chdir should be sent to notes. 214 f.TestTTYNotes(t, "mock chdir error") 215 // Chdir should be called. 216 wantChdir := fix("/tmp/foo/bar/lorem/ipsum") 217 if got := <-chdirCh; got != wantChdir { 218 t.Errorf("Chdir called with %s, want %s", got, wantChdir) 219 } 220 } 221 222 func listingBuf(filter string, lines ...string) *term.Buffer { 223 b := term.NewBufferBuilder(50) 224 b.Newline() // empty code area 225 cli.WriteListing(b, " LOCATION ", filter, lines...) 226 return b.Buffer() 227 } 228 229 func fix(path string) string { 230 if runtime.GOOS != "windows" { 231 return path 232 } 233 if path[0] == '/' { 234 path = "C:" + path 235 } 236 return strings.ReplaceAll(path, "/", "\\") 237 }