This commit captures the current state before implementing the composable monorepo template system. Key changes included: Infrastructure: - Add CockroachDB provisioner adapter for database provisioning - Add Redis provisioner adapter for cache provisioning - Add build events system with PostgreSQL storage - Add WebSocket endpoint for real-time build progress Code agent improvements: - Fix Claude Code adapter to use default allowed tools instead of dangerously-skip-permissions - Add context-aware stream closing for cancellation support - Improve parser tests for edge cases Build system: - Add build event constants and metrics - Remove deprecated git_operations.go (replaced by pod_git_operations.go) - Add rollback logic for multi-step provisioning operations Documentation: - Add composable-monorepo feature documentation - Add DNS/Cloudflare service documentation - Update deployment and troubleshooting guides Cookbooks: - Add fullstack-app cookbook - Refactor landing-test with shared library Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
128 lines
3.5 KiB
Go
128 lines
3.5 KiB
Go
package service
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/orchard9/rdev/internal/adapter/memory"
|
|
"github.com/orchard9/rdev/internal/domain"
|
|
)
|
|
|
|
func TestBuildProgressTracker_Start(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
tracker.Start("task-1", "project-1")
|
|
|
|
phase, percentage, ok := tracker.GetProgress("task-1")
|
|
if !ok {
|
|
t.Fatal("expected to find progress for task-1")
|
|
}
|
|
if phase != domain.BuildPhaseStarting {
|
|
t.Errorf("got phase %q, want %q", phase, domain.BuildPhaseStarting)
|
|
}
|
|
if percentage < 0 || percentage > 100 {
|
|
t.Errorf("got invalid percentage %f", percentage)
|
|
}
|
|
}
|
|
|
|
func TestBuildProgressTracker_RecordToolUse(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
tracker.Start("task-1", "project-1")
|
|
|
|
// Simulate reading phase
|
|
tracker.RecordToolUse("task-1", "Read")
|
|
phase, _, _ := tracker.GetProgress("task-1")
|
|
if phase != domain.BuildPhaseReading {
|
|
t.Errorf("after Read tool, got phase %q, want %q", phase, domain.BuildPhaseReading)
|
|
}
|
|
|
|
// Simulate writing phase
|
|
tracker.RecordToolUse("task-1", "Write")
|
|
phase, _, _ = tracker.GetProgress("task-1")
|
|
if phase != domain.BuildPhaseWriting {
|
|
t.Errorf("after Write tool, got phase %q, want %q", phase, domain.BuildPhaseWriting)
|
|
}
|
|
|
|
// Simulate testing phase
|
|
tracker.RecordToolUse("task-1", "Bash")
|
|
phase, _, _ = tracker.GetProgress("task-1")
|
|
if phase != domain.BuildPhaseTesting {
|
|
t.Errorf("after Bash tool, got phase %q, want %q", phase, domain.BuildPhaseTesting)
|
|
}
|
|
}
|
|
|
|
func TestBuildProgressTracker_Complete(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
tracker.Start("task-1", "project-1")
|
|
tracker.Complete("task-1", true)
|
|
|
|
// After completion, task should be removed
|
|
_, _, ok := tracker.GetProgress("task-1")
|
|
if ok {
|
|
t.Error("expected task to be removed after completion")
|
|
}
|
|
}
|
|
|
|
func TestBuildProgressTracker_PercentageIncrease(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
tracker.Start("task-1", "project-1")
|
|
|
|
_, initialPercent, _ := tracker.GetProgress("task-1")
|
|
|
|
// Record several tool uses
|
|
for i := 0; i < 5; i++ {
|
|
tracker.RecordToolUse("task-1", "Read")
|
|
}
|
|
|
|
_, newPercent, _ := tracker.GetProgress("task-1")
|
|
if newPercent <= initialPercent {
|
|
t.Errorf("expected percentage to increase from %f, got %f", initialPercent, newPercent)
|
|
}
|
|
}
|
|
|
|
func TestBuildProgressTracker_NonexistentTask(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
// These should not panic
|
|
tracker.RecordToolUse("nonexistent", "Read")
|
|
tracker.RecordOutput("nonexistent")
|
|
tracker.Complete("nonexistent", true)
|
|
|
|
_, _, ok := tracker.GetProgress("nonexistent")
|
|
if ok {
|
|
t.Error("expected not to find progress for nonexistent task")
|
|
}
|
|
}
|
|
|
|
func TestBuildProgressTracker_EmitsEvents(t *testing.T) {
|
|
streams := memory.NewStreamPublisher()
|
|
tracker := NewBuildProgressTracker(streams)
|
|
|
|
// Subscribe to events
|
|
events, cleanup := streams.Subscribe("task-1")
|
|
defer cleanup()
|
|
|
|
// Start should emit a progress event
|
|
tracker.Start("task-1", "project-1")
|
|
|
|
select {
|
|
case event := <-events:
|
|
if event.Type != "build.progress" {
|
|
t.Errorf("got event type %q, want build.progress", event.Type)
|
|
}
|
|
phase, ok := event.Data["phase"].(string)
|
|
if !ok || phase != "starting" {
|
|
t.Errorf("got phase %v, want 'starting'", event.Data["phase"])
|
|
}
|
|
default:
|
|
t.Error("expected progress event to be published")
|
|
}
|
|
}
|