@@ -462,3 +462,74 @@ func TestSpec_PublicAPI_UpdateScheduleInOnBlock(t *testing.T) {
462462 assert .Error (t , err , "UpdateScheduleInOnBlock should return error when no frontmatter lines present" )
463463 })
464464}
465+
466+ // TestSpec_PublicAPI_CalculateWorkflowHealth validates the pure health computation documented in the spec.
467+ // Spec: "Pure health computation for a single workflow"
468+ func TestSpec_PublicAPI_CalculateWorkflowHealth (t * testing.T ) {
469+ t .Run ("returns N/A display values for empty runs" , func (t * testing.T ) {
470+ health := cli .CalculateWorkflowHealth ("my-workflow" , nil , 80.0 )
471+ assert .Equal (t , "my-workflow" , health .WorkflowName , "WorkflowName should be the provided name" )
472+ assert .Equal (t , "N/A" , health .DisplayRate , "DisplayRate should be N/A for empty runs" )
473+ assert .Equal (t , "→" , health .Trend , "Trend should be stable for empty runs" )
474+ assert .Equal (t , 0 , health .TotalRuns , "TotalRuns should be 0 for empty runs" )
475+ })
476+
477+ t .Run ("counts successful and failed runs correctly" , func (t * testing.T ) {
478+ runs := []cli.WorkflowRun {
479+ {WorkflowName : "my-workflow" , Conclusion : "success" },
480+ {WorkflowName : "my-workflow" , Conclusion : "success" },
481+ {WorkflowName : "my-workflow" , Conclusion : "failure" },
482+ }
483+ health := cli .CalculateWorkflowHealth ("my-workflow" , runs , 80.0 )
484+ assert .Equal (t , 3 , health .TotalRuns , "TotalRuns should count all runs" )
485+ assert .Equal (t , 2 , health .SuccessCount , "SuccessCount should count runs with success conclusion" )
486+ assert .Equal (t , 1 , health .FailureCount , "FailureCount should count failure-conclusion runs" )
487+ assert .InDelta (t , 66.67 , health .SuccessRate , 0.1 , "SuccessRate should be the percentage of successes" )
488+ })
489+
490+ t .Run ("sets BelowThresh true when success rate is below threshold" , func (t * testing.T ) {
491+ runs := []cli.WorkflowRun {
492+ {WorkflowName : "my-workflow" , Conclusion : "failure" },
493+ {WorkflowName : "my-workflow" , Conclusion : "failure" },
494+ }
495+ health := cli .CalculateWorkflowHealth ("my-workflow" , runs , 80.0 )
496+ assert .True (t , health .BelowThresh , "BelowThresh should be true when success rate is below threshold" )
497+ })
498+
499+ t .Run ("sets BelowThresh false when success rate meets threshold" , func (t * testing.T ) {
500+ runs := []cli.WorkflowRun {
501+ {WorkflowName : "my-workflow" , Conclusion : "success" },
502+ {WorkflowName : "my-workflow" , Conclusion : "success" },
503+ {WorkflowName : "my-workflow" , Conclusion : "success" },
504+ {WorkflowName : "my-workflow" , Conclusion : "success" },
505+ }
506+ health := cli .CalculateWorkflowHealth ("my-workflow" , runs , 80.0 )
507+ assert .False (t , health .BelowThresh , "BelowThresh should be false when all runs succeed" )
508+ assert .Equal (t , 4 , health .SuccessCount , "SuccessCount should count all successful runs" )
509+ })
510+ }
511+
512+ // TestSpec_PublicAPI_CalculateHealthSummary validates the aggregate health computation documented in the spec.
513+ // Spec: "Aggregate health computation"
514+ func TestSpec_PublicAPI_CalculateHealthSummary (t * testing.T ) {
515+ t .Run ("returns correct totals for empty workflow list" , func (t * testing.T ) {
516+ summary := cli .CalculateHealthSummary (nil , "30d" , 80.0 )
517+ assert .Equal (t , "30d" , summary .Period , "Period should match the input period" )
518+ assert .Equal (t , 0 , summary .TotalWorkflows , "TotalWorkflows should be 0 for empty input" )
519+ assert .Equal (t , 0 , summary .HealthyWorkflows , "HealthyWorkflows should be 0 for empty input" )
520+ })
521+
522+ t .Run ("counts healthy workflows and preserves period" , func (t * testing.T ) {
523+ whs := []cli.WorkflowHealth {
524+ {WorkflowName : "wf-a" , SuccessRate : 90.0 , BelowThresh : false },
525+ {WorkflowName : "wf-b" , SuccessRate : 50.0 , BelowThresh : true },
526+ {WorkflowName : "wf-c" , SuccessRate : 100.0 , BelowThresh : false },
527+ }
528+ summary := cli .CalculateHealthSummary (whs , "7d" , 80.0 )
529+ assert .Equal (t , "7d" , summary .Period , "Period should be preserved in the summary" )
530+ assert .Equal (t , 3 , summary .TotalWorkflows , "TotalWorkflows should equal input workflow count" )
531+ assert .Equal (t , 2 , summary .HealthyWorkflows , "HealthyWorkflows should count workflows with SuccessRate >= threshold" )
532+ assert .Equal (t , 1 , summary .BelowThreshold , "BelowThreshold should count workflows with BelowThresh set" )
533+ assert .Len (t , summary .Workflows , 3 , "Workflows should include all input workflows" )
534+ })
535+ }
0 commit comments