Git Repository
Stackyard
Stackyard scannt lokale Entwicklungsordner und bündelt Projekte, Git-Status, TODOs, Toolchains, Docker-Compose-Setups, Datei- und Launcher-Funktionen sowie Operations-Informationen in einer lokalen WebUI.
HTTPS
https://zanvex.de/git/stackyard.gitinternal/app/service_test.go
Zum Verzeichnispackage app
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
"stackyard/internal/config"
"stackyard/internal/project"
"stackyard/internal/storage"
)
func TestServiceCreateAndCheckoutBranch(t *testing.T) {
root := t.TempDir()
repo := filepath.Join(root, "repo")
if err := os.MkdirAll(repo, 0o755); err != nil {
t.Fatalf("mkdir repo: %v", err)
}
runGit(t, repo, "init")
runGit(t, repo, "config", "user.email", "test@example.com")
runGit(t, repo, "config", "user.name", "tester")
if err := os.WriteFile(filepath.Join(repo, "go.mod"), []byte("module repo\n"), 0o644); err != nil {
t.Fatalf("write go.mod: %v", err)
}
runGit(t, repo, "add", "go.mod")
runGit(t, repo, "commit", "-m", "init")
store, err := storage.Open(filepath.Join(root, "stackyard.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
defer store.Close()
cfg := config.Config{
Roots: []config.RootConfig{{Name: "DEV", Path: root}},
Scanner: config.ScannerConfig{
MaxDepth: 2,
IgnoreDirs: []string{"node_modules"},
},
Launchers: config.LaunchersConfig{
VSCode: config.LauncherConfig{Enabled: false},
Sublime: config.LauncherConfig{Enabled: false},
Terminal: config.LauncherConfig{Enabled: false},
Explorer: config.LauncherConfig{Enabled: false},
},
}
svc := NewService(cfg, store)
projects, err := svc.Refresh(context.Background())
if err != nil {
t.Fatalf("refresh: %v", err)
}
if len(projects) != 1 {
t.Fatalf("expected 1 project, got %d", len(projects))
}
id := projects[0].ID
if err := svc.CreateBranch(context.Background(), id, "feature/test"); err != nil {
t.Fatalf("create branch: %v", err)
}
p, ok, err := svc.Get(context.Background(), id)
if err != nil || !ok {
t.Fatalf("get project after create: ok=%v err=%v", ok, err)
}
if p.Git.Branch != "feature/test" {
t.Fatalf("expected current branch feature/test, got %q", p.Git.Branch)
}
if err := svc.CheckoutBranch(context.Background(), id, "master"); err != nil && err.Error() != "branch does not exist" {
t.Fatalf("unexpected checkout error: %v", err)
}
mainBranch := "master"
if branchExists(t, repo, "main") {
mainBranch = "main"
}
if err := svc.CheckoutBranch(context.Background(), id, mainBranch); err != nil {
t.Fatalf("checkout branch: %v", err)
}
p, ok, err = svc.Get(context.Background(), id)
if err != nil || !ok {
t.Fatalf("get project after checkout: ok=%v err=%v", ok, err)
}
if p.Git.Branch != mainBranch {
t.Fatalf("expected current branch %q, got %q", mainBranch, p.Git.Branch)
}
}
func runGit(t *testing.T, dir string, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("git %v failed: %v\n%s", args, err, string(out))
}
}
func branchExists(t *testing.T, dir, branch string) bool {
t.Helper()
cmd := exec.Command("git", "branch", "--list", branch)
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("branch list failed: %v\n%s", err, string(out))
}
return string(out) != ""
}
func TestServiceCheckoutRejectsNonRepo(t *testing.T) {
root := t.TempDir()
projectDir := filepath.Join(root, "plain")
if err := os.MkdirAll(projectDir, 0o755); err != nil {
t.Fatalf("mkdir project: %v", err)
}
if err := os.WriteFile(filepath.Join(projectDir, "go.mod"), []byte("module plain\n"), 0o644); err != nil {
t.Fatalf("write go.mod: %v", err)
}
store, err := storage.Open(filepath.Join(root, "stackyard.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
defer store.Close()
svc := NewService(config.Config{
Roots: []config.RootConfig{{Name: "DEV", Path: root}},
Scanner: config.ScannerConfig{
MaxDepth: 2,
IgnoreDirs: []string{"node_modules"},
},
}, store)
projects, err := svc.Refresh(context.Background())
if err != nil {
t.Fatalf("refresh: %v", err)
}
if len(projects) != 1 {
t.Fatalf("expected 1 project, got %d", len(projects))
}
err = svc.CheckoutBranch(context.Background(), projects[0].ID, "main")
if err == nil || err.Error() != "project is not a git repository" {
t.Fatalf("expected non-repo error, got %v", err)
}
}
func TestServiceRefreshPreservesFavoriteAndState(t *testing.T) {
root := t.TempDir()
repo := filepath.Join(root, "repo")
if err := os.MkdirAll(repo, 0o755); err != nil {
t.Fatalf("mkdir repo: %v", err)
}
if err := os.WriteFile(filepath.Join(repo, "go.mod"), []byte("module repo\n"), 0o644); err != nil {
t.Fatalf("write go.mod: %v", err)
}
store, err := storage.Open(filepath.Join(root, "stackyard.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
defer store.Close()
svc := NewService(config.Config{
Roots: []config.RootConfig{{Name: "DEV", Path: root}},
Scanner: config.ScannerConfig{MaxDepth: 2},
}, store)
projects, err := svc.Refresh(context.Background())
if err != nil {
t.Fatalf("refresh: %v", err)
}
id := projects[0].ID
if err := svc.SetFavorite(context.Background(), id, true); err != nil {
t.Fatalf("set favorite: %v", err)
}
if err := svc.SetState(context.Background(), id, project.StatePaused); err != nil {
t.Fatalf("set state: %v", err)
}
projects, err = svc.Refresh(context.Background())
if err != nil {
t.Fatalf("refresh second: %v", err)
}
if !projects[0].Favorite || projects[0].State != project.StatePaused {
t.Fatalf("expected favorite/state preserved, got %+v", projects[0])
}
}