diff --git a/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj b/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
index cd7d32d..b0fca65 100644
--- a/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
+++ b/src/service/Domain/Microsoft.FeatureFlighting.Core.csproj
@@ -25,4 +25,10 @@
+
+
+ <_Parameter1>DynamicProxyGenAssembly2
+
+
+
diff --git a/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj b/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
index a84c880..c02de45 100644
--- a/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
+++ b/src/service/Infrastructure/Microsoft.FeatureFlighting.Infrastructure.csproj
@@ -21,4 +21,10 @@
+
+
+ <_Parameter1>Microsoft.FeatureFlighting.Infrastructure.Tests
+
+
+
diff --git a/src/service/Tests/Api.Tests/BackgroundTest/CacheBuilderBackgroundServiceTest.cs b/src/service/Tests/Api.Tests/BackgroundTest/CacheBuilderBackgroundServiceTest.cs
new file mode 100644
index 0000000..f027b47
--- /dev/null
+++ b/src/service/Tests/Api.Tests/BackgroundTest/CacheBuilderBackgroundServiceTest.cs
@@ -0,0 +1,75 @@
+using AppInsights.EnterpriseTelemetry;
+using CQRS.Mediatr.Lite;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.FeatureFlighting.API.Background;
+using Microsoft.FeatureFlighting.API.Controllers;
+using Microsoft.FeatureFlighting.Common.Cache;
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.BackgroundTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("CacheBuilderBackgroundService")]
+ [TestClass]
+ public class CacheBuilderBackgroundServiceTest
+ {
+ public Mock _mockConfiguration;
+ public Mock _mockBackgroundCacheManager;
+ public Mock _mockogger;
+
+ public Mock _mockHostedService;
+
+ public CacheBuilderBackgroundService CacheBuilderBackgroundService;
+
+ public CacheBuilderBackgroundServiceTest() {
+ _mockConfiguration = new Mock();
+ _mockogger = new Mock();
+ _mockBackgroundCacheManager = new Mock();
+
+ var testConfig = new Mock();
+ testConfig.Setup(s => s.Value).Returns("preprop,prod");
+
+ _mockConfiguration.Setup(c => c.GetSection("Env:Supported")).Returns(testConfig.Object);
+
+ var testConfigCache = new Mock();
+ testConfigCache.Setup(s => s.Value).Returns("true");
+
+ _mockConfiguration.Setup(c => c.GetSection("BackgroundCache:Enabled")).Returns(testConfigCache.Object);
+
+ var testConfigPeriod = new Mock();
+ testConfigPeriod.Setup(s => s.Value).Returns("10");
+
+ _mockConfiguration.Setup(c => c.GetSection("BackgroundCache:Period")).Returns(testConfigPeriod.Object);
+
+ Command Command = new UnsubscribeAlertsCommand("testFeature", "tesTenant", "preprop", "123", "1234", "test source");
+ CacheBuilderBackgroundService = new CacheBuilderBackgroundService(_mockBackgroundCacheManager.Object, _mockogger.Object, _mockConfiguration.Object);
+ }
+
+ [DataTestMethod]
+ [DataRow(true)]
+ [DataRow(false)]
+ public async Task StartAsync_Success(bool _isBackgroundRefreshEnabled)
+ {
+ var result = CacheBuilderBackgroundService.StartAsync(default).IsCompleted;
+ Assert.IsTrue(result);
+ }
+
+ [DataTestMethod]
+ public async Task StopAsync_Success()
+ {
+ var result = CacheBuilderBackgroundService.StopAsync(default).IsCompleted;
+ Assert.IsTrue(result);
+ }
+ }
+}
diff --git a/src/service/Tests/Api.Tests/ControllerTests/BaseClassExposedToTest.cs b/src/service/Tests/Api.Tests/ControllerTests/BaseClassExposedToTest.cs
new file mode 100644
index 0000000..9983c6b
--- /dev/null
+++ b/src/service/Tests/Api.Tests/ControllerTests/BaseClassExposedToTest.cs
@@ -0,0 +1,37 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.API.Controllers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.ControllerTests
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class BaseClassExposedToTest:BaseController
+ {
+ public BaseClassExposedToTest(IConfiguration configuration, ILogger logger) : base(configuration, logger)
+ {
+ }
+
+ public Tuple GetHeaders()
+ {
+ return base.GetHeaders();
+ }
+
+ public string GetHeaderValue(string headerKey, string defaultValue)
+ {
+ return base.GetHeaderValue(headerKey, defaultValue);
+ }
+
+ public string GetHeaderValue(string headerName)
+ {
+ return base.GetHeaderValue(headerName);
+ }
+ }
+}
diff --git a/src/service/Tests/Api.Tests/ControllerTests/BaseControllerTest.cs b/src/service/Tests/Api.Tests/ControllerTests/BaseControllerTest.cs
new file mode 100644
index 0000000..4899d04
--- /dev/null
+++ b/src/service/Tests/Api.Tests/ControllerTests/BaseControllerTest.cs
@@ -0,0 +1,99 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common.AppExceptions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.ControllerTests
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("BaseController")]
+ [TestClass]
+ public class BaseControllerTest
+ {
+
+ private readonly Mock _mockConfiguration;
+ private readonly Mock _mockLogger;
+ private readonly BaseClassExposedToTest _baseController;
+ public BaseControllerTest()
+ {
+ _mockConfiguration = new Mock();
+ _mockLogger = new Mock();
+
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "TestApp";
+ httpContext.Request.Headers["x-environment"] = "preprop";
+ httpContext.Request.Headers["x-correlationId"] = "TestCorrelationId";
+ httpContext.Request.Headers["x-messageId"] = "TestMessageId";
+ httpContext.Request.Headers["x-channel"] = "TestChannel";
+
+ var testConfig = new Mock();
+ testConfig.Setup(s => s.Value).Returns("preprop,prod");
+
+ _mockConfiguration.Setup(c => c.GetSection("Env:Supported")).Returns(testConfig.Object);
+
+ _baseController = new BaseClassExposedToTest(_mockConfiguration.Object, _mockLogger.Object)
+ {
+ ControllerContext = new ControllerContext()
+ {
+ HttpContext = httpContext
+ }
+ };
+ }
+
+ [TestMethod]
+ public async Task GetHeaders_WhenCalledWithValidHeaders_ShouldReturnHeaders()
+ {
+ var result = _baseController.GetHeaders();
+
+ Assert.AreEqual("TestApp", result.Item1);
+ Assert.AreEqual("preprop", result.Item2);
+ Assert.AreEqual("TestCorrelationId", result.Item3);
+ Assert.AreEqual("TestMessageId", result.Item4);
+ Assert.AreEqual("TestChannel", result.Item5);
+ }
+
+ [TestMethod]
+ public void GetHeaders_WhenCalledWithMissingHeaders_ShouldThrowDomainException()
+ {
+ var httpContext = new DefaultHttpContext();
+
+ var _baseClassExposedToTest = new BaseClassExposedToTest(_mockConfiguration.Object, _mockLogger.Object)
+ {
+ ControllerContext = new ControllerContext()
+ {
+ HttpContext = httpContext
+ }
+ };
+
+ Assert.ThrowsException(() => _baseClassExposedToTest.GetHeaders());
+ }
+
+ [TestMethod]
+ public void GetHeaders_WhenCalledWithUnsupportedEnvironment_ShouldThrowDomainException()
+ {
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "TestApp";
+ httpContext.Request.Headers["x-environment"] = "UnsupportedEnv";
+ httpContext.Request.Headers["x-correlationId"] = "TestCorrelationId";
+ httpContext.Request.Headers["x-messageId"] = "TestMessageId";
+ httpContext.Request.Headers["x-channel"] = "TestChannel";
+
+ _mockConfiguration.Setup(c => c.GetSection("Env:Supported").Value).Returns("TestEnv1,TestEnv2");
+ var _baseClassExposedToTest = new BaseClassExposedToTest(_mockConfiguration.Object, _mockLogger.Object)
+ {
+ ControllerContext = new ControllerContext()
+ {
+ HttpContext = httpContext
+ }
+ };
+
+ Assert.ThrowsException(() => _baseClassExposedToTest.GetHeaders());
+ }
+
+ }
+}
diff --git a/src/service/Tests/Api.Tests/ControllerTests/FeatureFlagsAdminControllerTest.cs b/src/service/Tests/Api.Tests/ControllerTests/FeatureFlagsAdminControllerTest.cs
new file mode 100644
index 0000000..c20292c
--- /dev/null
+++ b/src/service/Tests/Api.Tests/ControllerTests/FeatureFlagsAdminControllerTest.cs
@@ -0,0 +1,291 @@
+using AppInsights.EnterpriseTelemetry;
+using CQRS.Mediatr.Lite;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.API.Controllers;
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.ControllerTests
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("FeatureFlagsAdminController")]
+ [TestClass]
+ public class FeatureFlagsAdminControllerTest
+ {
+ public Mock _mockConfiguration;
+ public Mock _mockCommandBus;
+ public Mock _mockogger;
+ public Mock _mockQueryService;
+
+ public Mock _mockFeatureFlagsAdminController;
+
+ public FeatureFlagsAdminController featureFlagsAdminController;
+
+ public FeatureFlagsAdminControllerTest()
+ {
+ _mockQueryService = new Mock();
+ _mockConfiguration = new Mock();
+ _mockCommandBus = new Mock();
+ _mockogger = new Mock();
+
+
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "test-Tenant";
+ httpContext.Request.Headers["x-environment"] = "preprop";
+
+ var testConfig = new Mock();
+ testConfig.Setup(s => s.Value).Returns("preprop,prod");
+
+ _mockConfiguration.Setup(c => c.GetSection("Env:Supported")).Returns(testConfig.Object);
+
+ Command Command = new UnsubscribeAlertsCommand("testFeature", "tesTenant", "preprop", "123", "1234", "test source");
+ _mockCommandBus.Setup(c => c.Send(It.IsAny>()));
+ featureFlagsAdminController = new FeatureFlagsAdminController(_mockQueryService.Object, _mockCommandBus.Object, _mockConfiguration.Object, _mockogger.Object)
+ {
+ ControllerContext = new ControllerContext()
+ {
+ HttpContext = httpContext
+ }
+ };
+ }
+
+ [TestMethod]
+ public async Task GetAzureFeatureFlag_NotFound()
+ {
+ _mockQueryService.Setup(a => a.Query(It.IsAny>())).Returns(Task.FromResult(null));
+ var result=await featureFlagsAdminController.GetAzureFeatureFlag("testfeature name");
+
+ var azureFeatureFlagResult=result as NotFoundObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode,StatusCodes.Status404NotFound);
+ }
+
+ [TestMethod]
+ public async Task GetAzureFeatureFlag_Success()
+ {
+ _mockQueryService.Setup(query => query.Query(It.IsAny>())).Returns(Task.FromResult(GetAzureFeatureFlag()));
+ var result = await featureFlagsAdminController.GetAzureFeatureFlag("testfeature name");
+
+ var azureFeatureFlagResult = result as OkObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status200OK);
+ }
+
+ [TestMethod]
+ public async Task GetFeatureFlights_NotFound()
+ {
+ _mockQueryService.Setup(a => a.Query(It.IsAny>>())).Returns(Task.FromResult>(null));
+ var result = await featureFlagsAdminController.GetFeatureFlights();
+
+ var azureFeatureFlagResult = result as NotFoundObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status404NotFound);
+ }
+
+ [TestMethod]
+ public async Task GetFeatureFlights_Success()
+ {
+ _mockQueryService.Setup(a => a.Query(It.IsAny>>())).Returns(Task.FromResult>(GetFeatureFlightDtos()));
+ var result = await featureFlagsAdminController.GetFeatureFlights();
+
+ var azureFeatureFlagResult = result as OkObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status200OK);
+ }
+
+ [TestMethod]
+ public async Task CreateFeatureFlag_Success()
+ {
+ var featureFlag = GetAzureFeatureFlag();
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.CreateFeatureFlag(featureFlag);
+
+ var azureFeatureFlagResult = result as CreatedAtActionResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status201Created);
+ }
+
+ [TestMethod]
+ public async Task UpdateFeatureFlag_Success()
+ {
+ var featureFlag = GetAzureFeatureFlag();
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.UpdateFeatureFlag(featureFlag);
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task EnableFeatureFlag_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.EnableFeatureFlag("testfeature name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task DisableFeatureFlag_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.DisableFeatureFlag("testfeature name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task ActivateStage_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.ActivateStage("testfeature name","test stage name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task DeleteFeatureFlag_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.DeleteFeatureFlag("testfeature name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+
+ [TestMethod]
+ public async Task RebuildFlags_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny())).Returns(Task.FromResult(GetRebuildCommandResult()));
+ var result = await featureFlagsAdminController.RebuildFlags("test reason", new string[] { "feature1", "feature2" });
+
+ var azureFeatureFlagResult = result as OkObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status200OK);
+ }
+
+ [TestMethod]
+ public async Task SubscribeToAlerts_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.SubscribeToAlerts("testfeature name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task UnsubscribeFromAlerts_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny()));
+ var result = await featureFlagsAdminController.UnsubscribeFromAlerts("testfeature name");
+
+ var azureFeatureFlagResult = result as NoContentResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status204NoContent);
+ }
+
+ [TestMethod]
+ public async Task UpdateEvaluationMetrics_Success()
+ {
+ _mockCommandBus.Setup(a => a.Send(It.IsAny())).Returns(Task.FromResult(GetMetricsCommandResult()));
+ var result = await featureFlagsAdminController.UpdateEvaluationMetrics("testfeature name");
+
+ var azureFeatureFlagResult = result as OkObjectResult;
+
+ Assert.AreEqual(azureFeatureFlagResult.StatusCode, StatusCodes.Status200OK);
+ }
+
+ private AzureFeatureFlag GetAzureFeatureFlag()
+ {
+ return new AzureFeatureFlag
+ {
+ Id = Guid.NewGuid().ToString(),
+ Conditions = new AzureFilterCollection()
+ {
+ Client_Filters = new AzureFilter[] { new AzureFilter {
+ Name="name",Parameters=new AzureFilterParameters{ StageId="1",StageName="test stage",FlightContextKey="test key",IsActive="true",Operator="equal",Value="Jhon"} } }
+ },
+ Description = "Description",
+ Enabled = true,
+ Environment = "preprod",
+ IncrementalRingsEnabled = true,
+ IsFlagOptimized = true,
+ Label = "test label",
+ LastModifiedOn = DateTime.UtcNow,
+ Name = "name",
+ Version = "1.0",
+ Optimizations = new List { "test opt" },
+ Tenant = "test tenant"
+ };
+ }
+
+
+ private IEnumerable GetFeatureFlightDtos()
+ {
+ return new List() {
+ new FeatureFlightDto {
+ Id = Guid.NewGuid().ToString(),
+ Description = "Description",
+ Enabled = true,
+ Environment = "preprod",
+ Name = "name",
+ Version = "1.0",
+ Optimizations = new List { "test opt" },
+ Tenant = "test tenant",
+ Stages = new List { new StageDto { StageId=1,StageName="test"} },
+ Audit =new AuditDto{ EnabledOn=DateTime.UtcNow},
+ EvaluationMetrics =new EvaluationMetricsDto{AverageLatency=12345},
+ IsAzureFlightOptimized=true,
+ IsIncremental=true,
+ UsageReport=new FeatureUsageReportDto{ IsNew=true}
+ },
+ new FeatureFlightDto {
+ Id = Guid.NewGuid().ToString(),
+ Description = "Description",
+ Enabled = true,
+ Environment = "preprod",
+ Name = "name",
+ Version = "1.0",
+ Optimizations = new List { "test opt" },
+ Tenant = "test tenant",
+ Stages = new List { new StageDto { StageId=1,StageName="test"} },
+ Audit =new AuditDto{ EnabledOn=DateTime.UtcNow},
+ EvaluationMetrics =new EvaluationMetricsDto{AverageLatency=12345},
+ IsAzureFlightOptimized=true,
+ IsIncremental=true,
+ UsageReport=new FeatureUsageReportDto{ IsNew=true}
+ }
+ };
+ }
+
+ private RebuildCommandResult GetRebuildCommandResult()
+ {
+ return new RebuildCommandResult(new List { "test flight" });
+ }
+
+ private MetricsCommandResult GetMetricsCommandResult() {
+ return new MetricsCommandResult(new EvaluationMetricsDto { LastEvaluatedBy = "admin" }) {
+ };
+ }
+ }
+}
diff --git a/src/service/Tests/Api.Tests/ExceptionHandlerTests/AccessForbiddenExceptionHandlerTests.cs b/src/service/Tests/Api.Tests/ExceptionHandlerTests/AccessForbiddenExceptionHandlerTests.cs
index bb0eb60..bb0cc22 100644
--- a/src/service/Tests/Api.Tests/ExceptionHandlerTests/AccessForbiddenExceptionHandlerTests.cs
+++ b/src/service/Tests/Api.Tests/ExceptionHandlerTests/AccessForbiddenExceptionHandlerTests.cs
@@ -7,9 +7,11 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.FeatureFlighting.Common.AppExceptions;
using Microsoft.FeatureFlighting.Api.ExceptionHandler;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.FeatureFlighting.Api.Tests.ExceptionHandlerTests
{
+ [ExcludeFromCodeCoverage]
[TestClass]
public class AccessForbiddenExceptionHandlerTests
{
diff --git a/src/service/Tests/Api.Tests/MiddlewareTests/ClaimsAugmentationMiddlewareTest.cs b/src/service/Tests/Api.Tests/MiddlewareTests/ClaimsAugmentationMiddlewareTest.cs
new file mode 100644
index 0000000..edd8984
--- /dev/null
+++ b/src/service/Tests/Api.Tests/MiddlewareTests/ClaimsAugmentationMiddlewareTest.cs
@@ -0,0 +1,81 @@
+using CQRS.Mediatr.Lite;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Api.Middlewares;
+using Microsoft.FeatureFlighting.API.Controllers;
+using Microsoft.FeatureFlighting.Common.Authorization;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.MiddlewareTests
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("ClaimsAugmentationMiddleware")]
+ [TestClass]
+ public class ClaimsAugmentationMiddlewareTest
+ {
+ private Mock _mockTenantConfigurationProvider;
+ private Mock _mockConfiguration;
+ private Mock _mockAuthorizationService;
+
+ private ClaimsAugmentationMiddleware claimsAugmentationMiddleware;
+
+ public ClaimsAugmentationMiddlewareTest()
+ {
+ _mockTenantConfigurationProvider = new Mock();
+ _mockConfiguration = new Mock();
+ _mockAuthorizationService=new Mock();
+
+
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "test-Tenant";
+ httpContext.Request.Headers["x-environment"] = "preprop";
+
+ var requestDelegate = Mock.Of();
+
+ var testConfig = new Mock();
+ testConfig.Setup(s => s.Value).Returns("preprop,prod");
+
+ _mockConfiguration.Setup(c => c.GetSection("Env:Supported")).Returns(testConfig.Object);
+
+ claimsAugmentationMiddleware = new ClaimsAugmentationMiddleware(requestDelegate);
+ }
+
+ [TestMethod]
+ public async Task Invoke_Success()
+ {
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(GetTenantConfiguration()));
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(GetTenantConfiguration()));
+ _mockAuthorizationService.Setup(a => a.AugmentAdminClaims(It.IsAny()));
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "test-Tenant";
+ httpContext.Request.Headers["x-environment"] = "preprop";
+ var result = claimsAugmentationMiddleware.Invoke(httpContext, _mockAuthorizationService.Object, _mockTenantConfigurationProvider.Object).IsCompleted;
+
+ Assert.IsTrue(result);
+ }
+
+
+
+ private TenantConfiguration GetTenantConfiguration()
+ {
+ return new TenantConfiguration
+ {
+ Contact = "test contact",
+ IsDyanmic = true,
+ FlightsDatabase = null,
+ Authorization=new AuthorizationConfiguration { Type="1",Administrators="test,test1,test3"},
+
+ };
+ }
+ }
+}
diff --git a/src/service/Tests/Api.Tests/MiddlewareTests/MSALMiddlewareTest.cs b/src/service/Tests/Api.Tests/MiddlewareTests/MSALMiddlewareTest.cs
new file mode 100644
index 0000000..a02ea90
--- /dev/null
+++ b/src/service/Tests/Api.Tests/MiddlewareTests/MSALMiddlewareTest.cs
@@ -0,0 +1,82 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Api.Middlewares;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Net.Http;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.API.Tests.MiddlewareTests
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("MSALMiddleware")]
+ [TestClass]
+ public class MSALMiddlewareTest
+ {
+ private Mock _mockHttpContextAccessor;
+
+ private MSALMiddleware middleware;
+ public MSALMiddlewareTest()
+ {
+ _mockHttpContextAccessor = new Mock();
+
+ var httpContext = new DefaultHttpContext();
+ httpContext.Request.Headers["x-application"] = "test-Tenant";
+ httpContext.Request.Headers["x-environment"] = "preprop";
+
+ _mockHttpContextAccessor.Setup(h=>h.HttpContext).Returns(httpContext);
+
+ var authProps = new AuthenticationProperties();
+ authProps.StoreTokens(new List
+{
+ new AuthenticationToken{ Name = "access_token", Value = "test-jwt"}
+});
+ _mockHttpContextAccessor.Setup(h => h.HttpContext.AuthenticateAsync(It.IsAny())).Returns(Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), authProps, "Bearer"))));
+
+ var requestDelegate = Mock.Of();
+
+ var testConfig = new Mock();
+ testConfig.Setup(s => s.Value).Returns("preprop,prod");
+
+ middleware = new MSALMiddleware(requestDelegate);
+
+ }
+
+// [TestMethod]
+// public async Task Invoke_Success()
+// {
+// var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://test123.com");
+
+// var authProps = new AuthenticationProperties();
+// authProps.StoreTokens(new List
+//{
+// new AuthenticationToken{ Name = "access_token", Value = "test-jwt"}
+//});
+
+// var authenticationServiceMock = new Mock();
+// authenticationServiceMock.Setup(x => x.AuthenticateAsync(It.IsAny(), It.IsAny()))
+// .ReturnsAsync(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), authProps, "Bearer")));
+
+// var serviceProviderMock = new Mock();
+// serviceProviderMock
+// .Setup(s => s.GetService(typeof(IAuthenticationService)))
+// .Returns(authenticationServiceMock.Object);
+
+// var context = new DefaultHttpContext()
+// {
+// RequestServices = serviceProviderMock.Object
+// };
+
+// var result = middleware.Invoke(_mockHttpContextAccessor.Object.HttpContext).IsCompleted;
+// Assert.IsTrue(result);
+// }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/CacheTest/BackgroundTest/BackgroundCacheParametersTest.cs b/src/service/Tests/Common.Tests/CacheTest/BackgroundTest/BackgroundCacheParametersTest.cs
new file mode 100644
index 0000000..3041adb
--- /dev/null
+++ b/src/service/Tests/Common.Tests/CacheTest/BackgroundTest/BackgroundCacheParametersTest.cs
@@ -0,0 +1,47 @@
+using Microsoft.FeatureFlighting.Common.Cache;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.CacheTest.BackgroundTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("BackgroundCacheParameters")]
+ [TestClass]
+ public class BackgroundCacheParametersTest
+ {
+ [TestMethod]
+ public void UpdateRebuildTimestamp_ShouldSetNextRebuildTimestampCorrectly_WhenCacheDurationIsGreaterThanZero()
+ {
+ var parameters = new BackgroundCacheParameters { CacheDuration = 10 };
+
+ parameters.UpdateRebuildTimestamp();
+
+ Assert.IsTrue(parameters.NextRebuildTimestamp > DateTime.UtcNow);
+ Assert.IsTrue(parameters.NextRebuildTimestamp < DateTime.UtcNow.AddMinutes(11));
+ }
+
+ [TestMethod]
+ public void UpdateRebuildTimestamp_ShouldSetNextRebuildTimestampToMaxValue_WhenCacheDurationIsZero()
+ {
+ var parameters = new BackgroundCacheParameters { CacheDuration = 0 };
+
+ parameters.UpdateRebuildTimestamp();
+
+ Assert.AreEqual(DateTime.MaxValue, parameters.NextRebuildTimestamp);
+ }
+
+ [DataTestMethod]
+ [DataRow(10, 5, false)]
+ [DataRow(10, 15, true)]
+ public void ShouldRebuildCache_ShouldReturnCorrectValue(int cacheDuration, int gracePeriod, bool expected)
+ {
+ var parameters = new BackgroundCacheParameters { CacheDuration = cacheDuration };
+ parameters.UpdateRebuildTimestamp();
+
+ var result = parameters.ShouldRebuildCache(gracePeriod);
+
+ Assert.AreEqual(expected, result);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/AuthorizationConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/AuthorizationConfigurationTest.cs
new file mode 100644
index 0000000..e399fbe
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/AuthorizationConfigurationTest.cs
@@ -0,0 +1,61 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("AuthorizationConfiguration")]
+ [TestClass]
+ public class AuthorizationConfigurationTest
+ {
+ [TestMethod]
+ public void GetAdministrators_ShouldReturnCorrectList_WhenAdministratorsIsNotNull()
+ {
+ var config = new AuthorizationConfiguration { Administrators = "admin1,admin2,admin3" };
+
+ var result = config.GetAdministrators();
+
+ Assert.AreEqual(3, result.Count());
+
+ }
+
+ [TestMethod]
+ public void GetAdministrators_ShouldReturnEmptyList_WhenAdministratorsIsNull()
+ {
+ var config = new AuthorizationConfiguration { Administrators = null };
+
+ var result = config.GetAdministrators();
+
+ Assert.AreEqual(result.Count(),0);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldMergeCorrectly()
+ {
+ var config = new AuthorizationConfiguration { Type = "type1", Administrators = "admin1", SenderAppName = "app1" };
+ var defaultConfig = new AuthorizationConfiguration { Type = "type2", Administrators = "admin2", SenderAppName = "app2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("type1", config.Type);
+ Assert.AreEqual("admin1", config.Administrators);
+ Assert.AreEqual("app1", config.SenderAppName);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldUseDefaultValues_WhenValuesAreNull()
+ {
+ var config = new AuthorizationConfiguration { Type = null, Administrators = null, SenderAppName = null };
+ var defaultConfig = new AuthorizationConfiguration { Type = "type2", Administrators = "admin2", SenderAppName = "app2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("type2", config.Type);
+ Assert.AreEqual("admin2", config.Administrators);
+ Assert.AreEqual("app2", config.SenderAppName);
+ }
+
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/CacheConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/CacheConfigurationTest.cs
new file mode 100644
index 0000000..27ba19e
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/CacheConfigurationTest.cs
@@ -0,0 +1,62 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" CacheConfiguration")]
+ [TestClass]
+ public class CacheConfigurationTest
+ {
+ [DataTestMethod]
+ [DataRow("FeatureFlags", "FeatureFlagsCache")]
+ [DataRow("FeatureFlagNames", "FeatureFlagNamesCache")]
+ [DataRow("Graph", "GraphCache")]
+ [DataRow("RulesEngine", "RulesEngineCache")]
+ [DataRow("OperatorMapping", "OperatorMappingCache")]
+ [DataRow("InvalidOperation", "DefaultCache")]
+ public void GetCacheType_ShouldReturnCorrectCacheType(string operation, string expected)
+ {
+ var config = new CacheConfiguration
+ {
+ Type = "DefaultCache",
+ FeatureFlags = "FeatureFlagsCache",
+ FeatureFlagNames = "FeatureFlagNamesCache",
+ Graph = "GraphCache",
+ RulesEngine = "RulesEngineCache",
+ OperatorMapping = "OperatorMappingCache"
+ };
+
+ var result = config.GetCacheType(operation);
+
+ Assert.AreEqual(expected, result);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldMergeCorrectly()
+ {
+ var config = new CacheConfiguration { Type = "type1", FeatureFlags = "flags1", Graph = "graph1" };
+ var defaultConfig = new CacheConfiguration { Type = "type2", FeatureFlags = "flags2", Graph = "graph2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("type1", config.Type);
+ Assert.AreEqual("flags1", config.FeatureFlags);
+ Assert.AreEqual("graph1", config.Graph);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldUseDefaultValues_WhenValuesAreNull()
+ {
+ var config = new CacheConfiguration { Type = null, FeatureFlags = null, Graph = null };
+ var defaultConfig = new CacheConfiguration { Type = "type2", FeatureFlags = "flags2", Graph = "graph2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("type2", config.Type);
+ Assert.AreEqual("flags2", config.FeatureFlags);
+ Assert.AreEqual("graph2", config.Graph);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/CosmosDbConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/CosmosDbConfigurationTest.cs
new file mode 100644
index 0000000..dcf1bf2
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/CosmosDbConfigurationTest.cs
@@ -0,0 +1,43 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" CosmosDbConfiguration")]
+ [TestClass]
+ public class CosmosDbConfigurationTest
+ {
+ [TestMethod]
+ public void MergeWithDefault_ShouldMergeCorrectly()
+ {
+ var config = new CosmosDbConfiguration { Endpoint = "endpoint1", PrimaryKey = "key1", DatabaseId = "db1", ContainerId = "container1" };
+ var defaultConfig = new CosmosDbConfiguration { Endpoint = "endpoint2", PrimaryKey = "key2", DatabaseId = "db2", ContainerId = "container2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("endpoint1", config.Endpoint);
+ Assert.AreEqual("key1", config.PrimaryKey);
+ Assert.AreEqual("db1", config.DatabaseId);
+ Assert.AreEqual("container1", config.ContainerId);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldUseDefaultValues_WhenValuesAreNull()
+ {
+ var config = new CosmosDbConfiguration { Endpoint = null, PrimaryKey = null, DatabaseId = null, ContainerId = null };
+ var defaultConfig = new CosmosDbConfiguration { Endpoint = "endpoint2", PrimaryKey = "key2", DatabaseId = "db2", ContainerId = "container2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("endpoint2", config.Endpoint);
+ Assert.AreEqual("key2", config.PrimaryKey);
+ Assert.AreEqual("db2", config.DatabaseId);
+ Assert.AreEqual("container2", config.ContainerId);
+ }
+
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/EventStoreEmailConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/EventStoreEmailConfigurationTest.cs
new file mode 100644
index 0000000..a0a8489
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/EventStoreEmailConfigurationTest.cs
@@ -0,0 +1,34 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" EventStoreEmailConfiguration")]
+ [TestClass]
+ public class EventStoreEmailConfigurationTest
+ {
+ [TestMethod]
+ public void SetDefaultEmailTemplates_ShouldSetDefaultValues_WhenValuesAreNull()
+ {
+ var config = new EventStoreEmailConfiguration();
+
+ config.SetDefaultEmailTemplates();
+
+ Assert.AreEqual("A new feature flight \"<>\" has been created", config.FeatureFlightCreatedEmailSubject);
+ Assert.AreEqual("email-feature-flight-created", config.FeatureFlightCreatedEmailTemplate);
+ Assert.AreEqual("Feature flight \"<>\" has been updated", config.FeatureFlightUpdatedEmailSubject);
+ Assert.AreEqual("email-feature-flight-updated", config.FeatureFlightUpdatedEmailTemplate);
+ Assert.AreEqual("Feature flight \"<>\" has been enabled", config.FeatureFlightEnabledEmailSubject);
+ Assert.AreEqual("email-feature-flight-enabled", config.FeatureFlightEnabledEmailTemplate);
+ Assert.AreEqual("Feature flight \"<>\" has been disabled", config.FeatureFlightDisabledEmailSubject);
+ Assert.AreEqual("email-feature-flight-disabled", config.FeatureFlightDisabledEmailTemplate);
+ Assert.AreEqual("Feature flight \"<>\" has been deleted", config.FeatureFlightDeletedEmailSubject);
+ Assert.AreEqual("email-feature-flight-deleted", config.FeatureFlightDeletedEmailTemplate);
+ Assert.AreEqual("Alerts for Feature flight \"<>\" has been enabled", config.FeatureFlightAlertsEnabledEmailSubject);
+ Assert.AreEqual("email-feature-flight-alerts-enabled", config.FeatureFlightAlertsEnabledTemplate);
+ }
+ }
+}
+
diff --git a/src/service/Tests/Common.Tests/ConfigTest/FlagEvaluationConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/FlagEvaluationConfigurationTest.cs
new file mode 100644
index 0000000..2562a84
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/FlagEvaluationConfigurationTest.cs
@@ -0,0 +1,27 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("FlagEvaluationConfiguration")]
+ [TestClass]
+ public class FlagEvaluationConfigurationTest
+ {
+ [TestMethod]
+ public void CalculateFlagValue_ShouldReturnCorrectValue()
+ {
+ // Act
+ var result = FlagEvaluationConfiguration.GetDefault();
+
+ // Assert
+ Assert.IsNotNull(result);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/FlightOptimizationConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/FlightOptimizationConfigurationTest.cs
new file mode 100644
index 0000000..955d946
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/FlightOptimizationConfigurationTest.cs
@@ -0,0 +1,43 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("FlightOptimizationConfiguration")]
+ [TestClass]
+ public class FlightOptimizationConfigurationTest
+ {
+ [TestMethod]
+ public void MergeWithDefault_ShouldMergeCorrectly()
+ {
+ var config = new FlightOptimizationConfiguration { OptimizationRules = "rule1" };
+ var defaultConfig = new FlightOptimizationConfiguration { OptimizationRules = "rule2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("rule1", config.OptimizationRules);
+ }
+
+ [TestMethod]
+ public void MergeWithDefault_ShouldUseDefaultValues_WhenValuesAreNull()
+ {
+ var config = new FlightOptimizationConfiguration { OptimizationRules = null };
+ var defaultConfig = new FlightOptimizationConfiguration { OptimizationRules = "rule2" };
+
+ config.MergeWithDefault(defaultConfig);
+
+ Assert.AreEqual("rule2", config.OptimizationRules);
+ }
+
+ [TestMethod]
+ public void GetDefault_ShouldReturnDefaultConfiguration()
+ {
+ var defaultConfig = FlightOptimizationConfiguration.GetDefault();
+
+ Assert.IsFalse(defaultConfig.EnableOptimization);
+ Assert.AreEqual(string.Empty, defaultConfig.OptimizationRules);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/IntelligentAlertConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/IntelligentAlertConfigurationTest.cs
new file mode 100644
index 0000000..e8a2379
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/IntelligentAlertConfigurationTest.cs
@@ -0,0 +1,34 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("IntelligentAlertConfiguration")]
+ [TestClass]
+ public class IntelligentAlertConfigurationTest
+ {
+ [TestMethod]
+ public void MergeWithDefault_ShouldCorrectlyMergeDefaultConfiguration()
+ {
+ // Arrange
+ var defaultConfig = IntelligentAlertConfiguration.GetDefault();
+ var config = new IntelligentAlertConfiguration
+ {
+ AlertEventName = null,
+ AlertEmailSubject = null,
+ AlertEmailTemplate = null
+ };
+
+ // Act
+ config.MergeWithDefault(defaultConfig);
+
+ // Assert
+ Assert.AreEqual(defaultConfig.AlertEventName, config.AlertEventName);
+ Assert.AreEqual(defaultConfig.AlertEmailSubject, config.AlertEmailSubject);
+ Assert.AreEqual(defaultConfig.AlertEmailTemplate, config.AlertEmailTemplate);
+ }
+ }
+}
+
diff --git a/src/service/Tests/Common.Tests/ConfigTest/KustoConfiguratonTest.cs b/src/service/Tests/Common.Tests/ConfigTest/KustoConfiguratonTest.cs
new file mode 100644
index 0000000..bffd6c0
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/KustoConfiguratonTest.cs
@@ -0,0 +1,36 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("KustoConfiguraton")]
+ [TestClass]
+ public class KustoConfiguratonTest
+ {
+ [TestMethod]
+ public void SetDefault_ShouldCorrectlySetDefaultValues()
+ {
+ // Arrange
+ var config = new KustoConfiguraton();
+
+ // Act
+ config.SetDefault();
+
+ // Assert
+ Assert.AreEqual("count_", config.Column_Count);
+ Assert.AreEqual("Count", config.Column_Transformed_Count);
+ Assert.AreEqual("avg_TimeTaken", config.Column_AvgTime);
+ Assert.AreEqual("Average", config.Column_Transformed_AvgTime);
+ Assert.AreEqual("percentile_TimeTaken_95", config.Column_P95);
+ Assert.AreEqual("P95", config.Column_Transformed_P95);
+ Assert.AreEqual("percentile_TimeTaken_90", config.Column_P90);
+ Assert.AreEqual("P90", config.Column_Transformed_P90);
+ Assert.AreEqual("timestamp", config.Column_Timestamp);
+ Assert.AreEqual("Timestamp", config.Column_Transformed_Timestamp);
+ Assert.AreEqual("user_Id", config.Column_UserId);
+ Assert.AreEqual("userId", config.Column_Transformed_UserId);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/MetricConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/MetricConfigurationTest.cs
new file mode 100644
index 0000000..de0ca77
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/MetricConfigurationTest.cs
@@ -0,0 +1,32 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("MetricConfiguration")]
+ [TestClass]
+ public class MetricConfigurationTest
+ {
+ [TestMethod]
+ public void MergeWithDefault_ShouldCorrectlyMergeDefaultConfiguration()
+ {
+ // Arrange
+ var defaultConfig = MetricConfiguration.GetDefault();
+ var config = new MetricConfiguration
+ {
+ Enabled = true,
+ AppInsightsName = null,
+ TrackingEventName = null
+ };
+
+ // Act
+ config.MergeWithDefault(defaultConfig);
+
+ // Assert
+ Assert.AreEqual(defaultConfig.AppInsightsName, config.AppInsightsName);
+ Assert.AreEqual(defaultConfig.TrackingEventName, config.TrackingEventName);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/ParallelEvaluationConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/ParallelEvaluationConfigurationTest.cs
new file mode 100644
index 0000000..0a07736
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/ParallelEvaluationConfigurationTest.cs
@@ -0,0 +1,31 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("ParallelEvaluationConfiguration")]
+ [TestClass]
+ public class ParallelEvaluationConfigurationTest
+ {
+ [TestMethod]
+ public void GetBatchSize_ShouldReturnCorrectBatchSize()
+ {
+ // Arrange
+ var configZero = new ParallelEvaluationConfiguration { BatchSize = 0 };
+ var configNegative = new ParallelEvaluationConfiguration { BatchSize = -1 };
+ var configPositive = new ParallelEvaluationConfiguration { BatchSize = 5 };
+
+ // Act
+ var batchSizeZero = configZero.GetBatchSize();
+ var batchSizeNegative = configNegative.GetBatchSize();
+ var batchSizePositive = configPositive.GetBatchSize();
+
+ // Assert
+ Assert.AreEqual(1, batchSizeZero);
+ Assert.AreEqual(int.MaxValue, batchSizeNegative);
+ Assert.AreEqual(5, batchSizePositive);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/TenantChangeNotificationConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/TenantChangeNotificationConfigurationTest.cs
new file mode 100644
index 0000000..a57c251
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/TenantChangeNotificationConfigurationTest.cs
@@ -0,0 +1,62 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" TenantChangeNotificationConfiguration")]
+ [TestClass]
+ public class TenantChangeNotificationConfigurationTest
+ {
+ [TestMethod]
+ public void MergeOrDefault_ShouldMergeDefaultConfiguration_WhenIsSubscribedIsTrue()
+ {
+ // Arrange
+ var defaultConfig = new TenantChangeNotificationConfiguration
+ {
+ SubscribedEvents = "DefaultEvents",
+ Webhook = new WebhookConfiguration()
+ };
+
+ var config = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = true,
+ SubscribedEvents = null,
+ Webhook = null
+ };
+
+ // Act
+ config.MergeOrDefault(defaultConfig);
+
+ // Assert
+ Assert.AreEqual(defaultConfig.SubscribedEvents, config.SubscribedEvents);
+ Assert.AreEqual(defaultConfig.Webhook, config.Webhook);
+ }
+
+ [TestMethod]
+ public void MergeOrDefault_ShouldNotMergeDefaultConfiguration_WhenIsSubscribedIsFalse()
+ {
+ // Arrange
+ var defaultConfig = new TenantChangeNotificationConfiguration
+ {
+ SubscribedEvents = "DefaultEvents",
+ Webhook = new WebhookConfiguration()
+ };
+
+ var config = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = false,
+ SubscribedEvents = null,
+ Webhook = null
+ };
+
+ // Act
+ config.MergeOrDefault(defaultConfig);
+
+ // Assert
+ Assert.IsNull(config.SubscribedEvents);
+ Assert.IsNull(config.Webhook);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationComparerTest.cs b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationComparerTest.cs
new file mode 100644
index 0000000..96656e7
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationComparerTest.cs
@@ -0,0 +1,36 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" TenantConfigurationComparer")]
+ [TestClass]
+ public class TenantConfigurationComparerTest
+ {
+ [TestMethod]
+ public void Compare_Equals_GetHashCode_ShouldWorkCorrectly()
+ {
+ // Arrange
+ var comparer = TenantConfigurationComparer.Default.Value;
+ var tenant1 = new TenantConfiguration { Name = "Tenant1" };
+ var tenant2 = new TenantConfiguration { Name = "Tenant2" };
+ var tenant3 = new TenantConfiguration { Name = "Tenant1" };
+
+ // Act
+ var compareResult = comparer.Compare(tenant1, tenant2);
+ var equalsResult1 = comparer.Equals(tenant1, tenant2);
+ var equalsResult2 = comparer.Equals(tenant1, tenant3);
+ var hashCode1 = comparer.GetHashCode(tenant1);
+ var hashCode2 = comparer.GetHashCode(tenant3);
+
+ // Assert
+
+ Assert.IsFalse(equalsResult1);
+
+ Assert.AreEqual(hashCode1, hashCode2);
+ }
+
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationProviderTest.cs b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationProviderTest.cs
new file mode 100644
index 0000000..8105546
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationProviderTest.cs
@@ -0,0 +1,140 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("TenantConfigurationProvider")]
+ [TestClass]
+ public class TenantConfigurationProviderTest
+ {
+ private IConfiguration _mockConfiguration;
+ private TenantConfiguration _defaultTenantConfiguration;
+ public TenantConfigurationProviderTest() {
+
+ var singleTenantData=JsonConvert.SerializeObject(GetTenantConfiguration());
+ var multiTenantData=JsonConvert.SerializeObject(GetTenantConfigurations());
+ var webhookData=JsonConvert.SerializeObject(GetWebhookConfiguration());
+ var testConfig1 = new Mock();
+ testConfig1.Setup(s => s.Value).Returns(multiTenantData);
+
+ _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build();
+ }
+ [TestMethod]
+ public async Task Get_ShouldReturnTenantConfiguration_WhenTenantExists()
+ {
+ // Arrange
+ var tenantConfigurationProvider = new TenantConfigurationProvider(_mockConfiguration);
+
+ // Act
+ var result = await tenantConfigurationProvider.Get("Tenant");
+
+ // Assert
+ Assert.IsNotNull(result);
+ }
+
+ #region Test Data
+ private TenantConfiguration GetTenantConfiguration()
+ {
+ return new TenantConfiguration
+ {
+ Name = "Tenant",
+ ShortName = "Tenant",
+ Authorization = new AuthorizationConfiguration(),
+ Cache = new CacheConfiguration(),
+ Evaluation = FlagEvaluationConfiguration.GetDefault(),
+ FlightsDatabase = new CosmosDbConfiguration() {
+ Disabled = false,
+ PrimaryKeyLocation="test location"
+ },
+ Optimization = FlightOptimizationConfiguration.GetDefault(),
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration{ IsSubscribed=true,Webhook=new WebhookConfiguration { WebhookId= "EventStore" } },
+ Metrics = MetricConfiguration.GetDefault(),
+ BusinessRuleEngine = new BusinessRuleEngineConfiguration() {
+ Storage = new StorageConfiguration()
+ {
+ StorageConnectionString = "connectionString",
+ ContainerName = "containerName",
+ StorageConnectionStringKey = "connectionStringKey"
+ },
+ Enabled = false
+
+ }
+ };
+ }
+
+ private WebhookConfiguration GetWebhookConfiguration()
+ {
+ return new WebhookConfiguration { WebhookId = "EventStore",ClientSecret="test1",ClientSecretLocation="test2",ClientId="test3" };
+ }
+
+
+ private List GetTenantConfigurations()
+ {
+ return new List {
+
+ new TenantConfiguration
+ {
+ Name = "Tenant",
+ ShortName = "Tenant",
+ Authorization = new AuthorizationConfiguration(),
+ Cache = new CacheConfiguration(),
+ Evaluation = FlagEvaluationConfiguration.GetDefault(),
+ FlightsDatabase = new CosmosDbConfiguration()
+ {
+ Disabled = false,
+ },
+ Optimization = FlightOptimizationConfiguration.GetDefault(),
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration{ IsSubscribed=true,Webhook=new WebhookConfiguration { WebhookId= "EventStore" } },
+ Metrics = MetricConfiguration.GetDefault(),
+ BusinessRuleEngine = new BusinessRuleEngineConfiguration()
+ {
+ Storage = new StorageConfiguration()
+ {
+ StorageConnectionString = "connectionString",
+ ContainerName = "containerName",
+ StorageConnectionStringKey = "connectionStringKey"
+ },
+ Enabled = false
+
+ }
+ },
+ new TenantConfiguration
+ {
+ Name = "Tenant",
+ ShortName = "Tenant",
+ FlightsDatabase = new CosmosDbConfiguration()
+ {
+ Disabled = false,
+ },
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration{ IsSubscribed=true,Webhook=new WebhookConfiguration { WebhookId= "EventStore" } },
+ Metrics = new MetricConfiguration{
+ Enabled = true,
+ AppInsightsName = "ai-feature-flights-management-prod ",
+ TrackingEventName = "Flighting:FeatureFlags:Evaluated"},
+ BusinessRuleEngine = new BusinessRuleEngineConfiguration()
+ {
+ Storage = new StorageConfiguration()
+ {
+ StorageConnectionString = "connectionString",
+ ContainerName = "containerName",
+ StorageConnectionStringKey = "connectionStringKey"
+ },
+ Enabled = false
+
+ }
+ }
+ };
+ }
+ #endregion
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationTest.cs b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationTest.cs
new file mode 100644
index 0000000..91cb407
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ConfigTest/TenantConfigurationTest.cs
@@ -0,0 +1,43 @@
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ConfigTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" TenantConfiguration")]
+ [TestClass]
+ public class TenantConfigurationTest
+ {
+ [TestMethod]
+ public void MergeWithDefault_ShouldCorrectlyMergeDefaultConfiguration()
+ {
+ // Arrange
+ var defaultConfig = TenantConfiguration.GetDefault();
+ var config = new TenantConfiguration
+ {
+ Authorization = null,
+ Cache = null,
+ FlightsDatabase = null,
+ Optimization = null,
+ ChangeNotificationSubscription = null,
+ Evaluation = null,
+ IntelligentAlerts = null,
+ Metrics = null
+ };
+
+ // Act
+ config.MergeWithDefault(defaultConfig);
+
+ // Assert
+ Assert.AreEqual(defaultConfig.Authorization, config.Authorization);
+ Assert.AreEqual(defaultConfig.Cache, config.Cache);
+ Assert.AreEqual(defaultConfig.FlightsDatabase, config.FlightsDatabase);
+ Assert.AreEqual(defaultConfig.Optimization, config.Optimization);
+ Assert.AreEqual(defaultConfig.ChangeNotificationSubscription, config.ChangeNotificationSubscription);
+ Assert.AreEqual(defaultConfig.Evaluation, config.Evaluation);
+ Assert.AreEqual(defaultConfig.IntelligentAlerts, config.IntelligentAlerts);
+ Assert.AreEqual(defaultConfig.Metrics, config.Metrics);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ExtentionsTest/DictionaryExtensionsTest.cs b/src/service/Tests/Common.Tests/ExtentionsTest/DictionaryExtensionsTest.cs
new file mode 100644
index 0000000..19a39ff
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ExtentionsTest/DictionaryExtensionsTest.cs
@@ -0,0 +1,34 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ExtentionsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("DictionaryExtensions")]
+ [TestClass]
+ public class DictionaryExtensionsTest
+ {
+ [TestMethod]
+ public void Merge_ShouldMergeTwoDictionaries()
+ {
+ // Arrange
+ var dictionary1 = new Dictionary { { "key1", 1 }, { "key2", 2 } };
+ var dictionary2 = new Dictionary { { "key3", 3 }, { "key4", 4 } };
+
+ // Act
+ dictionary1.Merge(dictionary2);
+
+ // Assert
+ Assert.AreEqual(4, dictionary1.Count);
+ Assert.IsTrue(dictionary1.ContainsKey("key1"));
+ Assert.IsTrue(dictionary1.ContainsKey("key2"));
+ Assert.IsTrue(dictionary1.ContainsKey("key3"));
+ Assert.IsTrue(dictionary1.ContainsKey("key4"));
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ExtentionsTest/StringExtensionsTest.cs b/src/service/Tests/Common.Tests/ExtentionsTest/StringExtensionsTest.cs
new file mode 100644
index 0000000..c359f1b
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ExtentionsTest/StringExtensionsTest.cs
@@ -0,0 +1,38 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ExtentionsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" StringExtensions")]
+ [TestClass]
+ public class StringExtensionsTest
+ {
+ [TestMethod]
+ public void RemoveNonAscii_ShouldRemoveNonAsciiCharacters()
+ {
+ // Arrange
+ string source = "tést stríng";
+
+ // Act
+ string result = source.RemoveNonAscii();
+
+ // Assert
+ Assert.AreEqual("tst strng", result);
+ }
+
+ [TestMethod]
+ public void RemoveSpecialCharacters_ShouldRemoveSpecialCharacters()
+ {
+ // Arrange
+ string source = "tést; stríng\\";
+
+ // Act
+ string result = source.RemoveSpecialCharacters();
+
+ // Assert
+ Assert.AreEqual("tst strng\\", result);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/FlagUtilitiesTest.cs b/src/service/Tests/Common.Tests/FlagUtilitiesTest.cs
new file mode 100644
index 0000000..412103e
--- /dev/null
+++ b/src/service/Tests/Common.Tests/FlagUtilitiesTest.cs
@@ -0,0 +1,43 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("FlagUtilities")]
+ [TestClass]
+ public class FlagUtilitiesTest
+ {
+ [TestMethod]
+ public void GetFeatureFlagId_ShouldReturnCorrectId()
+ {
+ // Arrange
+ string appName = "testApp";
+ string envName = "testEnv";
+ string name = "testName";
+ string expectedId = string.Format("{0}_{1}_{2}", appName.ToLowerInvariant(), envName.ToLowerInvariant(), name); // Replace with actual format string
+
+ // Act
+ string id = FlagUtilities.GetFeatureFlagId(appName, envName, name);
+
+ // Assert
+ Assert.AreEqual(expectedId, id);
+ }
+
+ [TestMethod]
+ public void GetFeatureFlagName_ShouldReturnCorrectName()
+ {
+ // Arrange
+ string appName = "testApp";
+ string envName = "testEnv";
+ string name = "testName";
+ string id = string.Format("{0}:{1}:{2}", appName.ToLowerInvariant(), envName.ToLowerInvariant(), name); // Replace with actual format string
+
+ // Act
+ string actualName = FlagUtilities.GetFeatureFlagName(appName, envName, id);
+
+ // Assert
+ Assert.AreEqual(name, actualName);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/Microsoft.FeatureFlighting.Common.Tests.csproj b/src/service/Tests/Common.Tests/Microsoft.FeatureFlighting.Common.Tests.csproj
index fcd9c65..fe88f98 100644
--- a/src/service/Tests/Common.Tests/Microsoft.FeatureFlighting.Common.Tests.csproj
+++ b/src/service/Tests/Common.Tests/Microsoft.FeatureFlighting.Common.Tests.csproj
@@ -5,6 +5,18 @@
false
+
+
+
+
+
+
+ Always
+ true
+ PreserveNewest
+
+
+
diff --git a/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFeatureFlagTest.cs b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFeatureFlagTest.cs
new file mode 100644
index 0000000..6481e14
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFeatureFlagTest.cs
@@ -0,0 +1,66 @@
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.Model.AzureAppConfig
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("AzureFeatureFlag")]
+ [TestClass]
+ public class AzureFeatureFlagTest
+ {
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenTenantIsNull()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ Tenant = null,
+ Environment = "testEnvironment"
+ };
+
+ // Act
+ bool isValid = azureFeatureFlag.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Tenant cannot be null", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenEnvironmentIsNull()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ Tenant = "testTenant",
+ Environment = null
+ };
+
+ // Act
+ bool isValid = azureFeatureFlag.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Environment cannot be null", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnTrue_WhenTenantAndEnvironmentAreNotNull()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ Tenant = "testTenant",
+ Environment = "testEnvironment"
+ };
+
+ // Act
+ bool isValid = azureFeatureFlag.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+ Assert.IsNull(validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterCollectionTest.cs b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterCollectionTest.cs
new file mode 100644
index 0000000..cbfd821
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterCollectionTest.cs
@@ -0,0 +1,71 @@
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.Model.AzureAppConfig
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" AzureFilterCollection")]
+ [TestClass]
+ public class AzureFilterCollectionTest
+ {
+ [TestMethod]
+ public void IsValid_ShouldReturnTrue_WhenClientFiltersIsNull()
+ {
+ // Arrange
+ var azureFilterCollection = new AzureFilterCollection
+ {
+ Client_Filters = null
+ };
+
+ // Act
+ bool isValid = azureFilterCollection.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+ Assert.IsNull(validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenAnyFilterIsInvalid()
+ {
+ // Arrange
+ var azureFilterCollection = new AzureFilterCollection
+ {
+ Client_Filters = new AzureFilter[]
+ {
+ new AzureFilter { Name = "testName", Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" } },
+ new AzureFilter { Name = null, Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" } }
+ }
+ };
+
+ // Act
+ bool isValid = azureFilterCollection.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Filter name and filer parameters must be present", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnTrue_WhenAllFiltersAreValid()
+ {
+ // Arrange
+ var azureFilterCollection = new AzureFilterCollection
+ {
+ Client_Filters = new AzureFilter[]
+ {
+ new AzureFilter { Name = "testName", Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" } },
+ new AzureFilter { Name = "testName2", Parameters = new AzureFilterParameters { StageId = "2", IsActive = "false" } }
+ }
+ };
+
+ // Act
+ bool isValid = azureFilterCollection.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+ Assert.IsNull(validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterTest.cs b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterTest.cs
new file mode 100644
index 0000000..27f61ad
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ModelTest/AzureAppConfigTest/AzureFilterTest.cs
@@ -0,0 +1,118 @@
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.Model.AzureAppConfig
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" AzureFilter")]
+ [TestClass]
+ public class AzureFilterTest
+ {
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenNameIsNull()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = null,
+ Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" }
+ };
+
+ // Act
+ bool isValid = azureFilter.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Filter name and filer parameters must be present", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenStageIdIsNotANumber()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = "testName",
+ Parameters = new AzureFilterParameters { StageId = "notANumber", IsActive = "true" }
+ };
+
+ // Act
+ bool isValid = azureFilter.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Stage ID must be a number", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnFalse_WhenIsActiveIsNotBoolean()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = "testName",
+ Parameters = new AzureFilterParameters { StageId = "1", IsActive = "notABoolean" }
+ };
+
+ // Act
+ bool isValid = azureFilter.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("IsActive must be boolean", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsValid_ShouldReturnTrue_WhenAllPropertiesAreValid()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = "testName",
+ Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" }
+ };
+
+ // Act
+ bool isValid = azureFilter.IsValid(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+ Assert.IsNull(validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void IsActive_ShouldReturnTrue_WhenIsActiveIsTrue()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = "testName",
+ Parameters = new AzureFilterParameters { StageId = "1", IsActive = "true" }
+ };
+
+ // Act
+ bool isActive = azureFilter.IsActive();
+
+ // Assert
+ Assert.IsTrue(isActive);
+ }
+
+ [TestMethod]
+ public void IsActive_ShouldReturnFalse_WhenIsActiveIsFalse()
+ {
+ // Arrange
+ var azureFilter = new AzureFilter
+ {
+ Name = "testName",
+ Parameters = new AzureFilterParameters { StageId = "1", IsActive = "false" }
+ };
+
+ // Act
+ bool isActive = azureFilter.IsActive();
+
+ // Assert
+ Assert.IsFalse(isActive);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ModelTest/EvaluationMetricsTest.cs b/src/service/Tests/Common.Tests/ModelTest/EvaluationMetricsTest.cs
new file mode 100644
index 0000000..ead3f77
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ModelTest/EvaluationMetricsTest.cs
@@ -0,0 +1,26 @@
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ModelTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("EvaluationMetrics")]
+ [TestClass]
+ public class EvaluationMetricsTest
+ {
+ [TestMethod]
+ public void GetDefault_ShouldReturnDefaultEvaluationMetricsDto()
+ {
+ // Act
+ var defaultEvaluationMetricsDto = EvaluationMetricsDto.GetDefault();
+
+ // Assert
+ Assert.AreEqual(0, defaultEvaluationMetricsDto.EvaluationCount);
+ Assert.AreEqual(0, defaultEvaluationMetricsDto.TotalEvaluations);
+ Assert.AreEqual(0.0, defaultEvaluationMetricsDto.AverageLatency);
+ Assert.AreEqual(0.0, defaultEvaluationMetricsDto.P95Latency);
+ Assert.AreEqual(0.0, defaultEvaluationMetricsDto.P90Latency);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/ModelTest/RepotTest/UsageReportDtoTest.cs b/src/service/Tests/Common.Tests/ModelTest/RepotTest/UsageReportDtoTest.cs
new file mode 100644
index 0000000..ae52cc4
--- /dev/null
+++ b/src/service/Tests/Common.Tests/ModelTest/RepotTest/UsageReportDtoTest.cs
@@ -0,0 +1,77 @@
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.FeatureFlighting.Common.Tests.ModelTest.RepotTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" UsageReportDto")]
+ [TestClass]
+ public class UsageReportDtoTest
+ {
+ [TestMethod]
+ public void CreateFlightSelectorBody_ShouldCreateFlightSelectorBody()
+ {
+ // Arrange
+ var usageReportDto = new UsageReportDto("testTenant", "testEnvironment", "testUser")
+ {
+ UnusedFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature1" } },
+ LongInactiveFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature2" } },
+ LongActiveFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature3" } },
+ LongLaunchedFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature4" } }
+ };
+
+ // Act
+ usageReportDto.CreateFlightSelectorBody();
+
+ // Assert
+ Assert.IsNotNull(usageReportDto.FlightSelectorBody);
+ }
+
+ [TestMethod]
+ public void UpdatePendingAction_ShouldUpdatePendingAction()
+ {
+ // Arrange
+ var usageReportDto = new UsageReportDto("testTenant", "testEnvironment", "testUser")
+ {
+ UnusedFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature1" } },
+ LongInactiveFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature2" } },
+ LongActiveFeatures = new List { new ThresholdExceededReportDto { FeatureName = "feature3" } }
+ };
+
+ // Act
+ usageReportDto.UpdatePendingAction();
+
+ // Assert
+ Assert.IsTrue(usageReportDto.PendingAction);
+ Assert.AreEqual("Yes (See Below)", usageReportDto.PendingActionDescription);
+ }
+
+ [TestMethod]
+ public void ActiveFeaturesCount_ShouldReturnCorrectCount()
+ {
+ // Arrange
+ var usageReportDto = new UsageReportDto("testTenant", "testEnvironment", "testUser")
+ {
+ ActiveFeatures = new List { "feature1", "feature2", "feature3" }
+ };
+
+ // Assert
+ Assert.AreEqual(3, usageReportDto.ActiveFeaturesCount);
+ }
+
+ [TestMethod]
+ public void NewAddedFeaturesCount_ShouldReturnCorrectCount()
+ {
+ // Arrange
+ var usageReportDto = new UsageReportDto("testTenant", "testEnvironment", "testUser")
+ {
+ NewlyAddedFeatures = new List { "feature1", "feature2", "feature3" }
+ };
+
+ // Assert
+ Assert.AreEqual(3, usageReportDto.NewAddedFeaturesCount);
+ }
+ }
+}
diff --git a/src/service/Tests/Common.Tests/appsettings.test.json b/src/service/Tests/Common.Tests/appsettings.test.json
new file mode 100644
index 0000000..bac21b2
--- /dev/null
+++ b/src/service/Tests/Common.Tests/appsettings.test.json
@@ -0,0 +1,169 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ },
+ "Properties": {
+ "CorrelationId": "XCV",
+ "EndToEnd": "E2E",
+ "Tenant": "Tenant",
+ "TransactionId": "MessageId",
+ "User": "User",
+ "Custom": {
+ "ClientEnvironment": "x-environment"
+ }
+ }
+ },
+ "Graph": {
+ "Authority": "https://login.microsoftonline.com/{0}/v2.0",
+ "Tenant": "microsoft.onmicrosoft.com",
+ "ClientId": "71a156e9-6196-4afe-aa95-4ca2a00790ca",
+ "Scope": "https://graph.microsoft.com/.default",
+ "CachingEnabled": true,
+ "CacheExpiration": 240
+ },
+ "Authorization": {
+ "ExcludeUriList": "GET */api/v1/evaluate*,GET */api/v1/*/flighting*",
+ "AdminClaimType": "Experimentation",
+ "AdminClaimValue": "All",
+ "TenantAdminClaimValue": "manageexperimentation"
+ },
+ "Authentication": {
+ "Authority": "https://login.microsoftonline.com/microsoft.onmicrosoft.com",
+ "AllowedUpnDomains": "ntdev.microsoft.com,ntdev.corp.microsoft.com,windows.microsoft.com,winse.microsoft.com,microsoft.com,corp.microsoft.com,partners.extranet.microsoft.com,partners.microsoft.net"
+ },
+ "Application": {
+ "TenantIdHeaderKey": "x-application",
+ "CorrelationIdHeaderKey": "x-correlationid",
+ "TransactionIdHeaderKey": "x-messageid",
+ "EndToEndTrackingHeaderKey": "x-e2e-trackingid"
+ },
+ "ItTelemetryExtensions": {
+ "ServiceOffering": "Professional Services",
+ "ServiceLine": "Global Capacity Management",
+ "Service": "Field Experience Platform",
+ "Component": "Field Experience (FXP)",
+ "ComponentId": "fc351da6-7a0d-407f-8e9e-5ade3cb551af",
+ "CorrelationKey": "x-correlationid"
+ },
+ "Kusto": {
+ "Authentication": {
+ "Authority": "https://login.microsoftonline.com/{0}",
+ "TenantId": "microsoft.onmicrosoft.com",
+ "ClientId": "ef35e2f1-0d23-422b-b45a-d1e681b0fd56",
+ "AppResourceId": "https://datastudiostreaming.kusto.windows.net"
+ },
+ "Cluster": {
+ "Url": "https://datastudiostreaming.kusto.windows.net",
+ "Database": "Shared"
+ },
+ "QueryParams": {
+ "ServiceGroupId": "'a5009414-f8e2-49d5-9b18-58acc7ab3f0f','dd4e6965-ccd6-4bf8-89ae-a855e208b296'"
+ },
+ "Endpoint": {
+ "WebhookId": "13",
+ "ClientSecret": "test1",
+ "ClientSecretLocation": "test2",
+ "ClientId": "test3"
+ }
+ },
+ "FlightingDefaultContextParams": {
+ "ContextParam": "ENABLED:1,ENABLE:1,ENABLEFLIGHTING:1"
+ },
+ "BackwardCompatibleFlags": {
+ "Enabled": "true",
+ "TenantMapping": {
+ "FIELD_EXPERIENCE_FXP_": "FXP",
+ "ONE_PROFILE": "OneProfile",
+ "GLOBAL_RESOURCE_MANAGEMENT": "GRM",
+ "RELATIONSHIP_MANAGEMENT_EXPERIENCE": "RM",
+ "PURSUIT_EXPERIENCE": "Pursuit",
+ "LABOR_MANAGEMENT_CORE": "TimeManagement"
+ },
+ "ReverseTenantMapping": {
+ "FXP": "FIELD EXPERIENCE (FXP)",
+ "ONEPROFILE": "One Profile",
+ "GRM": "GLOBAL RESOURCE MANAGEMENT",
+ "RM": "RELATIONSHIP MANAGEMENT EXPERIENCE",
+ "PURSUIT": "PURSUIT EXPERIENCE",
+ "TIMEMANAGEMENT": "LABOR MANAGEMENT - CORE"
+ },
+ "FIELD_EXPERIENCE_FXP_": {
+ "DEV": "enableTestString,SyntheticTransactionBackward",
+ "SIT": "TestFlight1,DemoFlag,SyntheticTransactionBackward",
+ "UAT": "defaultUXEnabled,contextualHelpEnabled,modernUXEnabled",
+ "PROD": "defaultUXEnabled,contextualHelpEnabled,modernUXEnabled"
+ },
+ "GLOBAL_RESOURCE_MANAGEMENT": {
+ "DEV": "EnableTracing,UserBasedReturnRequestFlag,ResourceTimeAwayFlag,RMViewEdit,IsReturnRequestStatusEnabled",
+ "SIT": null,
+ "UAT": "*",
+ "PROD": "*"
+ },
+ "RELATIONSHIP_MANAGEMENT_EXPERIENCE": {
+ "DEV": null,
+ "SIT": null,
+ "UAT": null,
+ "PROD": null
+ },
+ "LABOR_MANAGEMENT_CORE": {
+ "SIT": "RatingEnabled",
+ "UAT": "RatingEnabled",
+ "PROD": "RatingEnabled"
+ },
+ "ONE_PROFILE": {
+ "DEV": null,
+ "SIT": null,
+ "UAT": null,
+ "PROD": null
+ }
+ },
+ "CarbonFlightingService": {
+ "Name": "CarbonFlightingService",
+ "BaseUrl": "https://flightingserviceprod.trafficmanager.net/api/v1/",
+ "RelativeUrl": "{Tenant}/{Env}/flighting?featureNames={featureNames}",
+ "AadResourceId": "cc1b9d80-0cfd-42dc-aea1-c610b6393ab9"
+ },
+ "FeatureManagement": {
+ "*": true
+ },
+ "AllowedHosts": "*",
+ "Tenants": {
+ "Default": {
+ "Name": "Tenant",
+ "ShortName": "Tenant",
+ "FlightsDatabase": {
+ "Disabled": false,
+ "PrimaryKeyLocation": "test location"
+ },
+ "ChangeNotificationSubscription": {
+ "IsSubscribed": true,
+ "Webhook": {
+ "WebhookId": "EventStore"
+ }
+ },
+ "Metrics": {
+ "Enabled": true,
+ "AppInsightsName": "ai-feature-flights-management-prod ",
+ "TrackingEventName": "Flighting:FeatureFlags:Evaluated"
+ },
+ "BusinessRuleEngine": {
+ "Storage": {
+ "StorageConnectionString": "connectionString",
+ "ContainerName": "containerName",
+ "StorageConnectionStringKey": "connectionStringKey"
+ },
+ "Enabled": false
+ }
+ }
+ },
+ "EventStore": {
+ "WebhookId": "11",
+ "ClientSecret": "test1",
+ "ClientSecretLocation": "test2",
+ "ClientId": "test3"
+ },
+ "test location": "location1"
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/ActivateStageTest/ActivateStageCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/ActivateStageTest/ActivateStageCommandTest.cs
new file mode 100644
index 0000000..110fa80
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/ActivateStageTest/ActivateStageCommandTest.cs
@@ -0,0 +1,82 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.Commands.ActivateStage
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("ActivateStageCommand")]
+ [TestClass]
+ public class ActivateStageCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenFeatureNameIsNull()
+ {
+ // Arrange
+ var command = new ActivateStageCommand(null, "testTenant", "testEnvironment", "testStage", "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenTenantIsNull()
+ {
+ // Arrange
+ var command = new ActivateStageCommand("testFeature", null, "testEnvironment", "testStage", "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenEnvironmentIsNull()
+ {
+ // Arrange
+ var command = new ActivateStageCommand("testFeature", "testTenant", null, "testStage", "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenStageNameIsNull()
+ {
+ // Arrange
+ var command = new ActivateStageCommand("testFeature", "testTenant", "testEnvironment", null, "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("Stage Name to be activated cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllPropertiesAreValid()
+ {
+ // Arrange
+ var command = new ActivateStageCommand("testFeature", "testTenant", "testEnvironment", "testStage", "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/CreateFeatureFlightTest/CreateFeatureFlightCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/CreateFeatureFlightTest/CreateFeatureFlightCommandTest.cs
new file mode 100644
index 0000000..72518a3
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/CreateFeatureFlightTest/CreateFeatureFlightCommandTest.cs
@@ -0,0 +1,64 @@
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.CreateFeatureFlightTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("CreateFeatureFlightCommand")]
+ [TestClass]
+ public class CreateFeatureFlightCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenAzureFeatureFlagIsNull()
+ {
+ // Arrange
+ var command = new CreateFeatureFlightCommand(null, "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ Assert.AreEqual("New Feature flag value cannot be null", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenAzureFeatureFlagIsInvalid()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ Label = "testLabel"
+ };
+ var command = new CreateFeatureFlightCommand(azureFeatureFlag, "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(isValid);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAzureFeatureFlagIsValid()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ Label = "testLabel",
+ Tenant= "testTenant",
+ Environment= "testEnvironment",
+ Conditions= new AzureFilterCollection() { Client_Filters=new AzureFilter[] { } },
+ };
+ var command = new CreateFeatureFlightCommand(azureFeatureFlag, "testCorrelationId", "testTransactionId", "testSource");
+
+ // Act
+ bool isValid = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(isValid);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/DeleteFeatureFlightTest/DeleteFeatureFlightCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/DeleteFeatureFlightTest/DeleteFeatureFlightCommandTest.cs
new file mode 100644
index 0000000..a9b9dcd
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/DeleteFeatureFlightTest/DeleteFeatureFlightCommandTest.cs
@@ -0,0 +1,69 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.DeleteFeatureFlightTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("DeleteFeatureFlightCommand")]
+ [TestClass]
+ public class DeleteFeatureFlightCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenFeatureNameIsEmpty()
+ {
+ // Arrange
+ var command = new DeleteFeatureFlightCommand("", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new DeleteFeatureFlightCommand("featureName", "", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new DeleteFeatureFlightCommand("featureName", "tenant", "", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new DeleteFeatureFlightCommand("featureName", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/DisableFeatureFlightTest/DisableFeatureFlightCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/DisableFeatureFlightTest/DisableFeatureFlightCommandTest.cs
new file mode 100644
index 0000000..e96bace
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/DisableFeatureFlightTest/DisableFeatureFlightCommandTest.cs
@@ -0,0 +1,17 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.DisableFeatureFlightTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("DisableFeatureFlightCommand")]
+ [TestClass]
+ public class DisableFeatureFlightCommandTest
+ {
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/EnableFeatureFlightTest/EnableFeatureFlightCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/EnableFeatureFlightTest/EnableFeatureFlightCommandTest.cs
new file mode 100644
index 0000000..317b3bc
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/EnableFeatureFlightTest/EnableFeatureFlightCommandTest.cs
@@ -0,0 +1,68 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.EnableFeatureFlightTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("EnableFeatureFlightCommand")]
+ [TestClass]
+ public class EnableFeatureFlightCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenFeatureNameIsEmpty()
+ {
+ // Arrange
+ var command = new EnableFeatureFlightCommand("", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new EnableFeatureFlightCommand("featureName", "", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new EnableFeatureFlightCommand("featureName", "tenant", "", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new EnableFeatureFlightCommand("featureName", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/GenerateReportTest/GenerateReportCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/GenerateReportTest/GenerateReportCommandTest.cs
new file mode 100644
index 0000000..06dd045
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/GenerateReportTest/GenerateReportCommandTest.cs
@@ -0,0 +1,54 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.GenerateReportTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("GenerateReportCommand")]
+ [TestClass]
+ public class GenerateReportCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new GenerateReportCommand("", "environment", false, "correlationId", "transactionId");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new GenerateReportCommand("tenant", "", false, "correlationId", "transactionId");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new GenerateReportCommand("tenant", "environment", false, "correlationId", "transactionId");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/RebuildFlightsTest/RebuildFlightsCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/RebuildFlightsTest/RebuildFlightsCommandTest.cs
new file mode 100644
index 0000000..83ff357
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/RebuildFlightsTest/RebuildFlightsCommandTest.cs
@@ -0,0 +1,55 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.RebuildFlightsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" RebuildFlightsCommand")]
+ [TestClass]
+ public class RebuildFlightsCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new RebuildFlightsCommand(new List { "feature1" }, "", "environment", "reason", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new RebuildFlightsCommand(new List { "feature1" }, "tenant", "", "reason", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new RebuildFlightsCommand(new List { "feature1" }, "tenant", "environment", "reason", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/SubscribeAlertsTest/SubscribeAlertsCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/SubscribeAlertsTest/SubscribeAlertsCommandTest.cs
new file mode 100644
index 0000000..31568ad
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/SubscribeAlertsTest/SubscribeAlertsCommandTest.cs
@@ -0,0 +1,68 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.SubscribeAlertsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("SubscribeAlertsCommand")]
+ [TestClass]
+ public class SubscribeAlertsCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenFeatureNameIsEmpty()
+ {
+ // Arrange
+ var command = new SubscribeAlertsCommand("", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new SubscribeAlertsCommand("featureName", "", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new SubscribeAlertsCommand("featureName", "tenant", "", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new SubscribeAlertsCommand("featureName", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/UnsubscribeAlertsTest/UnsubscribeAlertsCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/UnsubscribeAlertsTest/UnsubscribeAlertsCommandTest.cs
new file mode 100644
index 0000000..4f95c7b
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/UnsubscribeAlertsTest/UnsubscribeAlertsCommandTest.cs
@@ -0,0 +1,68 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.UnsubscribeAlertsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("UnsubscribeAlertsCommand")]
+ [TestClass]
+ public class UnsubscribeAlertsCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenFeatureNameIsEmpty()
+ {
+ // Arrange
+ var command = new UnsubscribeAlertsCommand("", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new UnsubscribeAlertsCommand("featureName", "", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new UnsubscribeAlertsCommand("featureName", "tenant", "", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new UnsubscribeAlertsCommand("featureName", "tenant", "environment", "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/UpdateFeatureFlightTest/UpdateFeatureFlightCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/UpdateFeatureFlightTest/UpdateFeatureFlightCommandTest.cs
new file mode 100644
index 0000000..813e5ec
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/UpdateFeatureFlightTest/UpdateFeatureFlightCommandTest.cs
@@ -0,0 +1,68 @@
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.UpdateFeatureFlightTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory("UpdateFeatureFlightCommand")]
+ [TestClass]
+ public class UpdateFeatureFlightCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenAzureFeatureFlagIsNull()
+ {
+ // Arrange
+ var command = new UpdateFeatureFlightCommand(null, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Updated Feature flag value cannot be null", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsFalse_WhenAzureFeatureFlagIsInvalid()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag();
+ var command = new UpdateFeatureFlightCommand(azureFeatureFlag, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.IsNotNull(validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAzureFeatureFlagIsValid()
+ {
+ // Arrange
+ var azureFeatureFlag = new AzureFeatureFlag
+ {
+ //Key = "feature1",
+ Label = "label1",
+ Enabled = true,
+ // Conditions = new Conditions { ClientFilters = new List() }
+ };
+ var command = new UpdateFeatureFlightCommand(azureFeatureFlag, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+
+ Assert.IsNotNull(validationErrorMessage);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CommandsTest/UpdateMetricsTest/UpdateMetricsCommandTest.cs b/src/service/Tests/Domain.Tests/CommandsTest/UpdateMetricsTest/UpdateMetricsCommandTest.cs
new file mode 100644
index 0000000..14de598
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CommandsTest/UpdateMetricsTest/UpdateMetricsCommandTest.cs
@@ -0,0 +1,98 @@
+using Microsoft.FeatureFlighting.Core.Commands;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.CommandsTest.UpdateMetricsTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestCategory(" UpdateMetricsCommand")]
+ [TestClass]
+ public class UpdateMetricsCommandTest
+ {
+ [TestMethod]
+ public void Validate_ShouldReturnIsIsFalse_WhenFeatureNameIsEmpty()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("", "tenant", "environment", 1, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Feature name cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsIsFalse_WhenTenantIsEmpty()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("featureName", "", "environment", 1, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Tenant cannot be null or empty | ", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnIsIsFalse_WhenEnvironmentIsEmpty()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("featureName", "tenant", "", 1, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsFalse(result);
+ Assert.AreEqual("Environment cannot be null or empty", validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("featureName", "tenant", "environment", 1, "correlationId", "transactionId", "source");
+
+ // Act
+ var result = command.Validate(out string validationErrorMessage);
+
+ // Assert
+ Assert.IsTrue(result);
+ Assert.AreEqual(string.Empty, validationErrorMessage);
+ }
+
+ [TestMethod]
+ public void AdjustTimespan_ShouldSetTimespanToDefault_WhenLastMetricsGeneratedOnIsNull()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("featureName", "tenant", "environment", 0, "correlationId", "transactionId", "source");
+ int defaultTimespan = 7;
+
+ // Act
+ command.AdjustTimespan(DateTime.UtcNow.AddDays(10), defaultTimespan);
+
+ // Assert
+ Assert.AreEqual(defaultTimespan, command.TimespanInDays);
+ }
+
+ [TestMethod]
+ public void AdjustTimespan_ShouldSetTimespanToDaysSinceMetricsGenerated_WhenLastMetricsGeneratedOnIsNotNull()
+ {
+ // Arrange
+ var command = new UpdateMetricsCommand("featureName", "tenant", "environment", 0, "correlationId", "transactionId", "source");
+ int defaultTimespan = 7;
+ DateTime lastMetricsGeneratedOn = DateTime.UtcNow.AddDays(-5);
+
+ // Act
+ command.AdjustTimespan(lastMetricsGeneratedOn, defaultTimespan);
+
+ // Assert
+ Assert.AreEqual(5, command.TimespanInDays);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/CoreModuleTest.cs b/src/service/Tests/Domain.Tests/CoreModuleTest.cs
new file mode 100644
index 0000000..050fcf2
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/CoreModuleTest.cs
@@ -0,0 +1,61 @@
+using Autofac;
+using CQRS.Mediatr.Lite;
+using Microsoft.FeatureFlighting.Core;
+using Microsoft.FeatureFlighting.Core.Evaluation;
+using Microsoft.FeatureFlighting.Core.Operators;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.PS.FlightingService.Core.Tests
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class CoreModuleTest
+ {
+ private IContainer _container;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ var builder = new ContainerBuilder();
+ builder.RegisterModule();
+ _container = builder.Build();
+ }
+
+ [TestMethod]
+ public void ShouldResolveRequestHandlerResolver()
+ {
+ var instance = _container.Resolve();
+ Assert.IsNotNull(instance);
+ }
+
+ [TestMethod]
+ public void BaseOperator_ThrowException()
+ {
+ try
+ {
+ var instance = _container.Resolve();
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ [TestMethod]
+ public void ShouldResolveIFeatureBatchBuilder()
+ {
+ var instance = _container.Resolve();
+ Assert.IsNotNull(instance);
+ }
+
+ // Add more tests for each type that should be resolvable...
+
+ [TestCleanup]
+ public void TearDown()
+ {
+ _container.Dispose();
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/BaseFeatureFlightCacheEventHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/BaseFeatureFlightCacheEventHandlerTest.cs
new file mode 100644
index 0000000..b27f35c
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/BaseFeatureFlightCacheEventHandlerTest.cs
@@ -0,0 +1,88 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class BaseFeatureFlightCacheEventHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private TestFeatureFlightCacheEventHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new TestFeatureFlightCacheEventHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task ProcessRequest_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task ProcessRequest_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private TestFeatureFlightEvent GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new TestFeatureFlightEvent(featureFlightAggregateRoot, loggerTrackingIds, "Test request");
+ }
+ }
+
+ internal class TestFeatureFlightCacheEventHandler : BaseFeatureFlightCacheEventHandler
+ {
+ public TestFeatureFlightCacheEventHandler(IFeatureFlightCache cache, ILogger logger) : base(cache, logger) { }
+ }
+
+ internal class TestFeatureFlightEvent : BaseFeatureFlightEvent
+ {
+ public TestFeatureFlightEvent(FeatureFlightAggregateRoot flight, LoggerTrackingIds trackingIds, string requestSource) : base(flight, trackingIds, requestSource)
+ {
+ }
+
+ public override string DisplayName => "TestFeatureFlightEvent";
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightCreatedCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightCreatedCacheHandlerTest.cs
new file mode 100644
index 0000000..d4550d7
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightCreatedCacheHandlerTest.cs
@@ -0,0 +1,74 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightCreatedCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightCreatedCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightCreatedCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetFeatureFlightCreated();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightCreated();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightCreated GetFeatureFlightCreated()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightCreated(featureFlightAggregateRoot, loggerTrackingIds);
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDeletedCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDeletedCacheHandlerTest.cs
new file mode 100644
index 0000000..e00085f
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDeletedCacheHandlerTest.cs
@@ -0,0 +1,74 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightDeletedCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightDeletedCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightDeletedCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetFeatureFlightDeleted();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightDeleted();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightDeleted GetFeatureFlightDeleted()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightDeleted(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDisabledCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDisabledCacheHandlerTest.cs
new file mode 100644
index 0000000..0fa4a47
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightDisabledCacheHandlerTest.cs
@@ -0,0 +1,74 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightDisabledCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightDisabledCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightDisabledCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightDisabled GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightDisabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightEnabledCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightEnabledCacheHandlerTest.cs
new file mode 100644
index 0000000..444f100
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightEnabledCacheHandlerTest.cs
@@ -0,0 +1,73 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightEnabledCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightEnabledCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightEnabledCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetFeatureFlightEnabled();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try {
+ var testEvent = GetFeatureFlightEnabled();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightEnabled GetFeatureFlightEnabled()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightEnabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightStageActivatedCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightStageActivatedCacheHandlerTest.cs
new file mode 100644
index 0000000..8d3a39a
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightStageActivatedCacheHandlerTest.cs
@@ -0,0 +1,74 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightStageActivatedCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightStageActivatedCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightStageActivatedCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetFeatureFlightStageActivated();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightStageActivated();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightStageActivated GetFeatureFlightStageActivated()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightStageActivated(featureFlightAggregateRoot, "stage name", loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightUpdatedCacheHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightUpdatedCacheHandlerTest.cs
new file mode 100644
index 0000000..499a21e
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/CacheHandlersTest/FeatureFlightUpdatedCacheHandlerTest.cs
@@ -0,0 +1,76 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.CacheHandlers;
+using Microsoft.FeatureFlighting.Core.Spec;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.CacheHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightUpdatedCacheHandlerTest
+ {
+ private Mock _mockCache;
+ private Mock _mockLogger;
+ private FeatureFlightUpdatedCacheHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockCache = new Mock();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightUpdatedCacheHandler(_mockCache.Object, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldDeleteFeatureFlights()
+ {
+ var testEvent = GetFeatureFlightUpdated();
+
+ await _handler.Handle(testEvent);
+
+ _mockCache.Verify(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenDeleteFeatureFlightsThrowsException()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightUpdated();
+ _mockCache.Setup(c => c.DeleteFeatureFlights(testEvent.TenantName, testEvent.Environment, It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightUpdated GetFeatureFlightUpdated()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+ FeatureFlightDto featureFlightDto=new FeatureFlightDto() { };
+
+ return new FeatureFlightUpdated(featureFlightAggregateRoot, featureFlightDto, "test type", loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/BaseFeatureFlightEventTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/BaseFeatureFlightEventTelemetryHandlerTest.cs
new file mode 100644
index 0000000..5807628
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/BaseFeatureFlightEventTelemetryHandlerTest.cs
@@ -0,0 +1,88 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class BaseFeatureFlightEventTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private TestFeatureFlightEventTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new TestFeatureFlightEventTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task ProcessRequest_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task ProcessRequest_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private TestFeatureFlightEvent GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+ FeatureFlightDto featureFlightDto = new FeatureFlightDto() { };
+
+ return new TestFeatureFlightEvent(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+
+ internal class TestFeatureFlightEventTelemetryHandler : BaseFeatureFlightEventTelemetryHandler
+ {
+ public TestFeatureFlightEventTelemetryHandler(ILogger logger) : base(logger) { }
+ }
+
+ internal class TestFeatureFlightEvent : BaseFeatureFlightEvent
+ {
+ public TestFeatureFlightEvent(FeatureFlightAggregateRoot flight, LoggerTrackingIds trackingIds, string requestSource) : base(flight, trackingIds, requestSource)
+ {
+ }
+
+ public override string DisplayName => "TestFeatureFlightEvent";
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsDisabledTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsDisabledTelemetryHandlerTest.cs
new file mode 100644
index 0000000..6d2ff3f
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsDisabledTelemetryHandlerTest.cs
@@ -0,0 +1,72 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightAlertsDisabledTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightAlertsDisabledTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightAlertsDisabledTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightAlertsDisabled GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightAlertsDisabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsEnabledTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsEnabledTelemetryHandlerTest.cs
new file mode 100644
index 0000000..ce34188
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightAlertsEnabledTelemetryHandlerTest.cs
@@ -0,0 +1,72 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightAlertsEnabledTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightAlertsEnabledTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightAlertsEnabledTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetFeatureFlightAlertsEnabled();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightAlertsEnabled();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightAlertsEnabled GetFeatureFlightAlertsEnabled()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightAlertsEnabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightCreatedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightCreatedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..5ea2f2e
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightCreatedTelemetryHandlerTest.cs
@@ -0,0 +1,73 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+
+ public class FeatureFlightCreatedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightCreatedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightCreatedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetFeatureFlightCreated();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetFeatureFlightCreated();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightCreated GetFeatureFlightCreated()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightCreated(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDeletedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDeletedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..31aeddd
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDeletedTelemetryHandlerTest.cs
@@ -0,0 +1,72 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightDeletedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightDeletedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightDeletedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightDeleted GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightDeleted(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDisabledTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDisabledTelemetryHandlerTest.cs
new file mode 100644
index 0000000..829c2b6
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightDisabledTelemetryHandlerTest.cs
@@ -0,0 +1,72 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightDisabledTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightDisabledTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightDisabledTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightDisabled GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightDisabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightEnabledTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightEnabledTelemetryHandlerTest.cs
new file mode 100644
index 0000000..54357fc
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightEnabledTelemetryHandlerTest.cs
@@ -0,0 +1,69 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ internal class FeatureFlightEnabledTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightEnabledTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightEnabledTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightEnabled GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightEnabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightRebuiltTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightRebuiltTelemetryHandlerTest.cs
new file mode 100644
index 0000000..02f1a65
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightRebuiltTelemetryHandlerTest.cs
@@ -0,0 +1,69 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ internal class FeatureFlightRebuiltTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightRebuiltTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightRebuiltTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightRebuilt GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightRebuilt(featureFlightAggregateRoot, "test reason", loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightStageActivatedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightStageActivatedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..6eb541a
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightStageActivatedTelemetryHandlerTest.cs
@@ -0,0 +1,69 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ internal class FeatureFlightStageActivatedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightStageActivatedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightStageActivatedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightStageActivated GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightStageActivated(featureFlightAggregateRoot, "test stage name", loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightUpdatedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightUpdatedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..6dd7035
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureFlightUpdatedTelemetryHandlerTest.cs
@@ -0,0 +1,71 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ internal class FeatureFlightUpdatedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureFlightUpdatedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightUpdatedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightUpdated GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+ FeatureFlightDto featureFlightDto = new FeatureFlightDto() { };
+
+ return new FeatureFlightUpdated(featureFlightAggregateRoot, featureFlightDto, "test type", loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureMetricsUpdatedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureMetricsUpdatedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..1bb434d
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/FeatureMetricsUpdatedTelemetryHandlerTest.cs
@@ -0,0 +1,69 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ public class FeatureMetricsUpdatedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private FeatureMetricsUpdatedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new FeatureMetricsUpdatedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ try
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private FeatureFlightMetricsUpdated GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightMetricsUpdated(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/ReportGeneratedTelemetryHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/ReportGeneratedTelemetryHandlerTest.cs
new file mode 100644
index 0000000..d687992
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/TelemetryHandlersTest/ReportGeneratedTelemetryHandlerTest.cs
@@ -0,0 +1,52 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.FeatureFlighting.Common.Model;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Events.TelemetryHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.TelemetryHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class ReportGeneratedTelemetryHandlerTest
+ {
+ private Mock _mockLogger;
+ private ReportGeneratedTelemetryHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockLogger = new Mock();
+ _handler = new ReportGeneratedTelemetryHandler(_mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldLogEvent()
+ {
+ var testEvent = GetReportGenerated();
+
+ await _handler.Handle(testEvent);
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldNotThrowException_WhenLoggingFails()
+ {
+ var testEvent = GetReportGenerated();
+ _mockLogger.Setup(l => l.Log(It.IsAny())).Throws(new System.Exception());
+
+ }
+
+ private ReportGenerated GetReportGenerated()
+ {
+ UsageReportDto usageReportDto = new UsageReportDto("test tenant", "env", "test user");
+
+ return new ReportGenerated(usageReportDto,"test1","test2");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/BaseFeatureFlightWebhookEventHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/BaseFeatureFlightWebhookEventHandlerTest.cs
new file mode 100644
index 0000000..62bbe02
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/BaseFeatureFlightWebhookEventHandlerTest.cs
@@ -0,0 +1,118 @@
+using AppInsights.EnterpriseTelemetry;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Common.Webhook;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.WebhookHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using Microsoft.FeatureFlighting.Common.Model.ChangeNotification;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.WebhookHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class BaseFeatureFlightWebhookEventHandlerTest
+ {
+ private Mock _mockTenantConfigurationProvider;
+ private Mock _mockWebhookTriggerManager;
+ private IConfiguration _mockConfiguration;
+ private Mock _mockLogger;
+ private TestFeatureFlightWebhookEventHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockTenantConfigurationProvider = new Mock();
+ _mockWebhookTriggerManager = new Mock();
+ _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build();
+ _mockLogger = new Mock();
+ _handler = new TestFeatureFlightWebhookEventHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task ProcessRequest_ShouldTriggerWebhook()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ var tenantConfiguration = new TenantConfiguration
+ {
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = true,
+ SubscribedEvents = "*",
+ Webhook = new WebhookConfiguration()
+ }
+ };
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).ReturnsAsync(tenantConfiguration);
+
+ await _handler.Handle(testEvent);
+
+ _mockWebhookTriggerManager.Verify(w => w.Trigger(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void ProcessRequest_ShouldLogAndThrowException_WhenTriggeringWebhookFails()
+ {
+ var testEvent = GetTestFeatureFlightEvent();
+ var tenantConfiguration = new TenantConfiguration
+ {
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = true,
+ SubscribedEvents = "*",
+ Webhook = new WebhookConfiguration()
+ }
+ };
+ try
+ {
+
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).ReturnsAsync(tenantConfiguration);
+ _mockWebhookTriggerManager.Setup(w => w.Trigger(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new System.Exception());
+ }
+ catch (Exception ex)
+ {
+ Assert.IsNotNull(ex.Message);
+ }
+ }
+
+ private TestFeatureFlightEvent GetTestFeatureFlightEvent()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new TestFeatureFlightEvent(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+
+ internal class TestFeatureFlightWebhookEventHandler : BaseFeatureFlightWebhookEventHandler
+ {
+ public TestFeatureFlightWebhookEventHandler(ITenantConfigurationProvider tenantConfigurationProvider, IWebhookTriggerManager webhookTriggerManager, IConfiguration configuration, ILogger logger) : base(tenantConfigurationProvider, webhookTriggerManager, configuration, logger) { }
+
+ protected override string NotificationSubject => "TestNotificationSubject";
+ protected override string NotificationContent => "TestNotificationContent";
+ }
+
+ internal class TestFeatureFlightEvent : BaseFeatureFlightEvent
+ {
+ public TestFeatureFlightEvent(FeatureFlightAggregateRoot flight, LoggerTrackingIds trackingIds, string requestSource) : base(flight, trackingIds, requestSource)
+ {
+ }
+
+ public override string DisplayName => "TestFeatureFlightEvent";
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsDisabledWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsDisabledWebhookHandlerTest.cs
new file mode 100644
index 0000000..1dcb70c
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsDisabledWebhookHandlerTest.cs
@@ -0,0 +1,98 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Common.Model.ChangeNotification;
+using Microsoft.FeatureFlighting.Common.Webhook;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.WebhookHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.WebhookHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightAlertsDisabledWebhookHandlerTest
+ {
+ private Mock _mockTenantConfigurationProvider;
+ private Mock _mockWebhookTriggerManager;
+ private IConfiguration _mockConfiguration;
+ private Mock _mockLogger;
+ private FeatureFlightAlertsDisabledWebhookHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockTenantConfigurationProvider = new Mock();
+ _mockWebhookTriggerManager = new Mock();
+ _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build();
+ _mockLogger = new Mock();
+ _handler = new FeatureFlightAlertsDisabledWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object);
+ }
+
+ [TestMethod]
+ public async Task Handle_ShouldTriggerWebhook()
+ {
+ var testEvent = GetFeatureFlightAlertsDisabled();
+ var tenantConfiguration = new TenantConfiguration
+ {
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = true,
+ SubscribedEvents = "*",
+ Webhook = new WebhookConfiguration()
+ }
+ };
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).ReturnsAsync(tenantConfiguration);
+
+ await _handler.Handle(testEvent);
+
+ _mockWebhookTriggerManager.Verify(w => w.Trigger(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once);
+ }
+
+ [TestMethod]
+ public void Handle_ShouldLogAndThrowException_WhenTriggeringWebhookFails()
+ {
+ var testEvent = GetFeatureFlightAlertsDisabled();
+ var tenantConfiguration = new TenantConfiguration
+ {
+ ChangeNotificationSubscription = new TenantChangeNotificationConfiguration
+ {
+ IsSubscribed = true,
+ SubscribedEvents = "*",
+ Webhook = new WebhookConfiguration()
+ }
+ };
+ _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).ReturnsAsync(tenantConfiguration);
+ _mockWebhookTriggerManager.Setup(w => w.Trigger(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new System.Exception());
+
+ Assert.ThrowsExceptionAsync(async () => await _handler.Handle(testEvent));
+
+ _mockLogger.Verify(l => l.Log(It.IsAny()), Times.Once);
+ }
+
+ private FeatureFlightAlertsDisabled GetFeatureFlightAlertsDisabled()
+ {
+ Feature feature = new Feature("test", "test");
+ Status status = new Status(true, true, new List { "test", "test" });
+ Tenant tenant = new Tenant("test", "test");
+ Settings settings = new Settings(new FlightOptimizationConfiguration());
+ Condition condition = new Condition(true, new AzureFilterCollection());
+ Audit audit = new Audit("test", DateTime.UtcNow, "test", DateTime.UtcNow, "test");
+ FeatureFlighting.Core.Domain.ValueObjects.Version version = new FeatureFlighting.Core.Domain.ValueObjects.Version();
+ LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds();
+ FeatureFlightAggregateRoot featureFlightAggregateRoot = new FeatureFlightAggregateRoot(feature, status, tenant, settings, condition, audit, version);
+
+ return new FeatureFlightAlertsDisabled(featureFlightAggregateRoot, loggerTrackingIds, "test source");
+ }
+ }
+}
diff --git a/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsEnabledWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsEnabledWebhookHandlerTest.cs
new file mode 100644
index 0000000..831702b
--- /dev/null
+++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightAlertsEnabledWebhookHandlerTest.cs
@@ -0,0 +1,98 @@
+using AppInsights.EnterpriseTelemetry;
+using AppInsights.EnterpriseTelemetry.Context;
+using Microsoft.Extensions.Configuration;
+using Microsoft.FeatureFlighting.Common;
+using Microsoft.FeatureFlighting.Common.Config;
+using Microsoft.FeatureFlighting.Common.Model.AzureAppConfig;
+using Microsoft.FeatureFlighting.Common.Model.ChangeNotification;
+using Microsoft.FeatureFlighting.Common.Webhook;
+using Microsoft.FeatureFlighting.Core.Domain;
+using Microsoft.FeatureFlighting.Core.Domain.Events;
+using Microsoft.FeatureFlighting.Core.Domain.ValueObjects;
+using Microsoft.FeatureFlighting.Core.Events.WebhookHandlers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.WebhookHandlersTest
+{
+ [ExcludeFromCodeCoverage]
+ [TestClass]
+ public class FeatureFlightAlertsEnabledWebhookHandlerTest
+ {
+ private Mock _mockTenantConfigurationProvider;
+ private Mock _mockWebhookTriggerManager;
+ private IConfiguration _mockConfiguration;
+ private Mock _mockLogger;
+ private FeatureFlightAlertsEnabledWebhookHandler _handler;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ _mockTenantConfigurationProvider = new Mock