150 lines
3.8 KiB
Go
150 lines
3.8 KiB
Go
|
|
package cmd
|
||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestResolveRecipePathDirectFile(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
recipePath := filepath.Join(tmpDir, "my-recipe.md")
|
||
|
|
if err := os.WriteFile(recipePath, []byte("# Recipe\n"), 0644); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, err := resolveRecipePath(recipePath)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("resolveRecipePath(%q) failed: %v", recipePath, err)
|
||
|
|
}
|
||
|
|
if got != recipePath {
|
||
|
|
t.Errorf("resolveRecipePath() = %q, want %q", got, recipePath)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestResolveRecipePathDirectFileMissing(t *testing.T) {
|
||
|
|
_, err := resolveRecipePath("/nonexistent/recipe.md")
|
||
|
|
if err == nil {
|
||
|
|
t.Fatal("expected error for missing recipe file, got nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestResolveRecipePathProjectLocal(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
origDir, _ := os.Getwd()
|
||
|
|
if err := os.Chdir(tmpDir); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer func() { _ = os.Chdir(origDir) }()
|
||
|
|
|
||
|
|
// Create .grokkit/recipes with a recipe, and a .git dir for project root detection
|
||
|
|
recipeDir := filepath.Join(tmpDir, ".grokkit", "recipes")
|
||
|
|
if err := os.MkdirAll(recipeDir, 0755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := os.MkdirAll(filepath.Join(tmpDir, ".git"), 0755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
recipePath := filepath.Join(recipeDir, "refactor.md")
|
||
|
|
if err := os.WriteFile(recipePath, []byte("# Refactor\n"), 0644); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, err := resolveRecipePath("refactor")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("resolveRecipePath('refactor') failed: %v", err)
|
||
|
|
}
|
||
|
|
if got != recipePath {
|
||
|
|
t.Errorf("resolveRecipePath() = %q, want %q", got, recipePath)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestResolveRecipePathNotFound(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
origDir, _ := os.Getwd()
|
||
|
|
if err := os.Chdir(tmpDir); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer func() { _ = os.Chdir(origDir) }()
|
||
|
|
|
||
|
|
// Create .git so findProjectRoot works, but no recipes
|
||
|
|
if err := os.MkdirAll(filepath.Join(tmpDir, ".git"), 0755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Override HOME to empty dir so global fallback also fails
|
||
|
|
oldHome := os.Getenv("HOME")
|
||
|
|
defer func() { _ = os.Setenv("HOME", oldHome) }()
|
||
|
|
_ = os.Setenv("HOME", tmpDir)
|
||
|
|
|
||
|
|
_, err := resolveRecipePath("nonexistent")
|
||
|
|
if err == nil {
|
||
|
|
t.Fatal("expected error for nonexistent recipe, got nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFindProjectRoot(t *testing.T) {
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
marker string
|
||
|
|
}{
|
||
|
|
{"git repo", ".git"},
|
||
|
|
{"gitignore", ".gitignore"},
|
||
|
|
{"grokkit dir", ".grokkit"},
|
||
|
|
{"go module", "go.mod"},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tt := range tests {
|
||
|
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
origDir, _ := os.Getwd()
|
||
|
|
|
||
|
|
// Create a subdirectory and chdir into it
|
||
|
|
subDir := filepath.Join(tmpDir, "sub", "deep")
|
||
|
|
if err := os.MkdirAll(subDir, 0755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := os.Chdir(subDir); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer func() { _ = os.Chdir(origDir) }()
|
||
|
|
|
||
|
|
// Place the marker at the root
|
||
|
|
markerPath := filepath.Join(tmpDir, tt.marker)
|
||
|
|
if tt.marker == ".git" || tt.marker == ".grokkit" {
|
||
|
|
if err := os.MkdirAll(markerPath, 0755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if err := os.WriteFile(markerPath, []byte(""), 0644); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
root, err := findProjectRoot()
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("findProjectRoot() failed: %v", err)
|
||
|
|
}
|
||
|
|
if root != tmpDir {
|
||
|
|
t.Errorf("findProjectRoot() = %q, want %q", root, tmpDir)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFindProjectRootNotInProject(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
origDir, _ := os.Getwd()
|
||
|
|
if err := os.Chdir(tmpDir); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer func() { _ = os.Chdir(origDir) }()
|
||
|
|
|
||
|
|
// Empty dir — no markers at all. This will walk up to / and fail.
|
||
|
|
_, err := findProjectRoot()
|
||
|
|
if err == nil {
|
||
|
|
// Might succeed if a parent dir has .git — that's OK in CI
|
||
|
|
t.Log("findProjectRoot() succeeded (likely found .git in a parent dir)")
|
||
|
|
}
|
||
|
|
}
|