a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
158 lines
4.1 KiB
Go
158 lines
4.1 KiB
Go
package docs
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
)
|
|
|
|
func buildBlamedGraph(t *testing.T) *graph.Graph {
|
|
t.Helper()
|
|
g := graph.New()
|
|
now := time.Now().Unix()
|
|
staleTS := time.Now().Add(-400 * 24 * time.Hour).Unix()
|
|
|
|
g.AddNode(&graph.Node{
|
|
ID: "pkg/a.go::Recent", Kind: graph.KindFunction, Name: "Recent",
|
|
FilePath: "pkg/a.go", StartLine: 10, Language: "go",
|
|
Meta: map[string]any{
|
|
"last_authored": map[string]any{
|
|
"email": "alice@example.com", "timestamp": now,
|
|
"commit": "deadbeef1234",
|
|
},
|
|
},
|
|
})
|
|
g.AddNode(&graph.Node{
|
|
ID: "pkg/a.go::Old", Kind: graph.KindFunction, Name: "Old",
|
|
FilePath: "pkg/a.go", StartLine: 30, Language: "go",
|
|
Meta: map[string]any{
|
|
"last_authored": map[string]any{
|
|
"email": "alice@example.com", "timestamp": staleTS,
|
|
"commit": "abcd5678abcd",
|
|
},
|
|
},
|
|
})
|
|
g.AddNode(&graph.Node{
|
|
ID: "pkg/b.go::Bob", Kind: graph.KindMethod, Name: "Bob",
|
|
FilePath: "pkg/b.go", StartLine: 5, Language: "go",
|
|
Meta: map[string]any{
|
|
"last_authored": map[string]any{
|
|
"email": "bob@example.com", "timestamp": now,
|
|
"commit": "01234567",
|
|
},
|
|
},
|
|
})
|
|
return g
|
|
}
|
|
|
|
type fakeHistory struct {
|
|
events []HistoryEvent
|
|
}
|
|
|
|
func (f *fakeHistory) HistorySince(since time.Time) []HistoryEvent {
|
|
var out []HistoryEvent
|
|
for _, e := range f.events {
|
|
if e.Timestamp.After(since) {
|
|
out = append(out, e)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func TestGenerate_AllSections(t *testing.T) {
|
|
g := buildBlamedGraph(t)
|
|
hist := &fakeHistory{events: []HistoryEvent{
|
|
{FilePath: "pkg/a.go", Kind: "modified", NodesAdded: 1, NodesRemoved: 0, Timestamp: time.Now()},
|
|
{FilePath: "pkg/b.go", Kind: "created", NodesAdded: 3, NodesRemoved: 0, Timestamp: time.Now()},
|
|
}}
|
|
bundle, err := Generate(Deps{Graph: g, History: hist}, Options{Since: 24 * time.Hour})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if len(bundle.RecentChanges) != 2 {
|
|
t.Errorf("recent changes = %d, want 2", len(bundle.RecentChanges))
|
|
}
|
|
if len(bundle.OwnershipRows) != 2 {
|
|
t.Errorf("owners = %d, want 2", len(bundle.OwnershipRows))
|
|
}
|
|
if len(bundle.StaleCodeRows) != 1 {
|
|
t.Errorf("stale rows = %d, want 1", len(bundle.StaleCodeRows))
|
|
}
|
|
}
|
|
|
|
func TestGenerate_SectionsFilter(t *testing.T) {
|
|
g := buildBlamedGraph(t)
|
|
bundle, err := Generate(Deps{Graph: g},
|
|
Options{Sections: []string{"stale"}})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if len(bundle.OwnershipRows) != 0 {
|
|
t.Errorf("ownership shouldn't render when not in sections; got %d", len(bundle.OwnershipRows))
|
|
}
|
|
if len(bundle.RecentChanges) != 0 {
|
|
t.Errorf("recent shouldn't render; got %d", len(bundle.RecentChanges))
|
|
}
|
|
if len(bundle.StaleCodeRows) != 1 {
|
|
t.Errorf("stale rows = %d, want 1", len(bundle.StaleCodeRows))
|
|
}
|
|
}
|
|
|
|
func TestRenderMarkdown_HasSections(t *testing.T) {
|
|
g := buildBlamedGraph(t)
|
|
bundle, err := Generate(Deps{Graph: g}, Options{})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
md := RenderMarkdown(bundle)
|
|
for _, want := range []string{"# Docs Bundle", "## Recent Changes", "## Ownership", "## Stale Code", "## Blame Enrichment"} {
|
|
if !strings.Contains(md, want) {
|
|
t.Errorf("markdown missing %q", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRenderJSON_RoundTrips(t *testing.T) {
|
|
g := buildBlamedGraph(t)
|
|
bundle, err := Generate(Deps{Graph: g}, Options{})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
data, err := RenderJSON(bundle)
|
|
if err != nil {
|
|
t.Fatalf("RenderJSON: %v", err)
|
|
}
|
|
if !strings.Contains(string(data), `"sections"`) {
|
|
t.Error("JSON should include sections field")
|
|
}
|
|
}
|
|
|
|
func TestGenerate_WithBlame(t *testing.T) {
|
|
g := buildBlamedGraph(t)
|
|
called := 0
|
|
bundle, err := Generate(Deps{
|
|
Graph: g,
|
|
Blame: func() (int, map[string]int, error) {
|
|
called++
|
|
return 42, map[string]int{"gortex": 42}, nil
|
|
},
|
|
}, Options{IncludeBlame: true})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if called != 1 {
|
|
t.Errorf("blame runner called %d times, want 1", called)
|
|
}
|
|
if bundle.Blame == nil || bundle.Blame.Enriched != 42 {
|
|
t.Fatalf("blame summary missing or wrong: %+v", bundle.Blame)
|
|
}
|
|
}
|
|
|
|
func TestGenerate_NilGraphFails(t *testing.T) {
|
|
if _, err := Generate(Deps{}, Options{}); err == nil {
|
|
t.Error("expected error when graph is nil")
|
|
}
|
|
}
|