using ClaudeDo.Data.Models; using ClaudeDo.Ui.ViewModels.Islands; using Xunit; using TaskStatus = ClaudeDo.Data.Models.TaskStatus; namespace ClaudeDo.Ui.Tests.ViewModels; /// /// [UX-Struktur A2/A4] Group 1's disabled-reason properties (grayed out with an explanation /// instead of hidden — see task A1) and the hover-or-selected gate for the optional row actions. /// public class TaskRowContextMenuTests { private static TaskRowViewModel MakeRow() => new() { Id = "t1" }; [Fact] public void SendToQueueDisabledReason_Null_When_Sendable() { var row = MakeRow(); row.Status = TaskStatus.Idle; Assert.True(row.CanSendToQueue); Assert.Null(row.SendToQueueDisabledReason); } [Fact] public void SendToQueueDisabledReason_Set_When_AlreadyQueued() { var row = MakeRow(); row.Status = TaskStatus.Queued; Assert.False(row.CanSendToQueue); Assert.NotNull(row.SendToQueueDisabledReason); } [Fact] public void SendToQueueDisabledReason_Set_When_Manual() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.IsManual = true; Assert.False(row.CanSendToQueue); Assert.NotNull(row.SendToQueueDisabledReason); } [Fact] public void CancelDisabledReason_Null_While_Running() { var row = MakeRow(); row.Status = TaskStatus.Running; Assert.Null(row.CancelDisabledReason); } [Fact] public void CancelDisabledReason_Set_When_NotRunning() { var row = MakeRow(); row.Status = TaskStatus.Idle; Assert.NotNull(row.CancelDisabledReason); } [Theory] [InlineData(TaskStatus.Idle)] [InlineData(TaskStatus.Running)] [InlineData(TaskStatus.Done)] public void QuickSessionDisabledReason_Is_Always_Null(TaskStatus status) { var row = MakeRow(); row.Status = status; row.IsManual = true; Assert.Null(row.QuickSessionDisabledReason); } [Fact] public void RefineDisabledReason_Null_When_Refinable() { var row = MakeRow(); row.Status = TaskStatus.Idle; Assert.True(row.CanRefine); Assert.Null(row.RefineDisabledReason); } [Fact] public void RefineDisabledReason_Set_When_Manual() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.IsManual = true; Assert.False(row.CanRefine); Assert.NotNull(row.RefineDisabledReason); } [Fact] public void RefineDisabledReason_Set_When_Refining() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.IsRefining = true; Assert.False(row.CanRefine); Assert.NotNull(row.RefineDisabledReason); } [Fact] public void RefineDisabledReason_Set_When_NotIdle() { var row = MakeRow(); row.Status = TaskStatus.Running; Assert.False(row.CanRefine); Assert.NotNull(row.RefineDisabledReason); } [Fact] public void PlanningDisabledReason_Null_When_OpenAvailable() { var row = MakeRow(); row.Status = TaskStatus.Idle; Assert.True(row.CanOpenPlanningSession); Assert.Null(row.PlanningDisabledReason); } [Fact] public void PlanningDisabledReason_Null_When_PlanningActive() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.PlanningPhase = PlanningPhase.Active; Assert.True(row.CanResumeOrDiscardPlanning); Assert.Null(row.PlanningDisabledReason); } [Fact] public void PlanningDisabledReason_Set_When_Finalized() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.PlanningPhase = PlanningPhase.Finalized; Assert.False(row.CanOpenPlanningSession); Assert.False(row.CanResumeOrDiscardPlanning); Assert.False(row.CanFinalizePlanning); Assert.NotNull(row.PlanningDisabledReason); } [Fact] public void PlanningDisabledReason_Set_When_Manual() { var row = MakeRow(); row.Status = TaskStatus.Idle; row.IsManual = true; Assert.NotNull(row.PlanningDisabledReason); } [Theory] [InlineData(false, false, false)] [InlineData(true, false, true)] [InlineData(false, true, true)] [InlineData(true, true, true)] public void ShowRowActions_Follows_Hover_Or_Selection(bool isHovered, bool isSelected, bool expected) { var row = MakeRow(); row.IsHovered = isHovered; row.IsSelected = isSelected; Assert.Equal(expected, row.ShowRowActions); } }