crawlkit/progress/progress_test.go
2026-05-02 19:19:53 -07:00

89 lines
1.9 KiB
Go

package progress
import (
"bytes"
"errors"
"log/slog"
"strings"
"testing"
"time"
)
func TestTrackerLogsCIStablePercentLines(t *testing.T) {
var out bytes.Buffer
now := time.Date(2026, 5, 2, 12, 0, 0, 0, time.UTC)
logger := testLogger(&out)
tracker := New(logger, Options{
Name: "sync",
Unit: "channels",
Total: 4,
MinDelta: 2,
Attrs: []any{"source", "api"},
Now: func() time.Time { return now },
})
tracker.Set(1)
tracker.Set(2, "phase", "messages")
tracker.Finish(nil)
logs := out.String()
if strings.Count(logs, `msg="sync progress"`) != 3 {
t.Fatalf("expected start, threshold, and finish lines:\n%s", logs)
}
for _, want := range []string{
`state=started`,
`state=progress`,
`state=finished`,
`unit=channels`,
`done=2`,
`total=4`,
`percent=50.0`,
`completion=50.0%`,
`source=api`,
`phase=messages`,
} {
if !strings.Contains(logs, want) {
t.Fatalf("missing %q in logs:\n%s", want, logs)
}
}
}
func TestTrackerFinishReportsFailure(t *testing.T) {
var out bytes.Buffer
logger := testLogger(&out)
tracker := New(logger, Options{Name: "import", Total: 10})
tracker.Set(3)
tracker.Finish(errors.New("boom"))
logs := out.String()
for _, want := range []string{`state=failed`, `done=3`, `percent=30.0`, `err=boom`} {
if !strings.Contains(logs, want) {
t.Fatalf("missing %q in logs:\n%s", want, logs)
}
}
}
func TestCompletionClampsToRange(t *testing.T) {
if got := Completion(-1, 4); got != "0.0%" {
t.Fatalf("low clamp = %s", got)
}
if got := Completion(5, 4); got != "100.0%" {
t.Fatalf("high clamp = %s", got)
}
if got := Completion(1, 0); got != "" {
t.Fatalf("unknown total = %q", got)
}
}
func testLogger(out *bytes.Buffer) *slog.Logger {
return slog.New(slog.NewTextHandler(out, &slog.HandlerOptions{
ReplaceAttr: func(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
return slog.Attr{}
}
return attr
},
}))
}