package store import ( "errors" "testing" ) func TestCreateProject_ReturnsCreatedProject(t *testing.T) { s := newNativeTasksTestStore(t) project, err := s.CreateProject("Sailing prep", "#3B82F6") if err != nil { t.Fatalf("CreateProject: %v", err) } if project.ID == "" { t.Error("expected a generated ID") } if project.Name != "Sailing prep" { t.Errorf("Name = %q, want %q", project.Name, "Sailing prep") } if project.Color != "#3B82F6" { t.Errorf("Color = %q, want %q", project.Color, "#3B82F6") } if project.Archived { t.Error("expected a newly created project to not be archived") } } func TestGetProjects_ExcludesArchived(t *testing.T) { s := newNativeTasksTestStore(t) active, err := s.CreateProject("Active project", "#111111") if err != nil { t.Fatal(err) } archived, err := s.CreateProject("Archived project", "#222222") if err != nil { t.Fatal(err) } if _, err := s.db.Exec(`UPDATE projects SET archived = 1 WHERE id = ?`, archived.ID); err != nil { t.Fatal(err) } projects, err := s.GetProjects() if err != nil { t.Fatalf("GetProjects: %v", err) } if len(projects) != 1 || projects[0].ID != active.ID { t.Fatalf("expected only the active project, got %+v", projects) } } func TestGetProjectByID_UnknownID_ReturnsErrNotFound(t *testing.T) { s := newNativeTasksTestStore(t) _, err := s.GetProjectByID("does-not-exist") if !errors.Is(err, ErrNativeTaskNotFound) { t.Fatalf("expected ErrNativeTaskNotFound, got %v", err) } } func TestSetTaskProject_UpdatesProjectID(t *testing.T) { s := newNativeTasksTestStore(t) project, err := s.CreateProject("Test project", "#333333") if err != nil { t.Fatal(err) } if err := s.SetTaskProject("real-1", project.ID); err != nil { t.Fatalf("SetTaskProject: %v", err) } task, err := s.GetNativeTaskByID("real-1") if err != nil { t.Fatal(err) } if task.ProjectID != project.ID { t.Errorf("ProjectID = %q, want %q", task.ProjectID, project.ID) } } func TestSetTaskProject_UnknownID_ReturnsErrNotFound(t *testing.T) { s := newNativeTasksTestStore(t) err := s.SetTaskProject("does-not-exist", "") if !errors.Is(err, ErrNativeTaskNotFound) { t.Fatalf("expected ErrNativeTaskNotFound, got %v", err) } } func TestSetProjectBudgetTracked_TogglesFlag(t *testing.T) { s := newNativeTasksTestStore(t) project, err := s.CreateProject("Sailing prep", "#3B82F6") if err != nil { t.Fatal(err) } if err := s.SetProjectBudgetTracked(project.ID, true); err != nil { t.Fatalf("SetProjectBudgetTracked: %v", err) } got, err := s.GetProjectByID(project.ID) if err != nil { t.Fatal(err) } if !got.BudgetTracked { t.Error("expected BudgetTracked = true") } if err := s.SetProjectBudgetTracked(project.ID, false); err != nil { t.Fatal(err) } got, err = s.GetProjectByID(project.ID) if err != nil { t.Fatal(err) } if got.BudgetTracked { t.Error("expected BudgetTracked = false after untoggling") } } func TestSetProjectBudgetTracked_UnknownID_ReturnsErrNotFound(t *testing.T) { s := newNativeTasksTestStore(t) if err := s.SetProjectBudgetTracked("does-not-exist", true); !errors.Is(err, ErrNativeTaskNotFound) { t.Errorf("err = %v, want ErrNativeTaskNotFound", err) } } func TestGetBudgetTrackedProjectIDs_ReturnsOnlyTracked(t *testing.T) { s := newNativeTasksTestStore(t) tracked, err := s.CreateProject("Tracked", "#111111") if err != nil { t.Fatal(err) } if _, err := s.CreateProject("Untracked", "#222222"); err != nil { t.Fatal(err) } if err := s.SetProjectBudgetTracked(tracked.ID, true); err != nil { t.Fatal(err) } ids, err := s.GetBudgetTrackedProjectIDs() if err != nil { t.Fatalf("GetBudgetTrackedProjectIDs: %v", err) } if !ids[tracked.ID] { t.Error("expected tracked project id present") } if len(ids) != 1 { t.Errorf("len(ids) = %d, want 1", len(ids)) } }