diff --git a/test/OpenIddict.Core.Tests/OpenIddictExtensionsTests.cs b/test/OpenIddict.Core.Tests/OpenIddictExtensionsTests.cs index 89cce806..aace74e4 100644 --- a/test/OpenIddict.Core.Tests/OpenIddictExtensionsTests.cs +++ b/test/OpenIddict.Core.Tests/OpenIddictExtensionsTests.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder.Internal; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Moq; @@ -14,7 +13,7 @@ using Xunit; namespace OpenIddict.Core.Tests { public class OpenIddictExtensionsTests { [Fact] - public void AddOpenIddict_ProviderIsRegistered() { + public void AddOpenIddict_RegistersProvider() { // Arrange var services = new ServiceCollection(); @@ -35,7 +34,7 @@ namespace OpenIddict.Core.Tests { [InlineData(typeof(OpenIddictScopeManager))] [InlineData(typeof(OpenIddictTokenManager))] [InlineData(typeof(OpenIddictServices))] - public void AddOpenIddict_BasicServicesAreRegistered(Type type) { + public void AddOpenIddict_RegistersCoreServices(Type type) { // Arrange var services = new ServiceCollection(); diff --git a/test/OpenIddict.EntityFramework.Tests/OpenIddictExtensionsTests.cs b/test/OpenIddict.EntityFramework.Tests/OpenIddictExtensionsTests.cs new file mode 100644 index 00000000..750409e4 --- /dev/null +++ b/test/OpenIddict.EntityFramework.Tests/OpenIddictExtensionsTests.cs @@ -0,0 +1,54 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace OpenIddict.EntityFramework.Tests { + public class OpenIddictExtensionsTests { + [Theory] + [InlineData(typeof(OpenIddictApplicationStore, OpenIddictToken, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictAuthorizationStore, OpenIddictToken, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictScopeStore, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictTokenStore, OpenIddictAuthorization, OpenIddictDbContext, Guid>))] + public void AddEntityFramework_RegistersEntityFrameworkStores(Type type) { + // Arrange + var services = new ServiceCollection(); + + var builder = new OpenIddictBuilder(services) { + ApplicationType = typeof(OpenIddictApplication), + AuthorizationType = typeof(OpenIddictAuthorization), + ScopeType = typeof(OpenIddictScope), + TokenType = typeof(OpenIddictToken) + }; + + // Act + builder.AddEntityFramework(); + + // Assert + Assert.Contains(services, service => service.ImplementationType == type); + } + + [Theory] + [InlineData(typeof(OpenIddictApplicationStore))] + [InlineData(typeof(OpenIddictAuthorizationStore))] + [InlineData(typeof(OpenIddictScopeStore))] + [InlineData(typeof(OpenIddictTokenStore))] + public void AddEntityFramework_KeyTypeDefaultsToString(Type type) { + // Arrange + var services = new ServiceCollection(); + + var builder = new OpenIddictBuilder(services) { + ApplicationType = typeof(OpenIddictApplication), + AuthorizationType = typeof(OpenIddictAuthorization), + ScopeType = typeof(OpenIddictScope), + TokenType = typeof(OpenIddictToken) + }; + + // Act + builder.AddEntityFramework(); + + // Assert + Assert.Contains(services, service => service.ImplementationType == type); + } + } +} diff --git a/test/OpenIddict.EntityFramework.Tests/Placeholder.cs b/test/OpenIddict.EntityFramework.Tests/Placeholder.cs deleted file mode 100644 index 8786e412..00000000 --- a/test/OpenIddict.EntityFramework.Tests/Placeholder.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace OpenIddict.EntityFramework.Tests { - public class Placeholder { } -} diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs new file mode 100644 index 00000000..4a9199dd --- /dev/null +++ b/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Xunit; + +namespace OpenIddict.Mvc.Tests { + public class OpenIddictExtensionsTests { + [Fact] + public void AddMvcBinders_RegistersModelBinderProvider() { + // Arrange + var services = new ServiceCollection(); + services.AddOptions(); + + var builder = new OpenIddictBuilder(services); + + // Act + builder.AddMvcBinders(); + + var provider = services.BuildServiceProvider(); + var options = provider.GetRequiredService>(); + + // Assert + Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictModelBinder); + } + } +} diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs new file mode 100644 index 00000000..b5d7908f --- /dev/null +++ b/test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using AspNet.Security.OpenIdConnect.Extensions; +using AspNet.Security.OpenIdConnect.Server; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Moq; +using Xunit; + +namespace OpenIddict.Mvc.Tests { + public class OpenIddictModelBinderTests { + [Theory] + [InlineData(typeof(object))] + [InlineData(typeof(IList))] + [InlineData(typeof(int[]))] + public async Task BindModelAsync_ThrowsAnExceptionForUnsupportedTypes(Type type) { + // Arrange + var binder = new OpenIddictModelBinder(); + var provider = new EmptyModelMetadataProvider(); + + var context = new DefaultModelBindingContext { + ModelMetadata = provider.GetMetadataForType(type) + }; + + // Act and assert + var exception = await Assert.ThrowsAsync(delegate { + return binder.BindModelAsync(context); + }); + + Assert.Equal("The specified model type is not supported by this binder.", exception.Message); + } + + [Fact] + public async Task BindModelAsync_ThrowsAnExceptionWhenRequestCannotBeFound() { + // Arrange + var binder = new OpenIddictModelBinder(); + var provider = new EmptyModelMetadataProvider(); + + var context = new DefaultModelBindingContext { + ActionContext = new ActionContext() { + HttpContext = new DefaultHttpContext(), + }, + + ModelMetadata = provider.GetMetadataForType(typeof(OpenIdConnectRequest)) + }; + + // Act and assert + var exception = await Assert.ThrowsAsync(delegate { + return binder.BindModelAsync(context); + }); + + Assert.Equal("The OpenID Connect request cannot be retrieved from the ASP.NET context. " + + "Make sure that 'app.UseOpenIddict()' is called before 'app.UseMvc()' and " + + "that the action route corresponds to the endpoint path registered via " + + "'services.AddOpenIddict().Enable[...]Endpoint(...)'.", exception.Message); + } + + [Fact] + public async Task BindModelAsync_ReturnsNullWhenResponseCannotBeFound() { + // Arrange + var binder = new OpenIddictModelBinder(); + var provider = new EmptyModelMetadataProvider(); + + var context = new DefaultModelBindingContext { + ActionContext = new ActionContext() { + HttpContext = new DefaultHttpContext(), + }, + + ModelMetadata = provider.GetMetadataForType(typeof(OpenIdConnectResponse)), + + ValidationState = new ValidationStateDictionary() + }; + + // Act + await binder.BindModelAsync(context); + + // Assert + Assert.True(context.Result.IsModelSet); + Assert.Null(context.Result.Model); + } + + [Fact] + public async Task BindModelAsync_ReturnsAmbientRequest() { + // Arrange + var binder = new OpenIddictModelBinder(); + var provider = new EmptyModelMetadataProvider(); + + var request = new OpenIdConnectRequest(); + + var features = new FeatureCollection(); + features.Set(new OpenIdConnectServerFeature { + Request = request + }); + + var context = new DefaultModelBindingContext { + ActionContext = new ActionContext() { + HttpContext = new DefaultHttpContext(features), + }, + + ModelMetadata = provider.GetMetadataForType(typeof(OpenIdConnectRequest)), + + ValidationState = new ValidationStateDictionary() + }; + + // Act + await binder.BindModelAsync(context); + + // Assert + Assert.True(context.Result.IsModelSet); + Assert.Same(request, context.Result.Model); + Assert.True(context.ValidationState[request].SuppressValidation); + } + + [Fact] + public async Task BindModelAsync_ReturnsAmbientResponse() { + // Arrange + var binder = new OpenIddictModelBinder(); + var provider = new EmptyModelMetadataProvider(); + + var response = new OpenIdConnectResponse(); + + var features = new FeatureCollection(); + features.Set(new OpenIdConnectServerFeature { + Response = response + }); + + var context = new DefaultModelBindingContext { + ActionContext = new ActionContext() { + HttpContext = new DefaultHttpContext(features), + }, + + ModelMetadata = provider.GetMetadataForType(typeof(OpenIdConnectResponse)), + + ValidationState = new ValidationStateDictionary() + }; + + // Act + await binder.BindModelAsync(context); + + // Assert + Assert.True(context.Result.IsModelSet); + Assert.Same(response, context.Result.Model); + Assert.True(context.ValidationState[response].SuppressValidation); + } + + [Theory] + [InlineData(typeof(object))] + [InlineData(typeof(IList))] + [InlineData(typeof(int[]))] + public void GetBinder_ReturnsNullForUnsupportedTypes(Type type) { + // Arrange + var provider = new OpenIddictModelBinder(); + + var metadata = new Mock(ModelMetadataIdentity.ForType(type)); + + var context = new Mock(); + context.Setup(mock => mock.Metadata) + .Returns(metadata.Object); + + // Act + var result = provider.GetBinder(context.Object); + + // Assert + Assert.Null(result); + } + + [Theory] + [InlineData(typeof(OpenIdConnectRequest))] + [InlineData(typeof(OpenIdConnectResponse))] + public void GetBinder_ReturnsNonNullForSupportedTypes(Type type) { + // Arrange + var binder = new OpenIddictModelBinder(); + + var metadata = new Mock(ModelMetadataIdentity.ForType(type)); + + var context = new Mock(); + context.Setup(mock => mock.Metadata) + .Returns(metadata.Object); + + // Act + var result = binder.GetBinder(context.Object); + + // Assert + Assert.Same(binder, result); + } + } +} diff --git a/test/OpenIddict.Mvc.Tests/Placeholder.cs b/test/OpenIddict.Mvc.Tests/Placeholder.cs deleted file mode 100644 index dbaa88c0..00000000 --- a/test/OpenIddict.Mvc.Tests/Placeholder.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace OpenIddict.Mvc.Tests { - public class Placeholder { } -} diff --git a/test/OpenIddict.Tests/OpenIddictExtensionsTests.cs b/test/OpenIddict.Tests/OpenIddictExtensionsTests.cs new file mode 100644 index 00000000..3454f031 --- /dev/null +++ b/test/OpenIddict.Tests/OpenIddictExtensionsTests.cs @@ -0,0 +1,60 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace OpenIddict.Tests { + public class OpenIddictExtensionsTests { + [Theory] + [InlineData(typeof(OpenIddictApplicationManager>))] + [InlineData(typeof(OpenIddictAuthorizationManager>))] + [InlineData(typeof(OpenIddictScopeManager>))] + [InlineData(typeof(OpenIddictTokenManager>))] + public void AddOpenIddict_RegistersCoreManagers(Type type) { + // Arrange + var services = new ServiceCollection(); + + // Act + services.AddOpenIddict(); + + // Assert + Assert.Contains(services, service => service.ImplementationType == type); + } + + [Theory] + [InlineData(typeof(OpenIddictApplicationStore, OpenIddictToken, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictAuthorizationStore, OpenIddictToken, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictScopeStore, OpenIddictDbContext, Guid>))] + [InlineData(typeof(OpenIddictTokenStore, OpenIddictAuthorization, OpenIddictDbContext, Guid>))] + public void AddOpenIddict_RegistersEntityFrameworkStores(Type type) { + // Arrange + var services = new ServiceCollection(); + + // Act + services.AddOpenIddict(); + + // Assert + Assert.Contains(services, service => service.ImplementationType == type); + } + + [Theory] + [InlineData(typeof(OpenIddictApplicationManager))] + [InlineData(typeof(OpenIddictAuthorizationManager))] + [InlineData(typeof(OpenIddictScopeManager))] + [InlineData(typeof(OpenIddictTokenManager))] + [InlineData(typeof(OpenIddictApplicationStore))] + [InlineData(typeof(OpenIddictAuthorizationStore))] + [InlineData(typeof(OpenIddictScopeStore))] + [InlineData(typeof(OpenIddictTokenStore))] + public void AddOpenIddict_KeyTypeDefaultsToString(Type type) { + // Arrange + var services = new ServiceCollection(); + + // Act + services.AddOpenIddict(); + + // Assert + Assert.Contains(services, service => service.ImplementationType == type); + } + } +} diff --git a/test/OpenIddict.Tests/Placeholder.cs b/test/OpenIddict.Tests/Placeholder.cs deleted file mode 100644 index 3c107643..00000000 --- a/test/OpenIddict.Tests/Placeholder.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace OpenIddict.Tests { - public class Placeholder { } -}