11
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"superwork-tui/internal/git"
|
||||
)
|
||||
|
||||
func makeHookCtx(workspaceRoot, worktreePath, branch string, issue int, main string) git.HookContext {
|
||||
return git.HookContext{
|
||||
WorkspaceRoot: workspaceRoot,
|
||||
WorktreePath: worktreePath,
|
||||
Branch: branch,
|
||||
IssueNumber: issue,
|
||||
MainBranch: main,
|
||||
}
|
||||
}
|
||||
|
||||
func writeScript(t *testing.T, dir, name, content string) string {
|
||||
t.Helper()
|
||||
p := filepath.Join(dir, name)
|
||||
if err := os.WriteFile(p, []byte(content), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// setupWorkspace returns workspaceRoot with .spx/ created.
|
||||
func setupWorkspace(t *testing.T) (workspaceRoot, spxDir string) {
|
||||
t.Helper()
|
||||
workspaceRoot = t.TempDir()
|
||||
spxDir = filepath.Join(workspaceRoot, ".spx")
|
||||
if err := os.MkdirAll(spxDir, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// --- RunPostCreateHook ---
|
||||
|
||||
func TestRunPostCreateHook_Missing(t *testing.T) {
|
||||
root, _ := setupWorkspace(t)
|
||||
ctx := makeHookCtx(root, root, "feat/x", 42, "main")
|
||||
// No script on disk → skipped.
|
||||
result := git.RunPostCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusSkipped {
|
||||
t.Errorf("want skipped, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPostCreateHook_Ok(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
worktree := t.TempDir()
|
||||
|
||||
// Script writes env vars to a file so we can assert them.
|
||||
envFile := filepath.Join(root, "env-dump.txt")
|
||||
script := `#!/bin/bash
|
||||
echo "WORKTREE_PATH=$WORKTREE_PATH" >> "` + envFile + `"
|
||||
echo "WORKSPACE_ROOT=$WORKSPACE_ROOT" >> "` + envFile + `"
|
||||
echo "BRANCH=$BRANCH" >> "` + envFile + `"
|
||||
echo "ISSUE_NUMBER=$ISSUE_NUMBER" >> "` + envFile + `"
|
||||
echo "MAIN_BRANCH=$MAIN_BRANCH" >> "` + envFile + `"
|
||||
exit 0
|
||||
`
|
||||
writeScript(t, spxDir, "worktree-post-create.sh", script)
|
||||
|
||||
ctx := makeHookCtx(root, worktree, "feat/my-branch", 99, "develop")
|
||||
result := git.RunPostCreateHook(context.Background(), ctx)
|
||||
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Fatalf("want ok, got %v (err=%s stderr=%s)", result.Status, result.ErrorMessage, result.Stderr)
|
||||
}
|
||||
if result.ExitCode != 0 {
|
||||
t.Errorf("want exit code 0, got %d", result.ExitCode)
|
||||
}
|
||||
if result.ScriptPath == "" {
|
||||
t.Error("ScriptPath must not be empty")
|
||||
}
|
||||
|
||||
envData, err := os.ReadFile(envFile)
|
||||
if err != nil {
|
||||
t.Fatalf("env dump not written: %v", err)
|
||||
}
|
||||
env := string(envData)
|
||||
checks := map[string]string{
|
||||
"WORKTREE_PATH": worktree,
|
||||
"WORKSPACE_ROOT": root,
|
||||
"BRANCH": "feat/my-branch",
|
||||
"ISSUE_NUMBER": "99",
|
||||
"MAIN_BRANCH": "develop",
|
||||
}
|
||||
for k, v := range checks {
|
||||
if !strings.Contains(env, k+"="+v) {
|
||||
t.Errorf("env missing %s=%s; got:\n%s", k, v, env)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPostCreateHook_Failed(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
writeScript(t, spxDir, "worktree-post-create.sh", "#!/bin/bash\nexit 3\n")
|
||||
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunPostCreateHook(context.Background(), ctx)
|
||||
|
||||
if result.Status != git.HookStatusFailed {
|
||||
t.Errorf("want failed, got %v", result.Status)
|
||||
}
|
||||
if result.ExitCode != 3 {
|
||||
t.Errorf("want ExitCode=3, got %d", result.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
// --- RunPreRemoveHook ---
|
||||
|
||||
func TestRunPreRemoveHook_Missing(t *testing.T) {
|
||||
root, _ := setupWorkspace(t)
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunPreRemoveHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusSkipped {
|
||||
t.Errorf("want skipped, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPreRemoveHook_Ok(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
writeScript(t, spxDir, "worktree-pre-remove.sh", "#!/bin/bash\nexit 0\n")
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunPreRemoveHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Errorf("want ok, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// --- RunImplTabPreCreateHook ---
|
||||
|
||||
func TestRunImplTabPreCreateHook_Missing(t *testing.T) {
|
||||
root, _ := setupWorkspace(t)
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunImplTabPreCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusSkipped {
|
||||
t.Errorf("want skipped, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunImplTabPreCreateHook_Ok(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
writeScript(t, spxDir, "impl-tab-pre-create.sh", "#!/bin/bash\nexit 0\n")
|
||||
ctx := makeHookCtx(root, root, "feat/x", 7, "main")
|
||||
result := git.RunImplTabPreCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Errorf("want ok, got %v", result.Status)
|
||||
}
|
||||
if result.ExitCode != 0 {
|
||||
t.Errorf("want exit 0, got %d", result.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunImplTabPreCreateHook_Failed(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
writeScript(t, spxDir, "impl-tab-pre-create.sh", "#!/bin/bash\nexit 7\n")
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunImplTabPreCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusFailed {
|
||||
t.Errorf("want failed, got %v", result.Status)
|
||||
}
|
||||
if result.ExitCode != 7 {
|
||||
t.Errorf("want ExitCode=7, got %d", result.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
// --- RunImplTabPostCloseHook ---
|
||||
|
||||
func TestRunImplTabPostCloseHook_Missing(t *testing.T) {
|
||||
root, _ := setupWorkspace(t)
|
||||
ctx := makeHookCtx(root, root, "feat/x", 1, "main")
|
||||
result := git.RunImplTabPostCloseHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusSkipped {
|
||||
t.Errorf("want skipped, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunImplTabPostCloseHook_Ok(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
writeScript(t, spxDir, "impl-tab-post-close.sh", "#!/bin/bash\nexit 0\n")
|
||||
ctx := makeHookCtx(root, root, "feat/x", 3, "main")
|
||||
result := git.RunImplTabPostCloseHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Errorf("want ok, got %v", result.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// --- CustomScriptPath override ---
|
||||
|
||||
func TestRunPostCreateHook_CustomScriptPath(t *testing.T) {
|
||||
root, _ := setupWorkspace(t)
|
||||
customDir := t.TempDir()
|
||||
customScript := filepath.Join(customDir, "my-hook.sh")
|
||||
if err := os.WriteFile(customScript, []byte("#!/bin/bash\nexit 0\n"), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := git.HookContext{
|
||||
WorkspaceRoot: root,
|
||||
WorktreePath: root,
|
||||
Branch: "feat/x",
|
||||
IssueNumber: 1,
|
||||
MainBranch: "main",
|
||||
CustomScriptPath: customScript, // absolute override
|
||||
}
|
||||
result := git.RunPostCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Errorf("want ok with custom path, got %v", result.Status)
|
||||
}
|
||||
if result.ScriptPath != customScript {
|
||||
t.Errorf("ScriptPath: want %q, got %q", customScript, result.ScriptPath)
|
||||
}
|
||||
}
|
||||
|
||||
// IssueNumber env value must be the decimal string, not anything else.
|
||||
func TestRunPostCreateHook_IssueNumberEnv(t *testing.T) {
|
||||
root, spxDir := setupWorkspace(t)
|
||||
envFile := filepath.Join(root, "issue-num.txt")
|
||||
script := "#!/bin/bash\necho -n \"$ISSUE_NUMBER\" > \"" + envFile + "\"\nexit 0\n"
|
||||
writeScript(t, spxDir, "worktree-post-create.sh", script)
|
||||
|
||||
ctx := makeHookCtx(root, root, "feat/x", 12345, "main")
|
||||
result := git.RunPostCreateHook(context.Background(), ctx)
|
||||
if result.Status != git.HookStatusOk {
|
||||
t.Fatalf("want ok, got %v", result.Status)
|
||||
}
|
||||
data, err := os.ReadFile(envFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := strings.TrimSpace(string(data))
|
||||
if got != strconv.Itoa(12345) {
|
||||
t.Errorf("ISSUE_NUMBER env: want %q, got %q", "12345", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user