using ItWorx.KnowledgeHub.Domain.Projects; namespace ItWorx.KnowledgeHub.Domain.Tests; public sealed class ProjectTests { private static readonly DateTimeOffset Now = new(2026, 8, 1, 12, 0, 0, TimeSpan.Zero); private static Project CreateProject() => Project.Create(Guid.NewGuid(), "Kennisbank vernieuwing", "Samenvatting", ProjectPriority.Medium, "Huidige stand.", Guid.NewGuid(), Guid.NewGuid(), Now); [Fact] public void Create_starts_in_concept_status_with_a_derived_slug() { var project = CreateProject(); Assert.Equal(ProjectLifecycleStatus.Concept, project.Status); Assert.Equal("kennisbank-vernieuwing", project.Slug); Assert.Empty(project.Technologies); } [Theory] [InlineData(ProjectLifecycleStatus.Concept, ProjectLifecycleStatus.Planned, true)] [InlineData(ProjectLifecycleStatus.Planned, ProjectLifecycleStatus.Active, true)] [InlineData(ProjectLifecycleStatus.Active, ProjectLifecycleStatus.Blocked, true)] [InlineData(ProjectLifecycleStatus.Blocked, ProjectLifecycleStatus.Active, true)] [InlineData(ProjectLifecycleStatus.Active, ProjectLifecycleStatus.Maintenance, true)] [InlineData(ProjectLifecycleStatus.Active, ProjectLifecycleStatus.Completed, true)] [InlineData(ProjectLifecycleStatus.Completed, ProjectLifecycleStatus.Paused, true)] [InlineData(ProjectLifecycleStatus.Paused, ProjectLifecycleStatus.Active, true)] [InlineData(ProjectLifecycleStatus.Concept, ProjectLifecycleStatus.Archived, true)] [InlineData(ProjectLifecycleStatus.Concept, ProjectLifecycleStatus.Active, false)] [InlineData(ProjectLifecycleStatus.Archived, ProjectLifecycleStatus.Active, false)] [InlineData(ProjectLifecycleStatus.Completed, ProjectLifecycleStatus.Active, false)] public void ChangeStatus_only_allows_the_documented_lifecycle_transitions( ProjectLifecycleStatus from, ProjectLifecycleStatus to, bool expectedAllowed) { Assert.Equal(expectedAllowed, Project.CanTransition(from, to)); } [Fact] public void ChangeStatus_throws_for_a_disallowed_transition() { var project = CreateProject(); var exception = Record.Exception(() => project.ChangeStatus(ProjectLifecycleStatus.Active, Guid.NewGuid(), Now)); Assert.IsType(exception); } [Fact] public void ChangeStatus_out_of_archived_is_always_rejected() { var project = CreateProject(); project.ChangeStatus(ProjectLifecycleStatus.Archived, Guid.NewGuid(), Now); var exception = Record.Exception(() => project.ChangeStatus(ProjectLifecycleStatus.Active, Guid.NewGuid(), Now)); Assert.IsType(exception); Assert.True(project.IsArchived); } [Fact] public void ReplaceTechnologies_normalizes_trims_deduplicates_and_bounds_the_list() { var project = CreateProject(); project.ReplaceTechnologies([" .NET ", ".net", "PostgreSQL", "", "React"]); Assert.Equal([".NET", "PostgreSQL", "React"], project.Technologies); } }