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(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightAlertsEnabledWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightAlertsEnabled(); + 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 = GetFeatureFlightAlertsEnabled(); + 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 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/WebhookHandlersTest/FeatureFlightCreatedWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightCreatedWebhookHandlerTest.cs new file mode 100644 index 0000000..8e78aec --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightCreatedWebhookHandlerTest.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 FeatureFlightCreatedWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightCreatedWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightCreatedWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightCreated(); + 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 = GetFeatureFlightCreated(); + 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 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/WebhookHandlersTest/FeatureFlightDeletedWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightDeletedWebhookHandlerTest.cs new file mode 100644 index 0000000..a55fd34 --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightDeletedWebhookHandlerTest.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 FeatureFlightDeletedWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightDeletedWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightDeletedWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightDeleted(); + 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 = GetFeatureFlightDeleted(); + 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 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/WebhookHandlersTest/FeatureFlightDisabledWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightDisabledWebhookHandlerTest.cs new file mode 100644 index 0000000..0ca600b --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightDisabledWebhookHandlerTest.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 FeatureFlightDisabledWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightDisabledWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightDisabledWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightDisabled(); + 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 = GetFeatureFlightDisabled(); + 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 FeatureFlightDisabled GetFeatureFlightDisabled() + { + 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/WebhookHandlersTest/FeatureFlightEnabledWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightEnabledWebhookHandlerTest.cs new file mode 100644 index 0000000..ebc5bd5 --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightEnabledWebhookHandlerTest.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 FeatureFlightEnabledWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightEnabledWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightEnabledWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightEnabled(); + 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 = GetFeatureFlightEnabled(); + 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 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/WebhookHandlersTest/FeatureFlightRebuiltWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightRebuiltWebhookHandlerTest.cs new file mode 100644 index 0000000..8318c22 --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightRebuiltWebhookHandlerTest.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 FeatureFlightRebuiltWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightRebuiltWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightRebuiltWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightRebuilt(); + 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 = GetFeatureFlightRebuilt(); + 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 FeatureFlightRebuilt GetFeatureFlightRebuilt() + { + 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/WebhookHandlersTest/FeatureFlightStageActivatedWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightStageActivatedWebhookHandlerTest.cs new file mode 100644 index 0000000..98e1ef6 --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightStageActivatedWebhookHandlerTest.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 FeatureFlightStageActivatedWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightStageActivatedWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightStageActivatedWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightStageActivated(); + 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 = GetFeatureFlightStageActivated(); + 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 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,"test activated stage", loggerTrackingIds, "test source"); + } + } +} diff --git a/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightUpdatedWebhookHandlerTest.cs b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightUpdatedWebhookHandlerTest.cs new file mode 100644 index 0000000..f935de3 --- /dev/null +++ b/src/service/Tests/Domain.Tests/EventsTest/WebhookHandlersTest/FeatureFlightUpdatedWebhookHandlerTest.cs @@ -0,0 +1,100 @@ +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; +using Microsoft.FeatureFlighting.Common.Model; + +namespace Microsoft.PS.FlightingService.Core.Tests.EventsTest.WebhookHandlersTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class FeatureFlightUpdatedWebhookHandlerTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockWebhookTriggerManager; + private IConfiguration _mockConfiguration; + private Mock _mockLogger; + private FeatureFlightUpdatedWebhookHandler _handler; + + [TestInitialize] + public void SetUp() + { + _mockTenantConfigurationProvider = new Mock(); + _mockWebhookTriggerManager = new Mock(); + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + _mockLogger = new Mock(); + _handler = new FeatureFlightUpdatedWebhookHandler(_mockTenantConfigurationProvider.Object, _mockWebhookTriggerManager.Object, _mockConfiguration, _mockLogger.Object); + } + + [TestMethod] + public async Task Handle_ShouldTriggerWebhook() + { + var testEvent = GetFeatureFlightUpdated(); + 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 = GetFeatureFlightUpdated(); + 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 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/FilterTests/AliasFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/AliasFilterTests.cs index df58050..ee380c5 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/AliasFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/AliasFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("AliasFilter")] [TestClass] public class AliasFilterTests: InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/CountryFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/CountryFilterTests.cs index edd5c2e..5def36c 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/CountryFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/CountryFilterTests.cs @@ -12,9 +12,11 @@ using Microsoft.FeatureFlighting.Common.AppExceptions; using Microsoft.FeatureFlighting.Core.FeatureFilters; using static Microsoft.AspNetCore.Hosting.Internal.HostingApplication; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("CountryFilter")] [TestClass] public class CountryFilterTests : InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/DateFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/DateFilterTests.cs index 231263f..7d81a35 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/DateFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/DateFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("DateFilter")] [TestClass] public class DateFilterTests : InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/GenericFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/GenericFilterTests.cs index 53d6ed0..f654d34 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/GenericFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/GenericFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("GenericFilter")] [TestClass] public class GenericFilterTests : InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/InitializeFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/InitializeFilterTests.cs index 77fa95b..3118c84 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/InitializeFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/InitializeFilterTests.cs @@ -8,9 +8,11 @@ using Microsoft.FeatureFlighting.Core.Spec; using Microsoft.FeatureFlighting.Core.Operators; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestClass] public class InitializeFilterTests { diff --git a/src/service/Tests/Domain.Tests/FilterTests/RegionFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/RegionFilterTests.cs index 3d055b4..96b29c7 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/RegionFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/RegionFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("RegionFilter")] [TestClass] public class RegionFilterTests:InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/RoleFilterTest.cs b/src/service/Tests/Domain.Tests/FilterTests/RoleFilterTest.cs new file mode 100644 index 0000000..a215ccd --- /dev/null +++ b/src/service/Tests/Domain.Tests/FilterTests/RoleFilterTest.cs @@ -0,0 +1,190 @@ +using Moq; +using Newtonsoft.Json; +using System.Threading.Tasks; +using AppInsights.EnterpriseTelemetry; +using Microsoft.AspNetCore.Http; +using System.Collections.Generic; +using Microsoft.FeatureManagement; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; +using Microsoft.FeatureFlighting.Core.Tests.FilterTests; + +namespace Microsoft.PS.FlightingService.Core.Tests.FilterTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("RoleFilter")] + [TestClass] + public class RoleFilterTest:InitializeFilterTests + { + private Mock httpContextAccessorMockWithoutRoleGroup; + private Mock httpContextAccessorMockInDefinedRoleGroup; + private Mock httpContextAccessorMockNotInDefinedRoleGroup; + private FeatureFilterEvaluationContext featureContextOperatorIn; + private FeatureFilterEvaluationContext featureContextOperatorNotIn; + private FeatureFilterEvaluationContext featureContextOperatorEquals; + private FeatureFilterEvaluationContext featureContextOperatorNotEquals; + private Mock loggerMock; + private Mock configMock; + private readonly string role = "1"; + + [TestInitialize] + public void TestStartup() + { + successfullMockEvaluatorStrategy = SetupMockOperatorEvaluatorStrategy(true); + failureMockEvaluatorStrategy = SetupMockOperatorEvaluatorStrategy(false); + + httpContextAccessorMockWithoutRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockWithoutRoleGroup, false, null); + httpContextAccessorMockInDefinedRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockInDefinedRoleGroup, true, "1"); + httpContextAccessorMockNotInDefinedRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockNotInDefinedRoleGroup, true, "3"); + + featureContextOperatorIn = SetFilterContext(featureContextOperatorIn, Operator.In); + featureContextOperatorNotIn = SetFilterContext(featureContextOperatorNotIn, Operator.NotIn); + featureContextOperatorEquals = SetFilterContext(featureContextOperatorEquals, Operator.Equals); + featureContextOperatorNotEquals = SetFilterContext(featureContextOperatorNotEquals, Operator.NotEquals); + configMock = SetConfigMock(configMock); + loggerMock = SetLoggerMock(loggerMock); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_True_If_Succeeds_Equals_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockInDefinedRoleGroup.Object, loggerMock.Object, successfullMockEvaluatorStrategy.Object); + featureContextOperatorEquals.Settings = roleFilter.BindParameters(featureContextOperatorEquals.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorEquals); + Assert.AreEqual(true, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_Fails_Equals_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockNotInDefinedRoleGroup.Object, loggerMock.Object, failureMockEvaluatorStrategy.Object); + featureContextOperatorEquals.Settings = roleFilter.BindParameters(featureContextOperatorEquals.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorEquals); + Assert.AreEqual(false, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_True_If_Succeeds_NotEquals_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockNotInDefinedRoleGroup.Object, loggerMock.Object, successfullMockEvaluatorStrategy.Object); + featureContextOperatorNotEquals.Settings = roleFilter.BindParameters(featureContextOperatorNotEquals.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorNotEquals); + Assert.AreEqual(true, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_Fails_NotEquals_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockInDefinedRoleGroup.Object, loggerMock.Object, failureMockEvaluatorStrategy.Object); + featureContextOperatorNotEquals.Settings = roleFilter.BindParameters(featureContextOperatorNotEquals.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorNotEquals); + Assert.AreEqual(false, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_True_If_Succeeds_In_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockInDefinedRoleGroup.Object, loggerMock.Object, successfullMockEvaluatorStrategy.Object); + featureContextOperatorIn.Settings = roleFilter.BindParameters(featureContextOperatorIn.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorIn); + Assert.AreEqual(true, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_Fails_In_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockNotInDefinedRoleGroup.Object, loggerMock.Object, failureMockEvaluatorStrategy.Object); + featureContextOperatorIn.Settings = roleFilter.BindParameters(featureContextOperatorIn.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorIn); + Assert.AreEqual(false, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_True_If_Succeeds_NotIn_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockNotInDefinedRoleGroup.Object, loggerMock.Object, successfullMockEvaluatorStrategy.Object); + featureContextOperatorNotIn.Settings = roleFilter.BindParameters(featureContextOperatorNotIn.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorNotIn); + Assert.AreEqual(true, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_Fails_NotIn_Operator() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockInDefinedRoleGroup.Object, loggerMock.Object, failureMockEvaluatorStrategy.Object); + featureContextOperatorNotIn.Settings = roleFilter.BindParameters(featureContextOperatorNotIn.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorNotIn); + Assert.AreEqual(false, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_HttpContext_Has_No_RoleGroup() + { + RoleFilter roleFilter = new RoleFilter(configMock.Object, httpContextAccessorMockWithoutRoleGroup.Object, loggerMock.Object, successfullMockEvaluatorStrategy.Object); + featureContextOperatorIn.Settings = roleFilter.BindParameters(featureContextOperatorIn.Parameters); + var featureFlagStatus = await roleFilter.EvaluateAsync(featureContextOperatorIn); + Assert.AreEqual(false, featureFlagStatus); + } + + public Mock SetupHttpContextAccessorMock(Mock httpContextAccessorMock, bool hasRoleGroup, string role) + { + httpContextAccessorMock = new Mock(); + + Dictionary contextParams = new Dictionary(); + if (hasRoleGroup) + contextParams.Add("role", role); + + var httpContext = new DefaultHttpContext(); + httpContext.Request.Headers[Constants.Flighting.FLIGHT_CONTEXT_HEADER] = JsonConvert.SerializeObject(contextParams); + httpContext.Items[Constants.Flighting.FLIGHT_TRACKER_PARAM] = JsonConvert.SerializeObject(new LoggerTrackingIds() + { + CorrelationId = "TCId", + TransactionId = "TTId" + }); + httpContextAccessorMock.Setup(_ => _.HttpContext).Returns(httpContext); + + return httpContextAccessorMock; + } + + private FeatureFilterEvaluationContext SetFilterContext(FeatureFilterEvaluationContext context, Operator filterOperator) + { + Dictionary filterSettings = new Dictionary + { + { "IsActive", "true" }, + { "StageId", "1" }, + { "Value", role } + }; + + switch (filterOperator) + { + case Operator.Equals: + filterSettings.Add("Operator", nameof(Operator.Equals)); + break; + case Operator.NotEquals: + filterSettings.Add("Operator", nameof(Operator.NotEquals)); + break; + case Operator.In: + filterSettings.Add("Operator", nameof(Operator.In)); + break; + case Operator.NotIn: + filterSettings.Add("Operator", nameof(Operator.NotIn)); + break; + default: + filterSettings.Add("Operator", nameof(Operator.Equals)); + break; + } + IConfiguration configuration = new ConfigurationBuilder() + .AddInMemoryCollection(filterSettings) + .Build(); + + context = new FeatureFilterEvaluationContext + { + Parameters = configuration + }; + return context; + } + } +} diff --git a/src/service/Tests/Domain.Tests/FilterTests/RoleGroupFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/RoleGroupFilterTests.cs index ebf8f9f..b7b8bdb 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/RoleGroupFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/RoleGroupFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("RoleGroupFilter")] [TestClass] public class RoleGroupFilterTests:InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/RolesFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/RolesFilterTests.cs index 46b256e..1d8ca0c 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/RolesFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/RolesFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("RoleFilter")] [TestClass] public class RolesFilterTests:InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/FilterTests/RulesEngineFilterTest.cs b/src/service/Tests/Domain.Tests/FilterTests/RulesEngineFilterTest.cs new file mode 100644 index 0000000..1c188c4 --- /dev/null +++ b/src/service/Tests/Domain.Tests/FilterTests/RulesEngineFilterTest.cs @@ -0,0 +1,152 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Common.AppExceptions; +using Microsoft.FeatureFlighting.Core.FeatureFilters; +using Microsoft.FeatureFlighting.Core.Operators; +using Microsoft.FeatureFlighting.Core.Spec; +using Microsoft.FeatureFlighting.Core.Tests.FilterTests; +using Microsoft.FeatureManagement; +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; +using static Microsoft.FeatureFlighting.Common.Constants; + +namespace Microsoft.PS.FlightingService.Core.Tests.FilterTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("RoleFilter")] + [TestClass] + public class RulesEngineFilterTest:InitializeFilterTests + { + private Mock httpContextAccessorMockWithoutRoleGroup; + private Mock httpContextAccessorMockInDefinedRoleGroup; + private Mock httpContextAccessorMockNotInDefinedRoleGroup; + private Mock _mockRulesEngineManager; + private FeatureFilterEvaluationContext featureContextOperatorNotEvaluates; + private FeatureFilterEvaluationContext featureContextOperatorEvaluates; + private Mock loggerMock; + private Mock configMock; + private readonly string ruleengine = "1"; + private Mock _mockRulesEngineEvaluator; + + + [TestInitialize] + public void TestStartup() + { + successfullMockEvaluatorStrategy = SetupMockOperatorEvaluatorStrategy(true); + failureMockEvaluatorStrategy = SetupMockOperatorEvaluatorStrategy(false); + + httpContextAccessorMockWithoutRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockWithoutRoleGroup, false, null); + httpContextAccessorMockInDefinedRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockInDefinedRoleGroup, true, "1"); + httpContextAccessorMockNotInDefinedRoleGroup = SetupHttpContextAccessorMock(httpContextAccessorMockNotInDefinedRoleGroup, true, "3"); + + _mockRulesEngineManager=new Mock (); + _mockRulesEngineEvaluator = new Mock(); + + featureContextOperatorNotEvaluates= SetFilterContext(featureContextOperatorNotEvaluates, Operator.NotEvaluates); + featureContextOperatorEvaluates= SetFilterContext(featureContextOperatorEvaluates, Operator.Evaluates); + configMock = SetConfigMock(configMock); + loggerMock = SetLoggerMock(loggerMock); + } + + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_Throws_Exception() + { + RulesEngineFilter rulesEngineFilter = new RulesEngineFilter(_mockRulesEngineManager.Object, httpContextAccessorMockInDefinedRoleGroup.Object, configMock.Object, loggerMock.Object); + featureContextOperatorEvaluates.Settings = rulesEngineFilter.BindParameters(featureContextOperatorEvaluates.Parameters); + try + { + var featureFlagStatus = await rulesEngineFilter.EvaluateAsync(featureContextOperatorEvaluates); + } + catch (System.Exception ex) + { + Assert.IsNotNull(ex.Message); + } + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_True_If_Succeeds_Equals_Operator() + { + RulesEngineFilter rulesEngineFilter = new RulesEngineFilter(_mockRulesEngineManager.Object, httpContextAccessorMockInDefinedRoleGroup.Object, configMock.Object, loggerMock.Object); + featureContextOperatorEvaluates.Settings = rulesEngineFilter.BindParameters(featureContextOperatorEvaluates.Parameters); + _mockRulesEngineManager.Setup(x => x.Build(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(_mockRulesEngineEvaluator.Object); + _mockRulesEngineEvaluator.Setup(x => x.Evaluate(It.IsAny>(), It.IsAny())).ReturnsAsync(new EvaluationResult(true,"pass")); + var featureFlagStatus = await rulesEngineFilter.EvaluateAsync(featureContextOperatorEvaluates); + Assert.AreEqual(true, featureFlagStatus); + } + + [TestMethod] + public async Task Feature_Filter_Must_Evaluate_To_False_If_Fails_Equals_Operator() + { + RulesEngineFilter rulesEngineFilter = new RulesEngineFilter(_mockRulesEngineManager.Object, httpContextAccessorMockInDefinedRoleGroup.Object, configMock.Object, loggerMock.Object); + featureContextOperatorNotEvaluates.Settings = rulesEngineFilter.BindParameters(featureContextOperatorNotEvaluates.Parameters); + _mockRulesEngineManager.Setup(x => x.Build(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(_mockRulesEngineEvaluator.Object); + _mockRulesEngineEvaluator.Setup(x => x.Evaluate(It.IsAny>(), It.IsAny())).ReturnsAsync(new EvaluationResult(false, "failed")); + var featureFlagStatus = await rulesEngineFilter.EvaluateAsync(featureContextOperatorNotEvaluates); + Assert.AreEqual(true, featureFlagStatus); + } + + public Mock SetupHttpContextAccessorMock(Mock httpContextAccessorMock, bool hasRoleGroup, string ruleengine) + { + httpContextAccessorMock = new Mock(); + + Dictionary contextParams = new Dictionary(); + if (hasRoleGroup) + contextParams.Add("ruleengine", ruleengine); + + var httpContext = new DefaultHttpContext(); + httpContext.Request.Headers[Constants.Flighting.FLIGHT_CONTEXT_HEADER] = JsonConvert.SerializeObject(contextParams); + httpContext.Items[Constants.Flighting.FLIGHT_TRACKER_PARAM] = JsonConvert.SerializeObject(new LoggerTrackingIds() + { + CorrelationId = "TCId", + TransactionId = "TTId" + }); + httpContext.Items[Flighting.FEATURE_ADD_ENABLED_CONTEXT] = false; + httpContext.Items[Flighting.FEATURE_ADD_DISABLED_CONTEXT] = false; + httpContextAccessorMock.Setup(_ => _.HttpContext).Returns(httpContext); + + return httpContextAccessorMock; + } + + private FeatureFilterEvaluationContext SetFilterContext(FeatureFilterEvaluationContext context, Operator filterOperator) + { + Dictionary filterSettings = new Dictionary + { + { "IsActive", "true" }, + { "StageId", "1" }, + { "Value", ruleengine } + }; + + switch (filterOperator) + { + case Operator.NotEvaluates: + filterSettings.Add("Operator", nameof(Operator.NotEvaluates)); + break; + case Operator.Evaluates: + filterSettings.Add("Operator", nameof(Operator.Evaluates)); + break; + default: + filterSettings.Add("Operator", nameof(Operator.NotEvaluates)); + break; + } + IConfiguration configuration = new ConfigurationBuilder() + .AddInMemoryCollection(filterSettings) + .Build(); + + context = new FeatureFilterEvaluationContext + { + Parameters = configuration + }; + return context; + } + } +} diff --git a/src/service/Tests/Domain.Tests/FilterTests/UserUpnFilterTests.cs b/src/service/Tests/Domain.Tests/FilterTests/UserUpnFilterTests.cs index 4137505..f815d9d 100644 --- a/src/service/Tests/Domain.Tests/FilterTests/UserUpnFilterTests.cs +++ b/src/service/Tests/Domain.Tests/FilterTests/UserUpnFilterTests.cs @@ -9,9 +9,11 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.FilterTests { + [ExcludeFromCodeCoverage] [TestCategory("UserUpnFilter")] [TestClass] public class UserUpnFilterTests: InitializeFilterTests diff --git a/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj b/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj index 4cf3125..729232c 100644 --- a/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj +++ b/src/service/Tests/Domain.Tests/Microsoft.PS.FlightingService.Core.Tests.csproj @@ -6,6 +6,18 @@ Preview + + + + + + + Always + true + PreserveNewest + + + all @@ -26,4 +38,8 @@ + + + + diff --git a/src/service/Tests/Domain.Tests/OperatorTests/EqualEvaluatorTests.cs b/src/service/Tests/Domain.Tests/OperatorTests/EqualEvaluatorTests.cs index fbe988d..6b50ffd 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/EqualEvaluatorTests.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/EqualEvaluatorTests.cs @@ -5,9 +5,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class EqualEvaluatorTests { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/GreaterThanEvaluatorTest.cs b/src/service/Tests/Domain.Tests/OperatorTests/GreaterThanEvaluatorTest.cs index a291110..0574e07 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/GreaterThanEvaluatorTest.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/GreaterThanEvaluatorTest.cs @@ -5,9 +5,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class GreaterThanEvaluatorTest { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/InEvaluatorTest.cs b/src/service/Tests/Domain.Tests/OperatorTests/InEvaluatorTest.cs index 19be9c7..2583b71 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/InEvaluatorTest.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/InEvaluatorTest.cs @@ -5,9 +5,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class InEvaluatorTest { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/LesserThanEvaluatorTest.cs b/src/service/Tests/Domain.Tests/OperatorTests/LesserThanEvaluatorTest.cs index cc04a87..e822c3a 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/LesserThanEvaluatorTest.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/LesserThanEvaluatorTest.cs @@ -1,10 +1,12 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.FeatureFlighting.Core.Operators; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class LesserThanEvaluatorTest { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/MemberOfSecurityGroupEvaluatorTests.cs b/src/service/Tests/Domain.Tests/OperatorTests/MemberOfSecurityGroupEvaluatorTests.cs index 51371cf..2c3f0bc 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/MemberOfSecurityGroupEvaluatorTests.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/MemberOfSecurityGroupEvaluatorTests.cs @@ -8,9 +8,11 @@ using System.Collections.Generic; using Microsoft.FeatureFlighting.Common.AppExceptions; using Microsoft.FeatureFlighting.Common.Group; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class MemberOfSecurityGroupOperatorTests { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/NotEqualEvaluatorTests.cs b/src/service/Tests/Domain.Tests/OperatorTests/NotEqualEvaluatorTests.cs index b178b11..b9d0a59 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/NotEqualEvaluatorTests.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/NotEqualEvaluatorTests.cs @@ -5,9 +5,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class NotEqualEvaluatorTests { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/NotInEvaluatorTests.cs b/src/service/Tests/Domain.Tests/OperatorTests/NotInEvaluatorTests.cs index dee2477..2fb251e 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/NotInEvaluatorTests.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/NotInEvaluatorTests.cs @@ -1,10 +1,12 @@ using Microsoft.FeatureFlighting.Common; using Microsoft.FeatureFlighting.Core.Operators; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class NotInEvaluatorTests { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/NotMemberOfSecurityGroupTests.cs b/src/service/Tests/Domain.Tests/OperatorTests/NotMemberOfSecurityGroupTests.cs index ed6f382..0eada1c 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/NotMemberOfSecurityGroupTests.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/NotMemberOfSecurityGroupTests.cs @@ -7,9 +7,11 @@ using System; using System.Collections.Generic; using Microsoft.FeatureFlighting.Common.Group; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class NotMemberOfSecurityGroupOperatorTests { diff --git a/src/service/Tests/Domain.Tests/OperatorTests/OperatorEvaluatorStrategyTest.cs b/src/service/Tests/Domain.Tests/OperatorTests/OperatorEvaluatorStrategyTest.cs index 5c0ac07..47fe8c0 100644 --- a/src/service/Tests/Domain.Tests/OperatorTests/OperatorEvaluatorStrategyTest.cs +++ b/src/service/Tests/Domain.Tests/OperatorTests/OperatorEvaluatorStrategyTest.cs @@ -7,9 +7,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.FeatureFlighting.Core.FeatureFilters; using Microsoft.FeatureFlighting.Infrastructure.Cache; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.FeatureFlighting.Core.Tests.OperatorTests { + [ExcludeFromCodeCoverage] [TestClass] public class OperatorEvaluatorStrategyTest { diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetAzureFeatureFlagTest/GetAzureFeatureFlagQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetAzureFeatureFlagTest/GetAzureFeatureFlagQueryTest.cs new file mode 100644 index 0000000..d3209db --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetAzureFeatureFlagTest/GetAzureFeatureFlagQueryTest.cs @@ -0,0 +1,44 @@ +using Microsoft.FeatureFlighting.Core.Queries; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.PS.FlightingService.Core.Tests.OptimizerTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("DuplicateFilterValuesOptimizationRule")] + [TestClass] + public class GetAzureFeatureFlagQueryTest + { + [TestMethod] + public void Validate_ShouldReturnFalse_WhenFeatureNameIsEmpty() + { + var query = new GetAzureFeatureFlagQuery("", "tenant", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenTenantNameIsEmpty() + { + var query = new GetAzureFeatureFlagQuery("feature", "", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenEnvironmentNameIsEmpty() + { + var query = new GetAzureFeatureFlagQuery("feature", "tenant", "", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid() + { + var query = new GetAzureFeatureFlagQuery("feature", "tenant", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsTrue(result); + } + } +} diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetEvaluationMetricsTests/GetEvaluationMetricsQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetEvaluationMetricsTests/GetEvaluationMetricsQueryTest.cs new file mode 100644 index 0000000..c6f6d2b --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetEvaluationMetricsTests/GetEvaluationMetricsQueryTest.cs @@ -0,0 +1,52 @@ +using Microsoft.FeatureFlighting.Core.Queries; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.PS.FlightingService.Core.Tests.QueriesTests.GetEvaluationMetricsTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("GetEvaluationMetricsQuery")] + [TestClass] + public class GetEvaluationMetricsQueryTest + { + [TestMethod] + public void Validate_ShouldReturnFalse_WhenFeatureNameIsEmpty() + { + var query = new GetEvaluationMetricsQuery("", "tenant", "environment", 1, "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenTenantIsEmpty() + { + var query = new GetEvaluationMetricsQuery("feature", "", "environment", 1, "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty() + { + var query = new GetEvaluationMetricsQuery("feature", "tenant", "", 1, "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenTimespanInDaysIsZeroOrNegative() + { + var query = new GetEvaluationMetricsQuery("feature", "tenant", "environment", 0, "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid() + { + var query = new GetEvaluationMetricsQuery("feature", "tenant", "environment", 1, "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsTrue(result); + } + } +} diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightTest/GetFeatureFlightQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightTest/GetFeatureFlightQueryTest.cs new file mode 100644 index 0000000..58a505c --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightTest/GetFeatureFlightQueryTest.cs @@ -0,0 +1,44 @@ +using Microsoft.FeatureFlighting.Core.Queries; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.PS.FlightingService.Core.Tests.QueriesTests.GetFeatureFlightTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("GetFeatureFlightQuery")] + [TestClass] + public class GetFeatureFlightQueryTest + { + [TestMethod] + public void Validate_ShouldReturnFalse_WhenFeatureNameIsEmpty() + { + var query = new GetFeatureFlightQuery("", "tenant", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenTenantIsEmpty() + { + var query = new GetFeatureFlightQuery("feature", "", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnFalse_WhenEnvironmentIsEmpty() + { + var query = new GetFeatureFlightQuery("feature", "tenant", "", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsFalse(result); + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenAllFieldsAreValid() + { + var query = new GetFeatureFlightQuery("feature", "tenant", "environment", "correlationId", "transactionId"); + var result = query.Validate(out string errorMessage); + Assert.IsTrue(result); + } + } +} diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightsTests/GetFeatureFlightsQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightsTests/GetFeatureFlightsQueryTest.cs new file mode 100644 index 0000000..b6efe2d --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureFlightsTests/GetFeatureFlightsQueryTest.cs @@ -0,0 +1,56 @@ +using Microsoft.FeatureFlighting.Core.Queries; +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.QueriesTests.GetFeatureFlightsTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("GetFeatureFlightsQuery")] + [TestClass] + public class GetFeatureFlightsQueryTest + { + [TestMethod] + public void Constructor_ShouldSetPropertiesCorrectly() + { + var tenant = "tenant1"; + var environment = "environment1"; + var correlationId = "correlationId1"; + var transactionId = "transactionId1"; + + var query = new GetFeatureFlightsQuery(tenant, environment, correlationId, transactionId); + + Assert.AreEqual(tenant, query.Tenant); + Assert.AreEqual(environment, query.Environment); + Assert.AreEqual(correlationId, query.CorrelationId); + Assert.AreEqual(transactionId, query.TransactionId); + } + + [DataTestMethod] + [DataRow(null, "environment1")] + [DataRow("tenant1", null)] + [DataRow(null, null)] + public void Validate_ShouldReturnFalse_WhenTenantOrEnvironmentIsNull(string tenant, string environment) + { + var query = new GetFeatureFlightsQuery(tenant, environment, "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsFalse(isValid); + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenTenantAndEnvironmentAreNotNull() + { + var query = new GetFeatureFlightsQuery("tenant1", "environment1", "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsTrue(isValid); + } + } +} diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureNamesTest/GetFeatureNamesQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureNamesTest/GetFeatureNamesQueryTest.cs new file mode 100644 index 0000000..930743b --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetFeatureNamesTest/GetFeatureNamesQueryTest.cs @@ -0,0 +1,51 @@ +using Microsoft.FeatureFlighting.Core.Queries; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.PS.FlightingService.Core.Tests.QueriesTests.GetFeatureNamesTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("GetFeatureNamesQuery")] + [TestClass] + public class GetFeatureNamesQueryTest + { + [TestMethod] + public void Constructor_ShouldSetPropertiesCorrectly() + { + var tenant = "tenant1"; + var environment = "environment1"; + var correlationId = "correlationId1"; + var transactionId = "transactionId1"; + + var query = new GetFeatureNamesQuery(tenant, environment, correlationId, transactionId); + + Assert.AreEqual(tenant, query.Tenant); + Assert.AreEqual(environment, query.Environment); + Assert.AreEqual(correlationId, query.CorrelationId); + Assert.AreEqual(transactionId, query.TransactionId); + } + + [DataTestMethod] + [DataRow(null, "environment1")] + [DataRow("tenant1", null)] + [DataRow(null, null)] + public void Validate_ShouldReturnFalse_WhenTenantOrEnvironmentIsNull(string tenant, string environment) + { + var query = new GetFeatureNamesQuery(tenant, environment, "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsFalse(isValid); + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenTenantAndEnvironmentAreNotNull() + { + var query = new GetFeatureNamesQuery("tenant1", "environment1", "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsTrue(isValid); + } + } +} diff --git a/src/service/Tests/Domain.Tests/QueriesTests/GetRegisteredTenantsTest/GetRegisteredTenantsQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/GetRegisteredTenantsTest/GetRegisteredTenantsQueryTest.cs new file mode 100644 index 0000000..eda41c7 --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/GetRegisteredTenantsTest/GetRegisteredTenantsQueryTest.cs @@ -0,0 +1,35 @@ +using Microsoft.FeatureFlighting.Core.Queries; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.PS.FlightingService.Core.Tests.QueriesTests.GetRegisteredTenantsTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("GetRegisteredTenantsQuery")] + [TestClass] + public class GetRegisteredTenantsQueryTest + { + [TestMethod] + public void Constructor_ShouldSetPropertiesCorrectly() + { + var includeDynamicTenants = true; + + var query = new GetRegisteredTenantsQuery(includeDynamicTenants); + + Assert.AreEqual(includeDynamicTenants, query.IncludeDynamicTenants); + Assert.IsNotNull(query.Id); + } + + [TestMethod] + public void Validate_ShouldAlwaysReturnTrue() + { + var query = new GetRegisteredTenantsQuery(true); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsTrue(isValid); + Assert.IsNull(validationErrorMessage); + } + } +} + diff --git a/src/service/Tests/Domain.Tests/QueriesTests/VerifyRuleEngineTest/VerifyRulesEngineQueryTest.cs b/src/service/Tests/Domain.Tests/QueriesTests/VerifyRuleEngineTest/VerifyRulesEngineQueryTest.cs new file mode 100644 index 0000000..a22172b --- /dev/null +++ b/src/service/Tests/Domain.Tests/QueriesTests/VerifyRuleEngineTest/VerifyRulesEngineQueryTest.cs @@ -0,0 +1,65 @@ +using Microsoft.FeatureFlighting.Core.Queries; +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.QueriesTests.VerifyRuleEngineTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("VerifyRulesEngineQuery")] + [TestClass] + public class VerifyRulesEngineQueryTest + { + [TestMethod] + public void Constructor_ShouldSetPropertiesCorrectly() + { + var tenant = "tenant1"; + var workflowName = "workflow1"; + var workflowPayload = "payload1"; + var flightContext = "context1"; + var debug = true; + var correlationId = "correlationId1"; + var transactionId = "transactionId1"; + + var query = new VerifyRulesEngineQuery(tenant, workflowName, workflowPayload, flightContext, debug, correlationId, transactionId); + + Assert.AreEqual(tenant, query.Tenant); + Assert.AreEqual(workflowName, query.WorkflowName); + Assert.AreEqual(workflowPayload, query.WorkflowPayload); + Assert.AreEqual(flightContext, query.FlightContext); + Assert.AreEqual(debug, query.Debug); + Assert.AreEqual(correlationId, query.CorrelationId); + Assert.AreEqual(transactionId, query.TransactionId); + Assert.IsNotNull(query.Id); + } + + [DataTestMethod] + [DataRow(null, "workflow1", "payload1", "context1")] + [DataRow("tenant1", null, "payload1", "context1")] + [DataRow("tenant1", "workflow1", null, "context1")] + [DataRow("tenant1", "workflow1", "payload1", null)] + public void Validate_ShouldReturnFalse_WhenAnyPropertyIsNull(string tenant, string workflowName, string workflowPayload, string flightContext) + { + var query = new VerifyRulesEngineQuery(tenant, workflowName, workflowPayload, flightContext, true, "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsFalse(isValid); + + } + + [TestMethod] + public void Validate_ShouldReturnTrue_WhenAllPropertiesAreNotNull() + { + var query = new VerifyRulesEngineQuery("tenant1", "workflow1", "payload1", "context1", true, "correlationId1", "transactionId1"); + + var isValid = query.Validate(out string validationErrorMessage); + + Assert.IsTrue(isValid); + } + } +} diff --git a/src/service/Tests/Domain.Tests/RulesEngineTests/OperatorTest.cs b/src/service/Tests/Domain.Tests/RulesEngineTests/OperatorTest.cs new file mode 100644 index 0000000..7aa13cc --- /dev/null +++ b/src/service/Tests/Domain.Tests/RulesEngineTests/OperatorTest.cs @@ -0,0 +1,71 @@ +using Microsoft.FeatureFlighting.Core.Operators; +using Microsoft.FeatureFlighting.Core.Spec; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Microsoft.PS.FlightingService.Core.Tests.RulesEngineTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("Operator")] + [TestClass] + public class OperatorTest + { + private readonly Mock _operatorStrategyMock; + private readonly BaseOperator _baseOperatorMock; + + public OperatorTest() + { + var result = new EvaluationResult(true, "pass"); + Task evaluationResult = Task.FromResult(result); + _operatorStrategyMock = new Mock(); + _baseOperatorMock = Mock.Of(op => op.Evaluate(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()) == evaluationResult); + } + + [TestMethod] + public void In_ShouldReturnTrue_WhenOperatorStrategyReturnsTrue() + { + _operatorStrategyMock.Setup(os => os.Get(FeatureFlighting.Core.FeatureFilters.Operator.In)).Returns(_baseOperatorMock); + FeatureFlighting.Core.RulesEngine.Operator.Initialize(_operatorStrategyMock.Object); + + var result = FeatureFlighting.Core.RulesEngine.Operator.In("contextValue", "configuredValue"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void NotIn_ShouldReturnTrue_WhenOperatorStrategyReturnsTrue() + { + _operatorStrategyMock.Setup(os => os.Get(FeatureFlighting.Core.FeatureFilters.Operator.NotIn)).Returns(_baseOperatorMock); + FeatureFlighting.Core.RulesEngine.Operator.Initialize(_operatorStrategyMock.Object); + + var result = FeatureFlighting.Core.RulesEngine.Operator.NotIn("contextValue", "configuredValue"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void IsMember_ShouldReturnTrue_WhenOperatorStrategyReturnsTrue() + { + _operatorStrategyMock.Setup(os => os.Get(FeatureFlighting.Core.FeatureFilters.Operator.MemberOfSecurityGroup)).Returns(_baseOperatorMock); + FeatureFlighting.Core.RulesEngine.Operator.Initialize(_operatorStrategyMock.Object); + + var result = FeatureFlighting.Core.RulesEngine.Operator.IsMember("contextValue", "configuredValue"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void IsNotMember_ShouldReturnTrue_WhenOperatorStrategyReturnsTrue() + { + _operatorStrategyMock.Setup(os => os.Get(FeatureFlighting.Core.FeatureFilters.Operator.NotMemberOfSecurityGroup)).Returns(_baseOperatorMock); + FeatureFlighting.Core.RulesEngine.Operator.Initialize(_operatorStrategyMock.Object); + + var result = FeatureFlighting.Core.RulesEngine.Operator.IsNotMember("contextValue", "configuredValue"); + + Assert.IsTrue(result); + } + + } +} diff --git a/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineEvaluatorTest.cs b/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineEvaluatorTest.cs new file mode 100644 index 0000000..3a4b91a --- /dev/null +++ b/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineEvaluatorTest.cs @@ -0,0 +1,52 @@ +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Core.RulesEngine; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using RulesEngine.Interfaces; +using RulesEngine.Models; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Microsoft.PS.FlightingService.Core.Tests.RulesEngineTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("RulesEngineEvaluator")] + [TestClass] + public class RulesEngineEvaluatorTest + { + private readonly Mock _rulesEngineMock; + private readonly RulesEngineEvaluator _rulesEngineEvaluator; + + public RulesEngineEvaluatorTest() + { + _rulesEngineMock = new Mock(); + _rulesEngineEvaluator = new RulesEngineEvaluator(_rulesEngineMock.Object, "workflow1", new TenantConfiguration()); + } + + [TestMethod] + public async Task Evaluate_ShouldReturnSuccessfulResult_WhenRulesEngineReturnsSuccessfulResult() + { + var ruleResultTree = new List { new RuleResultTree { IsSuccess = true } }; + _rulesEngineMock.Setup(re => re.ExecuteAllRulesAsync(It.IsAny(), It.IsAny())).ReturnsAsync(ruleResultTree); + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() { CorrelationId="test id",TransactionId="t 2001"}; + var result = await _rulesEngineEvaluator.Evaluate(new Dictionary(), loggerTrackingIds); + + Assert.IsTrue(result.Result); + } + + [TestMethod] + public async Task Evaluate_ShouldReturnFailedResult_WhenRulesEngineReturnsFailedResult() + { + var ruleResultTree = new List { new RuleResultTree { IsSuccess = false, ExceptionMessage = "Error" } }; + _rulesEngineMock.Setup(re => re.ExecuteAllRulesAsync(It.IsAny(), It.IsAny())).ReturnsAsync(ruleResultTree); + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() { CorrelationId = "test id", TransactionId = "t 2001" }; + var result = await _rulesEngineEvaluator.Evaluate(new Dictionary(), loggerTrackingIds); + + Assert.IsFalse(result.Result); + Assert.AreEqual("Error", result.Message); + } + } +} + diff --git a/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineManagerTest.cs b/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineManagerTest.cs new file mode 100644 index 0000000..ed1e8ce --- /dev/null +++ b/src/service/Tests/Domain.Tests/RulesEngineTests/RulesEngineManagerTest.cs @@ -0,0 +1,125 @@ +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Common.Storage; +using Microsoft.FeatureFlighting.Core.RulesEngine; +using Microsoft.FeatureFlighting.Core.Spec; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using RulesEngine.Interfaces; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Azure.Core.HttpHeader; + +namespace Microsoft.PS.FlightingService.Core.Tests.RulesEngineTests +{ + [ExcludeFromCodeCoverage] + [TestCategory("RulesEngineManager")] + [TestClass] + public class RulesEngineManagerTest + { + private Mock _mockRulesEngineEvaluator; + private Mock _mockOperatorEvaluatorStrategy; + private Mock _mockTenantConfigurationProvider; + private Mock _mockBlobProviderFactory; + private Mock _mockCacheFactory; + private Mock _mockCache; + private Mock _mockBlobProvider; + private readonly RulesEngineManager _rulesEngineManager; + + public RulesEngineManagerTest() + { + _mockOperatorEvaluatorStrategy=new Mock(); + _mockTenantConfigurationProvider=new Mock(); + _mockBlobProviderFactory=new Mock(); + _mockCacheFactory=new Mock(); + _mockRulesEngineEvaluator = new Mock(); + _mockCache = new Mock(); + _rulesEngineManager = new RulesEngineManager(_mockOperatorEvaluatorStrategy.Object,_mockTenantConfigurationProvider.Object,_mockBlobProviderFactory.Object,_mockCacheFactory.Object); + _mockBlobProvider=new Mock(); + } + + [TestMethod] + public async Task Build_Should_Be_Return_Null() + { + // Arrange + _mockTenantConfigurationProvider.Setup(m => m.Get(It.IsAny())).ReturnsAsync(new TenantConfiguration()); + // Setup your mocks and test inputs + + // Act + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() { CorrelationId = "test id", TransactionId = "t 2001" }; + var result = await _rulesEngineManager.Build("tenant1", "workflow1", loggerTrackingIds); + + // Assert + Assert.IsNull(result); + } + + [TestMethod] + public async Task Build_Should_Be_Return_cachedRuleEngine() + { + // Arrange + var _rulesEngineMock = new Mock(); + var _rulesEngineEvaluator = new RulesEngineEvaluator(_rulesEngineMock.Object, "workflow1", new TenantConfiguration()); + + _mockTenantConfigurationProvider.Setup(m => m.Get(It.IsAny())).ReturnsAsync(GetTenantConfiguration()); + _mockCacheFactory.Setup(m => m.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(m => m.Get(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(_rulesEngineEvaluator); + + // Act + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() { CorrelationId = "test id", TransactionId = "t 2001" }; + var result = await _rulesEngineManager.Build("tenant1", "workflow1", loggerTrackingIds); + + // Assert + Assert.IsNotNull(result); + } + + [TestMethod] + public async Task Build_Success() + { + // Arrange + var jsonString = "{\"WorkflowName\":\"test name\",\"WorkflowsToInject\":[\"id1\",\"id2\"]}"; ; + var _rulesEngineMock = new Mock(); + var _rulesEngineEvaluator = new RulesEngineEvaluator(_rulesEngineMock.Object, "workflow1", new TenantConfiguration()); + + _mockTenantConfigurationProvider.Setup(m => m.Get(It.IsAny())).ReturnsAsync(GetTenantConfiguration()); + _mockCacheFactory.Setup(m => m.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(new Mock().Object); + _mockCache.Setup(m => m.Get(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult(_rulesEngineEvaluator)); + _mockTenantConfigurationProvider.Setup(m => m.Get(It.IsAny())).ReturnsAsync(GetTenantConfiguration()); + _mockBlobProviderFactory.Setup(b=>b.CreateBreWorkflowProvider(It.IsAny())).Returns(Task.FromResult(_mockBlobProvider.Object)); + _mockBlobProvider.Setup(b=>b.Get(It.IsAny(),It.IsAny())).Returns(Task.FromResult(jsonString)); + + // Act + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() { CorrelationId = "test id", TransactionId = "t 2001" }; + var result = await _rulesEngineManager.Build("tenant1", "workflow1", loggerTrackingIds); + + // Assert + Assert.IsNotNull(result); + } + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration() + { + Name = "Test", + Contact = "32323232323", + IsDyanmic = true, + ShortName = "Test", + BusinessRuleEngine=new BusinessRuleEngineConfiguration() + { + CacheDuration=100, + Enabled=true, + Storage=new StorageConfiguration() + { + StorageConnectionString="test", + StorageConnectionStringKey="test", + ContainerName="test" + }, + } + }; + } + } +} diff --git a/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightCacheTest.cs b/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightCacheTest.cs new file mode 100644 index 0000000..22b70a6 --- /dev/null +++ b/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightCacheTest.cs @@ -0,0 +1,108 @@ +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Model; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Core.Cache; +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.PS.FlightingService.Core.Tests.ServicesTest.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("FeatureFlightCache")] + [TestClass] + public class FeatureFlightCacheTest + { + private readonly Mock _cacheFactoryMock; + private readonly FeatureFlightCache _featureFlightCache; + + public FeatureFlightCacheTest() + { + _cacheFactoryMock = new Mock(); + _featureFlightCache = new FeatureFlightCache(_cacheFactoryMock.Object); + } + + [TestMethod] + public async Task GetFeatureFlights_WithValidInputs_ShouldReturnExpectedResults() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var cacheMock = new Mock(); + var expectedResults = new List { new FeatureFlightDto { Name = "TestFeature", Enabled = true } }; + var serializedExpectedResults = expectedResults.Select(JsonConvert.SerializeObject).ToList(); + cacheMock.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(serializedExpectedResults); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + var result = await _featureFlightCache.GetFeatureFlights(tenant, environment, trackingIds); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + } + + [TestMethod] + public async Task GetFeatureNames_WithValidInputs_ShouldReturnExpectedResults() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var cacheMock = new Mock(); + var expectedResults = new List { new FeatureFlightDto { Name = "TestFeature", Enabled = true } }; + var serializedExpectedResults = expectedResults.Select(JsonConvert.SerializeObject).ToList(); + cacheMock.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(serializedExpectedResults); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + var result = await _featureFlightCache.GetFeatureNames(tenant, environment, trackingIds); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + } + + [TestMethod] + public async Task SetFeatureFlights_WithValidInputs_ShouldNotThrowException() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var featureFlights = new List { new FeatureFlightDto { Name = "TestFeature", Enabled = true } }; + var cacheMock = new Mock(); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + await _featureFlightCache.SetFeatureFlights(tenant, environment, featureFlights, trackingIds); + + // Assert + cacheMock.Verify(c => c.SetList(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + } + + [TestMethod] + public async Task DeleteFeatureFlights_WithValidInputs_ShouldNotThrowException() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var cacheMock = new Mock(); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + await _featureFlightCache.DeleteFeatureFlights(tenant, environment, trackingIds); + + // Assert + cacheMock.Verify(c => c.Delete(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + } + } +} diff --git a/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightResultCacheTest.cs b/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightResultCacheTest.cs new file mode 100644 index 0000000..0a07ecc --- /dev/null +++ b/src/service/Tests/Domain.Tests/ServicesTest/CacheTest/FeatureFlightResultCacheTest.cs @@ -0,0 +1,68 @@ +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Core.Services.Cache; +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.PS.FlightingService.Core.Tests.ServicesTest.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("FeatureFlightResultCache")] + [TestClass] + public class FeatureFlightResultCacheTest + { + private readonly Mock _cacheFactoryMock; + private readonly FeatureFlightResultCache _featureFlightResultCache; + + public FeatureFlightResultCacheTest() + { + _cacheFactoryMock = new Mock(); + _featureFlightResultCache = new FeatureFlightResultCache(_cacheFactoryMock.Object); + } + + [TestMethod] + public async Task GetFeatureFlightResults_WithValidInputs_ShouldReturnExpectedResults() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var cacheMock = new Mock(); + var expectedResults = new List> { new KeyValuePair("TestFeature", true) }; + cacheMock.Setup(c => c.GetListObject>(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(expectedResults); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + var result = await _featureFlightResultCache.GetFeatureFlightResults(tenant, environment, trackingIds); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedResults, result); + } + + [TestMethod] + public async Task SetFeatureFlightResult_WithValidInputs_ShouldNotThrowException() + { + // Arrange + string tenant = "TestTenant"; + string environment = "TestEnv"; + var trackingIds = new LoggerTrackingIds(); + var featureFlightResult = new KeyValuePair("TestFeature", true); + var cacheMock = new Mock(); + _cacheFactoryMock.Setup(cf => cf.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + + // Act + await _featureFlightResultCache.SetFeatureFlightResult(tenant, environment, featureFlightResult, null, trackingIds); + + // Assert + cacheMock.Verify(c => c.SetListObjects(It.IsAny(), It.IsAny>>(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + } +} diff --git a/src/service/Tests/Domain.Tests/ServicesTest/FeatureFlagEvaluatorTest.cs b/src/service/Tests/Domain.Tests/ServicesTest/FeatureFlagEvaluatorTest.cs new file mode 100644 index 0000000..ca227eb --- /dev/null +++ b/src/service/Tests/Domain.Tests/ServicesTest/FeatureFlagEvaluatorTest.cs @@ -0,0 +1,226 @@ +using AppInsights.EnterpriseTelemetry; +using AppInsights.EnterpriseTelemetry.Context; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Core; +using Microsoft.FeatureFlighting.Core.Evaluation; +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.PS.FlightingService.Core.Tests.ServicesTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("FeatureFlagEvaluator")] + [TestClass] + public class FeatureFlagEvaluatorTest + { + private readonly Mock _mockStrategyBuilder; + private readonly Mock _mockHttpContextAccessor; + private readonly Mock _mockTenantConfigurationProvider; + private readonly Mock _mockLogger; + private readonly Mock _mockConfiguration; + private readonly FeatureFlagEvaluator _featureFlagEvaluator; + + public FeatureFlagEvaluatorTest() + { + _mockStrategyBuilder = new Mock(); + _mockHttpContextAccessor = new Mock(); + _mockTenantConfigurationProvider = new Mock(); + _mockLogger = new Mock(); + _mockConfiguration = new Mock(); + + // ... + + var configurationSectionMock = new Mock(); + + // Mock GetChildren() to return a list of IConfigurationSection + configurationSectionMock.Setup(x => x.GetChildren()) + .Returns(new List { + new ConfigurationSection(new ConfigurationRoot(new List()), "Child1"), + new ConfigurationSection(new ConfigurationRoot(new List()), "Child2") + }); + var httpContext = new DefaultHttpContext(); + httpContext.Request.Headers["x-application"] = "test-Tenant"; + httpContext.Request.Headers["x-environment"] = "preprop"; + httpContext.Request.Headers["X-FlightContext"] = "test"; + + _mockHttpContextAccessor.Setup(h => h.HttpContext).Returns(httpContext); + + // Mock GetSection() to return the mocked IConfigurationSection + _mockConfiguration.Setup(x => x.GetSection("FeatureManagement")) + .Returns(configurationSectionMock.Object); + + // Now you can use configurationMock.Object in your tests + + // Assuming that FeatureFlagEvaluator has no dependencies + _featureFlagEvaluator = new FeatureFlagEvaluator(_mockStrategyBuilder.Object,_mockHttpContextAccessor.Object,_mockTenantConfigurationProvider.Object,_mockLogger.Object,_mockConfiguration.Object); + } + + [TestMethod] + public async Task Evaluate_WithValidInputs_ShouldReturnExpectedResults() + { + // Arrange + string applicationName = "TestApp"; + string environment = "TestEnv"; + List featureFlags = new List { "Feature1_test", "Feature2_test" }; + var _mockEvaluationStrategy = new Mock(); + + var featureEvaluationResults = new Dictionary { { "Feature1_test", true }, { "Feature2_test", false } }; + + _mockStrategyBuilder.Setup(s => s.GetStrategy(It.IsAny>(), It.IsAny())).Returns(_mockEvaluationStrategy.Object); + + _mockEvaluationStrategy.Setup(e => e.Evaluate(It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(featureEvaluationResults)); + + _mockTenantConfigurationProvider.Setup(t=>t.GetAllTenants()).Returns(GetTenantConfigurations()); + + // Act + var result = await _featureFlagEvaluator.Evaluate(applicationName, environment, featureFlags); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(2, result.Count); + } + + [DataTestMethod] + [DataRow(null)] + [DataRow("")] + public async Task Evaluate_ShouldReturnEmptyResults_when_empty_features(string feature) + { + // Arrange + string applicationName = "TestApp"; + string environment = "TestEnv"; + List featureFlags; + if (feature == null) + { + featureFlags =null; + } + else + { + featureFlags = new List { }; + } + var _mockEvaluationStrategy = new Mock(); + + var featureEvaluationResults = new Dictionary { { "Feature1_test", true }, { "Feature2_test", false } }; + + _mockStrategyBuilder.Setup(s => s.GetStrategy(It.IsAny>(), It.IsAny())).Returns(_mockEvaluationStrategy.Object); + + _mockEvaluationStrategy.Setup(e => e.Evaluate(It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(featureEvaluationResults)); + + _mockTenantConfigurationProvider.Setup(t => t.GetAllTenants()).Returns(GetTenantConfigurations()); + + // Act + var result = await _featureFlagEvaluator.Evaluate(applicationName, environment, featureFlags); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(0, result.Count); + } + + + [TestMethod] + public async Task Evaluate_Success() + { + // Arrange + string applicationName = "TestApp"; + string environment = "TestEnv"; + List featureFlags = new List { "T1__test", "T2_test" }; + + var _mockEvaluationStrategy = new Mock(); + + var featureEvaluationResults = new Dictionary { { "Feature1_test", true }, { "Feature2_test", false } }; + + _mockStrategyBuilder.Setup(s => s.GetStrategy(It.IsAny>(), It.IsAny())).Returns(_mockEvaluationStrategy.Object); + + _mockEvaluationStrategy.Setup(e => e.Evaluate(It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(featureEvaluationResults)); + + _mockTenantConfigurationProvider.Setup(t => t.GetAllTenants()).Returns(GetTenantConfigurations()); + + // Act + var result = await _featureFlagEvaluator.Evaluate(applicationName, environment, featureFlags); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(4, result.Count); + } + + [TestMethod] + public async Task Evaluate_WithNoFeatureFlags_ShouldReturnEmptyResults() + { + // Arrange + string applicationName = "TestApp"; + string environment = "TestEnv"; + List featureFlags = new List { "Feature1_test", "Feature2_test" }; + var _mockEvaluationStrategy = new Mock(); + + var featureEvaluationResults = new Dictionary { }; + + _mockStrategyBuilder.Setup(s => s.GetStrategy(It.IsAny>(), It.IsAny())).Returns(_mockEvaluationStrategy.Object); + + _mockEvaluationStrategy.Setup(e => e.Evaluate(It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(featureEvaluationResults)); + + _mockTenantConfigurationProvider.Setup(t => t.GetAllTenants()).Returns(GetTenantConfigurations()); + + // Act + var result = await _featureFlagEvaluator.Evaluate(applicationName, environment, featureFlags); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(result.Count,0); + } + + private IEnumerable GetTenantConfigurations() + { + return new List + { + new TenantConfiguration() + { + Name = "TestApp", + Contact="32323232323", + IsDyanmic=true, + ShortName="Test", + Evaluation=new FlagEvaluationConfiguration{ + + AddDisabledContext=true, + AddEnabledContext=true, + IgnoreException=false, + ParallelEvaluation=new ParallelEvaluationConfiguration{ + BatchSize=10, + ParallelMode="run parallely" + }, + } + }, + new TenantConfiguration() + { + Name = "T1", + Contact="32323232323", + IsDyanmic=true, + ShortName="Test", + Evaluation=new FlagEvaluationConfiguration{ + + AddDisabledContext=true, + AddEnabledContext=true, + IgnoreException=false, + ParallelEvaluation=new ParallelEvaluationConfiguration{ + BatchSize=10, + ParallelMode="run parallely" + }, + } + }, + new TenantConfiguration() + { + Name = "Test2", + Contact="32323232323", + IsDyanmic=true, + ShortName="Test", + } + }; + } + } +} diff --git a/src/service/Tests/Domain.Tests/appsettings.test.json b/src/service/Tests/Domain.Tests/appsettings.test.json new file mode 100644 index 0000000..a43d32a --- /dev/null +++ b/src/service/Tests/Domain.Tests/appsettings.test.json @@ -0,0 +1,172 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + }, + "ClientSideErrorSuppressionEnabled": true, + "EnvironmentInitializerEnabled": true, + "ResponseCodeTranslationEnabled": true, + "AutoTrackingEnabled": true, + "RequestTelemetryEnhanced": true, + "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'" + } + }, + "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": { + "Authorization": { + "Type": "AuthorizationService", + "ConnectionStringFormat": "RunAs=App;AppId={0};TenantId=microsoft.onmicrosoft.com;AppKey={1}", + "RequiredTenants": "FxPPlatform", + "SenderAppName": "Experimentation:Flighting:API", + "ExcludeUriList": "GET */api/v1/evaluate*,GET */api/v1/*/flighting*" + }, + "Caching": { + "Type": "URP", + "Cluster": "PS-PreProd-01", + "App": "FXP-Flighting", + "Location": "eastus", + "Secret": "URP-Secret", + "Graph": "InMemory" + } + }, + "GTA_IV_OPERATIONAL_REPORTING": { + "Authorization": { + "Type": "Configuration", + "Administrators": "admin@microsoft.com,6f40053e-5319-40e5-a90b-6f714506d96d" + }, + "Caching": { + "Type": "Redis", + "ConnectionString": "GTA-Redis-Connection-String", + "Timeout": 2000, + "Graph": "InMemory" + } + } + }, + "EventStore": { + "Email": { + "PublisherId": "12345", + "PublisherName": "FXP", + "SenderAddress": "USA", + "NotificationChannel": "Email", + "EmailSubjectPrefix": "FXP" + } + } +} diff --git a/src/service/Tests/Services.Tests/AuthenticationTest/AadTokenGeneratorTest.cs b/src/service/Tests/Services.Tests/AuthenticationTest/AadTokenGeneratorTest.cs new file mode 100644 index 0000000..089ab88 --- /dev/null +++ b/src/service/Tests/Services.Tests/AuthenticationTest/AadTokenGeneratorTest.cs @@ -0,0 +1,32 @@ +using Microsoft.FeatureFlighting.Infrastructure.Authentication; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.AuthenticationTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class AadTokenGeneratorTest + { + private readonly IDictionary _cache; + public AadTokenGeneratorTest() + { + _cache = new ConcurrentDictionary(); + } + + // Define the test method + [TestMethod] + public void GenerateToken() + { + var mockUserService = new Mock(); + // Act + var userController = new AadTokenGenerator(); + var result = userController.GenerateToken("sajchvah", "sachagsc", "csahcas", "xhasgdvghas"); + Assert.IsNotNull(result.Id); + // Assert + } + } +} diff --git a/src/service/Tests/Services.Tests/AuthenticationTest/IdentityContextTest.cs b/src/service/Tests/Services.Tests/AuthenticationTest/IdentityContextTest.cs new file mode 100644 index 0000000..845f53e --- /dev/null +++ b/src/service/Tests/Services.Tests/AuthenticationTest/IdentityContextTest.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Infrastructure.Authentication; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.AuthenticationTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class IdentityContextTest + { + private IdentityContext Setup() + { + var httpContextAccessorMock = new Mock(); + var iConfiguration = new Mock(); + var repositoryMock = new Mock>(); + return new IdentityContext(iConfiguration.Object, httpContextAccessorMock.Object); + } + + [TestMethod] + public void GetCurrentUserPrincipalName() + { + Assert.IsNull(Setup().GetCurrentUserPrincipalName()); + } + + [TestMethod] + public void GetSignedInUserPrincipalName() + { + Assert.IsNull(Setup().GetSignedInUserPrincipalName()); + } + [TestMethod] + public void GetSignedInAppId() + { + Assert.IsNull(Setup().GetSignedInAppId()); + } + + } +} diff --git a/src/service/Tests/Services.Tests/AuthorizationServiceTests.cs b/src/service/Tests/Services.Tests/AuthorizationTest/AuthorizationServiceTests.cs similarity index 97% rename from src/service/Tests/Services.Tests/AuthorizationServiceTests.cs rename to src/service/Tests/Services.Tests/AuthorizationTest/AuthorizationServiceTests.cs index 9d5173e..60ddd00 100644 --- a/src/service/Tests/Services.Tests/AuthorizationServiceTests.cs +++ b/src/service/Tests/Services.Tests/AuthorizationTest/AuthorizationServiceTests.cs @@ -1,173 +1,176 @@ -using Moq; -using System.Threading.Tasks; -using System.Security.Claims; -using Microsoft.AspNetCore.Http; -using System.Collections.Generic; -using Microsoft.Extensions.Configuration; -using Microsoft.FeatureFlighting.Common.Config; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.FeatureFlighting.Common.Authorization; -using Microsoft.FeatureFlighting.Common.AppExceptions; -using Microsoft.FeatureFlighting.Infrastructure.Authorization; - -namespace Services.Tests -{ - [TestClass] - public class AuthorizationServiceTests - { - private Mock httpAccessorMockWithPermissions; - private Mock httpAccessorMockWithoutPermissions; - private Mock httpAccessorWithSuperAdminPermissions; - private ITenantConfigurationProvider _tenantConfigurationProvider; - private IConfiguration _mockConfiguration; - - [TestInitialize] - public void TestStartup() - { - SetMockConfig(); - httpAccessorMockWithPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithPermissions, true, false); - httpAccessorMockWithoutPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithoutPermissions, false, false); - httpAccessorWithSuperAdminPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithoutPermissions, false, true); - } - - - [TestMethod] - public void Must_Authorize_When_Claims_Are_Present() - { - IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); - } - - [TestMethod] - public void Must_Authorize_When_Admin_Claims_Are_Present() - { - IAuthorizationService authService = new AuthorizationService(httpAccessorWithSuperAdminPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); - } - - [ExpectedException(typeof(AccessForbiddenException))] - [TestMethod] - public void Must_Authorize_When_Claims_Are_Not_Present() - { - IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithoutPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); - } - - [TestMethod] - public void Must_Return_Authorized_When_Having_Claims() - { - IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); - bool isAuthorized = authService.IsAuthorized("TestApp"); - Assert.IsTrue(isAuthorized); - } - - [TestMethod] - public void Must_Return_UnAuthorized_When_Not_Having_Claims() - { - IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithoutPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); - bool isAuthorized = authService.IsAuthorized("TestApp"); - Assert.IsFalse(isAuthorized); - } - - [TestMethod] - public void Must_Augment_Claims_And_Authorize_When_Admin_App_Is_Signed_In() - { - var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "6f40053e-5319-40e5-a90b-6f714506d96d"); - var tenant = "GTA IV OPERATIONAL REPORTING"; - IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.AugmentAdminClaims(tenant); - bool isAuthorized = authService.IsAuthorized(tenant); - Assert.IsTrue(isAuthorized); - } - - [TestMethod] - public void Must_Augment_Claims_And_Authorize_When_Admin_User_Is_Signed_In() - { - var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "admin@microsoft.com"); - var tenant = "GTA IV OPERATIONAL REPORTING"; - IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.AugmentAdminClaims(tenant); - bool isAuthorized = authService.IsAuthorized(tenant); - Assert.IsTrue(isAuthorized); - } - - [TestMethod] - public void Must_Augment_Claims_And_UnAuthorize_When_NonAdmin_Is_Signed_In() - { - var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "NON_ADMIN_ID"); - var tenant = "GTA IV OPERATIONAL REPORTING"; - IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); - authService.AugmentAdminClaims(tenant); - bool isAuthorized = authService.IsAuthorized(tenant); - Assert.IsFalse(isAuthorized); - } - - private Mock SetupHttpContextAccessorMock(Mock httpContextAccessorMock, bool hasPermissions, bool hasAdminPermission = false, string upn = null, string name = null, string appId = null) - { - httpContextAccessorMock = new Mock(); - - var httpContext = new DefaultHttpContext(); - - var claimsWithPermissions = new List() - { - new Claim("TestApp", "manageexperimentation") - }; - - var claimsWithoutPermissions = new List() - { - new Claim("TestApp", "testfeature") - }; - - var claimsWithAdminPermission = new List() - { - new Claim("Experimentation", "All") - }; - - - var identityWithClaims = new ClaimsIdentity(claimsWithPermissions, "TestAuthType"); - var identityWithoutClaims = new ClaimsIdentity(claimsWithoutPermissions, "TestAuthType"); - var identityWithAdminClaims = new ClaimsIdentity(claimsWithAdminPermission, "TestAuthType"); - - if (hasPermissions) - { - httpContext.User.AddIdentity(identityWithClaims); - } - else - { - httpContext.User.AddIdentity(identityWithoutClaims); - } - - if (hasAdminPermission) - { - httpContext.User.AddIdentity(identityWithAdminClaims); - } - - if (!string.IsNullOrWhiteSpace(upn)) - (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim("upn", upn)); - if (!string.IsNullOrWhiteSpace(name)) - (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim(ClaimTypes.Name, name)); - if (!string.IsNullOrWhiteSpace(appId)) - (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim("appid", appId)); - - httpContextAccessorMock.Setup(_ => _.HttpContext).Returns(httpContext); - - return httpContextAccessorMock; - } - - [DeploymentItem(@"appsettings.test.json", @"")] - private void SetMockConfig() - { - TenantConfiguration mockConfiguration = TenantConfiguration.GetDefault(); - mockConfiguration.Authorization = new() - { - Type = "Configuration", - Administrators = "tester-001@microsoft.com,appid-001,6f40053e-5319-40e5-a90b-6f714506d96d,admin@microsoft.com" - }; - Mock mockProvider = new(); - mockProvider.Setup(provider => provider.Get(It.IsAny())) - .Returns(Task.FromResult(mockConfiguration)); - _tenantConfigurationProvider = mockProvider.Object; - _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); - } - } -} +using Moq; +using System.Threading.Tasks; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.FeatureFlighting.Common.Authorization; +using Microsoft.FeatureFlighting.Common.AppExceptions; +using Microsoft.FeatureFlighting.Infrastructure.Authorization; +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.AuthorizationTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class AuthorizationServiceTests + { + private Mock httpAccessorMockWithPermissions; + private Mock httpAccessorMockWithoutPermissions; + private Mock httpAccessorWithSuperAdminPermissions; + private ITenantConfigurationProvider _tenantConfigurationProvider; + private IConfiguration _mockConfiguration; + + [TestInitialize] + public void TestStartup() + { + SetMockConfig(); + httpAccessorMockWithPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithPermissions, true, false); + httpAccessorMockWithoutPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithoutPermissions, false, false); + httpAccessorWithSuperAdminPermissions = SetupHttpContextAccessorMock(httpAccessorMockWithoutPermissions, false, true); + } + + + [TestMethod] + public void Must_Authorize_When_Claims_Are_Present() + { + IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); + } + + [TestMethod] + public void Must_Authorize_When_Admin_Claims_Are_Present() + { + IAuthorizationService authService = new AuthorizationService(httpAccessorWithSuperAdminPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); + } + + [ExpectedException(typeof(AccessForbiddenException))] + [TestMethod] + public void Must_Authorize_When_Claims_Are_Not_Present() + { + IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithoutPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.EnsureAuthorized("TestApp", "TestOp", "CorrId"); + } + + [TestMethod] + public void Must_Return_Authorized_When_Having_Claims() + { + IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); + bool isAuthorized = authService.IsAuthorized("TestApp"); + Assert.IsTrue(isAuthorized); + } + + [TestMethod] + public void Must_Return_UnAuthorized_When_Not_Having_Claims() + { + IAuthorizationService authService = new AuthorizationService(httpAccessorMockWithoutPermissions.Object, _tenantConfigurationProvider, _mockConfiguration); + bool isAuthorized = authService.IsAuthorized("TestApp"); + Assert.IsFalse(isAuthorized); + } + + [TestMethod] + public void Must_Augment_Claims_And_Authorize_When_Admin_App_Is_Signed_In() + { + var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "6f40053e-5319-40e5-a90b-6f714506d96d"); + var tenant = "GTA IV OPERATIONAL REPORTING"; + IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.AugmentAdminClaims(tenant); + bool isAuthorized = authService.IsAuthorized(tenant); + Assert.IsTrue(isAuthorized); + } + + [TestMethod] + public void Must_Augment_Claims_And_Authorize_When_Admin_User_Is_Signed_In() + { + var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "admin@microsoft.com"); + var tenant = "GTA IV OPERATIONAL REPORTING"; + IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.AugmentAdminClaims(tenant); + bool isAuthorized = authService.IsAuthorized(tenant); + Assert.IsTrue(isAuthorized); + } + + [TestMethod] + public void Must_Augment_Claims_And_UnAuthorize_When_NonAdmin_Is_Signed_In() + { + var mockHttpContextAccessor = SetupHttpContextAccessorMock(null, false, false, null, null, "NON_ADMIN_ID"); + var tenant = "GTA IV OPERATIONAL REPORTING"; + IAuthorizationService authService = new AuthorizationService(mockHttpContextAccessor.Object, _tenantConfigurationProvider, _mockConfiguration); + authService.AugmentAdminClaims(tenant); + bool isAuthorized = authService.IsAuthorized(tenant); + Assert.IsFalse(isAuthorized); + } + + private Mock SetupHttpContextAccessorMock(Mock httpContextAccessorMock, bool hasPermissions, bool hasAdminPermission = false, string upn = null, string name = null, string appId = null) + { + httpContextAccessorMock = new Mock(); + + var httpContext = new DefaultHttpContext(); + + var claimsWithPermissions = new List() + { + new Claim("TestApp", "manageexperimentation") + }; + + var claimsWithoutPermissions = new List() + { + new Claim("TestApp", "testfeature") + }; + + var claimsWithAdminPermission = new List() + { + new Claim("Experimentation", "All") + }; + + + var identityWithClaims = new ClaimsIdentity(claimsWithPermissions, "TestAuthType"); + var identityWithoutClaims = new ClaimsIdentity(claimsWithoutPermissions, "TestAuthType"); + var identityWithAdminClaims = new ClaimsIdentity(claimsWithAdminPermission, "TestAuthType"); + + if (hasPermissions) + { + httpContext.User.AddIdentity(identityWithClaims); + } + else + { + httpContext.User.AddIdentity(identityWithoutClaims); + } + + if (hasAdminPermission) + { + httpContext.User.AddIdentity(identityWithAdminClaims); + } + + if (!string.IsNullOrWhiteSpace(upn)) + (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim("upn", upn)); + if (!string.IsNullOrWhiteSpace(name)) + (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim(ClaimTypes.Name, name)); + if (!string.IsNullOrWhiteSpace(appId)) + (httpContext.User.Identity as ClaimsIdentity).AddClaim(new Claim("appid", appId)); + + httpContextAccessorMock.Setup(_ => _.HttpContext).Returns(httpContext); + + return httpContextAccessorMock; + } + + [DeploymentItem(@"appsettings.test.json", @"")] + private void SetMockConfig() + { + TenantConfiguration mockConfiguration = TenantConfiguration.GetDefault(); + mockConfiguration.Authorization = new() + { + Type = "Configuration", + Administrators = "tester-001@microsoft.com,appid-001,6f40053e-5319-40e5-a90b-6f714506d96d,admin@microsoft.com" + }; + Mock mockProvider = new(); + mockProvider.Setup(provider => provider.Get(It.IsAny())) + .Returns(Task.FromResult(mockConfiguration)); + _tenantConfigurationProvider = mockProvider.Object; + _mockConfiguration = new ConfigurationBuilder().AddJsonFile(@"appsettings.test.json").Build(); + } + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/BackgroundCacheManagerTest.cs b/src/service/Tests/Services.Tests/CacheTest/BackgroundCacheManagerTest.cs new file mode 100644 index 0000000..ce0d5eb --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/BackgroundCacheManagerTest.cs @@ -0,0 +1,79 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class BackgroundCacheManagerTest + { + + private BackgroundCacheManager Setup() + { + + // Arrange + var repositoryMock = new Mock>(); + var _logger = new Mock(); + return new BackgroundCacheManager(repositoryMock.Object, _logger.Object); + } + + // Define the test method + [TestMethod] + public void Dispose() + { + // Act + Setup().Dispose(); // Calling the method under test + var result = Setup().GetCacheableServiceIds(); + Assert.IsNotNull(result); + // Assert + Assert.IsNotNull(result); + } + + [TestMethod] + public void RebuildCache() + { + CancellationToken cancellationToken = default; + // Arrange + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds() + { + CorrelationId = "1", + TransactionId = "2" + }; + + Dictionary> _backgroundCacheableParams = new() + { + + }; + + var repositoryMock = new Mock>(); + var _logger = new Mock(); + var service = new BackgroundCacheManager(repositoryMock.Object, _logger.Object); + // Act + var result = service.RebuildCache(loggerTrackingIds, cancellationToken = default); + + Assert.IsNotNull(result); + // Assert + Assert.IsNotNull(repositoryMock); + } + + [TestMethod] + public void Init() + { + // Arrange + var repositoryMock = new Mock>(); + var _logger = new Mock(); + var service = new BackgroundCacheManager(repositoryMock.Object, _logger.Object); + // Act + service.Init(100); + // Assert + Assert.IsNotNull(repositoryMock); + } + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/CacheLogContextTest.cs b/src/service/Tests/Services.Tests/CacheTest/CacheLogContextTest.cs new file mode 100644 index 0000000..2c05c07 --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/CacheLogContextTest.cs @@ -0,0 +1,20 @@ +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class CacheLogContextTest + { + [TestMethod] + public void GetMetadata_Success() + { + var result = CacheLogContext.GetMetadata("host", "delete", "1243dsadde23213"); + Assert.IsNotNull(result); + } + + + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/FeatureFlightResultCacheFactoryTest.cs b/src/service/Tests/Services.Tests/CacheTest/FeatureFlightResultCacheFactoryTest.cs new file mode 100644 index 0000000..9db886a --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/FeatureFlightResultCacheFactoryTest.cs @@ -0,0 +1,55 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Authorization; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Authentication; +using Microsoft.FeatureFlighting.Infrastructure.Authorization; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class FeatureFlightResultCacheFactoryTest + { + private Mock _mockLogger; + private Mock _mockMemoryCache; + private Mock _mockFeatureFlightResultCacheFactory; + + private FeatureFlightResultCacheFactory _factory; + + public FeatureFlightResultCacheFactoryTest() + { + _mockLogger = new Mock(); + _mockMemoryCache = new Mock(); + + _factory = new FeatureFlightResultCacheFactory(_mockMemoryCache.Object, _mockLogger.Object); + + _mockFeatureFlightResultCacheFactory = new Mock(); + } + + + [TestMethod] + public void Create() + { + Mock cacheMock = new Mock(); + _mockFeatureFlightResultCacheFactory.Setup(feature => feature.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(cacheMock.Object); + var result = _mockFeatureFlightResultCacheFactory.Object.Create("tenant", "operation", "121242324", "sdfsfdf"); + Assert.IsNotNull(result); + } + + } +} \ No newline at end of file diff --git a/src/service/Tests/Services.Tests/CacheTest/FlightingCacheFactoryTest.cs b/src/service/Tests/Services.Tests/CacheTest/FlightingCacheFactoryTest.cs new file mode 100644 index 0000000..df94b1d --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/FlightingCacheFactoryTest.cs @@ -0,0 +1,115 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Authentication; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.FeatureFlighting.Infrastructure.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using System.Transactions; + + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class FlightingCacheFactoryTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockConfiguration; + private Mock _mockLogger; + private Mock _mockMemoryCache; + + private FlightingCacheFactory _factory; + public FlightingCacheFactoryTest() + { + _mockTenantConfigurationProvider = new Mock(); + _mockConfiguration = new Mock(); + _mockLogger = new Mock(); + _mockMemoryCache = new Mock(); + + _factory = new FlightingCacheFactory(_mockMemoryCache.Object, _mockTenantConfigurationProvider.Object, _mockConfiguration.Object, _mockLogger.Object); + } + + [TestMethod] + public void Create_success_when_cache_is_null() + { + var _tenantConfigurationProvider = new Mock(); + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(GetTenantConfiguration())); + var result = _factory.Create("tenant", "122122", "eweqwe23233"); + + Assert.IsNotNull(result); + } + + [DataTestMethod] + [DataRow("")] + [DataRow(null)] + public void Create_success_when_cache_type_is_null(string cacheType) + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + tenantConfiguration.Cache = new CacheConfiguration { Type = cacheType }; + + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = _factory.Create("tenant", "122122", "eweqwe23233"); + + Assert.IsNotNull(result); + } + + [DataTestMethod] + [DataRow("NoCache")] + [DataRow("Redis")] + [DataRow("")] + [DataRow("InMemory")] + public void Create_success_when_cache_type_is_not_null(string cacheType) + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + tenantConfiguration.Cache = new CacheConfiguration { Type = cacheType }; + + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = _factory.Create("tenant", "122122", "eweqwe23233"); + + Assert.IsNotNull(result); + } + + [TestMethod] + public void Create_success_when_redis_is_null() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + tenantConfiguration.Cache = new CacheConfiguration { Redis = null }; + + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = _factory.Create("tenant", "122122", "eweqwe23233"); + + Assert.IsNotNull(result); + } + + [TestMethod] + public void Create_success_when_URP_is_null() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + tenantConfiguration.Cache = new CacheConfiguration { URP = null }; + + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = _factory.Create("tenant", "122122", "eweqwe23233"); + + Assert.IsNotNull(result); + } + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration() + { + Name = "Test", + Contact = "32323232323", + IsDyanmic = true, + ShortName = "Test", + }; + } + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/InMemoryCacheTest.cs b/src/service/Tests/Services.Tests/CacheTest/InMemoryCacheTest.cs new file mode 100644 index 0000000..539be1f --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/InMemoryCacheTest.cs @@ -0,0 +1,143 @@ +using AppInsights.EnterpriseTelemetry; +using Castle.DynamicProxy; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Options; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class InMemoryCacheTest + { + private Mock _mockMemoryCache; + private IMemoryCache _memoryCache; + private Mock _mockLogger; + private string tenant; + private InMemoryCache inMemoryCache; + public InMemoryCacheTest() { + + tenant = "test"; + _mockLogger = new Mock(); + _mockMemoryCache = new Mock(); + //_mockMemoryCache.Setup(m => m.CreateEntry(It.IsAny())).Returns(new ICacheEntry); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object,tenant,_mockLogger.Object); + } + + [TestMethod] + public async Task Get_NoData() + { + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = await inMemoryCache.Get("1", "1212n2bn1b2", "212121"); + Assert.IsFalse(result); + } + + [TestMethod] + public async Task GetList_NoData() + { + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = await inMemoryCache.GetList("1", "1212n2bn1b2", "212121"); + Assert.IsNull(result); + } + + [TestMethod] + public async Task GetListObject_NoData() + { + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = await inMemoryCache.GetListObject("1", "1212n2bn1b2", "212121"); + Assert.IsNull(result); + } + + [TestMethod] + public async Task Delete_NoData() + { + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result=inMemoryCache.Delete("1", "1212n2bn1b2", "212121").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public async Task Set_NoData() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = inMemoryCache.Set("1", tenantConfiguration,"1212n2bn1b2", "212121").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public async Task SetList_NoData() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = inMemoryCache.SetList("1", new List { "tenant1", "tenant2" , "tenant3" }, "1212n2bn1b2", "212121").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public async Task SetListObjects_NoData() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + string? keyPayload = null; + var mockCacheEntry = new Mock(); + _mockMemoryCache.Setup(mc => mc.CreateEntry(It.IsAny())) + .Callback((object k) => keyPayload = (string)k) + .Returns(mockCacheEntry.Object); + inMemoryCache = new InMemoryCache(_mockMemoryCache.Object, tenant, _mockLogger.Object); + var result = inMemoryCache.SetListObjects("1", new List { "tenant1", "tenant2", "tenant3" }, "1212n2bn1b2", "212121").IsCompleted; + Assert.IsTrue(result); + } + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration() + { + Name = "Test", + Contact = "32323232323", + IsDyanmic = true, + ShortName = "Test", + }; + } + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/NoCacheTest.cs b/src/service/Tests/Services.Tests/CacheTest/NoCacheTest.cs new file mode 100644 index 0000000..c50cc5f --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/NoCacheTest.cs @@ -0,0 +1,105 @@ +using Microsoft.Azure.Cosmos.Serialization.HybridRow; +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +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.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class NoCacheTest + { + private NoCache noCache; + private Mock _mockCache; + public NoCacheTest() + { + noCache=new NoCache(); + _mockCache=new Mock(); + } + + [TestMethod] + public void Delete_Success() + { + var result = noCache.Delete("test", "1234", "210").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public async Task Get_NoResult() + { + var result = await noCache.Get("test", "1234", "210"); + Assert.IsNull(result); + } + + [TestMethod] + public async Task GetList_NoResult() + { + var result = await noCache.GetList("tested", "202", "101"); + Assert.IsNull(result); + } + + + [TestMethod] + public async Task GetListObject_NoResult() + { + try + { + var result = await noCache.GetListObject("test", "1234", "210"); + + } catch (Exception ex){ + Assert.IsNotNull(ex.Message); + } + } + + [TestMethod] + public void Set_success() + { + TenantConfiguration configuration = GetTenantConfiguration(); + var result = noCache.Set("test",configuration, "1234", "210").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public void SetList_success() + { + TenantConfiguration configuration = GetTenantConfiguration(); + var result = noCache.SetList("test", new List { "test1","test2"}, "1234", "210").IsCompleted; + Assert.IsTrue(result); + } + + [TestMethod] + public async Task SetListObject_NoResult() + { + try + { + await noCache.SetListObjects("test", new List { "test1", "test2" }, "1234", "210"); + + } + catch (Exception ex) + { + Assert.IsNotNull(ex.Message); + } + } + + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration() + { + Name = "Test", + Contact = "32323232323", + IsDyanmic = true, + ShortName = "Test", + }; + } + + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/RedisCacheTest.cs b/src/service/Tests/Services.Tests/CacheTest/RedisCacheTest.cs new file mode 100644 index 0000000..498eba0 --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/RedisCacheTest.cs @@ -0,0 +1,79 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using StackExchange.Redis; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("RedisCache")] + [TestClass] + public class RedisCacheTest + { + private readonly Mock _mockConnectionMultiplexer; + private readonly Mock _mockDatabase; + private readonly Mock _mockLogger; + private RedisCache _redisCache; + + public RedisCacheTest() + { + _mockConnectionMultiplexer = new Mock(); + _mockDatabase = new Mock(); + _mockLogger = new Mock(); + _redisCache = new RedisCache(_mockConnectionMultiplexer.Object, _mockLogger.Object, "localhost"); + + _mockConnectionMultiplexer.Setup(m => m.GetDatabase(It.IsAny(), It.IsAny())).Returns(_mockDatabase.Object); + } + + [TestMethod] + public async Task GetList_WhenCalledWithValidKey_NoResult() + { + // Arrange + var key = "TestKey"; + var expectedList = new RedisValue[] { "Value1", "Value2" }; + _mockDatabase.Setup(m => m.ListRangeAsync(key, 0, -1, CommandFlags.None)).Returns(Task.FromResult(expectedList)); + + // Act + var result = await _redisCache.GetList(key, "TestCorrelationId", "TestTransactionId"); + + // Assert + Assert.IsNull(result); + } + + [TestMethod] + public async Task Delete_WhenCalledWithValidKey_ThrowException() + { + // Arrange + var key = "TestKey"; + _mockDatabase.Setup(m => m.KeyDeleteAsync(key, CommandFlags.None)).ReturnsAsync(true); + + // Act + var result= _redisCache.Delete(key, "TestCorrelationId", "TestTransactionId").IsCompleted; + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public async Task SetList_WhenCalledWithValidKeyAndValues_ShouldSetList() + { + // Arrange + var key = "TestKey"; + var values = new List { "Value1", "Value2" }; + _mockDatabase.Setup(m => m.ListRightPushAsync(key, It.IsAny(), CommandFlags.None)).ReturnsAsync(values.Count); + + // Act + var result = _redisCache.SetList(key, values, "TestCorrelationId", "TestTransactionId").IsCompleted; + + // Assert + Assert.IsTrue(result); + } + } +} diff --git a/src/service/Tests/Services.Tests/CacheTest/UnifiedRedisCacheTest.cs b/src/service/Tests/Services.Tests/CacheTest/UnifiedRedisCacheTest.cs new file mode 100644 index 0000000..2274b9d --- /dev/null +++ b/src/service/Tests/Services.Tests/CacheTest/UnifiedRedisCacheTest.cs @@ -0,0 +1,28 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.FeatureFlighting.Infrastructure.Cache; +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.Infrastructure.Tests.CacheTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("UnifiedRedisCache")] + [TestClass] + public class UnifiedRedisCacheTest + { + private readonly Mock _mockLogger; + private readonly UnifiedRedisCache _unifiedRedisCache; + + public UnifiedRedisCacheTest() + { + _mockLogger = new Mock(); + _unifiedRedisCache = new UnifiedRedisCache("TestCluster", "TestApp", "TestAppSecret", "TestLocation", _mockLogger.Object); + } + } +} diff --git a/src/service/Tests/Services.Tests/GraphTest/ConfidentialClientApplicationBuilderWrapper.cs b/src/service/Tests/Services.Tests/GraphTest/ConfidentialClientApplicationBuilderWrapper.cs new file mode 100644 index 0000000..9523394 --- /dev/null +++ b/src/service/Tests/Services.Tests/GraphTest/ConfidentialClientApplicationBuilderWrapper.cs @@ -0,0 +1,27 @@ +using Microsoft.Identity.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.GraphTest +{ + public interface IConfidentialClientApplicationBuilderWrapper + { + IConfidentialClientApplication Build(string clientId, string authority, string clientSecret); + } + + public class ConfidentialClientApplicationBuilderWrapper + { + public IConfidentialClientApplication Build(string clientId, string authority, string clientSecret) + { + return ConfidentialClientApplicationBuilder + .Create(clientId) + .WithAuthority(authority) + .WithClientSecret(clientSecret) + .Build(); + } + + } +} diff --git a/src/service/Tests/Services.Tests/GraphTest/GraphGroupVerificationServiceTest.cs b/src/service/Tests/Services.Tests/GraphTest/GraphGroupVerificationServiceTest.cs new file mode 100644 index 0000000..6f773d8 --- /dev/null +++ b/src/service/Tests/Services.Tests/GraphTest/GraphGroupVerificationServiceTest.cs @@ -0,0 +1,245 @@ +using Microsoft.FeatureFlighting.Common.Caching; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Infrastructure.Graph; +using Microsoft.Graph; +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; +using AppInsights.EnterpriseTelemetry; +using Microsoft.Extensions.Configuration; +using Microsoft.Identity.Client; +using Microsoft.FeatureFlighting.Common.Cache; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.GraphTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("GraphGroupVerificationService")] + [TestClass] + public class GraphGroupVerificationServiceTest + { + private readonly Mock _mockGraphServiceClient; + private readonly Mock _mockCacheFactory; + private readonly Mock _mockCache; + private readonly Mock _mockLogger; + private readonly Mock _mockConfiguration; + private readonly GraphGroupVerificationService _graphGroupVerificationService; + + public GraphGroupVerificationServiceTest() + { + _mockGraphServiceClient = new Mock(); + _mockCacheFactory = new Mock(); + _mockLogger = new Mock(); + _mockConfiguration = new Mock(); + _mockCache = new Mock(); + + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:CacheExpiration")]).Returns("100"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:CachingEnabled")]).Returns("True"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Logging:LogLevel:Default")]).Returns("Debug"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:Tenant")]).Returns("contoso.onmicrosoft.com"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:Authority")]).Returns("https://login.microsoftonline.com/contoso.onmicrosoft.com"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:Scope")]).Returns("dev"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:ClientSecretLocation")]).Returns("secret"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "secret")]).Returns("value"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "Graph:ClientId")]).Returns("201"); + _graphGroupVerificationService = new GraphGroupVerificationService(_mockConfiguration.Object, _mockCacheFactory.Object, _mockLogger.Object); + } + + [TestMethod] + public async Task IsMember_WhenUserIsMemberOfGroup_ShouldReturnTrue() + { + // Arrange + var mockConfidentialClientApplicationBuilderWrapper = new Mock(); + mockConfidentialClientApplicationBuilderWrapper + .Setup(m => m.Build(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Mock.Of()); + var mockGraphServiceClientWrapper = new Mock(); + mockGraphServiceClientWrapper + .Setup(m => m.GetUser(It.IsAny())) + .ReturnsAsync(new User { Id = "testUserId", UserPrincipalName = "testUser@domain.com" }); + + var userUpn = "testuser@domain.com"; + var securityGroupIds = new List { "group1", "group2" }; + var trackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c=>c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain.com", "201","123" })); + // Act + var result = await _graphGroupVerificationService.IsMember(userUpn, securityGroupIds, trackingIds); + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public async Task IsMember_WhenUserIsMemberOfGroup_ShouldReturnFalse() + { + // Arrange + var mockConfidentialClientApplicationBuilderWrapper = new Mock(); + mockConfidentialClientApplicationBuilderWrapper + .Setup(m => m.Build(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Mock.Of()); + var mockGraphServiceClientWrapper = new Mock(); + mockGraphServiceClientWrapper + .Setup(m => m.GetUser(It.IsAny())) + .ReturnsAsync(new User { Id = "testUserId", UserPrincipalName = "testUser@domain.com" }); + + var userUpn = "testuser@domain.com"; + var securityGroupIds = new List { "group1", "group2" }; + var trackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + // Act + var result = await _graphGroupVerificationService.IsMember(userUpn, securityGroupIds, trackingIds); + + // Assert + Assert.IsFalse(result); + } + + [TestMethod] + public async Task IsUserAliasPartOfSecurityGroup_WhenUserIsMemberOfGroup_ShouldReturnTrue() + { + // Arrange + var mockConfidentialClientApplicationBuilderWrapper = new Mock(); + mockConfidentialClientApplicationBuilderWrapper + .Setup(m => m.Build(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Mock.Of()); + var mockGraphServiceClientWrapper = new Mock(); + mockGraphServiceClientWrapper + .Setup(m => m.GetUser(It.IsAny())) + .ReturnsAsync(new User { Id = "testUserId", UserPrincipalName = "testUser@domain.com" }); + + var userAlias = "testuser"; + var securityGroupIds = new List { "group1", "group2" }; + var trackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain.com", "201", "123" })); + // Act + var result = await _graphGroupVerificationService.IsUserAliasPartOfSecurityGroup(userAlias, securityGroupIds, trackingIds); + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public async Task IsUserAliasPartOfSecurityGroup_WhenUserIsMemberOfGroup_ShouldReturnFalse() + { + // Arrange + var mockConfidentialClientApplicationBuilderWrapper = new Mock(); + mockConfidentialClientApplicationBuilderWrapper + .Setup(m => m.Build(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Mock.Of()); + var mockGraphServiceClientWrapper = new Mock(); + mockGraphServiceClientWrapper + .Setup(m => m.GetUser(It.IsAny())) + .ReturnsAsync(new User { Id = "testUserId", UserPrincipalName = "testUser@domain.com" }); + + var userAlias = "testuser1"; + var securityGroupIds = new List { "group1", "group2" }; + var trackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + // Act + var result = await _graphGroupVerificationService.IsUserAliasPartOfSecurityGroup(userAlias, securityGroupIds, trackingIds); + + // Assert + Assert.IsFalse(result); + } + + [TestMethod] + public async Task GetCachedObject_Success() + { + // Arrange + var userAlias = "testuser1"; + var securityGroupIds = new List { "group1", "group2" }; + var trackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + BackgroundCacheParameters backgroundCacheParameters = new BackgroundCacheParameters { CacheKey = "test" }; + // Act + var result = await _graphGroupVerificationService.GetCachedObject(backgroundCacheParameters, trackingIds); + + // Assert + Assert.AreEqual(result.Count,3); + } + + [TestMethod] + public async Task SetCacheObject_Success() + { + // Arrange + var userAlias = "testuser1"; + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + BackgroundCacheableObject> backgroundCacheableObject = new BackgroundCacheableObject>() { + CacheParameters = new BackgroundCacheParameters { CacheKey = "test" ,CacheDuration=100,Tenant="t1000",ObjectId="o9000"}, + }; + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + // Act + var result = _graphGroupVerificationService.SetCacheObject(backgroundCacheableObject, loggerTrackingIds).IsCompleted; + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public async Task CreateCacheableObject_Success() + { + // Arrange + var _mockGraphServiceClient =new Mock(); + var _mockGroupTransitiveMembersCollectionWithReferencesPage=new Mock(); + var _mockGroupTransitiveMembersCollectionWithReferencesRequest = new Mock(); + var userAlias = "testuser1"; + + + _mockGraphServiceClient.Setup(c => c.Groups["group1"].TransitiveMembers.Request().GetAsync()).Returns(Task.FromResult(_mockGroupTransitiveMembersCollectionWithReferencesPage.Object)); + + _mockGroupTransitiveMembersCollectionWithReferencesPage.Setup(c => c.NextPageRequest).Returns(_mockGroupTransitiveMembersCollectionWithReferencesRequest.Object); + _mockGroupTransitiveMembersCollectionWithReferencesPage.Setup(c => c.NextPageRequest.GetAsync()).Returns(Task.FromResult(_mockGroupTransitiveMembersCollectionWithReferencesPage.Object)); + + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + + + BackgroundCacheParameters backgroundCacheParameters = new BackgroundCacheParameters { CacheKey = "test" }; + + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + // Act + var result = _graphGroupVerificationService.CreateCacheableObject(backgroundCacheParameters, loggerTrackingIds); + + // Assert + Assert.IsNotNull(result); + } + + [TestMethod] + public async Task RebuildCache_Success() + { + // Arrange + var _mockGraphServiceClient = new Mock(); + var _mockGroupTransitiveMembersCollectionWithReferencesPage = new Mock(); + var _mockGroupTransitiveMembersCollectionWithReferencesRequest = new Mock(); + var userAlias = "testuser1"; + + + _mockGraphServiceClient.Setup(c => c.Groups["group1"].TransitiveMembers.Request().GetAsync()).Returns(Task.FromResult(_mockGroupTransitiveMembersCollectionWithReferencesPage.Object)); + + _mockGroupTransitiveMembersCollectionWithReferencesPage.Setup(c => c.NextPageRequest).Returns(_mockGroupTransitiveMembersCollectionWithReferencesRequest.Object); + _mockGroupTransitiveMembersCollectionWithReferencesPage.Setup(c => c.NextPageRequest.GetAsync()).Returns(Task.FromResult(_mockGroupTransitiveMembersCollectionWithReferencesPage.Object)); + + _mockCacheFactory.Setup(c => c.Create(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(_mockCache.Object); + _mockCache.Setup(c => c.GetList(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.FromResult>(new List { "testUser@domain1.com", "201", "123" })); + + + BackgroundCacheParameters backgroundCacheParameters = new BackgroundCacheParameters { CacheKey = "test" }; + + LoggerTrackingIds loggerTrackingIds = new LoggerTrackingIds { CorrelationId = "TestCorrelationId", TransactionId = "TestTransactionId" }; + // Act + var result= _graphGroupVerificationService.RebuildCache(backgroundCacheParameters, loggerTrackingIds); + + // Assert + Assert.IsTrue(true); + } + } +} diff --git a/src/service/Tests/Services.Tests/GraphTest/GraphServiceClientWrapper.cs b/src/service/Tests/Services.Tests/GraphTest/GraphServiceClientWrapper.cs new file mode 100644 index 0000000..9810658 --- /dev/null +++ b/src/service/Tests/Services.Tests/GraphTest/GraphServiceClientWrapper.cs @@ -0,0 +1,32 @@ +using Microsoft.Graph; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.GraphTest +{ + public interface IGraphServiceClientWrapper + { + Task GetUser(string userId); + // Add other methods as needed + } + + public class GraphServiceClientWrapper + { + private readonly IGraphServiceClient _graphServiceClient; + + public GraphServiceClientWrapper(IGraphServiceClient graphServiceClient) + { + _graphServiceClient = graphServiceClient; + } + + public Task GetUser(string userId) + { + return _graphServiceClient.Users[userId].Request().GetAsync(); + } + // Implement other methods as needed + } +} + diff --git a/src/service/Tests/Services.Tests/StorageTest/BlobProviderFactoryTest.cs b/src/service/Tests/Services.Tests/StorageTest/BlobProviderFactoryTest.cs new file mode 100644 index 0000000..f756592 --- /dev/null +++ b/src/service/Tests/Services.Tests/StorageTest/BlobProviderFactoryTest.cs @@ -0,0 +1,111 @@ +using AppInsights.EnterpriseTelemetry; +using Azure.Storage.Blobs; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Common.Storage; +using Microsoft.FeatureFlighting.Infrastructure.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Collections.Concurrent; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; + + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.StorageTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("BlobProviderFactory")] + [TestClass] + public class BlobProviderFactoryTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockLogger; + private Mock _mockBlobProvider; + private BlobProviderFactory _factory; + + Mock> _mockBlobProviderCache; + + public BlobProviderFactoryTest() + { + _mockTenantConfigurationProvider = new Mock(); + _mockLogger = new Mock(); + _mockBlobProvider = new Mock(); + _mockBlobProviderCache = new Mock>(); + + _factory = new BlobProviderFactory(_mockTenantConfigurationProvider.Object, _mockLogger.Object); + } + + [TestMethod] + public async Task CreateBreWorkflowProvider_nodata_when_tenantConfiguration_BusinessRuleEngine_is_null() + { + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult( + new TenantConfiguration + { + BusinessRuleEngine = null + })); + + var result = await _factory.CreateBreWorkflowProvider("test"); + Assert.IsNull(null); + } + + [TestMethod] + public async Task CreateBreWorkflowProvider_nodata_when_tenantConfiguration_BusinessRuleEngine_storage_is_null() + { + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult( + new TenantConfiguration + { + BusinessRuleEngine = new BusinessRuleEngineConfiguration + { + Storage = null + } + })); + + var result = await _factory.CreateBreWorkflowProvider("test"); + Assert.IsNull(null); + } + + //[TestMethod] + //public async Task CreateBreWorkflowProvider_Success() + //{ + // _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(GetTenantConfiguration())); + // var _mockBlobServiceClient = new Mock(); + // _mockBlobProviderCache.Setup(b => b.Add(It.IsAny(), It.IsAny())); + // _mockBlobServiceClient.Setup(b => b.GetBlobContainerClient(It.IsAny())).Returns(new BlobContainerClient("test connection", "container name")); + // var result = await _factory.CreateBreWorkflowProvider("test"); + // Assert.IsNotNull(result); + //} + + //public Dictionary getIblobProviderData() + //{ + // Dictionary blobProviderCache = new Dictionary(); + + // blobProviderCache.Add("test", _mockBlobProvider.Object); + // blobProviderCache.Add("testTenant2", _mockBlobProvider.Object); + + // return blobProviderCache; + //} + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration() + { + BusinessRuleEngine = new BusinessRuleEngineConfiguration + { + Storage = new StorageConfiguration + { + StorageConnectionString = "test connection string", + ContainerName = "test container name" + } + }, + Name = "Test", + Contact = "32323232323", + IsDyanmic = true, + ShortName = "Test" + }; + } + } +} + diff --git a/src/service/Tests/Services.Tests/StorageTest/BlobProviderTest.cs b/src/service/Tests/Services.Tests/StorageTest/BlobProviderTest.cs new file mode 100644 index 0000000..d7225a8 --- /dev/null +++ b/src/service/Tests/Services.Tests/StorageTest/BlobProviderTest.cs @@ -0,0 +1,83 @@ +using Azure.Storage.Blobs.Models; +using Azure.Storage.Blobs; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Infrastructure.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AppInsights.EnterpriseTelemetry; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Azure; +using Azure; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.StorageTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("BlobProvider")] + [TestClass] + public class BlobProviderTest + { + private readonly Mock _mockBlobContainerClient; + private readonly Mock _mockLogger; + private readonly BlobProvider _blobProvider; + + public BlobProviderTest() + { + _mockBlobContainerClient = new Mock(); + _mockLogger = new Mock(); + _blobProvider = new BlobProvider(_mockBlobContainerClient.Object, _mockLogger.Object); + } + + [TestMethod] + public async Task Get_ShouldReturnContent_WhenBlobExists() + { + // Arrange + string blobName = "testBlob"; + string expectedContent = "testContent"; + var mockBlobClient = new Mock(); + var mockResponse = new Mock>(); + var mresponseResult = true; + var mockBlobDownloadResult = BlobsModelFactory.BlobDownloadResult(content: new BinaryData("mock content"), + details: new BlobDownloadDetails()); + mockResponse.Setup(m => m.Value).Returns(mresponseResult); + + mockBlobClient.Setup(m => m.ExistsAsync(default)).Returns(Task.FromResult>(mockResponse.Object)); + mockBlobClient.Setup(m => m.DownloadContentAsync()).ReturnsAsync(Response.FromValue(mockBlobDownloadResult, Mock.Of())); + _mockBlobContainerClient.Setup(m => m.GetBlobClient(blobName)).Returns(mockBlobClient.Object); + + // Act + string? content = await _blobProvider.Get(blobName, new LoggerTrackingIds()); + + // Assert + Assert.IsNotNull(content); + } + + [TestMethod] + public async Task Get_ShouldReturnNull_WhenBlobDoesNotExist() + { + // Arrange + string blobName = "testBlob"; + string expectedContent = "testContent"; + var mockBlobClient = new Mock(); + var mockResponse = new Mock>(); + var mresponseResult = false; + var mockBlobDownloadResult = BlobsModelFactory.BlobDownloadResult(content: new BinaryData("mock content"), + details: new BlobDownloadDetails()); + mockResponse.Setup(m => m.Value).Returns(mresponseResult); + + mockBlobClient.Setup(m => m.ExistsAsync(default)).Returns(Task.FromResult>(mockResponse.Object)); + //mockBlobClient.Setup(m => m.DownloadContentAsync()).ReturnsAsync(Response.FromValue(mockBlobDownloadResult, Mock.Of())); + _mockBlobContainerClient.Setup(m => m.GetBlobClient(blobName)).Returns(mockBlobClient.Object); + + // Act + string? content = await _blobProvider.Get(blobName, new LoggerTrackingIds()); + + // Assert + Assert.IsNull(content); + } + } +} diff --git a/src/service/Tests/Services.Tests/StorageTest/CosmosDbRepositoryTest.cs b/src/service/Tests/Services.Tests/StorageTest/CosmosDbRepositoryTest.cs new file mode 100644 index 0000000..175b9ad --- /dev/null +++ b/src/service/Tests/Services.Tests/StorageTest/CosmosDbRepositoryTest.cs @@ -0,0 +1,210 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.StorageTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("CosmosDbRepository")] + [TestClass] + public class CosmosDbRepositoryTest + { + private readonly Mock _mockContainer; + private readonly Mock _mockLogger; + private readonly Mock _mockConfiguration; + private readonly CosmosDbRepository _cosmosDbRepository; + + public CosmosDbRepositoryTest() + { + _mockContainer = new Mock(); + _mockLogger = new Mock(); + _mockConfiguration = new Mock(); + var cosnmosDbConfiguration = new CosmosDbConfiguration(); + cosnmosDbConfiguration.Endpoint = "https://login.microsoftonline.com/contoso.onmicrosoft.com"; + cosnmosDbConfiguration.PrimaryKey = "dG9rZW4gaXMgcmVhZGFibGU="; + cosnmosDbConfiguration.DatabaseId = "testDatabase"; + cosnmosDbConfiguration.ContainerId = "testContainer"; + + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "CosmosDb:MaxRequestsPerTcpConnection")]).Returns("10"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "CosmosDb:MaxRetryWaitTimeOnRateLimitedRequests")]).Returns("5"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "CosmosDb:MaxRetryAttemptsOnRateLimitedRequests")]).Returns("5"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "ComsosDb:Endpoint")]).Returns("test endpoint"); + _mockConfiguration.SetupGet(x => x[It.Is(s => s == "CosmosDb:MaxItemsPerQuery")]).Returns("10"); + + _cosmosDbRepository = new CosmosDbRepository(cosnmosDbConfiguration, _mockConfiguration.Object, _mockLogger.Object); + } + + [TestMethod] + public async Task Get_ThrowException() + { + // Arrange + string documentId = "testDocument"; + string partitionKey = "testPartition"; + var mockItemResponse = new Mock>(); + var expectedDocument = new TestClass(); + mockItemResponse.Setup(m => m.Resource).Returns(expectedDocument); + var _mockContainer = new Mock(); + + // Arrange + + var myItems = new List + { + new TestClass(), + new TestClass() + }; + var mockFeedIterator = new Mock>(); + var mockContainer = new Mock(); + var feedResponseMock = new Mock>(); + feedResponseMock.Setup(x => x.GetEnumerator()).Returns(myItems.GetEnumerator()); + + mockFeedIterator.Setup(m => m.HasMoreResults).Returns(true); + mockFeedIterator.Setup(m => m.ReadNextAsync(default)).ReturnsAsync(feedResponseMock.Object); + + mockContainer.Setup(m => m.GetItemQueryIterator(It.IsAny(), null, It.IsAny())).Returns(mockFeedIterator.Object); + + _mockContainer.Setup(m => m.ReadItemAsync(documentId, new PartitionKey(partitionKey), null, default)).ReturnsAsync(mockItemResponse.Object); + + try + { + // Act + var document = await _cosmosDbRepository.Get(documentId, partitionKey, new LoggerTrackingIds()); + } + catch (Exception ex) + { + Assert.IsNotNull(ex.Message); + } + } + + [TestMethod] + public async Task QueryAll_ThrowException() + { + // Arrange + string documentId = "testDocument"; + string partitionKey = "testPartition"; + var mockItemResponse = new Mock>(); + var expectedDocument = new TestClass(); + mockItemResponse.Setup(m => m.Resource).Returns(expectedDocument); + var _mockContainer = new Mock(); + + // Arrange + + var myItems = new List + { + new TestClass(), + new TestClass() + }; + var mockFeedIterator = new Mock>(); + var mockContainer = new Mock(); + var feedResponseMock = new Mock>(); + feedResponseMock.Setup(x => x.GetEnumerator()).Returns(myItems.GetEnumerator()); + + mockFeedIterator.Setup(m => m.HasMoreResults).Returns(true); + mockFeedIterator.Setup(m => m.ReadNextAsync(default)).ReturnsAsync(feedResponseMock.Object); + + mockContainer.Setup(m => m.GetItemQueryIterator(It.IsAny(), null, It.IsAny())).Returns(mockFeedIterator.Object); + + _mockContainer.Setup(m => m.ReadItemAsync(documentId, new PartitionKey(partitionKey), null, default)).ReturnsAsync(mockItemResponse.Object); + + try { + var document = await _cosmosDbRepository.QueryAll("SELECT * FROM C", partitionKey, new LoggerTrackingIds()); + } + catch (Exception ex) + { + Assert.IsNotNull(ex); + } + + } + + [TestMethod] + public async Task Save_ThrowException() + { + // Arrange + string documentId = "testDocument"; + string partitionKey = "testPartition"; + var mockItemResponse = new Mock>(); + var expectedDocument = new TestClass(); + mockItemResponse.Setup(m => m.Resource).Returns(expectedDocument); + var _mockContainer = new Mock(); + + // Arrange + + var myItems = new List + { + new TestClass(), + new TestClass() + }; + var mockContainer = new Mock(); + var itemResponseMock = new Mock>(); + + mockContainer.Setup(m => m.UpsertItemAsync(It.IsAny(),null,null,default)).Returns(Task.FromResult>(itemResponseMock.Object)); + + + try + { + var document = await _cosmosDbRepository.Save(new TestClass(), partitionKey, new LoggerTrackingIds()); + } + catch (Exception ex) + { + Assert.IsNotNull(ex); + } + } + + [TestMethod] + public async Task Delete_ThrowException() + { + // Arrange + string documentId = "testDocument"; + string partitionKey = "testPartition"; + var mockItemResponse = new Mock>(); + var expectedDocument = new TestClass(); + mockItemResponse.Setup(m => m.Resource).Returns(expectedDocument); + var _mockContainer = new Mock(); + + // Arrange + + var myItems = new List + { + new TestClass(), + new TestClass() + }; + var mockContainer = new Mock(); + var itemResponseMock = new Mock>(); + + mockContainer.Setup(m => m.DeleteItemAsync(It.IsAny(), It.IsAny(), null, default)).Returns(Task.FromResult>(itemResponseMock.Object)); + + + try + { + await _cosmosDbRepository.Delete("1", partitionKey, new LoggerTrackingIds(),default); + } + catch (Exception ex) + { + Assert.IsNotNull(ex); + } + } + } + + public class TestClass + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + + public TestClass() + { + Id = 1; + Name = "Test"; + Description = "Test Description"; + } + // Your class definition here + } +} diff --git a/src/service/Tests/Services.Tests/StorageTest/FlightsDbRepositoryFactoryTest.cs b/src/service/Tests/Services.Tests/StorageTest/FlightsDbRepositoryFactoryTest.cs new file mode 100644 index 0000000..3ecf9f9 --- /dev/null +++ b/src/service/Tests/Services.Tests/StorageTest/FlightsDbRepositoryFactoryTest.cs @@ -0,0 +1,65 @@ +using AppInsights.EnterpriseTelemetry; +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureFlighting.Common.Cache; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Infrastructure.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.StorageTest +{ + [ExcludeFromCodeCoverage] + [TestClass] + public class FlightsDbRepositoryFactoryTest + { + private Mock _mockTenantConfigurationProvider; + private Mock _mockConfiguration; + private Mock _mockLogger; + + private FlightsDbRepositoryFactory _factory; + + // private IConfiguration _mockConfiguration; + public FlightsDbRepositoryFactoryTest() + { + _mockTenantConfigurationProvider = new Mock(); + _mockConfiguration = new Mock(); + _mockLogger = new Mock(); + + _factory = new FlightsDbRepositoryFactory(_mockTenantConfigurationProvider.Object, _mockConfiguration.Object, _mockLogger.Object); + } + + + + [TestMethod] + public async Task GetFlightsRepository_when_FlightsDatabase_is_null() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = await _factory.GetFlightsRepository("Test"); + Assert.IsNull(result); + } + + [TestMethod] + public async Task GetFlightsRepository_when_Disabled_property_of_flightsDatabase_is_true() + { + TenantConfiguration tenantConfiguration = GetTenantConfiguration(); + tenantConfiguration.FlightsDatabase = new CosmosDbConfiguration { Disabled = true }; + _mockTenantConfigurationProvider.Setup(t => t.Get(It.IsAny())).Returns(Task.FromResult(tenantConfiguration)); + var result = await _factory.GetFlightsRepository("Test"); + Assert.IsNull(result); + } + + private TenantConfiguration GetTenantConfiguration() + { + return new TenantConfiguration + { + Contact = "test contact", + IsDyanmic = true, + FlightsDatabase = null + }; + } + } +} diff --git a/src/service/Tests/Services.Tests/WebhookTest/WebhookTriggerManagerTest.cs b/src/service/Tests/Services.Tests/WebhookTest/WebhookTriggerManagerTest.cs new file mode 100644 index 0000000..ef33466 --- /dev/null +++ b/src/service/Tests/Services.Tests/WebhookTest/WebhookTriggerManagerTest.cs @@ -0,0 +1,64 @@ +using Microsoft.FeatureFlighting.Common.Authentication; +using Microsoft.FeatureFlighting.Common.Config; +using Microsoft.FeatureFlighting.Common.Model.ChangeNotification; +using Microsoft.FeatureFlighting.Common; +using Microsoft.FeatureFlighting.Infrastructure.Webhook; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System.Diagnostics.CodeAnalysis; +using System.Net.Http; +using System.Threading.Tasks; +using AppInsights.EnterpriseTelemetry; +using System; + +namespace Microsoft.FeatureFlighting.Infrastructure.Tests.WebhookTest +{ + [ExcludeFromCodeCoverage] + [TestCategory("WebhookTriggerManager")] + [TestClass] + public class WebhookTriggerManagerTest + { + private readonly Mock _httpClientFactoryMock; + private readonly Mock _tokenGeneratorMock; + private readonly Mock _loggerMock; + private readonly WebhookTriggerManager _webhookTriggerManager; + + public WebhookTriggerManagerTest() + { + _httpClientFactoryMock = new Mock(); + _tokenGeneratorMock = new Mock(); + _loggerMock = new Mock(); + _webhookTriggerManager = new WebhookTriggerManager(_httpClientFactoryMock.Object, _tokenGeneratorMock.Object, _loggerMock.Object); + } + + [TestMethod] + public async Task Trigger_ThrowException() + { + // Arrange + var webhook = new WebhookConfiguration(); + webhook.HttpMethod = "GET"; + webhook.BaseEndpoint = "https://www.google.com"; + webhook.WebhookId = "test"; + webhook.AuthenticationAuthority = "https://login.microsoftonline.com/contoso.onmicrosoft.com"; + webhook.ClientId = "testClientId"; + webhook.ClientSecret = "nb3v4mn23v4234mn234nm2b34mn32b4b,m2n3mnb4mn234"; + webhook.ResourceId = "testResourceId"; + var featureFlightChangeEvent = new FeatureFlightChangeEvent(); + var trackingIds = new LoggerTrackingIds(); + var httpClient = new HttpClient(); + _httpClientFactoryMock.Setup(hcf => hcf.CreateClient(It.IsAny())).Returns(httpClient); + _tokenGeneratorMock.Setup(tg => tg.GenerateToken(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync("token"); + + try + { + // Act + var result = await _webhookTriggerManager.Trigger(webhook, featureFlightChangeEvent, trackingIds); + } + catch (Exception ex) + { + Assert.IsNotNull(ex.Message); + } + + } + } +}