chore(claude-do): TaskRowViewModel: manuelle OnPropertyChanged-Kette auf [Noti
src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs enthält ~107 handgeschriebene OnPropertyChanged(nameof(...))-Aufrufe in partial void OnXChanged-Methoden. Das Projekt nutzt an anderen Stellen den Generator: [NotifyPropertyChangedFor] in DetailsIslandViewModel.cs, ConflictResolverViewModel.cs, AgentConfigEditorViewModel.cs, Installer/WizardViewModel.cs. Das ist die eine Datei, in der eine ve ClaudeDo-Task: 87976462-5845-4e01-8233-32afadca02bd
This commit is contained in:
@@ -8,67 +8,206 @@ namespace ClaudeDo.Ui.ViewModels.Islands;
|
|||||||
public sealed partial class TaskRowViewModel : ViewModelBase
|
public sealed partial class TaskRowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
public required string Id { get; init; }
|
public required string Id { get; init; }
|
||||||
[ObservableProperty] private int _number;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowNumberBadge))]
|
||||||
|
private int _number;
|
||||||
[ObservableProperty] private string _title = "";
|
[ObservableProperty] private string _title = "";
|
||||||
[ObservableProperty] private string _listName = "";
|
[ObservableProperty] private string _listName = "";
|
||||||
[ObservableProperty] private bool _done;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsOverdue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanAddToMyDay))]
|
||||||
|
private bool _done;
|
||||||
[ObservableProperty] private bool _isStarred;
|
[ObservableProperty] private bool _isStarred;
|
||||||
[ObservableProperty] private bool _isMyDay;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private bool _isSelected;
|
[NotifyPropertyChangedFor(nameof(CanAddToMyDay))]
|
||||||
[ObservableProperty] private TaskStatus _status;
|
private bool _isMyDay;
|
||||||
[ObservableProperty] private PlanningPhase _planningPhase;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private string? _branch;
|
[NotifyPropertyChangedFor(nameof(ShowRowActions))]
|
||||||
|
private bool _isSelected;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipClass))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusLabel))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowStatusChip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsRunning))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsWaitingForReview))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsParked))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsQueued))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsWaiting))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasFailureReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(FailureReasonTooltip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipTooltip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDraft))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanned))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanOpenPlanningSession))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRemoveFromQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRefine))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CancelDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(RefineDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(PlanningDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(MarkAsDisabledReason))]
|
||||||
|
private TaskStatus _status;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanningParent))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(PlanningBadge))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowStatusChip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanActive))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanFinalized))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanOpenPlanningSession))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanResumeOrDiscardPlanning))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanQueuePlan))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanFinalizePlanning))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRefine))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(RefineDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(PlanningDisabledReason))]
|
||||||
|
private PlanningPhase _planningPhase;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasBranch))]
|
||||||
|
private string? _branch;
|
||||||
[ObservableProperty] private string? _diffStat;
|
[ObservableProperty] private string? _diffStat;
|
||||||
[ObservableProperty] private ClaudeDo.Data.Models.WorktreeState? _worktreeState;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private string? _worktreePath;
|
[NotifyPropertyChangedFor(nameof(IsParked))]
|
||||||
[ObservableProperty] private DateTime? _scheduledFor;
|
[NotifyPropertyChangedFor(nameof(StatusLabel))]
|
||||||
[ObservableProperty] private int _diffAdditions;
|
private ClaudeDo.Data.Models.WorktreeState? _worktreeState;
|
||||||
[ObservableProperty] private int _diffDeletions;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private bool _dropHintAbove;
|
[NotifyPropertyChangedFor(nameof(CanOpenWorktree))]
|
||||||
[ObservableProperty] private bool _dropHintBelow;
|
[NotifyPropertyChangedFor(nameof(OpenWorktreeDisabledReason))]
|
||||||
[ObservableProperty] private string? _parentTaskId;
|
private string? _worktreePath;
|
||||||
[ObservableProperty] private string? _createdBy;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private string? _blockedByTaskId;
|
[NotifyPropertyChangedFor(nameof(IsOverdue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasSchedule))]
|
||||||
|
private DateTime? _scheduledFor;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasDiff))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(DiffAdditionsText))]
|
||||||
|
private int _diffAdditions;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasDiff))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(DiffDeletionsText))]
|
||||||
|
private int _diffDeletions;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDropTarget))]
|
||||||
|
private bool _dropHintAbove;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDropTarget))]
|
||||||
|
private bool _dropHintBelow;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsChild))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsAgentSuggested))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowAsChild))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDraft))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanned))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanOpenPlanningSession))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(PlanningDisabledReason))]
|
||||||
|
private string? _parentTaskId;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsAgentSuggested))]
|
||||||
|
private string? _createdBy;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsQueued))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsWaiting))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipClass))]
|
||||||
|
private string? _blockedByTaskId;
|
||||||
[ObservableProperty] private string? _dependsOnTaskId;
|
[ObservableProperty] private string? _dependsOnTaskId;
|
||||||
[ObservableProperty] private bool _isExpanded = true;
|
[ObservableProperty] private bool _isExpanded = true;
|
||||||
[ObservableProperty] private bool _hasPlanningChildren;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private bool _hasQueuedSubtasks;
|
[NotifyPropertyChangedFor(nameof(IsPlanningParent))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanQueuePlan))]
|
||||||
|
private bool _hasPlanningChildren;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRemoveFromQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanQueuePlan))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
private bool _hasQueuedSubtasks;
|
||||||
[ObservableProperty] private bool _showListChip = true;
|
[ObservableProperty] private bool _showListChip = true;
|
||||||
[ObservableProperty] private bool _parentFinalized;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private bool _parentInView = true;
|
[NotifyPropertyChangedFor(nameof(IsDraft))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanned))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
private bool _parentFinalized;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowAsChild))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDraft))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsPlanned))]
|
||||||
|
private bool _parentInView = true;
|
||||||
// The three below are extrinsic — computed and assigned by TasksIslandViewModel.Regroup
|
// The three below are extrinsic — computed and assigned by TasksIslandViewModel.Regroup
|
||||||
// (it alone has the cross-row graph needed to walk DependsOnTaskId chains), mirroring how
|
// (it alone has the cross-row graph needed to walk DependsOnTaskId chains), mirroring how
|
||||||
// ParentInView is assigned by the same pass rather than derived locally.
|
// ParentInView is assigned by the same pass rather than derived locally.
|
||||||
[ObservableProperty] private bool _showAsChainMember;
|
[ObservableProperty] private bool _showAsChainMember;
|
||||||
[ObservableProperty] private int? _chainStep;
|
[ObservableProperty] private int? _chainStep;
|
||||||
[ObservableProperty] private string? _chainAfterLabel;
|
[ObservableProperty] private string? _chainAfterLabel;
|
||||||
[ObservableProperty] private int _roadblockCount;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasRoadblock))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(RoadblockTooltip))]
|
||||||
|
private int _roadblockCount;
|
||||||
// Only meaningful when Status=Failed; stamped by TaskRunner.MarkFailed. "unknown" for a
|
// Only meaningful when Status=Failed; stamped by TaskRunner.MarkFailed. "unknown" for a
|
||||||
// Failed task that predates this field. Null on every other status.
|
// Failed task that predates this field. Null on every other status.
|
||||||
[ObservableProperty] private string? _failureReason;
|
[ObservableProperty]
|
||||||
[ObservableProperty] private int? _failureTurnsUsed;
|
[NotifyPropertyChangedFor(nameof(HasFailureReason))]
|
||||||
[ObservableProperty] private int? _failureMaxTurns;
|
[NotifyPropertyChangedFor(nameof(FailureReasonLabel))]
|
||||||
[ObservableProperty] private bool _isRefining;
|
[NotifyPropertyChangedFor(nameof(FailureReasonTooltip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipTooltip))]
|
||||||
|
private string? _failureReason;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(FailureReasonTooltip))]
|
||||||
|
private int? _failureTurnsUsed;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(FailureReasonTooltip))]
|
||||||
|
private int? _failureMaxTurns;
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRefine))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(RefineDisabledReason))]
|
||||||
|
private bool _isRefining;
|
||||||
// Manual = a reminder only the user can do. Every "hand this to Claude" affordance is hidden
|
// Manual = a reminder only the user can do. Every "hand this to Claude" affordance is hidden
|
||||||
// and automation skips it; opening a hand-driven ConPTY session stays allowed.
|
// and automation skips it; opening a hand-driven ConPTY session stays allowed.
|
||||||
[ObservableProperty] private bool _isManual;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ManualBadge))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanRefine))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanOpenPlanningSession))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(RefineDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(PlanningDisabledReason))]
|
||||||
|
private bool _isManual;
|
||||||
// Set by the shell from Mission Control's open ConPTY panes: this task has a live hand-driven
|
// Set by the shell from Mission Control's open ConPTY panes: this task has a live hand-driven
|
||||||
// session, which outranks the persisted status on the lifecycle chip (an interactive task is
|
// session, which outranks the persisted status on the lifecycle chip (an interactive task is
|
||||||
// typically Idle+Active-worktree, i.e. would otherwise read "Parked").
|
// typically Idle+Active-worktree, i.e. would otherwise read "Parked").
|
||||||
[ObservableProperty] private bool _hasInteractiveSession;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsParked))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipClass))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusLabel))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowStatusChip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(StatusChipTooltip))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanSendToQueue))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(SendToQueueDisabledReason))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CanDeleteTask))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(DeleteDisabledReason))]
|
||||||
|
private bool _hasInteractiveSession;
|
||||||
// Set by the custom drag while this row is being dragged — drives the "grabbed" row style.
|
// Set by the custom drag while this row is being dragged — drives the "grabbed" row style.
|
||||||
[ObservableProperty] private bool _isDragging;
|
[ObservableProperty] private bool _isDragging;
|
||||||
|
|
||||||
// Set from PointerEntered/PointerExited in TaskRowView.axaml.cs. Drives ShowRowActions
|
// Set from PointerEntered/PointerExited in TaskRowView.axaml.cs. Drives ShowRowActions
|
||||||
// together with IsSelected, so hover-only affordances (refine button, unset star, dequeue-X)
|
// together with IsSelected, so hover-only affordances (refine button, unset star, dequeue-X)
|
||||||
// stay reachable via keyboard/selection, not just mouse hover.
|
// stay reachable via keyboard/selection, not just mouse hover.
|
||||||
[ObservableProperty] private bool _isHovered;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowRowActions))]
|
||||||
|
private bool _isHovered;
|
||||||
|
|
||||||
// Transient: set from HubBroadcaster's OperationProgress while the worker is still creating
|
// Transient: set from HubBroadcaster's OperationProgress while the worker is still creating
|
||||||
// this task's worktree (the silent gap between Queued and the first agent output). Cleared
|
// this task's worktree (the silent gap between Queued and the first agent output). Cleared
|
||||||
// by the next entity refresh — UpdateFromEntity always reflects a settled state, so there's
|
// by the next entity refresh — UpdateFromEntity always reflects a settled state, so there's
|
||||||
// nothing left to show past that point.
|
// nothing left to show past that point.
|
||||||
[ObservableProperty] private string? _creationPhase;
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasCreationPhase))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CreationPhaseLabel))]
|
||||||
|
private string? _creationPhase;
|
||||||
|
|
||||||
// True while a drag is hovering this row (i.e. it would show a drop-hint gap). Used to
|
// True while a drag is hovering this row (i.e. it would show a drop-hint gap). Used to
|
||||||
// suppress the ordinary hover highlight/transitions so they don't fight the hint.
|
// suppress the ordinary hover highlight/transitions so they don't fight the hint.
|
||||||
@@ -309,179 +448,6 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
|||||||
_ => "idle",
|
_ => "idle",
|
||||||
};
|
};
|
||||||
|
|
||||||
partial void OnStatusChanged(TaskStatus value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(StatusChipClass));
|
|
||||||
OnPropertyChanged(nameof(StatusLabel));
|
|
||||||
OnPropertyChanged(nameof(ShowStatusChip));
|
|
||||||
OnPropertyChanged(nameof(IsRunning));
|
|
||||||
OnPropertyChanged(nameof(IsWaitingForReview));
|
|
||||||
OnPropertyChanged(nameof(IsParked));
|
|
||||||
OnPropertyChanged(nameof(IsQueued));
|
|
||||||
OnPropertyChanged(nameof(IsWaiting));
|
|
||||||
OnPropertyChanged(nameof(HasFailureReason));
|
|
||||||
OnPropertyChanged(nameof(FailureReasonTooltip));
|
|
||||||
OnPropertyChanged(nameof(StatusChipTooltip));
|
|
||||||
OnPropertyChanged(nameof(IsDraft));
|
|
||||||
OnPropertyChanged(nameof(IsPlanned));
|
|
||||||
OnPropertyChanged(nameof(CanOpenPlanningSession));
|
|
||||||
OnPropertyChanged(nameof(CanRemoveFromQueue));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(CanRefine));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(CancelDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(RefineDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(PlanningDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(MarkAsDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnParentTaskIdChanged(string? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsChild));
|
|
||||||
OnPropertyChanged(nameof(IsAgentSuggested));
|
|
||||||
OnPropertyChanged(nameof(ShowAsChild));
|
|
||||||
OnPropertyChanged(nameof(IsDraft));
|
|
||||||
OnPropertyChanged(nameof(IsPlanned));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(CanOpenPlanningSession));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(PlanningDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnParentInViewChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(ShowAsChild));
|
|
||||||
OnPropertyChanged(nameof(IsDraft));
|
|
||||||
OnPropertyChanged(nameof(IsPlanned));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnCreatedByChanged(string? value) => OnPropertyChanged(nameof(IsAgentSuggested));
|
|
||||||
|
|
||||||
partial void OnParentFinalizedChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsDraft));
|
|
||||||
OnPropertyChanged(nameof(IsPlanned));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnPlanningPhaseChanged(PlanningPhase value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsPlanningParent));
|
|
||||||
OnPropertyChanged(nameof(PlanningBadge));
|
|
||||||
OnPropertyChanged(nameof(ShowStatusChip));
|
|
||||||
OnPropertyChanged(nameof(IsPlanActive));
|
|
||||||
OnPropertyChanged(nameof(IsPlanFinalized));
|
|
||||||
OnPropertyChanged(nameof(CanOpenPlanningSession));
|
|
||||||
OnPropertyChanged(nameof(CanResumeOrDiscardPlanning));
|
|
||||||
OnPropertyChanged(nameof(CanQueuePlan));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(CanFinalizePlanning));
|
|
||||||
OnPropertyChanged(nameof(CanRefine));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(RefineDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(PlanningDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnIsRefiningChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(CanRefine));
|
|
||||||
OnPropertyChanged(nameof(RefineDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnIsManualChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(ManualBadge));
|
|
||||||
OnPropertyChanged(nameof(CanRefine));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(CanOpenPlanningSession));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(RefineDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(PlanningDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnHasInteractiveSessionChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsParked));
|
|
||||||
OnPropertyChanged(nameof(StatusChipClass));
|
|
||||||
OnPropertyChanged(nameof(StatusLabel));
|
|
||||||
OnPropertyChanged(nameof(ShowStatusChip));
|
|
||||||
OnPropertyChanged(nameof(StatusChipTooltip));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
OnPropertyChanged(nameof(CanDeleteTask));
|
|
||||||
OnPropertyChanged(nameof(DeleteDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnFailureReasonChanged(string? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(HasFailureReason));
|
|
||||||
OnPropertyChanged(nameof(FailureReasonLabel));
|
|
||||||
OnPropertyChanged(nameof(FailureReasonTooltip));
|
|
||||||
OnPropertyChanged(nameof(StatusChipTooltip));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnFailureTurnsUsedChanged(int? value) => OnPropertyChanged(nameof(FailureReasonTooltip));
|
|
||||||
partial void OnFailureMaxTurnsChanged(int? value) => OnPropertyChanged(nameof(FailureReasonTooltip));
|
|
||||||
|
|
||||||
partial void OnHasQueuedSubtasksChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(CanRemoveFromQueue));
|
|
||||||
OnPropertyChanged(nameof(CanSendToQueue));
|
|
||||||
OnPropertyChanged(nameof(CanQueuePlan));
|
|
||||||
OnPropertyChanged(nameof(SendToQueueDisabledReason));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnIsHoveredChanged(bool value) => OnPropertyChanged(nameof(ShowRowActions));
|
|
||||||
partial void OnIsSelectedChanged(bool value) => OnPropertyChanged(nameof(ShowRowActions));
|
|
||||||
|
|
||||||
partial void OnBlockedByTaskIdChanged(string? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsQueued));
|
|
||||||
OnPropertyChanged(nameof(IsWaiting));
|
|
||||||
OnPropertyChanged(nameof(StatusChipClass));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnHasPlanningChildrenChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsPlanningParent));
|
|
||||||
OnPropertyChanged(nameof(CanQueuePlan));
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnNumberChanged(int value) => OnPropertyChanged(nameof(ShowNumberBadge));
|
|
||||||
partial void OnBranchChanged(string? value) => OnPropertyChanged(nameof(HasBranch));
|
|
||||||
partial void OnWorktreePathChanged(string? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(CanOpenWorktree));
|
|
||||||
OnPropertyChanged(nameof(OpenWorktreeDisabledReason));
|
|
||||||
}
|
|
||||||
partial void OnWorktreeStateChanged(ClaudeDo.Data.Models.WorktreeState? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsParked));
|
|
||||||
OnPropertyChanged(nameof(StatusLabel));
|
|
||||||
}
|
|
||||||
partial void OnDoneChanged(bool value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsOverdue));
|
|
||||||
OnPropertyChanged(nameof(CanAddToMyDay));
|
|
||||||
}
|
|
||||||
partial void OnIsMyDayChanged(bool value) => OnPropertyChanged(nameof(CanAddToMyDay));
|
|
||||||
partial void OnScheduledForChanged(DateTime? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsOverdue));
|
|
||||||
OnPropertyChanged(nameof(HasSchedule));
|
|
||||||
}
|
|
||||||
partial void OnDiffAdditionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffAdditionsText)); }
|
|
||||||
partial void OnDiffDeletionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffDeletionsText)); }
|
|
||||||
partial void OnRoadblockCountChanged(int value) { OnPropertyChanged(nameof(HasRoadblock)); OnPropertyChanged(nameof(RoadblockTooltip)); }
|
|
||||||
partial void OnDropHintAboveChanged(bool value) => OnPropertyChanged(nameof(IsDropTarget));
|
|
||||||
partial void OnDropHintBelowChanged(bool value) => OnPropertyChanged(nameof(IsDropTarget));
|
|
||||||
partial void OnCreationPhaseChanged(string? value)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(HasCreationPhase));
|
|
||||||
OnPropertyChanged(nameof(CreationPhaseLabel));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RefreshLocalized()
|
public void RefreshLocalized()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(StatusLabel));
|
OnPropertyChanged(nameof(StatusLabel));
|
||||||
|
|||||||
@@ -0,0 +1,463 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using ClaudeDo.Data.Models;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
|
using Xunit;
|
||||||
|
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Worker.Tests.UiVm;
|
||||||
|
|
||||||
|
// Characterization test for TaskRowViewModel's PropertyChanged fan-out. For every source
|
||||||
|
// property that today drives dependent notifications (via a handwritten partial OnXChanged),
|
||||||
|
// this pins down the exact SET of names raised when that property changes. Order is
|
||||||
|
// deliberately not asserted: a NotifyPropertyChangedFor-based rewrite raises the source
|
||||||
|
// property's own notification before its dependents instead of after, which is an unobservable
|
||||||
|
// reordering, not a behavior change. This test must stay green across that rewrite.
|
||||||
|
public class TaskRowViewModelNotificationsTests
|
||||||
|
{
|
||||||
|
private static HashSet<string?> Raised(TaskRowViewModel vm, System.Action mutate)
|
||||||
|
{
|
||||||
|
var raised = new HashSet<string?>();
|
||||||
|
vm.PropertyChanged += (_, e) => raised.Add(e.PropertyName);
|
||||||
|
mutate();
|
||||||
|
return raised;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StatusChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.Status = TaskStatus.Running);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.Status),
|
||||||
|
nameof(TaskRowViewModel.StatusChipClass),
|
||||||
|
nameof(TaskRowViewModel.StatusLabel),
|
||||||
|
nameof(TaskRowViewModel.ShowStatusChip),
|
||||||
|
nameof(TaskRowViewModel.IsRunning),
|
||||||
|
nameof(TaskRowViewModel.IsWaitingForReview),
|
||||||
|
nameof(TaskRowViewModel.IsParked),
|
||||||
|
nameof(TaskRowViewModel.IsQueued),
|
||||||
|
nameof(TaskRowViewModel.IsWaiting),
|
||||||
|
nameof(TaskRowViewModel.HasFailureReason),
|
||||||
|
nameof(TaskRowViewModel.FailureReasonTooltip),
|
||||||
|
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||||
|
nameof(TaskRowViewModel.IsDraft),
|
||||||
|
nameof(TaskRowViewModel.IsPlanned),
|
||||||
|
nameof(TaskRowViewModel.CanOpenPlanningSession),
|
||||||
|
nameof(TaskRowViewModel.CanRemoveFromQueue),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.CanRefine),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.CancelDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.RefineDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.PlanningDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.MarkAsDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParentTaskIdChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.ParentTaskId = "parent");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.ParentTaskId),
|
||||||
|
nameof(TaskRowViewModel.IsChild),
|
||||||
|
nameof(TaskRowViewModel.IsAgentSuggested),
|
||||||
|
nameof(TaskRowViewModel.ShowAsChild),
|
||||||
|
nameof(TaskRowViewModel.IsDraft),
|
||||||
|
nameof(TaskRowViewModel.IsPlanned),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.CanOpenPlanningSession),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.PlanningDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParentInViewChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.ParentInView = false);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.ParentInView),
|
||||||
|
nameof(TaskRowViewModel.ShowAsChild),
|
||||||
|
nameof(TaskRowViewModel.IsDraft),
|
||||||
|
nameof(TaskRowViewModel.IsPlanned),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreatedByChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.CreatedBy = "someone");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.CreatedBy),
|
||||||
|
nameof(TaskRowViewModel.IsAgentSuggested),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ParentFinalizedChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.ParentFinalized = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.ParentFinalized),
|
||||||
|
nameof(TaskRowViewModel.IsDraft),
|
||||||
|
nameof(TaskRowViewModel.IsPlanned),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PlanningPhaseChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.PlanningPhase = PlanningPhase.Active);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.PlanningPhase),
|
||||||
|
nameof(TaskRowViewModel.IsPlanningParent),
|
||||||
|
nameof(TaskRowViewModel.PlanningBadge),
|
||||||
|
nameof(TaskRowViewModel.ShowStatusChip),
|
||||||
|
nameof(TaskRowViewModel.IsPlanActive),
|
||||||
|
nameof(TaskRowViewModel.IsPlanFinalized),
|
||||||
|
nameof(TaskRowViewModel.CanOpenPlanningSession),
|
||||||
|
nameof(TaskRowViewModel.CanResumeOrDiscardPlanning),
|
||||||
|
nameof(TaskRowViewModel.CanQueuePlan),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.CanFinalizePlanning),
|
||||||
|
nameof(TaskRowViewModel.CanRefine),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.RefineDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.PlanningDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsRefiningChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.IsRefining = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.IsRefining),
|
||||||
|
nameof(TaskRowViewModel.CanRefine),
|
||||||
|
nameof(TaskRowViewModel.RefineDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsManualChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.IsManual = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.IsManual),
|
||||||
|
nameof(TaskRowViewModel.ManualBadge),
|
||||||
|
nameof(TaskRowViewModel.CanRefine),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.CanOpenPlanningSession),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.RefineDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.PlanningDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasInteractiveSessionChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.HasInteractiveSession = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.HasInteractiveSession),
|
||||||
|
nameof(TaskRowViewModel.IsParked),
|
||||||
|
nameof(TaskRowViewModel.StatusChipClass),
|
||||||
|
nameof(TaskRowViewModel.StatusLabel),
|
||||||
|
nameof(TaskRowViewModel.ShowStatusChip),
|
||||||
|
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
nameof(TaskRowViewModel.CanDeleteTask),
|
||||||
|
nameof(TaskRowViewModel.DeleteDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FailureReasonChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.FailureReason = "error");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.FailureReason),
|
||||||
|
nameof(TaskRowViewModel.HasFailureReason),
|
||||||
|
nameof(TaskRowViewModel.FailureReasonLabel),
|
||||||
|
nameof(TaskRowViewModel.FailureReasonTooltip),
|
||||||
|
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FailureTurnsUsedChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.FailureTurnsUsed = 5);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.FailureTurnsUsed),
|
||||||
|
nameof(TaskRowViewModel.FailureReasonTooltip),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FailureMaxTurnsChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.FailureMaxTurns = 10);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.FailureMaxTurns),
|
||||||
|
nameof(TaskRowViewModel.FailureReasonTooltip),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasQueuedSubtasksChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.HasQueuedSubtasks = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.HasQueuedSubtasks),
|
||||||
|
nameof(TaskRowViewModel.CanRemoveFromQueue),
|
||||||
|
nameof(TaskRowViewModel.CanSendToQueue),
|
||||||
|
nameof(TaskRowViewModel.CanQueuePlan),
|
||||||
|
nameof(TaskRowViewModel.SendToQueueDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsHoveredChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.IsHovered = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.IsHovered),
|
||||||
|
nameof(TaskRowViewModel.ShowRowActions),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsSelectedChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.IsSelected = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.IsSelected),
|
||||||
|
nameof(TaskRowViewModel.ShowRowActions),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BlockedByTaskIdChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.BlockedByTaskId = "blocker");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.BlockedByTaskId),
|
||||||
|
nameof(TaskRowViewModel.IsQueued),
|
||||||
|
nameof(TaskRowViewModel.IsWaiting),
|
||||||
|
nameof(TaskRowViewModel.StatusChipClass),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasPlanningChildrenChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.HasPlanningChildren = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.HasPlanningChildren),
|
||||||
|
nameof(TaskRowViewModel.IsPlanningParent),
|
||||||
|
nameof(TaskRowViewModel.CanQueuePlan),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NumberChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.Number = 5);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.Number),
|
||||||
|
nameof(TaskRowViewModel.ShowNumberBadge),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BranchChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.Branch = "main");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.Branch),
|
||||||
|
nameof(TaskRowViewModel.HasBranch),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WorktreePathChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.WorktreePath = @"C:\repo\worktrees\t");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.WorktreePath),
|
||||||
|
nameof(TaskRowViewModel.CanOpenWorktree),
|
||||||
|
nameof(TaskRowViewModel.OpenWorktreeDisabledReason),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WorktreeStateChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.WorktreeState = ClaudeDo.Data.Models.WorktreeState.Active);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.WorktreeState),
|
||||||
|
nameof(TaskRowViewModel.IsParked),
|
||||||
|
nameof(TaskRowViewModel.StatusLabel),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DoneChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.Done = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.Done),
|
||||||
|
nameof(TaskRowViewModel.IsOverdue),
|
||||||
|
nameof(TaskRowViewModel.CanAddToMyDay),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsMyDayChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.IsMyDay = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.IsMyDay),
|
||||||
|
nameof(TaskRowViewModel.CanAddToMyDay),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ScheduledForChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.ScheduledFor = DateTime.UtcNow);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.ScheduledFor),
|
||||||
|
nameof(TaskRowViewModel.IsOverdue),
|
||||||
|
nameof(TaskRowViewModel.HasSchedule),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DiffAdditionsChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.DiffAdditions = 5);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.DiffAdditions),
|
||||||
|
nameof(TaskRowViewModel.HasDiff),
|
||||||
|
nameof(TaskRowViewModel.DiffAdditionsText),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DiffDeletionsChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.DiffDeletions = 5);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.DiffDeletions),
|
||||||
|
nameof(TaskRowViewModel.HasDiff),
|
||||||
|
nameof(TaskRowViewModel.DiffDeletionsText),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RoadblockCountChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.RoadblockCount = 3);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.RoadblockCount),
|
||||||
|
nameof(TaskRowViewModel.HasRoadblock),
|
||||||
|
nameof(TaskRowViewModel.RoadblockTooltip),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DropHintAboveChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.DropHintAbove = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.DropHintAbove),
|
||||||
|
nameof(TaskRowViewModel.IsDropTarget),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DropHintBelowChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.DropHintBelow = true);
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.DropHintBelow),
|
||||||
|
nameof(TaskRowViewModel.IsDropTarget),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreationPhaseChanged_Notifies_Dependents()
|
||||||
|
{
|
||||||
|
var vm = new TaskRowViewModel { Id = "t" };
|
||||||
|
var raised = Raised(vm, () => vm.CreationPhase = "creating_worktree");
|
||||||
|
Assert.Equal(new HashSet<string?>
|
||||||
|
{
|
||||||
|
nameof(TaskRowViewModel.CreationPhase),
|
||||||
|
nameof(TaskRowViewModel.HasCreationPhase),
|
||||||
|
nameof(TaskRowViewModel.CreationPhaseLabel),
|
||||||
|
}, raised);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user