rdev/internal/sdlc/artifact_test.go
jordan 56e3f83955 feat: add auth scopes, OpenAPI docs, SDLC guides, and code quality improvements
- Add auth.RequireScope() to all handler routes for proper authorization
- Add SDLC OpenAPI endpoint documentation (state, features, tasks, branches, merge, archive, orchestrator)
- Add SDLC documentation guides (getting-started, cli-reference, api-reference, command-catalog)
- Add artifact_test.go for SDLC artifact coverage
- Add CLAUDE.md rules: auth scopes requirement, error wrapping with %w
- Fix error wrapping to use %w instead of %v throughout codebase
- Improve CLI merge command with conflict detection and resolution
- Fix handler tests to include auth middleware for RequireScope
- Add cookbook tree runner scripts for automated testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:55:50 -07:00

150 lines
3.8 KiB
Go

package sdlc
import (
"testing"
"time"
)
func TestNewArtifact(t *testing.T) {
tests := []struct {
artType ArtifactType
wantPath string
}{
{ArtifactSpec, "spec.md"},
{ArtifactDesign, "design.md"},
{ArtifactTasks, "tasks.md"},
{ArtifactQAPlan, "qa-plan.md"},
{ArtifactReview, "review.md"},
{ArtifactAudit, "audit.md"},
{ArtifactQAResults, "qa-results.md"},
}
for _, tt := range tests {
t.Run(string(tt.artType), func(t *testing.T) {
art := NewArtifact(tt.artType)
if art.Status != StatusPending {
t.Errorf("NewArtifact() status = %v, want %v", art.Status, StatusPending)
}
if art.Path != tt.wantPath {
t.Errorf("NewArtifact() path = %v, want %v", art.Path, tt.wantPath)
}
})
}
}
func TestArtifact_Approve(t *testing.T) {
art := NewArtifact(ArtifactSpec)
art.Approve("user@example.com")
if art.Status != StatusApproved {
t.Errorf("Approve() status = %v, want %v", art.Status, StatusApproved)
}
if art.ApprovedBy != "user@example.com" {
t.Errorf("Approve() approvedBy = %v, want %v", art.ApprovedBy, "user@example.com")
}
if art.ApprovedAt == nil {
t.Error("Approve() approvedAt should not be nil")
}
if art.RejectedBy != "" {
t.Errorf("Approve() should clear rejectedBy, got %v", art.RejectedBy)
}
if art.RejectedAt != nil {
t.Error("Approve() should clear rejectedAt")
}
}
func TestArtifact_Reject(t *testing.T) {
art := NewArtifact(ArtifactSpec)
art.Reject("reviewer@example.com")
if art.Status != StatusRejected {
t.Errorf("Reject() status = %v, want %v", art.Status, StatusRejected)
}
if art.RejectedBy != "reviewer@example.com" {
t.Errorf("Reject() rejectedBy = %v, want %v", art.RejectedBy, "reviewer@example.com")
}
if art.RejectedAt == nil {
t.Error("Reject() rejectedAt should not be nil")
}
}
func TestArtifact_ApproveAfterReject(t *testing.T) {
art := NewArtifact(ArtifactSpec)
// First reject
art.Reject("reviewer@example.com")
if art.Status != StatusRejected {
t.Fatalf("expected rejected status after Reject()")
}
// Then approve
art.Approve("approver@example.com")
if art.Status != StatusApproved {
t.Errorf("Approve() after Reject() status = %v, want %v", art.Status, StatusApproved)
}
if art.RejectedBy != "" {
t.Errorf("Approve() should clear rejectedBy, got %v", art.RejectedBy)
}
if art.RejectedAt != nil {
t.Error("Approve() should clear rejectedAt")
}
}
func TestArtifact_MarkDraft(t *testing.T) {
art := NewArtifact(ArtifactSpec)
art.MarkDraft()
if art.Status != StatusDraft {
t.Errorf("MarkDraft() status = %v, want %v", art.Status, StatusDraft)
}
}
func TestArtifact_MarkPassed(t *testing.T) {
art := NewArtifact(ArtifactQAResults)
art.MarkPassed()
if art.Status != StatusPassed {
t.Errorf("MarkPassed() status = %v, want %v", art.Status, StatusPassed)
}
}
func TestArtifact_MarkFailed(t *testing.T) {
art := NewArtifact(ArtifactQAResults)
art.MarkFailed()
if art.Status != StatusFailed {
t.Errorf("MarkFailed() status = %v, want %v", art.Status, StatusFailed)
}
}
func TestArtifact_MarkNeedsFix(t *testing.T) {
art := NewArtifact(ArtifactReview)
art.MarkNeedsFix()
if art.Status != StatusNeedsFix {
t.Errorf("MarkNeedsFix() status = %v, want %v", art.Status, StatusNeedsFix)
}
}
func TestArtifact_ApprovedAtTimestamp(t *testing.T) {
art := NewArtifact(ArtifactSpec)
before := time.Now().UTC()
art.Approve("user@example.com")
after := time.Now().UTC()
if art.ApprovedAt.Before(before) || art.ApprovedAt.After(after) {
t.Errorf("ApprovedAt %v not in expected range [%v, %v]", art.ApprovedAt, before, after)
}
}
func TestArtifact_RejectedAtTimestamp(t *testing.T) {
art := NewArtifact(ArtifactSpec)
before := time.Now().UTC()
art.Reject("user@example.com")
after := time.Now().UTC()
if art.RejectedAt.Before(before) || art.RejectedAt.After(after) {
t.Errorf("RejectedAt %v not in expected range [%v, %v]", art.RejectedAt, before, after)
}
}