using Data.SeaHavenIndustries.Enums; using SeaHaven.Services.Helpers; namespace SeaHavenIndustries.Tests; public class WorkOrderBoardMutationRulesTests { [Theory] [InlineData(LifecycleStatus.Canceled, true)] [InlineData(LifecycleStatus.Completed, true)] [InlineData(LifecycleStatus.Scheduled, false)] [InlineData(LifecycleStatus.Incomplete, false)] public void IsReadOnly_ReflectsTerminalStatuses(LifecycleStatus status, bool expected) { Assert.Equal(expected, WorkOrderBoardMutationRules.IsReadOnly(status)); } [Fact] public void ShouldBlockStatusChangeWhenPastDue_BlocksOnlyLifecycleStatus() { Assert.True(WorkOrderBoardMutationRules.ShouldBlockStatusChangeWhenPastDue( WorkOrderBoardFieldNames.LifecycleStatus, isPastDue: true)); Assert.False(WorkOrderBoardMutationRules.ShouldBlockStatusChangeWhenPastDue( WorkOrderBoardFieldNames.ScheduledDate, isPastDue: true)); Assert.False(WorkOrderBoardMutationRules.ShouldBlockStatusChangeWhenPastDue( WorkOrderBoardFieldNames.DueDate, isPastDue: true)); } [Fact] public void ShouldAutoSchedule_WhenIncompleteWithDate_DoesNotRequireAssignee() { Assert.True(WorkOrderBoardMutationRules.ShouldAutoSchedule( LifecycleStatus.Incomplete, new DateTime(2026, 6, 25), assignTo: null)); } [Fact] public void ShouldAutoSchedule_WhenPendingWithConcreteDate() { Assert.True(WorkOrderBoardMutationRules.ShouldAutoSchedule( LifecycleStatus.Pending, new DateTime(2026, 6, 25), assignTo: null)); } [Fact] public void ShouldAutoSchedule_FalseWhenAlreadyScheduled() { Assert.False(WorkOrderBoardMutationRules.ShouldAutoSchedule( LifecycleStatus.Scheduled, new DateTime(2026, 6, 25), assignTo: null)); } [Fact] public void ShouldAutoSchedule_FalseWhenScheduleWeekOnly() { Assert.False(WorkOrderBoardMutationRules.ShouldAutoSchedule( LifecycleStatus.Incomplete, new DateTime(2026, 6, 25), assignTo: null, scheduleWeekOnly: true)); } [Fact] public void ShouldAutoSchedule_FalseWhenInProgress() { Assert.False(WorkOrderBoardMutationRules.ShouldAutoSchedule( LifecycleStatus.InProgress, new DateTime(2026, 6, 25), assignTo: null)); } [Fact] public void ShouldDemoteFromScheduled_WhenDateCleared() { Assert.True(WorkOrderBoardMutationRules.ShouldDemoteFromScheduled( LifecycleStatus.Scheduled, scheduledDate: null)); } [Fact] public void ShouldDemoteFromScheduled_WhenWeekOnly() { Assert.True(WorkOrderBoardMutationRules.ShouldDemoteFromScheduled( LifecycleStatus.Scheduled, new DateTime(2026, 6, 25), scheduleWeekOnly: true)); } [Fact] public void ShouldDemoteFromScheduled_FalseWhenConcreteDateRemains() { Assert.False(WorkOrderBoardMutationRules.ShouldDemoteFromScheduled( LifecycleStatus.Scheduled, new DateTime(2026, 6, 25))); } [Fact] public void ShouldDemoteFromScheduled_FalseWhenInProgress() { Assert.False(WorkOrderBoardMutationRules.ShouldDemoteFromScheduled( LifecycleStatus.InProgress, scheduledDate: null)); } [Fact] public void CanPatchBoardField_AllowsOnlyFlagColorWhenCompleted() { Assert.True(WorkOrderBoardMutationRules.CanPatchBoardField( LifecycleStatus.Completed, WorkOrderBoardFieldNames.FlagColor)); Assert.False(WorkOrderBoardMutationRules.CanPatchBoardField( LifecycleStatus.Completed, WorkOrderBoardFieldNames.LifecycleStatus)); Assert.False(WorkOrderBoardMutationRules.CanPatchBoardField( LifecycleStatus.Completed, WorkOrderBoardFieldNames.SiteCode)); Assert.False(WorkOrderBoardMutationRules.CanPatchBoardField( LifecycleStatus.Canceled, WorkOrderBoardFieldNames.FlagColor)); Assert.True(WorkOrderBoardMutationRules.CanPatchBoardField( LifecycleStatus.Scheduled, WorkOrderBoardFieldNames.AssignTo)); } [Fact] public void CanMutateComments_FalseOnlyWhenCanceled() { Assert.True(WorkOrderBoardMutationRules.CanMutateComments(LifecycleStatus.Completed)); Assert.True(WorkOrderBoardMutationRules.CanMutateComments(LifecycleStatus.Scheduled)); Assert.False(WorkOrderBoardMutationRules.CanMutateComments(LifecycleStatus.Canceled)); } [Fact] public void CanMutateExtraMedia_AllowsExtraOnCompleted() { Assert.True(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Completed, WorkOrderMediaCategory.Extra)); Assert.True(WorkOrderBoardMutationRules.CanMutateExtraMedia(LifecycleStatus.Completed, null)); Assert.False(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Completed, WorkOrderMediaCategory.Before)); Assert.False(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Completed, WorkOrderMediaCategory.After)); Assert.True(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Completed, WorkOrderMediaCategory.Aveta)); Assert.False(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Canceled, WorkOrderMediaCategory.Extra)); Assert.False(WorkOrderBoardMutationRules.CanMutateExtraMedia( LifecycleStatus.Canceled, WorkOrderMediaCategory.Aveta)); } [Fact] public void IsReschedule_WhenPreviousDateExistsAndChanges() { Assert.True(WorkOrderBoardMutationRules.IsReschedule( new DateTime(2026, 6, 20), new DateTime(2026, 6, 25))); Assert.False(WorkOrderBoardMutationRules.IsReschedule( null, new DateTime(2026, 6, 25))); } }