using FluentAssertions; using Xunit; namespace StellaOps.FeatureFlags.Tests; [Trait("Category", "Unit")] public class FeatureFlagModelsTests { [Fact] public void FeatureFlagResult_CanBeCreated() { // Act var result = new FeatureFlagResult( Key: "test-flag", Enabled: true, Variant: "blue", Reason: "Test reason", Source: "TestProvider"); // Assert result.Key.Should().Be("test-flag"); result.Enabled.Should().BeTrue(); result.Variant.Should().Be("blue"); result.Reason.Should().Be("Test reason"); result.Source.Should().Be("TestProvider"); } [Fact] public void FeatureFlagResult_WithNullOptionalValues() { // Act var result = new FeatureFlagResult( Key: "simple-flag", Enabled: false, Variant: null, Reason: null, Source: "TestProvider"); // Assert result.Variant.Should().BeNull(); result.Reason.Should().BeNull(); } [Fact] public void FeatureFlagEvaluationContext_Empty_HasNullValues() { // Act var context = FeatureFlagEvaluationContext.Empty; // Assert context.UserId.Should().BeNull(); context.TenantId.Should().BeNull(); context.Environment.Should().BeNull(); context.Attributes.Should().BeNull(); } [Fact] public void FeatureFlagEvaluationContext_CanBeCreatedWithAllValues() { // Arrange var attributes = new Dictionary { { "role", "admin" }, { "subscription", "premium" } }; // Act var context = new FeatureFlagEvaluationContext( UserId: "user-123", TenantId: "tenant-456", Environment: "production", Attributes: attributes); // Assert context.UserId.Should().Be("user-123"); context.TenantId.Should().Be("tenant-456"); context.Environment.Should().Be("production"); context.Attributes.Should().HaveCount(2); context.Attributes!["role"].Should().Be("admin"); } [Fact] public void FeatureFlagDefinition_CanBeCreatedWithRequiredValues() { // Act var definition = new FeatureFlagDefinition( Key: "my-feature", Description: "My feature description", DefaultValue: true, Enabled: false); // Assert definition.Key.Should().Be("my-feature"); definition.Description.Should().Be("My feature description"); definition.DefaultValue.Should().BeTrue(); definition.Enabled.Should().BeFalse(); definition.Tags.Should().BeNull(); } [Fact] public void FeatureFlagDefinition_CanBeCreatedWithTags() { // Arrange var tags = new List { "team-a", "critical" }; // Act var definition = new FeatureFlagDefinition( Key: "feature", Description: null, DefaultValue: false, Enabled: true, Tags: tags); // Assert definition.Tags.Should().NotBeNull(); definition.Tags.Should().Contain("team-a"); definition.Tags.Should().Contain("critical"); } [Fact] public void FeatureFlagChangedEvent_CanBeCreated() { // Arrange var timestamp = DateTimeOffset.UtcNow; // Act var evt = new FeatureFlagChangedEvent( Key: "toggle-flag", OldValue: false, NewValue: true, Source: "ConfigProvider", Timestamp: timestamp); // Assert evt.Key.Should().Be("toggle-flag"); evt.OldValue.Should().BeFalse(); evt.NewValue.Should().BeTrue(); evt.Source.Should().Be("ConfigProvider"); evt.Timestamp.Should().Be(timestamp); } [Fact] public void FeatureFlagOptions_HasCorrectDefaults() { // Act var options = new FeatureFlagOptions(); // Assert options.DefaultValue.Should().BeFalse(); options.EnableCaching.Should().BeTrue(); options.CacheDuration.Should().Be(TimeSpan.FromSeconds(30)); options.EnableLogging.Should().BeTrue(); options.EnableMetrics.Should().BeTrue(); } [Fact] public void FeatureFlagOptions_CanBeModified() { // Act var options = new FeatureFlagOptions { DefaultValue = true, EnableCaching = false, CacheDuration = TimeSpan.FromHours(1), EnableLogging = false }; // Assert options.DefaultValue.Should().BeTrue(); options.EnableCaching.Should().BeFalse(); options.CacheDuration.Should().Be(TimeSpan.FromHours(1)); options.EnableLogging.Should().BeFalse(); } [Fact] public void FeatureFlagEvaluationContext_RecordEquality() { // Arrange var context1 = new FeatureFlagEvaluationContext("user", "tenant", "env", null); var context2 = new FeatureFlagEvaluationContext("user", "tenant", "env", null); var context3 = new FeatureFlagEvaluationContext("other", "tenant", "env", null); // Assert - Records have value equality context1.Should().Be(context2); context1.Should().NotBe(context3); } [Fact] public void FeatureFlagResult_RecordEquality() { // Arrange var result1 = new FeatureFlagResult("key", true, null, "reason", "source"); var result2 = new FeatureFlagResult("key", true, null, "reason", "source"); var result3 = new FeatureFlagResult("key", false, null, "reason", "source"); // Assert result1.Should().Be(result2); result1.Should().NotBe(result3); } }