package routes import ( "archive/tar" "compress/gzip" "io" "net/http" "net/http/httptest" "os" "os/exec" "path/filepath" "strings" "testing" "time" gogit "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "gitview/internal/config" ) // testWorkspace uses real Git objects so the handlers exercise repository behavior. func testWorkspace(t *testing.T) (*config.Config, string) { t.Helper() scan := t.TempDir() path := filepath.Join(scan, "sample") repo, err := gogit.PlainInit(path, false) if err != nil { t.Fatal(err) } if err := repo.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.NewBranchReferenceName("main"))); err != nil { t.Fatal(err) } wt, err := repo.Worktree() if err != nil { t.Fatal(err) } for name, content := range map[string]string{"README.md": "# Sample project\n\nA useful README.\n", "src/main.go": "package main\n\nfunc main() {}\n", "plain.unknownextension": "hello \n"} { if err := os.MkdirAll(filepath.Dir(filepath.Join(path, name)), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(path, name), []byte(content), 0644); err != nil { t.Fatal(err) } } if _, err := wt.Add("."); err != nil { t.Fatal(err) } signature := &object.Signature{Name: "Test Author", Email: "author@example.com", When: time.Date(2026, 1, 2, 12, 0, 0, 0, time.UTC)} hash, err := wt.Commit("Initial project", &gogit.CommitOptions{Author: signature}) if err != nil { t.Fatal(err) } if _, err := repo.CreateTag("v1.0.0", hash, nil); err != nil { t.Fatal(err) } if err := repo.Storer.SetReference(plumbing.NewHashReference(plumbing.NewBranchReferenceName("develop"), hash)); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(path, "description"), []byte("A sample repository"), 0644); err != nil { t.Fatal(err) } c := &config.Config{} c.Repo.ScanPath = scan c.Repo.MainBranch = []string{"main", "master"} c.Repo.Readme = []string{"README.md"} c.Dirs.Templates, _ = filepath.Abs("../../templates") c.Dirs.Static, _ = filepath.Abs("../../static") c.Meta.Title = "Gitview" c.Meta.SyntaxHighlight = "github" return c, hash.String() } func TestRepositoryBrowsing(t *testing.T) { c, hash := testWorkspace(t) handler := Handlers(c) for _, tt := range []struct { path, contains string status int }{ {"/", "sample", 200}, {"/sample", "Sample project", 200}, {"/sample/tree/main/", "README.md", 200}, {"/sample/tree/main/src", "main.go", 200}, {"/sample/blob/main/src/main.go", "chroma", 200}, {"/sample/blob/main/plain.unknownextension", "hello", 200}, {"/sample/blob/main/src/main.go?raw=true", "package main", 200}, {"/sample/log/main", "Initial project", 200}, {"/sample/commit/" + hash, "diff-add", 200}, {"/sample/refs/", "v1.0.0", 200}, {"/static/app.js", "filterRepositories", 200}, {"/missing", "could not be found", 404}, {"/sample/tree/missing/", "could not be found", 404}, {"/sample/blob/main/missing", "could not be found", 404}, {"/sample/tree/main/missing", "could not be found", 404}, {"/sample/unknown", "could not be found", 404}, {"/unknown/path/again", "could not be found", 404}, } { t.Run(tt.path, func(t *testing.T) { w := httptest.NewRecorder() handler.ServeHTTP(w, httptest.NewRequest("GET", tt.path, nil)) if w.Code != tt.status || !strings.Contains(w.Body.String(), tt.contains) { t.Fatalf("status %d, expected %d containing %q; body: %.500s", w.Code, tt.status, tt.contains, w.Body.String()) } }) } w := httptest.NewRecorder() handler.ServeHTTP(w, httptest.NewRequest("GET", "/sample", nil)) if strings.Contains(w.Body.String(), "