feat: all tests

This commit is contained in:
verse91
2026-05-09 23:18:08 +07:00
parent be3c08171b
commit 17f33ff480
16 changed files with 460 additions and 43 deletions
+61
View File
@@ -0,0 +1,61 @@
package core_test
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/versenilvis/iris/commands/core"
)
func TestFileGenerator(t *testing.T) {
// Create a temp directory structure
tmp := t.TempDir()
os.Mkdir(filepath.Join(tmp, ".git"), 0755)
os.Mkdir(filepath.Join(tmp, "src"), 0755)
os.Mkdir(filepath.Join(tmp, "docs"), 0755)
os.WriteFile(filepath.Join(tmp, "src", "main.go"), []byte("package main"), 0644)
os.WriteFile(filepath.Join(tmp, "src", "utils.go"), []byte("package core"), 0644)
os.WriteFile(filepath.Join(tmp, "README.md"), []byte("# Readme"), 0644)
// Helper to change CWD for test
oldWd, _ := os.Getwd()
os.Chdir(tmp)
defer os.Chdir(oldWd)
t.Run("dirOnly shows only dirs", func(t *testing.T) {
gen := core.FileGenerator("/")
results := gen([]string{"cd", ""}, "cd ", "")
for _, r := range results {
if r.Desc != "directory" {
t.Errorf("FileGenerator(\"/\") suggested a non-directory: %s", r.Cmd)
}
}
})
t.Run("Filter extension", func(t *testing.T) {
gen := core.FileGenerator(".go")
results := gen([]string{"go", "src/"}, "go src/", "src/")
foundMain := false
for _, r := range results {
if r.Cmd == "src/main.go" {
foundMain = true
}
}
if !foundMain {
t.Errorf("FileGenerator(\".go\") did not suggest src/main.go")
}
})
t.Run("Hidden files are skipped", func(t *testing.T) {
gen := core.FileGenerator()
results := gen([]string{"ls", ""}, "ls ", "")
for _, r := range results {
if strings.HasPrefix(filepath.Base(r.Cmd), ".") {
t.Errorf("FileGenerator suggested hidden file: %s", r.Cmd)
}
}
})
}
+73
View File
@@ -0,0 +1,73 @@
package core_test
import (
"testing"
"github.com/versenilvis/iris/commands/core"
"github.com/versenilvis/iris/integration/shell"
)
type mockAdapter struct {
shell.BashAdapter
}
func (m *mockAdapter) ScanAliases() map[string]string {
return map[string]string{
"gca": "git commit -a",
"ta": "tmux a -t",
}
}
func TestLookup(t *testing.T) {
// Use mock adapter
shell.Current = &mockAdapter{}
core.Register(&core.Spec{
Name: "git",
Description: "git command",
Subcommands: []core.Subcommand{
{Name: "commit", Description: "commit changes"},
{Name: "remote", Description: "manage remotes", Subcommands: []core.Subcommand{
{Name: "add", Description: "add remote"},
}},
},
Options: []core.Option{
{Name: "--verbose", Description: "verbose output"},
},
})
tests := []struct {
name string
input string
minCount int
checkCmd string
}{
{"Top-level suggestions", "gi", 1, "git"},
{"Subcommand suggestions", "git ", 2, "git commit"},
{"Alias expansion", "gca", 1, "git commit -a"},
{"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"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
results := core.Lookup(tt.input)
if len(results) < tt.minCount {
t.Errorf("Lookup(%q) returned %d results; want at least %d", tt.input, len(results), tt.minCount)
}
if tt.checkCmd != "" {
found := false
for _, r := range results {
if r.Cmd == tt.checkCmd {
found = true
break
}
}
if !found {
t.Errorf("Lookup(%q) did not suggest %q", tt.input, tt.checkCmd)
}
}
})
}
}
+55
View File
@@ -0,0 +1,55 @@
package core_test
import (
"reflect"
"testing"
"github.com/versenilvis/iris/commands/core"
)
func TestTokenize(t *testing.T) {
tests := []struct {
input string
expected []string
}{
{"", []string{""}},
{"git ", []string{"git", ""}},
{"git add", []string{"git", "add"}},
{"git commit -m \"hello world\"", []string{"git", "commit", "-m", "hello world"}},
{"git commit -m \"hello", []string{"git", "commit", "-m", "hello"}},
{"git commit -m 'hello world'", []string{"git", "commit", "-m", "hello world"}},
{"git commit -m 'hello", []string{"git", "commit", "-m", "hello"}},
{"ls -l \"file name\"", []string{"ls", "-l", "file name"}},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
got := core.Tokenize(tt.input)
if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("Tokenize(%q) = %v; want %v", tt.input, got, tt.expected)
}
})
}
}
func TestHasPrefix(t *testing.T) {
tests := []struct {
s string
prefix string
want bool
}{
{"Hello", "hel", true},
{"Thử nghiệm", "thử", true},
{"Iris", "Iris-Longer", false},
{"Iris", "", true},
{"", "a", false},
}
for _, tt := range tests {
t.Run(tt.s+"_"+tt.prefix, func(t *testing.T) {
if got := core.HasPrefix(tt.s, tt.prefix); got != tt.want {
t.Errorf("HasPrefix(%q, %q) = %v; want %v", tt.s, tt.prefix, got, tt.want)
}
})
}
}
+58
View File
@@ -0,0 +1,58 @@
package fs_test
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/versenilvis/iris/commands/fs"
)
func TestZoxideGenerator(t *testing.T) {
// Create a mock zoxide binary
tmp := t.TempDir()
mockZoxide := filepath.Join(tmp, "zoxide")
// Script that prints mock directories
script := "#!/bin/sh\necho \"/home/verse/project1\n/home/verse/docs\n/home/verse/dev/iris\""
os.WriteFile(mockZoxide, []byte(script), 0755)
// Add tmp to PATH
oldPath := os.Getenv("PATH")
os.Setenv("PATH", tmp+string(os.PathListSeparator)+oldPath)
defer os.Setenv("PATH", oldPath)
gen := fs.ZoxideGenerator()
t.Run("Query returns correct result when partial is empty", func(t *testing.T) {
results := gen([]string{"z", ""}, "z ", "")
if len(results) == 0 {
t.Errorf("Expected results from zoxide history, got 0")
}
})
t.Run("Path replaces home dir with ~", func(t *testing.T) {
home, _ := os.UserHomeDir()
results := gen([]string{"z", ""}, "z ", "")
foundHome := false
for _, r := range results {
if strings.HasPrefix(r.Desc, "~") {
foundHome = true
break
}
}
if !foundHome && home != "" {
t.Logf("Warning: Did not find ~ in descriptions, home is %s", home)
}
})
t.Run("Sort by descending score", func(t *testing.T) {
results := gen([]string{"z", "i"}, "z ", "i")
if len(results) >= 1 {
if results[0].Cmd == "" {
t.Errorf("Empty result command")
}
}
})
}
+54
View File
@@ -0,0 +1,54 @@
package tests
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/versenilvis/iris/commands/core"
_ "github.com/versenilvis/iris/commands/fs" // Register z command
)
func TestIntegration_ZoxideMultiWord(t *testing.T) {
// Create mock directory with spaces
tmp := t.TempDir()
targetDir := filepath.Join(tmp, "My Awesome Project")
os.MkdirAll(targetDir, 0755)
// Mock shell environment
oldWd, _ := os.Getwd()
os.Chdir(tmp)
defer os.Chdir(oldWd)
// Mock zoxide binary
mockBinDir := t.TempDir()
mockZoxide := filepath.Join(mockBinDir, "zoxide")
script := "#!/bin/sh\necho \"" + targetDir + "\""
os.WriteFile(mockZoxide, []byte(script), 0755)
oldPath := os.Getenv("PATH")
os.Setenv("PATH", mockBinDir+string(os.PathListSeparator)+oldPath)
defer os.Setenv("PATH", oldPath)
t.Run("z matches multi-word folder without quotes", func(t *testing.T) {
// Simulating user typing "z My Awe"
input := "z My Awe"
results := core.Lookup(input)
found := false
for _, r := range results {
// Expected result should be "z My Awesome Project/"
if strings.Contains(r.Cmd, "My Awesome Project") {
found = true
// Check for word duplication bug: "z My My Awesome..."
if strings.Contains(r.Cmd, "My My") {
t.Errorf("Word duplication detected in suggestion: %s", r.Cmd)
}
}
}
if !found {
t.Errorf("Could not find 'My Awesome Project' in suggestions for %q", input)
}
})
}
+50
View File
@@ -0,0 +1,50 @@
package root_test
import (
"os"
"path/filepath"
"testing"
"github.com/versenilvis/iris/commands/core"
"github.com/versenilvis/iris/root"
)
func TestMergeResults(t *testing.T) {
// Setup mock Registry
core.Registry = make(map[string]*core.Spec)
core.Register(&core.Spec{
Name: "ls",
Description: "list files",
})
// Setup mock history file
tmp := t.TempDir()
histFile := filepath.Join(tmp, ".bash_history")
os.WriteFile(histFile, []byte("ls -l\ncd /tmp\ngit status\n"), 0644)
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmp)
defer os.Setenv("HOME", oldHome)
t.Run("History mode returns history items", func(t *testing.T) {
results := root.MergeResults("", "history")
if len(results) == 0 {
t.Errorf("MergeResults history mode returned 0 items")
}
})
t.Run("Spec mode returns command results and dedups", func(t *testing.T) {
core.Register(&core.Spec{Name: "git", Description: "git"})
results := root.MergeResults("gi", "spec")
foundGit := false
for _, r := range results {
if r.Cmd == "git" {
foundGit = true
}
}
if !foundGit {
t.Errorf("MergeResults spec mode did not find 'git'")
}
})
}
+62
View File
@@ -0,0 +1,62 @@
package shell_test
import (
"os"
"path/filepath"
"reflect"
"testing"
"github.com/versenilvis/iris/integration/shell"
)
func TestSplitAliasTokens(t *testing.T) {
tests := []struct {
input string
expected []string
}{
{"g='git commit'", []string{"g='git commit'"}},
{"a=b c=d", []string{"a=b", "c=d"}},
{"ta='tmux a -t' l='ls -l'", []string{"ta='tmux a -t'", "l='ls -l'"}},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
got := shell.SplitAliasTokens(tt.input)
if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("SplitAliasTokens(%q) = %v; want %v", tt.input, got, tt.expected)
}
})
}
}
func TestScanPosixAliases(t *testing.T) {
tmp := t.TempDir()
aliasFile := filepath.Join(tmp, ".bashrc")
content := `
# some comments
alias g='git'
alias gca='git commit -a'
alias multi="a" b="c"
`
os.WriteFile(aliasFile, []byte(content), 0644)
oldHome := os.Getenv("HOME")
os.Setenv("HOME", tmp)
defer os.Setenv("HOME", oldHome)
aliases := shell.ScanPosixAliases([]string{".bashrc"})
expected := map[string]string{
"g": "git",
"gca": "git commit -a",
"multi": "a",
"b": "c",
}
for k, v := range expected {
if aliases[k] != v {
t.Errorf("Expected alias %s=%s, got %s", k, v, aliases[k])
}
}
}