diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 964784e..386ba0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: run: | total=$(go tool cover -func=coverage.out | awk '/^total:/ {gsub("%","",$3); print $3}') # Current enforced coverage floor. Codex PRs raise this incrementally toward 90%. - min=45.0 + min=50.0 awk -v t="$total" -v m="$min" 'BEGIN { if (t+0 < m+0) { printf "Coverage %.1f%% is below floor %.1f%%\n", t, m diff --git a/render/depgraph_test.go b/render/depgraph_test.go index 0cabb75..c5a9c07 100644 --- a/render/depgraph_test.go +++ b/render/depgraph_test.go @@ -103,3 +103,32 @@ func TestDepgraphRendersExternalDepsAndSummarySection(t *testing.T) { } } } + +func TestDepgraphWrapsLongDependencyLines(t *testing.T) { + project := scanner.DepsProject{ + Root: t.TempDir(), + Files: []scanner.FileAnalysis{ + {Path: "main.go", Functions: []string{"main"}}, + }, + ExternalDeps: map[string][]string{ + "go": { + "github.com/example/super-long-package-alpha", + "github.com/example/super-long-package-beta", + "github.com/example/super-long-package-gamma", + "github.com/example/super-long-package-delta", + "github.com/example/super-long-package-epsilon", + }, + }, + } + + var buf bytes.Buffer + Depgraph(&buf, project) + output := buf.String() + + if !strings.Contains(output, "Go:") { + t.Fatalf("expected go language dependency label, got:\n%s", output) + } + if !strings.Contains(output, "super-long-package-alpha") || !strings.Contains(output, "super-long-package-epsilon") { + t.Fatalf("expected long dependency names to be present, got:\n%s", output) + } +} diff --git a/render/skyline_test.go b/render/skyline_test.go index 23ace2b..5599d15 100644 --- a/render/skyline_test.go +++ b/render/skyline_test.go @@ -274,3 +274,79 @@ func TestSkylineMinMax(t *testing.T) { }) } } + +func TestSkylineTickCmd(t *testing.T) { + cmd := tickCmd() + if cmd == nil { + t.Fatal("expected non-nil tick command") + } + + msg := cmd() + if _, ok := msg.(tickMsg); !ok { + t.Fatalf("expected tickMsg, got %T", msg) + } +} + +func TestSkylineAnimationModelInit(t *testing.T) { + m := animationModel{} + if cmd := m.Init(); cmd == nil { + t.Fatal("expected non-nil init command") + } +} + +func TestSkylineAnimationModelUpdatePhaseTwo(t *testing.T) { + t.Run("starts shooting star at configured frame", func(t *testing.T) { + m := animationModel{ + phase: 2, + frame: 9, + sceneLeft: 3, + } + + updated, cmd := m.Update(tickMsg(time.Now())) + if cmd == nil { + t.Fatal("expected tick command") + } + got := updated.(animationModel) + if !got.shootingStarActive { + t.Fatal("expected shooting star to become active") + } + if got.shootingStarCol != m.sceneLeft { + t.Fatalf("shootingStarCol = %d, want %d", got.shootingStarCol, m.sceneLeft) + } + }) + + t.Run("deactivates shooting star after leaving scene", func(t *testing.T) { + m := animationModel{ + phase: 2, + frame: 15, + sceneRight: 10, + shootingStarActive: true, + shootingStarCol: 9, + } + + updated, cmd := m.Update(tickMsg(time.Now())) + if cmd == nil { + t.Fatal("expected tick command") + } + got := updated.(animationModel) + if got.shootingStarActive { + t.Fatal("expected shooting star to deactivate after leaving scene") + } + }) + + t.Run("quits after final frame", func(t *testing.T) { + m := animationModel{ + phase: 2, + frame: 39, + } + + updated, cmd := m.Update(tickMsg(time.Now())) + if cmd == nil { + t.Fatal("expected quit command") + } + got := updated.(animationModel) + if !got.done { + t.Fatal("expected animation model to be marked done") + } + }) +}