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(), "