diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-07-16 06:31:26 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-07-16 06:31:26 +0000 |
| commit | 06f34745698665be807d59cd143d6e8c5174115c (patch) | |
| tree | 41f3ea8aa35cf18ad63fa2186425993c16a3553b /internal/store/estimate_inference_test.go | |
| parent | 73c3440c579e645ada20f761bbc3eb1c43927e7f (diff) | |
Infer a default estimate from same-project/label averages
Diffstat (limited to 'internal/store/estimate_inference_test.go')
| -rw-r--r-- | internal/store/estimate_inference_test.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/internal/store/estimate_inference_test.go b/internal/store/estimate_inference_test.go new file mode 100644 index 0000000..9321f11 --- /dev/null +++ b/internal/store/estimate_inference_test.go @@ -0,0 +1,90 @@ +// internal/store/estimate_inference_test.go +package store + +import ( + "testing" + "time" + + "task-dashboard/internal/models" +) + +func TestAverageEstimateForProject_AveragesUserEnteredEstimates(t *testing.T) { + s := newNativeTasksTestStore(t) + project, err := s.CreateProject("Sailing prep", "#3B82F6") + if err != nil { + t.Fatal(err) + } + due := time.Now() + for _, minutes := range []int{30, 60} { + task := models.Task{ID: newTaskID(), Content: "task", ProjectID: project.ID, EstimatedMinutes: minutes, DueDate: &due} + if err := s.CreateNativeTask(task); err != nil { + t.Fatal(err) + } + } + // An unestimated task under the same project must not skew the average. + if err := s.CreateNativeTask(models.Task{ID: "t-unestimated", Content: "no estimate", ProjectID: project.ID}); err != nil { + t.Fatal(err) + } + + avg, ok, err := s.AverageEstimateForProject(project.ID) + if err != nil { + t.Fatalf("AverageEstimateForProject: %v", err) + } + if !ok { + t.Fatal("expected ok = true") + } + if avg != 45 { + t.Errorf("avg = %d, want 45", avg) + } +} + +func TestAverageEstimateForProject_NoEstimatedTasks_ReturnsNotOK(t *testing.T) { + s := newNativeTasksTestStore(t) + project, err := s.CreateProject("Empty", "#111111") + if err != nil { + t.Fatal(err) + } + + _, ok, err := s.AverageEstimateForProject(project.ID) + if err != nil { + t.Fatal(err) + } + if ok { + t.Error("expected ok = false when no tasks have an estimate") + } +} + +func TestAverageEstimateForLabel_AveragesUserEnteredEstimates(t *testing.T) { + s := newNativeTasksTestStore(t) + for _, minutes := range []int{20, 40} { + task := models.Task{ID: newTaskID(), Content: "task", Labels: []string{"errands"}, EstimatedMinutes: minutes} + if err := s.CreateNativeTask(task); err != nil { + t.Fatal(err) + } + } + if err := s.CreateNativeTask(models.Task{ID: "t-other-label", Content: "other", Labels: []string{"unrelated"}, EstimatedMinutes: 100}); err != nil { + t.Fatal(err) + } + + avg, ok, err := s.AverageEstimateForLabel("errands") + if err != nil { + t.Fatalf("AverageEstimateForLabel: %v", err) + } + if !ok { + t.Fatal("expected ok = true") + } + if avg != 30 { + t.Errorf("avg = %d, want 30", avg) + } +} + +func TestAverageEstimateForLabel_NoMatches_ReturnsNotOK(t *testing.T) { + s := newNativeTasksTestStore(t) + _, ok, err := s.AverageEstimateForLabel("nonexistent") + if err != nil { + t.Fatal(err) + } + if ok { + t.Error("expected ok = false") + } +} |
