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  }