234 lines
5.6 KiB
Go
234 lines
5.6 KiB
Go
package spec
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
func TestLookup(t *testing.T) {
|
|
// Setup Registry
|
|
Registry = make(map[string]*Spec)
|
|
Register(&Spec{
|
|
Name: "git",
|
|
Subcommands: []Subcommand{
|
|
{Name: "commit", Options: []Option{{Name: "--message"}}, MaxArgs: 1},
|
|
{Name: "remote", Subcommands: []Subcommand{{Name: "add"}}},
|
|
},
|
|
Options: []Option{{Name: "--verbose"}},
|
|
})
|
|
|
|
// Setup Aliases
|
|
ShellAliases = map[string]string{
|
|
"gca": "git commit -a",
|
|
"ta": "tmux a -t",
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
minResults int
|
|
mustContain string
|
|
}{
|
|
{"Top-level", "gi", 1, "git"},
|
|
{"Subcommand", "git ", 1, "git commit"},
|
|
{"Alias expansion", "gca", 1, "git commit -a"},
|
|
{"Alias with space", "ta", 1, "tmux a -t"},
|
|
{"Deep subcommand", "git remote ", 1, "git remote add"},
|
|
{"Option dedup", "git --verbose -", 0, ""},
|
|
{"Flag with value ignore", "git --output=json ", 2, "git --output=json commit"},
|
|
{"Unknown root command", "unknowncmd ", 0, ""},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
results := Lookup(tt.input)
|
|
if len(results) < tt.minResults {
|
|
t.Errorf("Lookup(%q) got %d results; want at least %d", tt.input, len(results), tt.minResults)
|
|
}
|
|
if tt.mustContain != "" {
|
|
found := false
|
|
for _, r := range results {
|
|
if strings.Contains(r.Cmd, tt.mustContain) || strings.Contains(r.Desc, tt.mustContain) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("Lookup(%q) results did not contain %q", tt.input, tt.mustContain)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLookup_NoFlagGateAndPriority(t *testing.T) {
|
|
Registry["demo"] = &Spec{
|
|
Name: "demo",
|
|
Subcommands: []Subcommand{
|
|
{Name: "sub1", Priority: 85},
|
|
},
|
|
Options: []Option{
|
|
{Name: "--verbose", Priority: 70},
|
|
},
|
|
}
|
|
|
|
results := Lookup("demo ")
|
|
foundSub, foundOpt := false, false
|
|
for _, r := range results {
|
|
if strings.Contains(r.Cmd, "sub1") {
|
|
foundSub = true
|
|
if r.Priority != 85 {
|
|
t.Errorf("expected subcommand Priority 85, got %d", r.Priority)
|
|
}
|
|
}
|
|
if strings.Contains(r.Cmd, "--verbose") {
|
|
foundOpt = true
|
|
if r.Priority != 70 {
|
|
t.Errorf("expected option Priority 70, got %d", r.Priority)
|
|
}
|
|
}
|
|
}
|
|
if !foundSub {
|
|
t.Error("expected sub1 in lookup results")
|
|
}
|
|
if !foundOpt {
|
|
t.Error("expected --verbose in lookup results even without typed dash")
|
|
}
|
|
|
|
partialResults := Lookup("demo ver")
|
|
foundPartialOpt := false
|
|
for _, r := range partialResults {
|
|
if strings.Contains(r.Cmd, "--verbose") {
|
|
foundPartialOpt = true
|
|
break
|
|
}
|
|
}
|
|
if !foundPartialOpt {
|
|
t.Error("expected --verbose when partial query is 'ver' (trimmed dash match)")
|
|
}
|
|
}
|
|
|
|
func TestLookupConcurrent(t *testing.T) {
|
|
Registry = make(map[string]*Spec)
|
|
Register(&Spec{
|
|
Name: "git",
|
|
Subcommands: []Subcommand{
|
|
{Name: "commit", Options: []Option{{Name: "--message"}}, MaxArgs: 1},
|
|
},
|
|
})
|
|
|
|
ShellAliases = map[string]string{
|
|
"gca": "git commit -a",
|
|
}
|
|
|
|
var wg sync.WaitGroup
|
|
const goroutines = 10
|
|
const iterations = 50
|
|
|
|
for range goroutines {
|
|
wg.Go(func() {
|
|
for range iterations {
|
|
_ = Lookup("gca")
|
|
_ = Lookup("git ")
|
|
}
|
|
})
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestLookup_AliasFileGenerator(t *testing.T) {
|
|
ResetRegistry()
|
|
Register(&Spec{
|
|
Name: "nvim",
|
|
Generator: FileGenerator(),
|
|
})
|
|
// alias "nv" -> "nvim", single token with trailing space
|
|
ShellAliases = map[string]string{"nv": "nvim"}
|
|
|
|
results := Lookup("nv ")
|
|
if len(results) == 0 {
|
|
t.Errorf("expected file suggestions for alias 'nv ' -> 'nvim', got none")
|
|
}
|
|
for _, r := range results {
|
|
if !strings.HasPrefix(r.Cmd, "nvim ") {
|
|
t.Errorf("expected suggestion to start with 'nvim ', got %q", r.Cmd)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLookup_NvimFileGenerator(t *testing.T) {
|
|
ResetRegistry()
|
|
Register(&Spec{
|
|
Name: "nvim",
|
|
Generator: FileGenerator(),
|
|
})
|
|
results := Lookup("nvim ")
|
|
if len(results) == 0 {
|
|
t.Errorf("expected file suggestions for 'nvim ', got none")
|
|
}
|
|
}
|
|
|
|
func TestLookup_OptionAndFilePriority(t *testing.T) {
|
|
ResetRegistry()
|
|
Register(&Spec{
|
|
Name: "nvim",
|
|
Generator: FileGenerator(),
|
|
Options: []Option{
|
|
{Name: "-c", Description: "Execute cmd"},
|
|
{Name: "--cmd", Description: "Execute cmd before config"},
|
|
},
|
|
})
|
|
|
|
// When query is 'nvim ', files should be prioritized over flags
|
|
resultsEmpty := Lookup("nvim ")
|
|
if len(resultsEmpty) == 0 {
|
|
t.Fatalf("expected results for 'nvim ', got 0")
|
|
}
|
|
// first result should be a file or dir (Priority 50), not option (Priority 10)
|
|
if strings.HasPrefix(resultsEmpty[0].Cmd, "nvim -") {
|
|
t.Errorf("expected file/dir as top result for 'nvim ', got %q", resultsEmpty[0].Cmd)
|
|
}
|
|
|
|
// When query is 'nvim -', flags should be prioritized (Priority 80)
|
|
resultsDash := Lookup("nvim -")
|
|
if len(resultsDash) == 0 {
|
|
t.Fatalf("expected results for 'nvim -', got 0")
|
|
}
|
|
if !strings.HasPrefix(resultsDash[0].Cmd, "nvim -") {
|
|
t.Errorf("expected option as top result for 'nvim -', got %q", resultsDash[0].Cmd)
|
|
}
|
|
}
|
|
|
|
func TestLookup_NestedDirectoryTrailingSpace(t *testing.T) {
|
|
ResetRegistry()
|
|
Register(&Spec{
|
|
Name: "cat",
|
|
Generator: FileGenerator(),
|
|
})
|
|
|
|
tmpDir := t.TempDir()
|
|
subDir := filepath.Join(tmpDir, "subdir")
|
|
_ = os.Mkdir(subDir, 0755)
|
|
testFile := filepath.Join(subDir, "hello.txt")
|
|
_ = os.WriteFile(testFile, []byte("hi"), 0644)
|
|
|
|
query := "cat " + subDir + "/ "
|
|
results := Lookup(query)
|
|
if len(results) == 0 {
|
|
t.Fatalf("expected results for %q, got 0", query)
|
|
}
|
|
found := false
|
|
for _, r := range results {
|
|
if strings.Contains(r.Cmd, "hello.txt") {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("expected hello.txt in results, got %v", results)
|
|
}
|
|
}
|