From 1becdd698d3705d02a8943e0dd682837a129b344 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Mon, 25 Sep 2023 17:05:22 -0700 Subject: [PATCH 1/6] Updating dependencies --- ...Microsoft.FeatureManagement.AspNetCore.csproj | 10 +--------- .../Tests.FeatureManagement.csproj | 16 ++++------------ 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj index 612eecfc..6236b82a 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj +++ b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj @@ -11,7 +11,7 @@ - netstandard2.0;netcoreapp3.1;net5.0;net6.0 + netcoreapp3.1;net5.0;net6.0 true false ..\..\build\Microsoft.FeatureManagement.snk @@ -31,14 +31,6 @@ - - - - - - - - diff --git a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj index 7501c259..0e869107 100644 --- a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj +++ b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1;netcoreapp3.1;net5.0;net6.0 + netcoreapp3.1;net5.0;net6.0 false 8.0 True @@ -13,28 +13,20 @@ - - - - - - - - - + - + - + From b18d7bb306839ef3a91758c8c42d42cb1c31cad5 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Thu, 28 Sep 2023 16:31:59 -0700 Subject: [PATCH 2/6] Updates packages and resolves issues --- Microsoft.FeatureManagement.sln | 9 +- examples/ConsoleApp/ConsoleApp.csproj | 2 +- .../FeatureFlagDemo/FeatureFlagDemo.csproj | 2 +- examples/RazorPages/RazorPages.csproj | 2 +- .../TargetingConsoleApp.csproj | 2 +- ...tCoreFeatureManagementBuilderExtensions.cs | 1 - ...rosoft.FeatureManagement.AspNetCore.csproj | 4 +- .../Microsoft.FeatureManagement.csproj | 2 +- .../FeatureManagementAspNetCore.cs | 187 ++++++++++++++++ .../Features.cs | 11 + .../MvcFilter.cs | 2 +- .../Pages/RazorTestAll.cshtml | 0 .../Pages/RazorTestAll.cshtml.cs | 2 +- .../Pages/RazorTestAny.cshtml | 0 .../Pages/RazorTestAny.cshtml.cs | 2 +- .../Pages/_ViewImports.cshtml | 3 + .../TestController.cs | 2 +- .../TestFilter.cs | 32 +++ .../Tests.FeatureManagement.AspNetCore.csproj | 43 ++++ .../appsettings.json | 28 +++ .../FeatureManagement.cs | 210 ++---------------- tests/Tests.FeatureManagement/Features.cs | 1 + .../Pages/_ViewImports.cshtml | 3 - .../Tests.FeatureManagement.csproj | 25 ++- 24 files changed, 355 insertions(+), 220 deletions(-) create mode 100644 tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs create mode 100644 tests/Tests.FeatureManagement.AspNetCore/Features.cs rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/MvcFilter.cs (91%) rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/Pages/RazorTestAll.cshtml (100%) rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/Pages/RazorTestAll.cshtml.cs (89%) rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/Pages/RazorTestAny.cshtml (100%) rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/Pages/RazorTestAny.cshtml.cs (90%) create mode 100644 tests/Tests.FeatureManagement.AspNetCore/Pages/_ViewImports.cshtml rename tests/{Tests.FeatureManagement => Tests.FeatureManagement.AspNetCore}/TestController.cs (94%) create mode 100644 tests/Tests.FeatureManagement.AspNetCore/TestFilter.cs create mode 100644 tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj create mode 100644 tests/Tests.FeatureManagement.AspNetCore/appsettings.json delete mode 100644 tests/Tests.FeatureManagement/Pages/_ViewImports.cshtml diff --git a/Microsoft.FeatureManagement.sln b/Microsoft.FeatureManagement.sln index d4c7ce05..90205454 100644 --- a/Microsoft.FeatureManagement.sln +++ b/Microsoft.FeatureManagement.sln @@ -19,7 +19,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "examples\Cons EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TargetingConsoleApp", "examples\TargetingConsoleApp\TargetingConsoleApp.csproj", "{6558C21E-CF20-4278-AA08-EB9D1DF29D66}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorPages", "examples\RazorPages\RazorPages.csproj", "{BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPages", "examples\RazorPages\RazorPages.csproj", "{BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.FeatureManagement.AspNetCore", "tests\Tests.FeatureManagement.AspNetCore\Tests.FeatureManagement.AspNetCore.csproj", "{FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -55,6 +57,10 @@ Global {BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2}.Release|Any CPU.Build.0 = Release|Any CPU + {FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -65,6 +71,7 @@ Global {E50FB931-7A42-440E-AC47-B8DFE5E15394} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72} {6558C21E-CF20-4278-AA08-EB9D1DF29D66} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72} {BA29A1BB-81D5-4EB1-AF37-6ECF64AF27E2} = {FB5C34DF-695C-4DF9-8AED-B3EA2516EA72} + {FC0DC3E2-5646-4AEC-A7DB-2D6167BC3BB4} = {8ED6FFEE-4037-49A2-9709-BC519C104A90} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {84DA6C54-F140-4518-A1B4-E4CF42117FBD} diff --git a/examples/ConsoleApp/ConsoleApp.csproj b/examples/ConsoleApp/ConsoleApp.csproj index 1230fedf..92f5cd47 100644 --- a/examples/ConsoleApp/ConsoleApp.csproj +++ b/examples/ConsoleApp/ConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net6.0; Consoto.Banking.AccountService diff --git a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj index 7ab458e3..05d793dd 100644 --- a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj +++ b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0; diff --git a/examples/RazorPages/RazorPages.csproj b/examples/RazorPages/RazorPages.csproj index 2e72ac40..e67500f5 100644 --- a/examples/RazorPages/RazorPages.csproj +++ b/examples/RazorPages/RazorPages.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net6.0; diff --git a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj index 1230fedf..92f5cd47 100644 --- a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj +++ b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net6.0; Consoto.Banking.AccountService diff --git a/src/Microsoft.FeatureManagement.AspNetCore/AspNetCoreFeatureManagementBuilderExtensions.cs b/src/Microsoft.FeatureManagement.AspNetCore/AspNetCoreFeatureManagementBuilderExtensions.cs index 1ffea01a..742b942e 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/AspNetCoreFeatureManagementBuilderExtensions.cs +++ b/src/Microsoft.FeatureManagement.AspNetCore/AspNetCoreFeatureManagementBuilderExtensions.cs @@ -3,7 +3,6 @@ // using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; -using Microsoft.FeatureManagement.FeatureFilters; using Microsoft.FeatureManagement.Mvc; using System; using System.Collections.Generic; diff --git a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj index 6236b82a..32cf3865 100644 --- a/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj +++ b/src/Microsoft.FeatureManagement.AspNetCore/Microsoft.FeatureManagement.AspNetCore.csproj @@ -11,7 +11,7 @@ - netcoreapp3.1;net5.0;net6.0 + net6.0;net7.0 true false ..\..\build\Microsoft.FeatureManagement.snk @@ -28,7 +28,7 @@ https://aka.ms/AzureAppConfigurationPackageIcon © Microsoft Corporation. All rights reserved. - + diff --git a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj index beb3ceb4..7dab29ea 100644 --- a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj +++ b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj @@ -11,7 +11,7 @@ - netstandard2.0;netcoreapp3.1;net5.0;net6.0 + netstandard2.0;netstandard2.1; true false ..\..\build\Microsoft.FeatureManagement.snk diff --git a/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs b/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs new file mode 100644 index 00000000..62919797 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/FeatureManagementAspNetCore.cs @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.FeatureManagement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace Tests.FeatureManagement.AspNetCore +{ + public class FeatureManagementAspNetCore + { + [Fact] + public async Task Integrates() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => + { + services + .AddSingleton(config) + .AddFeatureManagement() + .AddFeatureFilter(); + + services.AddMvcCore(o => + { + DisableEndpointRouting(o); + o.Filters.AddForFeature(Enum.GetName(typeof(Features), Features.ConditionalFeature)); + }); + }) + .Configure(app => + { + app.UseForFeature(Enum.GetName(typeof(Features), Features.ConditionalFeature), a => a.Use(async (ctx, next) => + { + ctx.Response.Headers[nameof(RouterMiddleware)] = bool.TrueString; + + await next(); + })); + + app.UseMvc(); + })); + + IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); + + TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); + + testFeatureFilter.Callback = _ => Task.FromResult(true); + + HttpResponseMessage res = await testServer.CreateClient().GetAsync(""); + + Assert.True(res.Headers.Contains(nameof(MvcFilter))); + Assert.True(res.Headers.Contains(nameof(RouterMiddleware))); + + testFeatureFilter.Callback = _ => Task.FromResult(false); + + res = await testServer.CreateClient().GetAsync(""); + + Assert.False(res.Headers.Contains(nameof(MvcFilter))); + Assert.False(res.Headers.Contains(nameof(RouterMiddleware))); + } + + [Fact] + public async Task GatesFeatures() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => + { + services + .AddSingleton(config) + .AddFeatureManagement() + .AddFeatureFilter(); + + services.AddMvcCore(o => DisableEndpointRouting(o)); + }) + .Configure(app => app.UseMvc())); + + IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); + + TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); + + // + // Enable all features + testFeatureFilter.Callback = ctx => Task.FromResult(true); + + HttpResponseMessage gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); + HttpResponseMessage gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); + + Assert.Equal(HttpStatusCode.OK, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); + + // + // Enable 1/2 features + testFeatureFilter.Callback = ctx => Task.FromResult(ctx.FeatureName == Enum.GetName(typeof(Features), Features.ConditionalFeature)); + + gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); + gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); + + Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); + + // + // Enable no + testFeatureFilter.Callback = ctx => Task.FromResult(false); + + gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); + gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); + + Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.NotFound, gateAnyResponse.StatusCode); + } + + [Fact] + public async Task GatesRazorPageFeatures() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => + { + services + .AddSingleton(config) + .AddFeatureManagement() + .AddFeatureFilter(); + + services.AddRazorPages(); + + services.AddMvc(o => DisableEndpointRouting(o)); + }) + .Configure(app => + { + app.UseMvc(); + })); + + IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); + + TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); + + // + // Enable all features + testFeatureFilter.Callback = ctx => Task.FromResult(true); + + HttpResponseMessage gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); + HttpResponseMessage gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); + + Assert.Equal(HttpStatusCode.OK, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); + + // + // Enable 1/2 features + testFeatureFilter.Callback = ctx => Task.FromResult(ctx.FeatureName == Enum.GetName(typeof(Features), Features.ConditionalFeature)); + + gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); + gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); + + Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); + + // + // Enable no + testFeatureFilter.Callback = ctx => Task.FromResult(false); + + gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); + gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); + + Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); + Assert.Equal(HttpStatusCode.NotFound, gateAnyResponse.StatusCode); + } + + private static void DisableEndpointRouting(MvcOptions options) + { + // + // Endpoint routing is disabled by default in .NET Core 2.1 since it didn't exist. + options.EnableEndpointRouting = false; + } + } +} diff --git a/tests/Tests.FeatureManagement.AspNetCore/Features.cs b/tests/Tests.FeatureManagement.AspNetCore/Features.cs new file mode 100644 index 00000000..5d26be98 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/Features.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +namespace Tests.FeatureManagement.AspNetCore +{ + enum Features + { + ConditionalFeature, + ConditionalFeature2 + } +} diff --git a/tests/Tests.FeatureManagement/MvcFilter.cs b/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs similarity index 91% rename from tests/Tests.FeatureManagement/MvcFilter.cs rename to tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs index 40c63131..0635a289 100644 --- a/tests/Tests.FeatureManagement/MvcFilter.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/MvcFilter.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Filters; -namespace Tests.FeatureManagement +namespace Tests.FeatureManagement.AspNetCore { public class MvcFilter : IAsyncActionFilter { diff --git a/tests/Tests.FeatureManagement/Pages/RazorTestAll.cshtml b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAll.cshtml similarity index 100% rename from tests/Tests.FeatureManagement/Pages/RazorTestAll.cshtml rename to tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAll.cshtml diff --git a/tests/Tests.FeatureManagement/Pages/RazorTestAll.cshtml.cs b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAll.cshtml.cs similarity index 89% rename from tests/Tests.FeatureManagement/Pages/RazorTestAll.cshtml.cs rename to tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAll.cshtml.cs index 698ee597..5867aa30 100644 --- a/tests/Tests.FeatureManagement/Pages/RazorTestAll.cshtml.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAll.cshtml.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.FeatureManagement.Mvc; -namespace Tests.FeatureManagement.Pages +namespace Tests.FeatureManagement.AspNetCore.Pages { [FeatureGate(Features.ConditionalFeature, Features.ConditionalFeature2)] public class RazorTestAllModel : PageModel diff --git a/tests/Tests.FeatureManagement/Pages/RazorTestAny.cshtml b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAny.cshtml similarity index 100% rename from tests/Tests.FeatureManagement/Pages/RazorTestAny.cshtml rename to tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAny.cshtml diff --git a/tests/Tests.FeatureManagement/Pages/RazorTestAny.cshtml.cs b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAny.cshtml.cs similarity index 90% rename from tests/Tests.FeatureManagement/Pages/RazorTestAny.cshtml.cs rename to tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAny.cshtml.cs index 90fa47cf..54a96fae 100644 --- a/tests/Tests.FeatureManagement/Pages/RazorTestAny.cshtml.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/Pages/RazorTestAny.cshtml.cs @@ -6,7 +6,7 @@ using Microsoft.FeatureManagement; using Microsoft.FeatureManagement.Mvc; -namespace Tests.FeatureManagement.Pages +namespace Tests.FeatureManagement.AspNetCore.Pages { [FeatureGate(RequirementType.Any, Features.ConditionalFeature, Features.ConditionalFeature2)] public class RazorTestAnyModel : PageModel diff --git a/tests/Tests.FeatureManagement.AspNetCore/Pages/_ViewImports.cshtml b/tests/Tests.FeatureManagement.AspNetCore/Pages/_ViewImports.cshtml new file mode 100644 index 00000000..e7acf585 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using Tests.FeatureManagement.AspNetCore +@namespace Tests.FeatureManagement.AspNetCore.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/tests/Tests.FeatureManagement/TestController.cs b/tests/Tests.FeatureManagement.AspNetCore/TestController.cs similarity index 94% rename from tests/Tests.FeatureManagement/TestController.cs rename to tests/Tests.FeatureManagement.AspNetCore/TestController.cs index 5def4cf6..2f4c8ce5 100644 --- a/tests/Tests.FeatureManagement/TestController.cs +++ b/tests/Tests.FeatureManagement.AspNetCore/TestController.cs @@ -5,7 +5,7 @@ using Microsoft.FeatureManagement; using Microsoft.FeatureManagement.Mvc; -namespace Tests.FeatureManagement +namespace Tests.FeatureManagement.AspNetCore { [Route("")] public class TestController : Controller diff --git a/tests/Tests.FeatureManagement.AspNetCore/TestFilter.cs b/tests/Tests.FeatureManagement.AspNetCore/TestFilter.cs new file mode 100644 index 00000000..fbd49122 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/TestFilter.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.Extensions.Configuration; +using Microsoft.FeatureManagement; +using System; +using System.Threading.Tasks; + +namespace Tests.FeatureManagement.AspNetCore +{ + class TestFilter : IFeatureFilter, IFilterParametersBinder + { + public Func ParametersBinderCallback { get; set; } + + public Func> Callback { get; set; } + + public object BindParameters(IConfiguration parameters) + { + if (ParametersBinderCallback != null) + { + return ParametersBinderCallback(parameters); + } + + return parameters; + } + + public Task EvaluateAsync(FeatureFilterEvaluationContext context) + { + return Callback?.Invoke(context) ?? Task.FromResult(false); + } + } +} diff --git a/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj new file mode 100644 index 00000000..4ae0e4f8 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj @@ -0,0 +1,43 @@ + + + + net6.0;net7.0; + false + 8.0 + True + ..\..\build\Microsoft.FeatureManagement.snk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/tests/Tests.FeatureManagement.AspNetCore/appsettings.json b/tests/Tests.FeatureManagement.AspNetCore/appsettings.json new file mode 100644 index 00000000..ab9e0eb7 --- /dev/null +++ b/tests/Tests.FeatureManagement.AspNetCore/appsettings.json @@ -0,0 +1,28 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*", + + "FeatureManagement": { + "ConditionalFeature": { + "EnabledFor": [ + { + "Name": "Test", + "Parameters": { + "P1": "V1" + } + } + ] + }, + "ConditionalFeature2": { + "EnabledFor": [ + { + "Name": "Test" + } + ] + } + } +} diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index 9ecd3e7f..88d15306 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -1,11 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.FeatureManagement; @@ -13,8 +8,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Net.Http; using System.Threading.Tasks; using Xunit; @@ -22,11 +15,6 @@ namespace Tests.FeatureManagement { public class FeatureManagement { - private const string OnFeature = "OnTestFeature"; - private const string OffFeature = "OffFeature"; - private const string ConditionalFeature = "ConditionalFeature"; - private const string ContextualFeature = "ContextualFeature"; - [Fact] public async Task ReadsConfiguration() { @@ -43,9 +31,9 @@ public async Task ReadsConfiguration() IFeatureManager featureManager = serviceProvider.GetRequiredService(); - Assert.True(await featureManager.IsEnabledAsync(OnFeature)); + Assert.True(await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.OnTestFeature))); - Assert.False(await featureManager.IsEnabledAsync(OffFeature)); + Assert.False(await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.OffTestFeature))); IEnumerable featureFilters = serviceProvider.GetRequiredService>(); @@ -61,117 +49,16 @@ public async Task ReadsConfiguration() Assert.Equal("V1", evaluationContext.Parameters["P1"]); - Assert.Equal(ConditionalFeature, evaluationContext.FeatureName); + Assert.Equal(Enum.GetName(typeof(Features), Features.ConditionalFeature), evaluationContext.FeatureName); return Task.FromResult(true); }; - await featureManager.IsEnabledAsync(ConditionalFeature); + await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.True(called); } - [Fact] - public async Task Integrates() - { - IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - - TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => - { - services - .AddSingleton(config) - .AddFeatureManagement() - .AddFeatureFilter(); - - services.AddMvcCore(o => - { - DisableEndpointRouting(o); - o.Filters.AddForFeature(ConditionalFeature); - }); - }) - .Configure(app => - { - - app.UseForFeature(ConditionalFeature, a => a.Use(async (ctx, next) => - { - ctx.Response.Headers[nameof(RouterMiddleware)] = bool.TrueString; - - await next(); - })); - - app.UseMvc(); - })); - - IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); - - TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); - - testFeatureFilter.Callback = _ => Task.FromResult(true); - - HttpResponseMessage res = await testServer.CreateClient().GetAsync(""); - - Assert.True(res.Headers.Contains(nameof(MvcFilter))); - Assert.True(res.Headers.Contains(nameof(RouterMiddleware))); - - testFeatureFilter.Callback = _ => Task.FromResult(false); - - res = await testServer.CreateClient().GetAsync(""); - - Assert.False(res.Headers.Contains(nameof(MvcFilter))); - Assert.False(res.Headers.Contains(nameof(RouterMiddleware))); - } - - [Fact] - public async Task GatesFeatures() - { - IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - - TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => - { - services - .AddSingleton(config) - .AddFeatureManagement() - .AddFeatureFilter(); - - services.AddMvcCore(o => DisableEndpointRouting(o)); - }) - .Configure(app => app.UseMvc())); - - IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); - - TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); - - // - // Enable all features - testFeatureFilter.Callback = ctx => Task.FromResult(true); - - HttpResponseMessage gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - HttpResponseMessage gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.OK, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable 1/2 features - testFeatureFilter.Callback = ctx => Task.FromResult(ctx.FeatureName == Enum.GetName(typeof(Features), Features.ConditionalFeature)); - - gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable no - testFeatureFilter.Callback = ctx => Task.FromResult(false); - - gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.NotFound, gateAnyResponse.StatusCode); - } - [Fact] public async Task CustomFilterContextualTargetingWithNullSetting() { @@ -194,60 +81,6 @@ public async Task CustomFilterContextualTargetingWithNullSetting() Assert.True(await featureManager.IsEnabledAsync("CustomFilterFeature")); } - [Fact] - public async Task GatesRazorPageFeatures() - { - IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - - TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => - { - services - .AddSingleton(config) - .AddFeatureManagement() - .AddFeatureFilter(); - - services.AddMvc(o => DisableEndpointRouting(o)); - }) - .Configure(app => - { - app.UseMvc(); - })); - - IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); - - TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); - - // - // Enable all features - testFeatureFilter.Callback = ctx => Task.FromResult(true); - - HttpResponseMessage gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); - HttpResponseMessage gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); - - Assert.Equal(HttpStatusCode.OK, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable 1/2 features - testFeatureFilter.Callback = ctx => Task.FromResult(ctx.FeatureName == Enum.GetName(typeof(Features), Features.ConditionalFeature)); - - gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable no - testFeatureFilter.Callback = ctx => Task.FromResult(false); - - gateAllResponse = await testServer.CreateClient().GetAsync("RazorTestAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("RazorTestAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.NotFound, gateAnyResponse.StatusCode); - } - [Fact] public async Task TimeWindow() { @@ -458,11 +291,11 @@ public async Task UsesContext() context.AccountId = "NotEnabledAccount"; - Assert.False(await featureManager.IsEnabledAsync(ContextualFeature, context)); + Assert.False(await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ContextualFeature), context)); context.AccountId = "abc"; - Assert.True(await featureManager.IsEnabledAsync(ContextualFeature, context)); + Assert.True(await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ContextualFeature), context)); } [Fact] @@ -530,7 +363,7 @@ public async Task ThrowsExceptionForMissingFeatureFilter() IFeatureManager featureManager = serviceProvider.GetRequiredService(); - FeatureManagementException e = await Assert.ThrowsAsync(async () => await featureManager.IsEnabledAsync(ConditionalFeature)); + FeatureManagementException e = await Assert.ThrowsAsync(async () => await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature))); Assert.Equal(FeatureManagementError.MissingFeatureFilter, e.Error); } @@ -556,7 +389,7 @@ public async Task SwallowsExceptionForMissingFeatureFilter() IFeatureManager featureManager = serviceProvider.GetRequiredService(); - var isEnabled = await featureManager.IsEnabledAsync(ConditionalFeature); + var isEnabled = await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.False(isEnabled); } @@ -591,7 +424,7 @@ public async Task CustomFeatureDefinitionProvider() { FeatureDefinition testFeature = new FeatureDefinition { - Name = ConditionalFeature, + Name = Enum.GetName(typeof(Features), Features.ConditionalFeature), EnabledFor = new List() { new FeatureFilterConfiguration @@ -629,12 +462,12 @@ public async Task CustomFeatureDefinitionProvider() Assert.Equal("V1", evaluationContext.Parameters["P1"]); - Assert.Equal(ConditionalFeature, evaluationContext.FeatureName); + Assert.Equal(Enum.GetName(typeof(Features), Features.ConditionalFeature), evaluationContext.FeatureName); return Task.FromResult(true); }; - await featureManager.IsEnabledAsync(ConditionalFeature); + await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.True(called); } @@ -676,7 +509,7 @@ public async Task ThreadsafeSnapshot() for (int i = 0; i < 1000; i++) { - tasks.Add(featureManager.IsEnabledAsync(ConditionalFeature)); + tasks.Add(featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature))); } Assert.True(called); @@ -844,8 +677,6 @@ public async Task RequirementTypeAllExceptions() { IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - string filterOneId = "1"; - var services = new ServiceCollection(); services @@ -889,7 +720,7 @@ public async Task BindsFeatureFlagSettings() { new FeatureDefinition { - Name = ConditionalFeature, + Name = Enum.GetName(typeof(Features), Features.ConditionalFeature), EnabledFor = new List() { testFilterConfiguration @@ -930,7 +761,7 @@ public async Task BindsFeatureFlagSettings() return Task.FromResult(true); }; - await featureManager.IsEnabledAsync(ConditionalFeature); + await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.True(binderCalled); @@ -940,7 +771,7 @@ public async Task BindsFeatureFlagSettings() called = false; - await featureManager.IsEnabledAsync(ConditionalFeature); + await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.False(binderCalled); @@ -954,20 +785,11 @@ public async Task BindsFeatureFlagSettings() called = false; - await featureManager.IsEnabledAsync(ConditionalFeature); + await featureManager.IsEnabledAsync(Enum.GetName(typeof(Features), Features.ConditionalFeature)); Assert.True(binderCalled); Assert.True(called); } - - private static void DisableEndpointRouting(MvcOptions options) - { -#if NET6_0 || NET5_0 || NETCOREAPP3_1 - // - // Endpoint routing is disabled by default in .NET Core 2.1 since it didn't exist. - options.EnableEndpointRouting = false; -#endif - } } } diff --git a/tests/Tests.FeatureManagement/Features.cs b/tests/Tests.FeatureManagement/Features.cs index 3b2177c1..93847df3 100644 --- a/tests/Tests.FeatureManagement/Features.cs +++ b/tests/Tests.FeatureManagement/Features.cs @@ -11,6 +11,7 @@ enum Features OffTestFeature, ConditionalFeature, ConditionalFeature2, + ContextualFeature, AnyFilterFeature, AllFilterFeature } diff --git a/tests/Tests.FeatureManagement/Pages/_ViewImports.cshtml b/tests/Tests.FeatureManagement/Pages/_ViewImports.cshtml deleted file mode 100644 index 9999731f..00000000 --- a/tests/Tests.FeatureManagement/Pages/_ViewImports.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@using Tests.FeatureManagement -@namespace Tests.FeatureManagement.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj index 0e869107..07c0ad66 100644 --- a/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj +++ b/tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1;net5.0;net6.0 + net48;net6.0;net7.0 false 8.0 True @@ -9,30 +9,35 @@ + + - + - - + - - + - + - - + + + + + + Always + From f0c910dfffece3395ce47bc0d30c7839193268a2 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Thu, 28 Sep 2023 16:57:38 -0700 Subject: [PATCH 3/6] Remove pointless semicolon --- examples/ConsoleApp/ConsoleApp.csproj | 2 +- examples/FeatureFlagDemo/FeatureFlagDemo.csproj | 2 +- examples/RazorPages/RazorPages.csproj | 2 +- examples/TargetingConsoleApp/TargetingConsoleApp.csproj | 2 +- .../Microsoft.FeatureManagement.csproj | 2 +- .../Tests.FeatureManagement.AspNetCore.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/ConsoleApp/ConsoleApp.csproj b/examples/ConsoleApp/ConsoleApp.csproj index 92f5cd47..1230fedf 100644 --- a/examples/ConsoleApp/ConsoleApp.csproj +++ b/examples/ConsoleApp/ConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0; + net6.0 Consoto.Banking.AccountService diff --git a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj index 05d793dd..7ab458e3 100644 --- a/examples/FeatureFlagDemo/FeatureFlagDemo.csproj +++ b/examples/FeatureFlagDemo/FeatureFlagDemo.csproj @@ -1,7 +1,7 @@  - net6.0; + net6.0 diff --git a/examples/RazorPages/RazorPages.csproj b/examples/RazorPages/RazorPages.csproj index e67500f5..e6046fb7 100644 --- a/examples/RazorPages/RazorPages.csproj +++ b/examples/RazorPages/RazorPages.csproj @@ -1,7 +1,7 @@  - net6.0; + net6.0 diff --git a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj index 92f5cd47..1230fedf 100644 --- a/examples/TargetingConsoleApp/TargetingConsoleApp.csproj +++ b/examples/TargetingConsoleApp/TargetingConsoleApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0; + net6.0 Consoto.Banking.AccountService diff --git a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj index 7dab29ea..aaf8898e 100644 --- a/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj +++ b/src/Microsoft.FeatureManagement/Microsoft.FeatureManagement.csproj @@ -11,7 +11,7 @@ - netstandard2.0;netstandard2.1; + netstandard2.0;netstandard2.1 true false ..\..\build\Microsoft.FeatureManagement.snk diff --git a/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj index 4ae0e4f8..c798e1ad 100644 --- a/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj +++ b/tests/Tests.FeatureManagement.AspNetCore/Tests.FeatureManagement.AspNetCore.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0; + net6.0;net7.0 false 8.0 True From bab0180e7a9fee283da173f54d97c0c72c400bb2 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Wed, 4 Oct 2023 14:49:55 -0700 Subject: [PATCH 4/6] Adjusts dotnet installation for buiddy build --- build/install-dotnet.ps1 | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/build/install-dotnet.ps1 b/build/install-dotnet.ps1 index 56196544..11552a78 100644 --- a/build/install-dotnet.ps1 +++ b/build/install-dotnet.ps1 @@ -1,10 +1,8 @@ -# Installs .NET Core 2.1, .NET 5 and .NET 6 for CI/CD environment +# Installs .NET 6 and .NET 7 for CI/CD environment # see: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#examples [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; -&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.816 +&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 6.0 -&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 5.0.408 - -&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) +&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0 \ No newline at end of file From c9b4f1408da65b10e758beffa1f3603c50568564 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Thu, 5 Oct 2023 09:18:36 -0700 Subject: [PATCH 5/6] Removes ASP.NET tests from .NET tests --- .../FeatureManagement.cs | 101 ------------------ 1 file changed, 101 deletions(-) diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index 9429f52a..029a0e7d 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -87,107 +87,6 @@ public async Task ReadsOnlyFeatureManagementSection() } } - [Fact] - public async Task Integrates() - { - IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - - TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => - { - services - .AddSingleton(config) - .AddFeatureManagement() - .AddFeatureFilter(); - - services.AddMvcCore(o => - { - DisableEndpointRouting(o); - o.Filters.AddForFeature(ConditionalFeature); - }); - }) - .Configure(app => - { - - app.UseForFeature(ConditionalFeature, a => a.Use(async (ctx, next) => - { - ctx.Response.Headers[nameof(RouterMiddleware)] = bool.TrueString; - - await next(); - })); - - app.UseMvc(); - })); - - IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); - - TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); - - testFeatureFilter.Callback = _ => Task.FromResult(true); - - HttpResponseMessage res = await testServer.CreateClient().GetAsync(""); - - Assert.True(res.Headers.Contains(nameof(MvcFilter))); - Assert.True(res.Headers.Contains(nameof(RouterMiddleware))); - - testFeatureFilter.Callback = _ => Task.FromResult(false); - - res = await testServer.CreateClient().GetAsync(""); - - Assert.False(res.Headers.Contains(nameof(MvcFilter))); - Assert.False(res.Headers.Contains(nameof(RouterMiddleware))); - } - - [Fact] - public async Task GatesFeatures() - { - IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); - - TestServer testServer = new TestServer(WebHost.CreateDefaultBuilder().ConfigureServices(services => - { - services - .AddSingleton(config) - .AddFeatureManagement() - .AddFeatureFilter(); - - services.AddMvcCore(o => DisableEndpointRouting(o)); - }) - .Configure(app => app.UseMvc())); - - IEnumerable featureFilters = testServer.Host.Services.GetRequiredService>(); - - TestFilter testFeatureFilter = (TestFilter)featureFilters.First(f => f is TestFilter); - - // - // Enable all features - testFeatureFilter.Callback = ctx => Task.FromResult(true); - - HttpResponseMessage gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - HttpResponseMessage gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.OK, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable 1/2 features - testFeatureFilter.Callback = ctx => Task.FromResult(ctx.FeatureName == Enum.GetName(typeof(Features), Features.ConditionalFeature)); - - gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.OK, gateAnyResponse.StatusCode); - - // - // Enable no - testFeatureFilter.Callback = ctx => Task.FromResult(false); - - gateAllResponse = await testServer.CreateClient().GetAsync("gateAll"); - gateAnyResponse = await testServer.CreateClient().GetAsync("gateAny"); - - Assert.Equal(HttpStatusCode.NotFound, gateAllResponse.StatusCode); - Assert.Equal(HttpStatusCode.NotFound, gateAnyResponse.StatusCode); - } - [Fact] public async Task CustomFilterContextualTargetingWithNullSetting() { From f3ce959436c931b0bc8161ee5c7e28fb4824a229 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Thu, 5 Oct 2023 09:21:34 -0700 Subject: [PATCH 6/6] Removes unused usings --- tests/Tests.FeatureManagement/FeatureManagement.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index 029a0e7d..439375a6 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -9,8 +9,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; -using System.Net.Http; using System.Text; using System.Threading.Tasks; using Xunit;