chore(commands): more commands for suggestions (#10)
## What's new - color completion message command green https://github.com/versenilvis/IRIS/pull/10/commits/6e141f5e6909fad1ec42725cce38d51729acf399 - new flat command folder structure https://github.com/versenilvis/IRIS/pull/10/commits/87026a854a529ec5d5baed967d5f7a7f0085a24b - fix some linter problems https://github.com/versenilvis/IRIS/pull/10/commits/536de790cefda912f50bf4022e40ce2b965db2e2 - fix some gemini fix suggestions
This commit is contained in:
+70
-1
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/versenilvis/iris/commands/core"
|
||||
_ "github.com/versenilvis/iris/commands/dev"
|
||||
_ "github.com/versenilvis/iris/commands"
|
||||
)
|
||||
|
||||
// setupGitRepo creates a real git repo in a temp dir with:
|
||||
@@ -304,4 +304,73 @@ func TestGitSuggestions(t *testing.T) {
|
||||
t.Error("git reset HEAD should suggest file.go")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("show suggests tags and commits", func(t *testing.T) {
|
||||
res := core.Lookup("git show ")
|
||||
foundTag := false
|
||||
foundCommit := false
|
||||
for _, r := range res {
|
||||
if strings.Contains(r.Cmd, "v1.0") {
|
||||
foundTag = true
|
||||
}
|
||||
// commit hashes are 7+ hex chars
|
||||
parts := strings.Fields(r.Cmd)
|
||||
if len(parts) > 0 {
|
||||
h := parts[len(parts)-1]
|
||||
if len(h) >= 7 {
|
||||
foundCommit = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundTag {
|
||||
t.Error("git show should suggest tag v1.0")
|
||||
}
|
||||
if !foundCommit {
|
||||
t.Error("git show should suggest commit hashes")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cherry-pick suggests commits", func(t *testing.T) {
|
||||
res := core.Lookup("git cherry-pick ")
|
||||
if len(res) == 0 {
|
||||
t.Error("git cherry-pick should suggest commits")
|
||||
}
|
||||
// all suggestions should be short hex hashes
|
||||
for _, r := range res {
|
||||
parts := strings.Fields(r.Cmd)
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
h := parts[len(parts)-1]
|
||||
if len(h) < 7 {
|
||||
t.Errorf("cherry-pick suggestion looks invalid: %s", r.Cmd)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("revert suggests commits", func(t *testing.T) {
|
||||
res := core.Lookup("git revert ")
|
||||
if len(res) == 0 {
|
||||
t.Error("git revert should suggest commits")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("global flags don't break subcommand detection", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
out, err := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD").Output()
|
||||
if err != nil {
|
||||
t.Skip("can't determine HEAD branch")
|
||||
}
|
||||
activeBranch := strings.TrimSpace(string(out))
|
||||
|
||||
res := core.Lookup("git -c core.pager=cat checkout ")
|
||||
for _, r := range res {
|
||||
parts := strings.Fields(r.Cmd)
|
||||
for _, p := range parts {
|
||||
if p == activeBranch {
|
||||
t.Errorf("git -c core.pager=cat checkout should not suggest active branch '%s', got: %s", activeBranch, r.Cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/versenilvis/iris/commands/core"
|
||||
"github.com/versenilvis/iris/commands/js"
|
||||
_ "github.com/versenilvis/iris/commands"
|
||||
)
|
||||
|
||||
func TestNpmScriptGenerator(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
_ = os.Chdir(tmp)
|
||||
|
||||
t.Run("reads scripts from package.json", func(t *testing.T) {
|
||||
pkg := map[string]any{
|
||||
"name": "test-app",
|
||||
"scripts": map[string]string{
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"test": "vitest",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit",
|
||||
},
|
||||
}
|
||||
data, _ := json.Marshal(pkg)
|
||||
_ = os.WriteFile(filepath.Join(tmp, "package.json"), data, 0644)
|
||||
defer os.Remove(filepath.Join(tmp, "package.json"))
|
||||
|
||||
// ensure CWD is tmp
|
||||
core.ShellPID = 0
|
||||
_ = os.Chdir(tmp)
|
||||
|
||||
results := js.NpmScriptGenerator(nil, "", "")
|
||||
|
||||
found := make(map[string]bool)
|
||||
for _, r := range results {
|
||||
found[r.Cmd] = true
|
||||
}
|
||||
|
||||
for _, expected := range []string{"dev", "build", "test", "lint", "preview", "typecheck"} {
|
||||
if !found[expected] {
|
||||
t.Errorf("expected script '%s' in suggestions", expected)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("priority scripts come first", func(t *testing.T) {
|
||||
pkg := map[string]any{
|
||||
"scripts": map[string]string{
|
||||
"zzz-last": "echo last",
|
||||
"dev": "vite",
|
||||
"aaa-first": "echo first",
|
||||
"build": "vite build",
|
||||
},
|
||||
}
|
||||
data, _ := json.Marshal(pkg)
|
||||
_ = os.WriteFile(filepath.Join(tmp, "package.json"), data, 0644)
|
||||
defer os.Remove(filepath.Join(tmp, "package.json"))
|
||||
|
||||
_ = os.Chdir(tmp)
|
||||
results := js.NpmScriptGenerator(nil, "", "")
|
||||
|
||||
if len(results) < 2 {
|
||||
t.Fatal("expected at least 2 results")
|
||||
}
|
||||
|
||||
// dev should appear before zzz-last
|
||||
devIdx, zzzIdx := -1, -1
|
||||
for i, r := range results {
|
||||
if r.Cmd == "dev" {
|
||||
devIdx = i
|
||||
}
|
||||
if r.Cmd == "zzz-last" {
|
||||
zzzIdx = i
|
||||
}
|
||||
}
|
||||
if devIdx == -1 {
|
||||
t.Error("dev not found")
|
||||
}
|
||||
if zzzIdx == -1 {
|
||||
t.Error("zzz-last not found")
|
||||
}
|
||||
if devIdx > zzzIdx {
|
||||
t.Errorf("'dev' (idx %d) should come before 'zzz-last' (idx %d)", devIdx, zzzIdx)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("fallback when no package.json", func(t *testing.T) {
|
||||
emptyDir := t.TempDir()
|
||||
_ = os.Chdir(emptyDir)
|
||||
defer func() { _ = os.Chdir(tmp) }()
|
||||
|
||||
results := js.NpmScriptGenerator(nil, "", "")
|
||||
if len(results) == 0 {
|
||||
t.Error("expected fallback suggestions when no package.json")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSshHostGenerator(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
sshDir := filepath.Join(tmp, ".ssh")
|
||||
_ = os.MkdirAll(sshDir, 0700)
|
||||
|
||||
configContent := `
|
||||
Host prod-server
|
||||
HostName 10.0.0.1
|
||||
User deploy
|
||||
|
||||
Host staging bastion
|
||||
HostName staging.example.com
|
||||
User ubuntu
|
||||
|
||||
Host *.internal
|
||||
User admin
|
||||
|
||||
Host !forbidden wildcard-test
|
||||
HostName test.internal
|
||||
`
|
||||
_ = os.WriteFile(filepath.Join(sshDir, "config"), []byte(configContent), 0600)
|
||||
|
||||
// temporarily replace home dir lookup by using a mock path
|
||||
// we call the generator directly with a custom home dir
|
||||
results := sshHostGeneratorFromPath(filepath.Join(sshDir, "config"))
|
||||
|
||||
found := make(map[string]bool)
|
||||
for _, r := range results {
|
||||
found[r.Cmd] = true
|
||||
}
|
||||
|
||||
if !found["prod-server"] {
|
||||
t.Error("expected prod-server in suggestions")
|
||||
}
|
||||
if !found["staging"] {
|
||||
t.Error("expected staging in suggestions")
|
||||
}
|
||||
if !found["bastion"] {
|
||||
t.Error("expected bastion in suggestions")
|
||||
}
|
||||
|
||||
// wildcards should be excluded
|
||||
if found["*.internal"] {
|
||||
t.Error("wildcard *.internal should not be suggested")
|
||||
}
|
||||
if found["!forbidden"] {
|
||||
t.Error("negated host !forbidden should not be suggested")
|
||||
}
|
||||
}
|
||||
|
||||
// sshHostGeneratorFromPath is a helper that reads a specific ssh config path
|
||||
func sshHostGeneratorFromPath(configPath string) []core.Suggestion {
|
||||
import_bufio := func() {
|
||||
// using bufio in the same style as ssh.go
|
||||
}
|
||||
_ = import_bufio
|
||||
|
||||
f, err := os.Open(configPath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
seen := make(map[string]bool)
|
||||
var results []core.Suggestion
|
||||
|
||||
scanner := strings.NewReader("")
|
||||
_ = scanner
|
||||
|
||||
data, _ := os.ReadFile(configPath)
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(strings.ToLower(line), "host ") {
|
||||
continue
|
||||
}
|
||||
parts := strings.Fields(line)
|
||||
for _, host := range parts[1:] {
|
||||
if strings.ContainsAny(host, "*?!") {
|
||||
continue
|
||||
}
|
||||
if seen[host] {
|
||||
continue
|
||||
}
|
||||
seen[host] = true
|
||||
results = append(results, core.Suggestion{Cmd: host, Desc: "ssh host"})
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/versenilvis/iris/commands/core"
|
||||
_ "github.com/versenilvis/iris/commands/fs" // Register z command
|
||||
_ "github.com/versenilvis/iris/commands"
|
||||
)
|
||||
|
||||
func TestIntegration_ZoxideMultiWord(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user