Validate shell completion across supported shells
This commit is contained in:
93
completion_shell_test.go
Normal file
93
completion_shell_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package commandkit
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCompletionConsumerInShells(t *testing.T) {
|
||||
if os.Getenv("COMMANDKIT_COMPLETION_SHELLS") != "1" {
|
||||
t.Skip("set COMMANDKIT_COMPLETION_SHELLS=1 to run shell completion checks")
|
||||
}
|
||||
dir := t.TempDir()
|
||||
app := filepath.Join(dir, "probe")
|
||||
build := exec.Command("go", "build", "-o", app, "./testdata/completion")
|
||||
if output, err := build.CombinedOutput(); err != nil {
|
||||
t.Fatalf("build completion fixture: %v\n%s", err, output)
|
||||
}
|
||||
if err := os.Mkdir(filepath.Join(dir, "partial dir"), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "partial file"), nil, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name, line string
|
||||
want []string
|
||||
directory bool
|
||||
}{
|
||||
{"canonical command", "probe ru", []string{"run"}, false},
|
||||
{"entered alias", "probe shortcut --format=ya", []string{"shortcut", "--format=yaml"}, false},
|
||||
{"choice", "probe run --format=te", []string{"run", "--format=text"}, false},
|
||||
{"no file fallback", `probe run --format=./partial\ f`, []string{"run", "--format=./partial f"}, false},
|
||||
{"separated file", `probe run --config ./partial\ f`, []string{"run", "--config", "./partial file"}, false},
|
||||
{"attached file", `probe run --config=./partial\ f`, []string{"run", "--config=./partial file"}, false},
|
||||
{"short attached file", `probe run -c./partial\ f`, []string{"run", "-c./partial file"}, false},
|
||||
{"short cluster equals file", `probe run -sc=./partial\ f`, []string{"run", "-sc=./partial file"}, false},
|
||||
{"separated directory", "probe run --directory ./partial", []string{"run", "--directory", "./partial dir"}, true},
|
||||
{"attached directory", "probe run --directory=./partial", []string{"run", "--directory=./partial dir"}, true},
|
||||
{"empty operand", "probe run ", []string{"run", "alpha"}, false},
|
||||
{"leading dash", "probe run --for", []string{"run", "--format"}, false},
|
||||
}
|
||||
for _, shell := range []string{"bash", "zsh", "fish"} {
|
||||
generator := exec.Command(app, "completion", shell)
|
||||
script, err := generator.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("generate %s script: %v\n%s", shell, err, script)
|
||||
}
|
||||
scriptPath := filepath.Join(dir, shell+".completion")
|
||||
if err := os.WriteFile(scriptPath, script, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(shell+"/"+tc.name, func(t *testing.T) {
|
||||
log := filepath.Join(dir, "log")
|
||||
if err := os.WriteFile(log, nil, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
terminal := exec.Command("python3", "internal/cobra/testdata/completion_terminal.py", shell, scriptPath, tc.line)
|
||||
terminal.Env = append(os.Environ(), "PATH="+dir+string(os.PathListSeparator)+os.Getenv("PATH"), "HOME="+dir, "TERM=xterm", "PROBE_LOG="+log, "PROBE_DIR="+dir)
|
||||
if output, err := terminal.CombinedOutput(); err != nil {
|
||||
t.Fatalf("shell completion: %v\n%s", err, output)
|
||||
}
|
||||
content, err := os.ReadFile(log)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var got []string
|
||||
if err := json.Unmarshal(content, &got); err != nil {
|
||||
t.Fatalf("fixture output %q: %v", content, err)
|
||||
}
|
||||
if tc.directory && len(got) > 0 {
|
||||
got[len(got)-1] = strings.TrimSuffix(got[len(got)-1], "/")
|
||||
}
|
||||
if !reflect.DeepEqual(got, tc.want) {
|
||||
t.Fatalf("edited arguments=%q, want %q", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
t.Run(shell+"/descriptions", func(t *testing.T) {
|
||||
terminal := exec.Command("python3", "internal/cobra/testdata/completion_terminal.py", shell, scriptPath, "probe run --format=")
|
||||
terminal.Env = append(os.Environ(), "PATH="+dir+string(os.PathListSeparator)+os.Getenv("PATH"), "HOME="+dir, "TERM=xterm", "PROBE_LOG="+filepath.Join(dir, "log"), "PROBE_DIR="+dir, "PROBE_LIST=1")
|
||||
output, err := terminal.CombinedOutput()
|
||||
if err != nil || !strings.Contains(string(output), "Readable text") || !strings.Contains(string(output), "YAML output") {
|
||||
t.Fatalf("completion descriptions: %v\n%s", err, output)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user