From ee2e139ae57a48e485083e76cb98d4ffbce2d595 Mon Sep 17 00:00:00 2001 From: IgorHrabrov <18480638+IgorHrabrov@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:52:15 +0200 Subject: [PATCH] Port the AspNet.Security.OpenIdConnect.Primitives tests --- .../Primitives/OpenIddictConverterTests.cs | 322 ++++++ .../Primitives/OpenIddictExtensionsTests.cs | 915 +++++++++++++++ .../Primitives/OpenIddictMessageTests.cs | 450 ++++++++ .../Primitives/OpenIddictParameterTests.cs | 1026 +++++++++++++++++ .../Primitives/OpenIddictRequestTests.cs | 334 ++++++ .../Primitives/OpenIddictResponseTests.cs | 137 +++ 6 files changed, 3184 insertions(+) create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictRequestTests.cs create mode 100644 test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictResponseTests.cs diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs new file mode 100644 index 00000000..1c5fa082 --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictConverterTests.cs @@ -0,0 +1,322 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIddictConverterTests + { + [Fact] + public void CanConvert_ThrowsAnExceptionForNullType() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => converter.CanConvert(type: null)); + + Assert.Equal("type", exception.ParamName); + } + + [Theory] + [InlineData(typeof(OpenIddictMessage), true)] + [InlineData(typeof(OpenIddictRequest), true)] + [InlineData(typeof(OpenIddictResponse), true)] + [InlineData(typeof(OpenIddictMessage[]), false)] + [InlineData(typeof(OpenIddictRequest[]), false)] + [InlineData(typeof(OpenIddictResponse[]), false)] + [InlineData(typeof(OpenIddictParameter), false)] + [InlineData(typeof(OpenIddictParameter?), false)] + [InlineData(typeof(OpenIddictParameter[]), false)] + [InlineData(typeof(OpenIddictParameter?[]), false)] + [InlineData(typeof(object), false)] + [InlineData(typeof(long), false)] + public void CanConvert_ReturnsExpectedResult(Type type, bool result) + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + Assert.Equal(result, converter.CanConvert(type)); + } + + [Fact] + public void ReadJson_ThrowsAnExceptionForNullReader() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.ReadJson(reader: null, type: null, value: null, serializer: null); + }); + + Assert.Equal("reader", exception.ParamName); + } + + [Fact] + public void ReadJson_ThrowsAnExceptionForNullType() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.ReadJson(reader: new JsonTextReader(TextReader.Null), type: null, value: null, serializer: null); + }); + + Assert.Equal("type", exception.ParamName); + } + + [Fact] + public void ReadJson_ThrowsAnExceptionForUnexpectedJsonToken() + { + // Arrange + var converter = new OpenIddictConverter(); + using var reader = new JsonTextReader(new StringReader("[0,1,2,3]")); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.ReadJson(reader: reader, type: typeof(OpenIddictRequest), value: null, serializer: null); + }); + + Assert.Equal("An error occurred while reading the JSON payload.", exception.Message); + } + + [Theory] + [InlineData(typeof(OpenIddictMessage[]))] + [InlineData(typeof(OpenIddictRequest[]))] + [InlineData(typeof(OpenIddictResponse[]))] + [InlineData(typeof(OpenIddictParameter))] + [InlineData(typeof(OpenIddictParameter?))] + [InlineData(typeof(OpenIddictParameter[]))] + [InlineData(typeof(OpenIddictParameter?[]))] + [InlineData(typeof(object))] + [InlineData(typeof(long))] + public void ReadJson_ThrowsAnExceptionForUnsupportedType(Type type) + { + // Arrange + var converter = new OpenIddictConverter(); + using var reader = new JsonTextReader(new StringReader(@"{""name"":""value""}")); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.ReadJson(reader, type, value: null, serializer: null); + }); + + Assert.StartsWith("The specified type is not supported.", exception.Message); + Assert.Equal("type", exception.ParamName); + } + + [Fact] + public void ReadJson_PopulatesExistingInstance() + { + // Arrange + var message = new OpenIddictMessage(); + var converter = new OpenIddictConverter(); + var reader = new JsonTextReader(new StringReader(@"{""name"":""value""}")); + + // Act + var result = converter.ReadJson(reader: reader, type: typeof(OpenIddictMessage), value: message, serializer: null); + + // Assert + Assert.Same(message, result); + Assert.Equal("value", message.GetParameter("name")); + } + + [Theory] + [InlineData(typeof(OpenIddictMessage))] + [InlineData(typeof(OpenIddictRequest))] + [InlineData(typeof(OpenIddictResponse))] + public void ReadJson_ReturnsRequestedType(Type type) + { + // Arrange + var converter = new OpenIddictConverter(); + var reader = new JsonTextReader(new StringReader(@"{""name"":""value""}")); + + // Act + var result = (OpenIddictMessage)converter.ReadJson(reader, type, value: null, serializer: null); + + // Assert + Assert.IsType(type, result); + Assert.Equal("value", result.GetParameter("name")); + } + + [Fact] + public void ReadJson_PreservesNullParameters() + { + // Arrange + var converter = new OpenIddictConverter(); + var reader = new JsonTextReader( + new StringReader(@"{""string"":null,""bool"":null,""long"":null,""array"":null,""object"":null}")); + + // Act + var result = (OpenIddictMessage)converter.ReadJson(reader, typeof(OpenIddictMessage), value: null, serializer: null); + + // Assert + Assert.Equal(5, result.GetParameters().Count()); + Assert.NotNull(result.GetParameter("string")); + Assert.NotNull(result.GetParameter("bool")); + Assert.NotNull(result.GetParameter("long")); + Assert.NotNull(result.GetParameter("array")); + Assert.NotNull(result.GetParameter("object")); + Assert.Null((string)result.GetParameter("string")); + Assert.Null((bool?)result.GetParameter("bool")); + Assert.Null((long?)result.GetParameter("long")); + Assert.Null((JArray)result.GetParameter("array")); + Assert.Null((JObject)result.GetParameter("object")); + } + + [Fact] + public void ReadJson_PreservesEmptyParameters() + { + // Arrange + var converter = new OpenIddictConverter(); + var reader = new JsonTextReader(new StringReader(@"{""string"":"""",""array"":[],""object"":{}}")); + + // Act + var result = (OpenIddictMessage)converter.ReadJson(reader, typeof(OpenIddictMessage), value: null, serializer: null); + + // Assert + Assert.Equal(3, result.GetParameters().Count()); + Assert.NotNull(result.GetParameter("string")); + Assert.NotNull(result.GetParameter("array")); + Assert.NotNull(result.GetParameter("object")); + Assert.Empty((string)result.GetParameter("string")); + Assert.Empty((JArray)result.GetParameter("array")); + Assert.Empty((JObject)result.GetParameter("object")); + } + + [Fact] + public void WriteJson_ThrowsAnExceptionForNullWriter() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.WriteJson(writer: null, value: null, serializer: null); + }); + + Assert.Equal("writer", exception.ParamName); + } + + [Fact] + public void WriteJson_ThrowsAnExceptionForNullValue() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.WriteJson(writer: new JsonTextWriter(TextWriter.Null), value: null, serializer: null); + }); + + Assert.Equal("value", exception.ParamName); + } + + [Fact] + public void WriteJson_ThrowsAnExceptionForInvalidValue() + { + // Arrange + var converter = new OpenIddictConverter(); + + // Act and assert + var exception = Assert.Throws(() => + { + converter.WriteJson(writer: new JsonTextWriter(TextWriter.Null), value: new object(), serializer: null); + }); + + Assert.StartsWith("The specified object is not supported.", exception.Message); + Assert.Equal("value", exception.ParamName); + } + + [Fact] + public void WriteJson_WritesEmptyPayloadForEmptyMessages() + { + // Arrange + var message = new OpenIddictMessage(); + var converter = new OpenIddictConverter(); + var writer = new StringWriter(CultureInfo.InvariantCulture); + + // Act + converter.WriteJson(writer: new JsonTextWriter(writer), value: message, serializer: null); + + Assert.Equal("{}", writer.ToString()); + } + + [Fact] + public void WriteJson_PreservesNullParameters() + { + // Arrange + var converter = new OpenIddictConverter(); + var writer = new StringWriter(CultureInfo.InvariantCulture); + + var message = new OpenIddictMessage(); + message.AddParameter("string", new OpenIddictParameter((string)null)); + message.AddParameter("bool", new OpenIddictParameter((bool?)null)); + message.AddParameter("long", new OpenIddictParameter((long?)null)); + message.AddParameter("array", new OpenIddictParameter((JArray)null)); + message.AddParameter("object", new OpenIddictParameter((JObject)null)); + + // Act + converter.WriteJson(writer: new JsonTextWriter(writer), value: message, serializer: null); + + // Assert + Assert.Equal(@"{""string"":null,""bool"":null,""long"":null,""array"":null,""object"":null}", writer.ToString()); + } + + [Fact] + public void WriteJson_PreservesEmptyParameters() + { + // Arrange + var converter = new OpenIddictConverter(); + var writer = new StringWriter(CultureInfo.InvariantCulture); + + var message = new OpenIddictMessage(); + message.AddParameter("string", new OpenIddictParameter(string.Empty)); + message.AddParameter("array", new OpenIddictParameter(new JArray())); + message.AddParameter("object", new OpenIddictParameter(new JObject())); + + // Act + converter.WriteJson(writer: new JsonTextWriter(writer), value: message, serializer: null); + + // Assert + Assert.Equal(@"{""string"":"""",""array"":[],""object"":{}}", writer.ToString()); + } + + [Fact] + public void WriteJson_WritesExpectedPayload() + { + // Arrange + var converter = new OpenIddictConverter(); + var writer = new StringWriter(CultureInfo.InvariantCulture); + + var message = new OpenIddictMessage(); + message.AddParameter("string", "value"); + message.AddParameter("array", new JArray("value")); + + // Act + converter.WriteJson(writer: new JsonTextWriter(writer), value: message, serializer: null); + + // Assert + Assert.Equal(@"{""string"":""value"",""array"":[""value""]}", writer.ToString()); + } + } +} diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs new file mode 100644 index 00000000..11543477 --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs @@ -0,0 +1,915 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIdConnectExtensionsTests + { + [Fact] + public void GetAcrValues_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.GetAcrValues()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, new string[0])] + [InlineData("mod-pr", new[] { "mod-pr" })] + [InlineData("mod-pr ", new[] { "mod-pr" })] + [InlineData(" mod-pr ", new[] { "mod-pr" })] + [InlineData("mod-pr mod-mf", new[] { "mod-pr", "mod-mf" })] + [InlineData("mod-pr mod-mf", new[] { "mod-pr", "mod-mf" })] + [InlineData("mod-pr mod-mf ", new[] { "mod-pr", "mod-mf" })] + [InlineData(" mod-pr mod-mf", new[] { "mod-pr", "mod-mf" })] + [InlineData("mod-pr mod-pr mod-mf", new[] { "mod-pr", "mod-mf" })] + [InlineData("mod-pr MOD-PR mod-mf", new[] { "mod-pr", "MOD-PR", "mod-mf" })] + public void GetAcrValues_ReturnsExpectedAcrValues(string value, string[] values) + { + // Arrange + var request = new OpenIddictRequest + { + AcrValues = value + }; + + // Act + var actualValues = request.GetAcrValues(); + + // Assert + Assert.Equal(values.Length, actualValues.Count); + foreach (var val in actualValues) + { + Assert.Contains(val, values); + } + } + + [Fact] + public void GetResponseTypes_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest)null; + + // Act + var exception = Assert.Throws(() => request.GetResponseTypes()); + + // Assert + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, new string[0])] + [InlineData("code", new[] { "code" })] + [InlineData("code ", new[] { "code" })] + [InlineData(" code ", new[] { "code" })] + [InlineData("code id_token", new[] { "code", "id_token" })] + [InlineData("code id_token", new[] { "code", "id_token" })] + [InlineData("code id_token ", new[] { "code", "id_token" })] + [InlineData(" code id_token", new[] { "code", "id_token" })] + [InlineData("code code id_token", new[] { "code", "id_token" })] + [InlineData("code CODE id_token", new[] { "code", "CODE", "id_token" })] + public void GetResponseTypes_ReturnsExpectedResponseTypes(string value, string[] responseTypes) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = value + }; + + // Act + var actualResponseTypes = request.GetResponseTypes(); + + // Assert + Assert.Equal(responseTypes.Length, actualResponseTypes.Count); + foreach (var rt in actualResponseTypes) + { + Assert.Contains(rt, responseTypes); + } + } + + [Fact] + public void GetScopes_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.GetScopes()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, new string[0])] + [InlineData("openid", new[] { "openid" })] + [InlineData("openid ", new[] { "openid" })] + [InlineData(" openid ", new[] { "openid" })] + [InlineData("openid profile", new[] { "openid", "profile" })] + [InlineData("openid profile", new[] { "openid", "profile" })] + [InlineData("openid profile ", new[] { "openid", "profile" })] + [InlineData(" openid profile", new[] { "openid", "profile" })] + [InlineData("openid openid profile", new[] { "openid", "profile" })] + [InlineData("openid OPENID profile", new[] { "openid", "OPENID", "profile" })] + public void GetScopes_ReturnsExpectedScopes(string scope, string[] scopes) + { + // Arrange + var request = new OpenIddictRequest + { + Scope = scope + }; + + // Act + var actualScopes = request.GetScopes(); + + // Assert + Assert.Equal(scopes.Length, actualScopes.Count); + foreach (var scp in actualScopes) + { + Assert.Contains(scp, scopes); + } + } + + [Fact] + public void HasAcrValue_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.HasAcrValue("mod-mf")); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void HasAcrValue_ThrowsAnExceptionForNullOrEmptyAcrValue(string value) + { + // Arrange + var request = new OpenIddictRequest(); + + // Act and assert + var exception = Assert.Throws(() => request.HasAcrValue(value)); + + Assert.Equal("value", exception.ParamName); + Assert.StartsWith("The value cannot be null or empty.", exception.Message); + } + + [Theory] + [InlineData(null, false)] + [InlineData("mod-mf", true)] + [InlineData("mod-mf mod-pr", true)] + [InlineData(" mod-mf mod-pr", true)] + [InlineData("mod-pr mod-mf", true)] + [InlineData("mod-pr mod-mf ", true)] + [InlineData("mod-pr mod-mf mod-cstm", true)] + [InlineData("mod-pr mod-mf mod-cstm ", true)] + [InlineData("mod-pr mod-mf mod-cstm ", true)] + [InlineData("mod-pr", false)] + [InlineData("mod-pr mod-cstm", false)] + [InlineData("MOD-MF", false)] + [InlineData("MOD-MF MOD-PR", false)] + [InlineData(" MOD-MF MOD-PR", false)] + [InlineData("MOD-PR MOD-MF", false)] + [InlineData("MOD-PR MOD-MF ", false)] + [InlineData("MOD-PR MOD-MF MOD-CSTM", false)] + [InlineData("MOD-PR MOD-MF MOD-CSTM ", false)] + [InlineData("MOD-PR MOD-MF MOD-CSTM ", false)] + [InlineData("MOD-PR", false)] + [InlineData("MOD-PR MOD-CSTM", false)] + public void HasAcrValue_ReturnsExpectedResult(string value, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + AcrValues = value + }; + + // Act and assert + Assert.Equal(result, request.HasAcrValue("mod-mf")); + } + + [Fact] + public void HasPrompt_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => + { + request.HasPrompt(OpenIddictConstants.Prompts.Consent); + }); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void HasPrompt_ThrowsAnExceptionForNullOrEmptyPrompt(string prompt) + { + // Arrange + var request = new OpenIddictRequest(); + + // Act and assert + var exception = Assert.Throws(() => request.HasPrompt(prompt)); + + Assert.Equal("prompt", exception.ParamName); + Assert.StartsWith("The prompt cannot be null or empty.", exception.Message); + } + + [Theory] + [InlineData(null, false)] + [InlineData("consent", true)] + [InlineData("consent login", true)] + [InlineData(" consent login", true)] + [InlineData("login consent", true)] + [InlineData("login consent ", true)] + [InlineData("login consent select_account", true)] + [InlineData("login consent select_account ", true)] + [InlineData("login consent select_account ", true)] + [InlineData("login", false)] + [InlineData("login select_account", false)] + [InlineData("CONSENT", false)] + [InlineData("CONSENT LOGIN", false)] + [InlineData(" CONSENT LOGIN", false)] + [InlineData("LOGIN CONSENT", false)] + [InlineData("LOGIN CONSENT ", false)] + [InlineData("LOGIN CONSENT SELECT_ACCOUNT", false)] + [InlineData("LOGIN CONSENT SELECT_ACCOUNT ", false)] + [InlineData("LOGIN CONSENT SELECT_ACCOUNT ", false)] + [InlineData("LOGIN", false)] + [InlineData("LOGIN SELECT_ACCOUNT", false)] + public void HasPrompt_ReturnsExpectedResult(string prompt, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + Prompt = prompt + }; + + // Act and assert + Assert.Equal(result, request.HasPrompt(OpenIddictConstants.Prompts.Consent)); + } + + [Fact] + public void HasResponseType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => + { + request.HasResponseType(OpenIddictConstants.ResponseTypes.Code); + }); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void HasResponseType_ThrowsAnExceptionForNullOrEmptyResponseType(string type) + { + // Arrange + var request = new OpenIddictRequest(); + + // Act and assert + var exception = Assert.Throws(() => request.HasResponseType(type)); + + Assert.Equal("type", exception.ParamName); + Assert.StartsWith("The response type cannot be null or empty.", exception.Message); + } + + [Theory] + [InlineData(null, false)] + [InlineData("code", true)] + [InlineData("code id_token", true)] + [InlineData(" code id_token", true)] + [InlineData("id_token code", true)] + [InlineData("id_token code ", true)] + [InlineData("id_token code token", true)] + [InlineData("id_token code token ", true)] + [InlineData("id_token code token ", true)] + [InlineData("id_token", false)] + [InlineData("id_token token", false)] + [InlineData("CODE", false)] + [InlineData("CODE ID_TOKEN", false)] + [InlineData(" CODE ID_TOKEN", false)] + [InlineData("ID_TOKEN CODE", false)] + [InlineData("ID_TOKEN CODE ", false)] + [InlineData("ID_TOKEN CODE TOKEN", false)] + [InlineData("ID_TOKEN CODE TOKEN ", false)] + [InlineData("ID_TOKEN CODE TOKEN ", false)] + [InlineData("ID_TOKEN", false)] + [InlineData("ID_TOKEN TOKEN", false)] + public void HasResponseType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.HasResponseType(OpenIddictConstants.ResponseTypes.Code)); + } + + [Fact] + public void HasScope_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => + { + request.HasScope(OpenIddictConstants.Scopes.OpenId); + }); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void HasScope_ThrowsAnExceptionForNullOrEmptyScope(string scope) + { + // Arrange + var request = new OpenIddictRequest(); + + // Act and assert + var exception = Assert.Throws(() => request.HasScope(scope)); + + Assert.Equal("scope", exception.ParamName); + Assert.StartsWith("The scope cannot be null or empty.", exception.Message); + } + + [Theory] + [InlineData(null, false)] + [InlineData("openid", true)] + [InlineData("openid ", true)] + [InlineData(" openid ", true)] + [InlineData("openid profile", true)] + [InlineData("openid profile", true)] + [InlineData("openid profile ", true)] + [InlineData(" openid profile", true)] + [InlineData("profile", false)] + [InlineData("profile email", false)] + [InlineData("OPENID", false)] + [InlineData("OPENID ", false)] + [InlineData(" OPENID ", false)] + [InlineData("OPENID PROFILE", false)] + [InlineData("OPENID PROFILE", false)] + [InlineData("OPENID PROFILE ", false)] + [InlineData(" OPENID PROFILE", false)] + [InlineData("PROFILE", false)] + [InlineData("PROFILE EMAIL", false)] + public void HasScope_ReturnsExpectedResult(string scope, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + Scope = scope + }; + + // Act and assert + Assert.Equal(result, request.HasScope(OpenIddictConstants.Scopes.OpenId)); + } + + [Fact] + public void IsNoneFlow_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsNoneFlow()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("none", true)] + [InlineData("none ", true)] + [InlineData(" none", true)] + [InlineData("none id_token", false)] + [InlineData(" none id_token", false)] + [InlineData("none id_token ", false)] + [InlineData(" none id_token ", false)] + [InlineData("NONE", false)] + [InlineData("NONE ", false)] + [InlineData(" NONE", false)] + [InlineData("NONE ID_TOKEN", false)] + [InlineData(" NONE ID_TOKEN", false)] + [InlineData("NONE ID_TOKEN ", false)] + [InlineData(" NONE ID_TOKEN ", false)] + public void IsNoneFlow_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsNoneFlow()); + } + + [Fact] + public void IsAuthorizationCodeFlow_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsAuthorizationCodeFlow()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("code", true)] + [InlineData("code ", true)] + [InlineData(" code", true)] + [InlineData("code id_token", false)] + [InlineData(" code id_token", false)] + [InlineData("code id_token ", false)] + [InlineData(" code id_token ", false)] + [InlineData("CODE", false)] + [InlineData("CODE ", false)] + [InlineData(" CODE", false)] + [InlineData("CODE ID_TOKEN", false)] + [InlineData(" CODE ID_TOKEN", false)] + [InlineData("CODE ID_TOKEN ", false)] + [InlineData(" CODE ID_TOKEN ", false)] + public void IsAuthorizationCodeFlow_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsAuthorizationCodeFlow()); + } + + [Fact] + public void IsImplicitFlow_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsImplicitFlow()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("id_token", true)] + [InlineData("id_token ", true)] + [InlineData(" id_token", true)] + [InlineData("id_token token", true)] + [InlineData(" id_token token", true)] + [InlineData("id_token token ", true)] + [InlineData(" id_token token ", true)] + [InlineData("token", true)] + [InlineData("token ", true)] + [InlineData(" token", true)] + [InlineData("code id_token", false)] + [InlineData("code id_token token", false)] + [InlineData("code token", false)] + [InlineData("ID_TOKEN", false)] + [InlineData("ID_TOKEN ", false)] + [InlineData(" ID_TOKEN", false)] + [InlineData("ID_TOKEN TOKEN", false)] + [InlineData(" ID_TOKEN TOKEN", false)] + [InlineData("ID_TOKEN TOKEN ", false)] + [InlineData(" ID_TOKEN TOKEN ", false)] + [InlineData("TOKEN", false)] + [InlineData("TOKEN ", false)] + [InlineData(" TOKEN", false)] + [InlineData("CODE ID_TOKEN", false)] + [InlineData("CODE ID_TOKEN TOKEN", false)] + [InlineData("CODE TOKEN", false)] + public void IsImplicitFlow_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsImplicitFlow()); + } + + [Fact] + public void IsHybridFlow_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsHybridFlow()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("code id_token", true)] + [InlineData("code id_token ", true)] + [InlineData(" code id_token", true)] + [InlineData("code id_token token", true)] + [InlineData(" code id_token token", true)] + [InlineData("code id_token token ", true)] + [InlineData(" code id_token token ", true)] + [InlineData(" code id_token token ", true)] + [InlineData("code token", true)] + [InlineData("code token ", true)] + [InlineData(" code token", true)] + [InlineData("id_token", false)] + [InlineData("id_token token", false)] + [InlineData("token", false)] + [InlineData("CODE ID_TOKEN", false)] + [InlineData("CODE ID_TOKEN ", false)] + [InlineData(" CODE ID_TOKEN", false)] + [InlineData("CODE ID_TOKEN TOKEN", false)] + [InlineData(" CODE ID_TOKEN TOKEN", false)] + [InlineData("CODE ID_TOKEN TOKEN ", false)] + [InlineData(" CODE ID_TOKEN TOKEN ", false)] + [InlineData(" CODE ID_TOKEN TOKEN ", false)] + [InlineData("CODE TOKEN", false)] + [InlineData("CODE TOKEN ", false)] + [InlineData(" CODE TOKEN", false)] + [InlineData("ID_TOKEN", false)] + [InlineData("ID_TOKEN TOKEN", false)] + [InlineData("TOKEN", false)] + public void IsHybridFlow_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsHybridFlow()); + } + + [Fact] + public void IsFragmentResponseMode_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsFragmentResponseMode()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, null, false)] + [InlineData("unknown", null, false)] + [InlineData("query", null, false)] + [InlineData("form_post", null, false)] + [InlineData("fragment", null, true)] + [InlineData("fragment ", null, false)] + [InlineData(" fragment", null, false)] + [InlineData(" fragment ", null, false)] + [InlineData(null, "code", false)] + [InlineData(null, "code id_token", true)] + [InlineData(null, "code id_token token", true)] + [InlineData(null, "code token", true)] + [InlineData(null, "id_token", true)] + [InlineData(null, "id_token token", true)] + [InlineData(null, "token", true)] + [InlineData("QUERY", null, false)] + [InlineData("FRAGMENT", null, false)] + [InlineData("FORM_POST", null, false)] + [InlineData(null, "CODE", false)] + [InlineData(null, "CODE ID_TOKEN", false)] + [InlineData(null, "CODE ID_TOKEN TOKEN", false)] + [InlineData(null, "CODE TOKEN", false)] + [InlineData(null, "ID_TOKEN", false)] + [InlineData(null, "ID_TOKEN TOKEN", false)] + [InlineData(null, "TOKEN", false)] + public void IsFragmentResponseMode_ReturnsExpectedResult(string mode, string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseMode = mode, + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsFragmentResponseMode()); + } + + [Fact] + public void IsQueryResponseMode_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsQueryResponseMode()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, null, false)] + [InlineData("unknown", null, false)] + [InlineData("query", null, true)] + [InlineData("query ", null, false)] + [InlineData(" query", null, false)] + [InlineData(" query ", null, false)] + [InlineData("fragment", null, false)] + [InlineData("form_post", null, false)] + [InlineData(null, "none", true)] + [InlineData(null, "code", true)] + [InlineData(null, "code id_token token", false)] + [InlineData(null, "code token", false)] + [InlineData(null, "id_token", false)] + [InlineData(null, "id_token token", false)] + [InlineData(null, "token", false)] + [InlineData("QUERY", null, false)] + [InlineData("FRAGMENT", null, false)] + [InlineData("FORM_POST", null, false)] + [InlineData(null, "CODE", false)] + [InlineData(null, "CODE ID_TOKEN", false)] + [InlineData(null, "CODE ID_TOKEN TOKEN", false)] + [InlineData(null, "CODE TOKEN", false)] + [InlineData(null, "ID_TOKEN", false)] + [InlineData(null, "ID_TOKEN TOKEN", false)] + [InlineData(null, "TOKEN", false)] + public void IsQueryResponseMode_ReturnsExpectedResult(string mode, string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseMode = mode, + ResponseType = type + }; + + // Act and assert + Assert.Equal(result, request.IsQueryResponseMode()); + } + + [Fact] + public void IsFormPostResponseMode_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsFormPostResponseMode()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("query", false)] + [InlineData("fragment", false)] + [InlineData("form_post", true)] + [InlineData("form_post ", false)] + [InlineData(" form_post", false)] + [InlineData(" form_post ", false)] + [InlineData("QUERY", false)] + [InlineData("FRAGMENT", false)] + [InlineData("FORM_POST", false)] + public void IsFormPostResponseMode_ReturnsExpectedResult(string mode, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + ResponseMode = mode + }; + + // Act and assert + Assert.Equal(result, request.IsFormPostResponseMode()); + } + + [Fact] + public void IsAuthorizationCodeGrantType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsAuthorizationCodeGrantType()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("authorization_code", true)] + [InlineData("authorization_code ", false)] + [InlineData(" authorization_code", false)] + [InlineData(" authorization_code ", false)] + [InlineData("client_credentials", false)] + [InlineData("password", false)] + [InlineData("refresh_token", false)] + [InlineData("AUTHORIZATION_CODE", false)] + [InlineData("CLIENT_CREDENTIALS", false)] + [InlineData("PASSWORD", false)] + [InlineData("REFRESH_TOKEN", false)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code", false)] + public void IsAuthorizationCodeGrantType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + GrantType = type + }; + + // Act and assert + Assert.Equal(result, request.IsAuthorizationCodeGrantType()); + } + + [Fact] + public void IsClientCredentialsGrantType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsClientCredentialsGrantType()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("authorization_code", false)] + [InlineData("client_credentials", true)] + [InlineData("client_credentials ", false)] + [InlineData(" client_credentials", false)] + [InlineData(" client_credentials ", false)] + [InlineData("password", false)] + [InlineData("refresh_token", false)] + [InlineData("AUTHORIZATION_CODE", false)] + [InlineData("CLIENT_CREDENTIALS", false)] + [InlineData("PASSWORD", false)] + [InlineData("REFRESH_TOKEN", false)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code", false)] + public void IsClientCredentialsGrantType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + GrantType = type + }; + + // Act and assert + Assert.Equal(result, request.IsClientCredentialsGrantType()); + } + + [Fact] + public void IsDeviceCodeGrantType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest)null; + + // Act and assert + var exception = Assert.Throws(() => request.IsDeviceCodeGrantType()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("authorization_code", false)] + [InlineData("client_credentials", false)] + [InlineData("password", false)] + [InlineData("refresh_token", false)] + [InlineData("AUTHORIZATION_CODE", false)] + [InlineData("CLIENT_CREDENTIALS", false)] + [InlineData("PASSWORD", false)] + [InlineData("REFRESH_TOKEN", false)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code", true)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code ", false)] + [InlineData(" urn:ietf:params:oauth:grant-type:device_code", false)] + [InlineData(" urn:ietf:params:oauth:grant-type:device_code ", false)] + public void IsDeviceCodeGrantType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + GrantType = type + }; + + // Act and assert + Assert.Equal(result, request.IsDeviceCodeGrantType()); + } + + [Fact] + public void IsPasswordGrantType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsPasswordGrantType()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("authorization_code", false)] + [InlineData("client_credentials", false)] + [InlineData("password", true)] + [InlineData("password ", false)] + [InlineData(" password", false)] + [InlineData(" password ", false)] + [InlineData("refresh_token", false)] + [InlineData("AUTHORIZATION_CODE", false)] + [InlineData("CLIENT_CREDENTIALS", false)] + [InlineData("PASSWORD", false)] + [InlineData("REFRESH_TOKEN", false)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code", false)] + public void IsPasswordGrantType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + GrantType = type + }; + + // Act and assert + Assert.Equal(result, request.IsPasswordGrantType()); + } + + [Fact] + public void IsRefreshTokenGrantType_ThrowsAnExceptionForNullRequest() + { + // Arrange + var request = (OpenIddictRequest) null; + + // Act and assert + var exception = Assert.Throws(() => request.IsRefreshTokenGrantType()); + + Assert.Equal("request", exception.ParamName); + } + + [Theory] + [InlineData(null, false)] + [InlineData("unknown", false)] + [InlineData("authorization_code", false)] + [InlineData("client_credentials", false)] + [InlineData("password", false)] + [InlineData("refresh_token", true)] + [InlineData("refresh_token ", false)] + [InlineData(" refresh_token", false)] + [InlineData(" refresh_token ", false)] + [InlineData("AUTHORIZATION_CODE", false)] + [InlineData("CLIENT_CREDENTIALS", false)] + [InlineData("PASSWORD", false)] + [InlineData("REFRESH_TOKEN", false)] + [InlineData("urn:ietf:params:oauth:grant-type:device_code", false)] + public void IsRefreshTokenGrantType_ReturnsExpectedResult(string type, bool result) + { + // Arrange + var request = new OpenIddictRequest + { + GrantType = type + }; + + // Act and assert + Assert.Equal(result, request.IsRefreshTokenGrantType()); + } + } +} diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs new file mode 100644 index 00000000..034f9634 --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictMessageTests.cs @@ -0,0 +1,450 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIddictMessageTests + { + [Fact] + public void Constructor_ImportsParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair("parameter", 42) + }); + + // Assert + Assert.Equal(42, (long) message.GetParameter("parameter")); + } + + [Fact] + public void Constructor_IgnoresNamelessParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair(null, new OpenIddictParameter()), + new KeyValuePair(string.Empty, new OpenIddictParameter()) + }); + + // Assert + Assert.Empty(message.GetParameters()); + } + + [Fact] + public void Constructor_PreservesEmptyParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair("null-parameter", (string) null), + new KeyValuePair("empty-parameter", string.Empty) + }); + + // Assert + Assert.Equal(2, message.GetParameters().Count()); + } + + [Fact] + public void Constructor_IgnoresDuplicateParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair("parameter", "Fabrikam"), + new KeyValuePair("parameter", "Contoso") + }); + + // Assert + Assert.Single(message.GetParameters()); + Assert.Equal("Fabrikam", message.GetParameter("parameter")); + } + + [Fact] + public void Constructor_SupportsMultiValuedParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair("parameter", new[] { "Fabrikam", "Contoso" }) + }); + + // Assert + Assert.Single(message.GetParameters()); + Assert.Equal(new[] { "Fabrikam", "Contoso" }, (string[]) message.GetParameter("parameter")); + } + + [Fact] + public void Constructor_ExtractsSingleValuedParameters() + { + // Arrange and act + var message = new OpenIddictMessage(new[] + { + new KeyValuePair("parameter", new[] { "Fabrikam" }) + }); + + // Assert + Assert.Single(message.GetParameters()); + Assert.Equal("Fabrikam", message.GetParameter("parameter")?.Value); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void AddParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + var exception = Assert.Throws(() => + { + message.AddParameter(name, new OpenIddictParameter()); + }); + + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void AddParameter_AddsExpectedParameter() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.AddParameter("parameter", 42); + + // Assert + Assert.Equal(42, message.GetParameter("parameter")); + } + + [Fact] + public void AddParameter_IsCaseSensitive() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.AddParameter("PARAMETER", 42); + + // Assert + Assert.Null(message.GetParameter("parameter")); + } + + [Fact] + public void AddParameter_PreservesEmptyParameters() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.AddParameter("string", string.Empty); + message.AddParameter("array", new JArray()); + message.AddParameter("object", new JObject()); + message.AddParameter("value", new JValue(string.Empty)); + + // Assert + Assert.Empty((string) message.GetParameter("string")); + Assert.Equal(new JArray(), (JArray) message.GetParameter("array")); + Assert.Equal(new JObject(), (JObject) message.GetParameter("object")); + Assert.Equal(new JValue(string.Empty), (JValue) message.GetParameter("value")); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void GetParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + var exception = Assert.Throws(() => message.GetParameter(name)); + + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void GetParameter_ReturnsExpectedParameter() + { + // Arrange + var message = new OpenIddictMessage(); + + message.SetParameter("parameter", 42); + + // Act and assert + Assert.Equal(42, (int) message.GetParameter("parameter")); + } + + [Fact] + public void GetParameter_IsCaseSensitive() + { + // Arrange + var message = new OpenIddictMessage(); + + message.SetParameter("parameter", 42); + + // Act and assert + Assert.Null(message.GetParameter("PARAMETER")); + } + + [Fact] + public void GetParameter_ReturnsNullForUnsetParameter() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + Assert.Null(message.GetParameter("parameter")); + } + + [Fact] + public void GetParameters_EnumeratesParameters() + { + // Arrange + var parameters = new Dictionary + { + ["int"] = int.MaxValue, + ["long"] = long.MaxValue, + ["string"] = "value" + }; + + var message = new OpenIddictMessage(parameters); + + // Act and assert + Assert.Equal(parameters, message.GetParameters()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void HasParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + var exception = Assert.Throws(() => message.HasParameter(name)); + + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Theory] + [InlineData("parameter", true)] + [InlineData("PARAMETER", false)] + [InlineData("missing_parameter", false)] + public void HasParameter_ReturnsExpectedResult(string parameter, bool result) + { + // Arrange + var message = new OpenIddictMessage(); + + message.SetParameter("parameter", "value"); + + // Act and assert + Assert.Equal(result, message.HasParameter(parameter)); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RemoveParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + var exception = Assert.Throws(() => message.RemoveParameter(name)); + + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void RemoveParameter_RemovesExpectedParameter() + { + // Arrange + var message = new OpenIddictMessage(); + message.AddParameter("parameter", 42); + + // Act + message.RemoveParameter("parameter"); + + // Assert + Assert.Null(message.GetParameter("parameter")); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void SetParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act and assert + var exception = Assert.Throws(() => message.SetParameter(name, null)); + + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void SetParameter_AddsExpectedParameter() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.SetParameter("parameter", 42); + + // Assert + Assert.Equal(42, message.GetParameter("parameter")); + } + + [Fact] + public void SetParameter_IsCaseSensitive() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.SetParameter("PARAMETER", 42); + + // Assert + Assert.Null(message.GetParameter("parameter")); + } + + [Fact] + public void SetParameter_RemovesNullParameters() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.SetParameter("null", null); + + // Assert + Assert.Empty(message.GetParameters()); + } + + [Fact] + public void SetParameter_RemovesEmptyParameters() + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + message.SetParameter("string", string.Empty); + message.SetParameter("array", new JArray()); + message.SetParameter("object", new JObject()); + message.SetParameter("value", new JValue(string.Empty)); + + // Assert + Assert.Empty(message.GetParameters()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void TryGetParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var message = new OpenIddictMessage(); + + // Act + var exception = Assert.Throws(() => message.TryGetParameter(name, out OpenIddictParameter parameter)); + + // Assert + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void TryGetParameter_ReturnsTrueAndExpectedParameter() + { + // Arrange + var name = "paramName"; + var val = "paramValue"; + var message = new OpenIddictMessage(); + message.SetParameter(name, val); + + // Act + var success = message.TryGetParameter(name, out OpenIddictParameter parameter); + + // Assert + Assert.True(success); + Assert.Equal(val, (string)parameter.Value); + } + + [Fact] + public void TryGetParameter_ReturnsFalse() + { + // Arrange + var name = "paramName"; + var message = new OpenIddictMessage(); + + // Act + var success = message.TryGetParameter(name, out OpenIddictParameter parameter); + + // Assert + Assert.False(success); + Assert.Null(parameter.Value); + } + + [Fact] + public void ToString_ReturnsJsonRepresentation() + { + // Arrange + var message = JsonConvert.DeserializeObject(@"{ + ""redirect_uris"": [ + ""https://client.example.org/callback"", + ""https://client.example.org/callback2"" + ], + ""client_name"": ""My Example Client"", + ""token_endpoint_auth_method"": ""client_secret_basic"", + ""logo_uri"": ""https://client.example.org/logo.png"", + ""jwks_uri"": ""https://client.example.org/my_public_keys.jwks"", + ""example_extension_parameter"": ""example_value"" +}"); + + // Act and assert + Assert.Equal(JsonConvert.SerializeObject(message, Formatting.Indented), message.ToString()); + } + + [Theory] + [InlineData(OpenIddictConstants.Parameters.AccessToken)] + [InlineData(OpenIddictConstants.Parameters.Assertion)] + [InlineData(OpenIddictConstants.Parameters.ClientAssertion)] + [InlineData(OpenIddictConstants.Parameters.ClientSecret)] + [InlineData(OpenIddictConstants.Parameters.Code)] + [InlineData(OpenIddictConstants.Parameters.IdToken)] + [InlineData(OpenIddictConstants.Parameters.IdTokenHint)] + [InlineData(OpenIddictConstants.Parameters.Password)] + [InlineData(OpenIddictConstants.Parameters.RefreshToken)] + [InlineData(OpenIddictConstants.Parameters.Token)] + public void ToString_ExcludesSensitiveParameters(string parameter) + { + // Arrange + var message = new OpenIddictMessage(); + message.AddParameter(parameter, "secret value"); + + // Act and assert + Assert.DoesNotContain("secret value", message.ToString()); + Assert.Equal("[removed for security reasons]", JObject.Parse(message.ToString())[parameter]); + } + } +} diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs new file mode 100644 index 00000000..8b133c88 --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs @@ -0,0 +1,1026 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIddictParameterTests + { + [Fact] + public void Equals_ReturnsTrueWhenBothParametersAreNull() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act and assert + Assert.True(parameter.Equals(new OpenIddictParameter())); + } + + [Fact] + public void Equals_ReturnsTrueWhenReferencesAreIdentical() + { + // Arrange + var value = new JObject(); + var parameter = new OpenIddictParameter(value); + + // Act and assert + Assert.True(parameter.Equals(new OpenIddictParameter(value))); + } + + [Fact] + public void Equals_ReturnsFalseWhenCurrentValueIsNull() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act and assert + Assert.False(parameter.Equals(new OpenIddictParameter(42))); + } + + [Fact] + public void Equals_ReturnsFalseWhenOtherValueIsNull() + { + // Arrange + var parameter = new OpenIddictParameter(42); + + // Act and assert + Assert.False(parameter.Equals(new OpenIddictParameter())); + } + + [Fact] + public void Equals_ReturnsFalseForDifferentTypes() + { + // Arrange, act and assert + Assert.False(new OpenIddictParameter(true).Equals(new OpenIddictParameter("true"))); + Assert.False(new OpenIddictParameter("true").Equals(new OpenIddictParameter(true))); + + Assert.False(new OpenIddictParameter("42").Equals(new OpenIddictParameter(42))); + Assert.False(new OpenIddictParameter(42).Equals(new OpenIddictParameter("42"))); + + Assert.False(new OpenIddictParameter(new JObject()).Equals(new OpenIddictParameter(new JArray()))); + Assert.False(new OpenIddictParameter(new JArray()).Equals(new OpenIddictParameter(new JObject()))); + } + + [Fact] + public void Equals_UsesSequenceEqualForArrays() + { + // Arrange + var parameter = new OpenIddictParameter(new[] { "Fabrikam", "Contoso" }); + + // Act and assert + Assert.True(parameter.Equals(new string[] { "Fabrikam", "Contoso" })); + Assert.False(parameter.Equals(new string[] { "Contoso", "Fabrikam" })); + } + + [Fact] + public void Equals_UsesDeepEqualsForJsonArrays() + { + // Arrange + var parameter = new OpenIddictParameter(new JArray(new[] { 0, 1, 2, 3 })); + + // Act and assert + Assert.True(parameter.Equals(new JArray(new[] { 0, 1, 2, 3 }))); + Assert.False(parameter.Equals(new JArray())); + Assert.False(parameter.Equals(new JArray(new[] { 0, 1, 2 }))); + Assert.False(parameter.Equals(new JArray(new[] { 3, 2, 1, 0 }))); + } + + [Fact] + public void Equals_UsesDeepEqualsForJsonObjects() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject + { + ["field"] = new JArray(new[] { 0, 1, 2, 3 }) + }); + + // Act and assert + Assert.True(parameter.Equals(new JObject + { + ["field"] = new JArray(new[] { 0, 1, 2, 3 }) + })); + + Assert.False(parameter.Equals(new JObject())); + + Assert.False(parameter.Equals(new JObject + { + ["field"] = "value" + })); + + Assert.False(parameter.Equals(new JObject + { + ["field"] = new JArray(new[] { 0, 1, 2 }) + })); + } + + [Fact] + public void Equals_ComparesUnderlyingValuesForJsonValues() + { + // Arrange + var value = new JValue(42); + var parameter = new OpenIddictParameter(value); + + // Act and assert + Assert.True(parameter.Equals(new OpenIddictParameter(42))); + Assert.False(parameter.Equals(new OpenIddictParameter(100))); + } + + [Fact] + public void Equals_SupportsNullJsonValues() + { + // Arrange + var parameter = new OpenIddictParameter(42); + + // Act and assert + Assert.False(parameter.Equals(new OpenIddictParameter(new JValue((long?) null)))); + } + + [Fact] + public void Equals_SupportsJsonValues() + { + // Arrange + var parameter = new OpenIddictParameter(42); + + // Act and assert + Assert.True(parameter.Equals(new OpenIddictParameter(new JValue(42)))); + Assert.False(parameter.Equals(new OpenIddictParameter(new JValue(100)))); + } + + [Fact] + public void Equals_ReturnsFalseForNonParameters() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act and assert + Assert.False(parameter.Equals(new object())); + } + + [Fact] + public void GetHashCode_ReturnsZeroForNullValues() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act and assert + Assert.Equal(0, parameter.GetHashCode()); + } + + [Fact] + public void GetHashCode_ReturnsHashCodeValue() + { + // Arrange + var value = "Fabrikam"; + var parameter = new OpenIddictParameter(value); + + // Act and assert + Assert.Equal(value.GetHashCode(), parameter.GetHashCode()); + } + + [Fact] + public void GetHashCode_ReturnsUnderlyingJsonValueHashCode() + { + // Arrange + var value = "Fabrikam"; + var parameter = new OpenIddictParameter(new JValue(value)); + + // Act and assert + Assert.Equal(value.GetHashCode(), parameter.GetHashCode()); + } + + [Fact] + public void GetParameter_ThrowsAnExceptionForNegativeIndex() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act + var exception = Assert.Throws(() => parameter.GetParameter(-1)); + + // Assert + Assert.Equal("index", exception.ParamName); + Assert.StartsWith("The item index cannot be negative.", exception.Message); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void GetParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act + var exception = Assert.Throws(() => parameter.GetParameter(name)); + + // Assert + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The item name cannot be null or empty.", exception.Message); + } + + [Fact] + public void GetParameter_ReturnsNullForPrimitiveValues() + { + // Arrange + var parameter = new OpenIddictParameter(42); + + // Act and assert + Assert.Null(parameter.GetParameter(0)); + Assert.Null(parameter.GetParameter("parameter")); + } + + [Fact] + public void GetParameter_ReturnsNullForOutOfRangeArrayIndex() + { + // Arrange + var parameter = new OpenIddictParameter(new[] + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Null(parameter.GetParameter(2)); + } + + [Fact] + public void GetParameter_ReturnsNullForArrays() + { + // Arrange + var parameter = new OpenIddictParameter(new[] + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Null(parameter.GetParameter("Fabrikam")); + } + + [Fact] + public void GetParameter_ReturnsNullForOutOfRangeJsonArrayIndex() + { + // Arrange + var parameter = new OpenIddictParameter(new JArray + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Null(parameter.GetParameter(2)); + } + + [Fact] + public void GetParameter_ReturnsNullForNonexistentItem() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject()); + + // Act and assert + Assert.Null(parameter.GetParameter("parameter")); + } + + [Fact] + public void GetParameter_ReturnsNullForJsonArrays() + { + // Arrange + var parameter = new OpenIddictParameter(new JArray + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Null(parameter.GetParameter("Fabrikam")); + } + + [Fact] + public void GetParameter_ReturnsNullForJsonObjects() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject + { + ["parameter"] = new JValue("value") + }); + + // Act and assert + Assert.Null(parameter.GetParameter(0)); + } + + [Fact] + public void GetParameter_ReturnsNullForNullJsonObjects() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject + { + ["property"] = null + }); + + // Act and assert + Assert.Null(parameter.GetParameter(0)); + Assert.Null(parameter.GetParameter("parameter")); + } + + [Fact] + public void GetParameter_ReturnsExpectedNodeForArray() + { + // Arrange + var parameter = new OpenIddictParameter(new[] + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Equal("Fabrikam", (string) parameter.GetParameter(0)); + } + + [Fact] + public void GetParameter_ReturnsExpectedParameterForJsonObject() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject + { + ["parameter"] = new JValue("value") + }); + + // Act and assert + Assert.Equal("value", (string) parameter.GetParameter("parameter")); + } + + [Fact] + public void GetParameter_ReturnsExpectedNodeForJsonArray() + { + // Arrange + var parameter = new OpenIddictParameter(new JArray + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Equal("Fabrikam", (string) parameter.GetParameter(0)); + } + + [Fact] + public void GetParameters_ReturnsEmptyEnumerationForPrimitiveValues() + { + // Arrange + var parameter = new OpenIddictParameter(42); + + // Act and assert + Assert.Empty(parameter.GetParameters()); + } + + [Fact] + public void GetParameters_ReturnsExpectedParametersForArrays() + { + // Arrange + var parameters = new[] + { + "Fabrikam", + "Contoso" + }; + + var parameter = new OpenIddictParameter(parameters); + + // Act and assert + Assert.Equal(parameters, from element in parameter.GetParameters() + select (string) element.Value); + } + + [Fact] + public void GetParameters_ReturnsEmptyEnumerationForJsonValues() + { + // Arrange + var parameter = new OpenIddictParameter(new JValue(42)); + + // Act and assert + Assert.Empty(parameter.GetParameters()); + } + + [Fact] + public void GetParameters_ReturnsNullKeysForJsonArrays() + { + // Arrange + var parameters = new[] + { + "Fabrikam", + "Contoso" + }; + + var parameter = new OpenIddictParameter(new JArray(parameters)); + + // Act and assert + Assert.All(from element in parameter.GetParameters() + select element.Key, key => Assert.Null(key)); + } + + [Fact] + public void GetParameters_ReturnsExpectedParametersForJsonArrays() + { + // Arrange + var parameters = new[] + { + "Fabrikam", + "Contoso" + }; + + var parameter = new OpenIddictParameter(new JArray(parameters)); + + // Act and assert + Assert.Equal(parameters, from element in parameter.GetParameters() + select (string) element.Value); + } + + [Fact] + public void GetParameters_ReturnsExpectedParametersForJsonObjects() + { + // Arrange + var parameters = new Dictionary + { + ["parameter"] = "value" + }; + + var parameter = new OpenIddictParameter(JObject.FromObject(parameters)); + + // Act and assert + Assert.Equal(parameters, parameter.GetParameters().ToDictionary(pair => pair.Key, pair => (string) pair.Value)); + } + + [Fact] + public void IsNullOrEmpty_ReturnsTrueForNullValues() + { + // Arrange, act and assert + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((bool?) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((long?) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((string) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((string[]) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((JArray) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((JObject) null))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((JValue) null))); + } + + [Fact] + public void IsNullOrEmpty_ReturnsTrueForEmptyValues() + { + // Arrange, act and assert + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(string.Empty))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new string[0]))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JArray()))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JObject()))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JValue(string.Empty)))); + } + + [Fact] + public void IsNullOrEmpty_ReturnsFalseForNonEmptyValues() + { + // Arrange, act and assert + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(true))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((bool?) true))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(42))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((long?) 42))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter("Fabrikam"))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new[] { "Fabrikam" }))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JArray("Fabrikam")))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JObject { ["property"] = "value" }))); + Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new JValue("Fabrikam")))); + } + + [Fact] + public void ToString_ReturnsEmptyStringForNullValues() + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act and assert + Assert.Empty(parameter.ToString()); + } + + [Fact] + public void ToString_ReturnsStringValue() + { + // Arrange + var parameter = new OpenIddictParameter("Fabrikam"); + + // Act and assert + Assert.Equal("Fabrikam", parameter.ToString()); + } + + [Fact] + public void ToString_ReturnsSimpleRepresentationForArrays() + { + // Arrange + var parameter = new OpenIddictParameter(new[] + { + "Fabrikam", + "Contoso" + }); + + // Act and assert + Assert.Equal("Fabrikam, Contoso", parameter.ToString()); + } + + [Fact] + public void ToString_ReturnsJsonRepresentation() + { + // Arrange + var parameter = new OpenIddictParameter(new JObject + { + ["parameter"] = new JValue("value") + }); + + // Act and assert + Assert.Equal(@"{""parameter"":""value""}", parameter.ToString()); + } + + [Fact] + public void ToString_ReturnsEmptyStringForNullJsonValues() + { + // Arrange + var parameter = new OpenIddictParameter(new JValue((object) null)); + + // Act and assert + Assert.Empty(parameter.ToString()); + } + + [Fact] + public void ToString_ReturnsUnderlyingJsonValue() + { + // Arrange + var parameter = new OpenIddictParameter(new JValue("Fabrikam")); + + // Act and assert + Assert.Equal("Fabrikam", parameter.ToString()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void TryGetParameter_ThrowsAnExceptionForNullOrEmptyName(string name) + { + // Arrange + var parameter = new OpenIddictParameter(); + + // Act + var exception = Assert.Throws(() => parameter.TryGetParameter(name, out OpenIddictParameter val)); + + // Assert + Assert.Equal("name", exception.ParamName); + Assert.StartsWith("The parameter name cannot be null or empty.", exception.Message); + } + + [Fact] + public void TryGetParameter_ReturnsTrueAndExpectedParameter() + { + // Arrange + var name = "paramName"; + var val = new JValue("paramValue"); + var parameter = new OpenIddictParameter(new JObject + { + [name] = val + }); + + // Act + var success = parameter.TryGetParameter(name, out OpenIddictParameter expectedParameter); + + // Assert + Assert.True(success); + Assert.Equal(val, expectedParameter.Value); + } + + [Fact] + public void TryGetParameter_ReturnsFalse() + { + // Arrange + var name = "paramName"; + var parameter = new OpenIddictParameter(); + + // Act + var success = parameter.TryGetParameter(name, out OpenIddictParameter val); + + // Assert + Assert.False(success); + Assert.Null(val.Value); + } + + [Fact] + public void BoolConverter_CanCreateParameterFromBooleanValue() + { + // Arrange, act and assert + Assert.True((bool) new OpenIddictParameter(true).Value); + Assert.True((bool) new OpenIddictParameter((bool?) true).Value); + + Assert.False((bool) new OpenIddictParameter(false).Value); + Assert.False((bool) new OpenIddictParameter((bool?) false).Value); + } + + [Fact] + public void BoolConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.False((bool) new OpenIddictParameter()); + Assert.False((bool) (OpenIddictParameter?) null); + + Assert.Null((bool?) new OpenIddictParameter()); + Assert.Null((bool?) (OpenIddictParameter?) null); + } + + [Fact] + public void BoolConverter_ReturnsDefaultValueForUnsupportedPrimitiveValues() + { + // Arrange, act and assert + Assert.False((bool) new OpenIddictParameter("Fabrikam")); + Assert.Null((bool?) new OpenIddictParameter("Fabrikam")); + } + + [Fact] + public void BoolConverter_ReturnsDefaultValueForUnsupportedArrays() + { + // Arrange, act and assert + Assert.False((bool) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + Assert.Null((bool?) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + } + + [Fact] + public void BoolConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.False((bool) new OpenIddictParameter(new JArray())); + Assert.Null((bool?) new OpenIddictParameter(new JArray())); + } + + [Fact] + public void BoolConverter_CanConvertFromPrimitiveValues() + { + // Arrange, act and assert + Assert.True((bool) new OpenIddictParameter(true)); + Assert.True((bool?) new OpenIddictParameter(true)); + Assert.True((bool) new OpenIddictParameter("true")); + Assert.True((bool?) new OpenIddictParameter("true")); + + Assert.False((bool) new OpenIddictParameter(false)); + Assert.False((bool?) new OpenIddictParameter(false)); + Assert.False((bool) new OpenIddictParameter("false")); + Assert.False((bool?) new OpenIddictParameter("false")); + } + + [Fact] + public void BoolConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.True((bool) new OpenIddictParameter(new JValue(true))); + Assert.True((bool?) new OpenIddictParameter(new JValue(true))); + Assert.True((bool) new OpenIddictParameter(new JValue("true"))); + Assert.True((bool?) new OpenIddictParameter(new JValue("true"))); + + Assert.False((bool) new OpenIddictParameter(new JValue(false))); + Assert.False((bool?) new OpenIddictParameter(new JValue(false))); + Assert.False((bool) new OpenIddictParameter(new JValue("false"))); + Assert.False((bool?) new OpenIddictParameter(new JValue("false"))); + } + + [Fact] + public void JArrayConverter_CanCreateParameterFromJArrayValue() + { + // Arrange + var array = new JArray("Fabrikam", "Contoso"); + + // Act + var parameter = new OpenIddictParameter(array); + + // Assert + Assert.Same(array, parameter.Value); + } + + [Fact] + public void JArrayConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Null((JArray) new OpenIddictParameter()); + Assert.Null((JArray) (OpenIddictParameter?) null); + } + + [Fact] + public void JArrayConverter_ReturnsDefaultValueForUnsupportedPrimitiveValues() + { + // Arrange, act and assert + Assert.Null((JArray) new OpenIddictParameter("Fabrikam")); + } + + [Fact] + public void JArrayConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Null((JArray) new OpenIddictParameter(new JObject())); + } + + [Fact] + public void JArrayConverter_ReturnsDefaultValueForUnsupportedSerializedJson() + { + // Arrange, act and assert + Assert.Null((JArray) new OpenIddictParameter(@"{""Property"":""value""}")); + Assert.Null((JArray) new OpenIddictParameter("[")); + } + + [Fact] + public void JArrayConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal(new JArray("Contoso", "Fabrikam"), (JArray) new OpenIddictParameter(new JArray("Contoso", "Fabrikam"))); + } + + [Fact] + public void JArrayConverter_CanConvertFromSerializedJson() + { + // Arrange, act and assert + Assert.Equal(new JArray("Contoso", "Fabrikam"), (JArray) new OpenIddictParameter(@"[""Contoso"",""Fabrikam""]")); + } + + [Fact] + public void JArrayConverter_CanConvertFromArrays() + { + // Arrange, act and assert + Assert.Equal(new JArray("Contoso", "Fabrikam"), (JArray) new OpenIddictParameter(new[] { "Contoso", "Fabrikam" })); + } + + [Fact] + public void JObjectConverter_CanCreateParameterFromJObjectValue() + { + // Arrange + var value = JObject.FromObject(new { Property = "value" }); + + // Act + var parameter = new OpenIddictParameter(value); + + // Assert + Assert.Same(value, parameter.Value); + } + + [Fact] + public void JObjectConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Null((JObject) new OpenIddictParameter()); + Assert.Null((JObject) (OpenIddictParameter?) null); + } + + [Fact] + public void JObjectConverter_ReturnsDefaultValueForUnsupportedPrimitiveValues() + { + // Arrange, act and assert + Assert.Null((JObject) new OpenIddictParameter("Fabrikam")); + } + + [Fact] + public void JObjectConverter_ReturnsDefaultValueForUnsupportedArrays() + { + // Arrange, act and assert + Assert.Null((JObject) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + } + + [Fact] + public void JObjectConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Null((JObject) new OpenIddictParameter(new JArray())); + } + + [Fact] + public void JObjectConverter_ReturnsDefaultValueForUnsupportedSerializedJson() + { + // Arrange, act and assert + Assert.Null((JObject) new OpenIddictParameter(@"[""Fabrikam"",""Contoso""]")); + Assert.Null((JObject) new OpenIddictParameter("{")); + } + + [Fact] + public void JObjectConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal(JObject.FromObject(new { Property = "value" }), (JObject) new OpenIddictParameter(JObject.FromObject(new { Property = "value" }))); + } + + [Fact] + public void JObjectConverter_CanConvertFromSerializedJson() + { + // Arrange, act and assert + Assert.Equal(JObject.FromObject(new { Property = "value" }), (JObject) new OpenIddictParameter(@"{""Property"":""value""}")); + } + + [Fact] + public void JValueConverter_CanCreateParameterFromJValueValue() + { + // Arrange + var value = new JValue("Fabrikam"); + + // Act + var parameter = new OpenIddictParameter(value); + + // Assert + Assert.Same(value, parameter.Value); + } + + [Fact] + public void JValueConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Null((JValue) new OpenIddictParameter()); + Assert.Null((JValue) (OpenIddictParameter?) null); + } + + [Fact] + public void JValueConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Null((JValue) new OpenIddictParameter(new JArray())); + } + + [Fact] + public void JValueConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal(new JValue(true), (JValue) new OpenIddictParameter(new JValue(true))); + Assert.Equal(new JValue(42), (JValue) new OpenIddictParameter(new JValue(42))); + Assert.Equal(new JValue("Fabrikam"), (JValue) new OpenIddictParameter(new JValue("Fabrikam"))); + } + + [Fact] + public void LongConverter_CanCreateParameterFromLongValue() + { + // Arrange, act and assert + Assert.Equal(42, (long) new OpenIddictParameter(42).Value); + Assert.Equal(42, (long) new OpenIddictParameter((long?) 42).Value); + } + + [Fact] + public void LongConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Equal(0, (long) new OpenIddictParameter()); + Assert.Null((long?) new OpenIddictParameter()); + } + + [Fact] + public void LongConverter_ReturnsDefaultValueForUnsupportedPrimitiveValues() + { + // Arrange, act and assert + Assert.Equal(0, (long) new OpenIddictParameter("Fabrikam")); + Assert.Null((long?) new OpenIddictParameter("Fabrikam")); + } + + [Fact] + public void LongConverter_ReturnsDefaultValueForUnsupportedArrays() + { + // Arrange, act and assert + Assert.Equal(0, (long) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + Assert.Null((long?) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + } + + [Fact] + public void LongConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Equal(0, (long) new OpenIddictParameter(new JArray())); + Assert.Null((long?) new OpenIddictParameter(new JArray())); + } + + [Fact] + public void LongConverter_CanConvertFromPrimitiveValues() + { + // Arrange, act and assert + Assert.Equal(42, (long) new OpenIddictParameter(42)); + Assert.Equal(42, (long?) new OpenIddictParameter(42)); + Assert.Equal(42, (long) new OpenIddictParameter(42)); + Assert.Equal(42, (long?) new OpenIddictParameter(42)); + } + + [Fact] + public void LongConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42))); + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42))); + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42f))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42f))); + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42f))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42f))); + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42m))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42m))); + Assert.Equal(42, (long) new OpenIddictParameter(new JValue(42m))); + Assert.Equal(42, (long?) new OpenIddictParameter(new JValue(42m))); + } + + [Fact] + public void StringConverter_CanCreateParameterFromStringValue() + { + // Arrange, act and assert + Assert.Equal("Fabrikam", (string) new OpenIddictParameter("Fabrikam").Value); + } + + [Fact] + public void StringConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Null((string) new OpenIddictParameter()); + Assert.Null((string) (OpenIddictParameter?) null); + } + + [Fact] + public void StringConverter_ReturnsDefaultValueForArrays() + { + // Arrange, act and assert + Assert.Null((string) new OpenIddictParameter(new[] { "Fabrikam", "Contoso" })); + } + + [Fact] + public void StringConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Null((string) new OpenIddictParameter(new JArray())); + } + + [Fact] + public void StringConverter_CanConvertFromPrimitiveValues() + { + // Arrange, act and assert + Assert.Equal("Fabrikam", (string) new OpenIddictParameter("Fabrikam")); + Assert.Equal("False", (string) new OpenIddictParameter(false)); + Assert.Equal("42", (string) new OpenIddictParameter(42)); + } + + [Fact] + public void StringConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal("Fabrikam", (string) new OpenIddictParameter(new JValue("Fabrikam"))); + Assert.Equal("False", (string) new OpenIddictParameter(new JValue(false))); + Assert.Equal("42", (string) new OpenIddictParameter(new JValue(42))); + } + + [Fact] + public void StringArrayConverter_CanCreateParameterFromArray() + { + // Arrange + var array = new[] { "Fabrikam", "Contoso" }; + + // Act + var parameter = new OpenIddictParameter(array); + + // Assert + Assert.Same(array, parameter.Value); + } + + [Fact] + public void StringArrayConverter_CanCreateParameterFromPrimitiveValues() + { + // Arrange, act and assert + Assert.Equal(new[] { "Fabrikam" }, (string[]) new OpenIddictParameter("Fabrikam")); + Assert.Equal(new[] { "False" }, (string[]) new OpenIddictParameter(false)); + Assert.Equal(new[] { "42" }, (string[]) new OpenIddictParameter(42)); + } + + [Fact] + public void StringArrayConverter_ReturnsDefaultValueForNullValues() + { + // Arrange, act and assert + Assert.Null((string[]) new OpenIddictParameter()); + } + + [Fact] + public void StringArrayConverter_ReturnsSingleElementArrayForStringValue() + { + // Arrange, act and assert + Assert.Equal(new[] { "Fabrikam" }, (string[]) new OpenIddictParameter("Fabrikam")); + } + + [Fact] + public void StringArrayConverter_ReturnsDefaultValueForUnsupportedJsonValues() + { + // Arrange, act and assert + Assert.Null((string[]) new OpenIddictParameter(new JObject())); + } + + [Fact] + public void StringArrayConverter_CanConvertFromJsonValues() + { + // Arrange, act and assert + Assert.Equal(new[] { "Fabrikam" }, (string[]) new OpenIddictParameter(new JValue("Fabrikam"))); + Assert.Equal(new[] { "False" }, (string[]) new OpenIddictParameter(new JValue(false))); + Assert.Equal(new[] { "42" }, (string[]) new OpenIddictParameter(new JValue(42))); + Assert.Equal(new[] { "Fabrikam" }, (string[]) new OpenIddictParameter(new JArray("Fabrikam"))); + Assert.Equal(new[] { "Fabrikam", "Contoso" }, (string[]) new OpenIddictParameter(new JArray(new[] { "Fabrikam", "Contoso" }))); + } + } +} diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictRequestTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictRequestTests.cs new file mode 100644 index 00000000..5d06a9ef --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictRequestTests.cs @@ -0,0 +1,334 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIddictRequestTests + { + public static IEnumerable Properties + { + get + { + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.AccessToken), + /* name: */ OpenIddictConstants.Parameters.AccessToken, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.AcrValues), + /* name: */ OpenIddictConstants.Parameters.AcrValues, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Assertion), + /* name: */ OpenIddictConstants.Parameters.Assertion, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Audiences), + /* name: */ OpenIddictConstants.Parameters.Audience, + /* value: */ new OpenIddictParameter(new[] { "Fabrikam", "Contoso" }) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Claims), + /* name: */ OpenIddictConstants.Parameters.Claims, + /* value: */ new OpenIddictParameter(new JObject { ["userinfo"] = new JObject() }) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ClaimsLocales), + /* name: */ OpenIddictConstants.Parameters.ClaimsLocales, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ClientAssertion), + /* name: */ OpenIddictConstants.Parameters.ClientAssertion, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ClientAssertionType), + /* name: */ OpenIddictConstants.Parameters.ClientAssertionType, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ClientId), + /* name: */ OpenIddictConstants.Parameters.ClientId, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ClientSecret), + /* name: */ OpenIddictConstants.Parameters.ClientSecret, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Code), + /* name: */ OpenIddictConstants.Parameters.Code, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.CodeChallenge), + /* name: */ OpenIddictConstants.Parameters.CodeChallenge, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.CodeChallengeMethod), + /* name: */ OpenIddictConstants.Parameters.CodeChallengeMethod, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.CodeVerifier), + /* name: */ OpenIddictConstants.Parameters.CodeVerifier, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.DeviceCode), + /* name: */ OpenIddictConstants.Parameters.DeviceCode, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Display), + /* name: */ OpenIddictConstants.Parameters.Display, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.GrantType), + /* name: */ OpenIddictConstants.Parameters.GrantType, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.IdentityProvider), + /* name: */ OpenIddictConstants.Parameters.IdentityProvider, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.IdTokenHint), + /* name: */ OpenIddictConstants.Parameters.IdTokenHint, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.LoginHint), + /* name: */ OpenIddictConstants.Parameters.LoginHint, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Nonce), + /* name: */ OpenIddictConstants.Parameters.Nonce, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.MaxAge), + /* name: */ OpenIddictConstants.Parameters.MaxAge, + /* value: */ new OpenIddictParameter((long?) 42) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Password), + /* name: */ OpenIddictConstants.Parameters.Password, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.PostLogoutRedirectUri), + /* name: */ OpenIddictConstants.Parameters.PostLogoutRedirectUri, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Prompt), + /* name: */ OpenIddictConstants.Parameters.Prompt, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.RedirectUri), + /* name: */ OpenIddictConstants.Parameters.RedirectUri, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.RefreshToken), + /* name: */ OpenIddictConstants.Parameters.RefreshToken, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Registration), + /* name: */ OpenIddictConstants.Parameters.Registration, + /* value: */ new OpenIddictParameter(new JObject { ["policy_uri"] = "http://www.fabrikam.com/policy" }) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Request), + /* name: */ OpenIddictConstants.Parameters.Request, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.RequestId), + /* name: */ OpenIddictConstants.Parameters.RequestId, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.RequestUri), + /* name: */ OpenIddictConstants.Parameters.RequestUri, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Resources), + /* name: */ OpenIddictConstants.Parameters.Resource, + /* value: */ new OpenIddictParameter(new[] { "https://fabrikam.com/", "https://contoso.com/" }) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ResponseMode), + /* name: */ OpenIddictConstants.Parameters.ResponseMode, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.ResponseType), + /* name: */ OpenIddictConstants.Parameters.ResponseType, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Scope), + /* name: */ OpenIddictConstants.Parameters.Scope, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.State), + /* name: */ OpenIddictConstants.Parameters.State, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Token), + /* name: */ OpenIddictConstants.Parameters.Token, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.TokenTypeHint), + /* name: */ OpenIddictConstants.Parameters.TokenTypeHint, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.UiLocales), + /* name: */ OpenIddictConstants.Parameters.UiLocales, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.UserCode), + /* name: */ OpenIddictConstants.Parameters.UserCode, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictRequest.Username), + /* name: */ OpenIddictConstants.Parameters.Username, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + } + } + + [Theory] + [MemberData(nameof(Properties))] + public void PropertyGetter_ReturnsExpectedParameter(string property, string name, OpenIddictParameter value) + { + // Arrange + var request = new OpenIddictRequest(); + request.SetParameter(name, value); + + // Act and assert + Assert.Equal(value.Value, typeof(OpenIddictRequest).GetProperty(property).GetValue(request)); + } + + [Theory] + [MemberData(nameof(Properties))] + public void PropertySetter_AddsExpectedParameter(string property, string name, OpenIddictParameter value) + { + // Arrange + var request = new OpenIddictRequest(); + + // Act + typeof(OpenIddictRequest).GetProperty(property).SetValue(request, value.Value); + + // Assert + Assert.Equal(value, request.GetParameter(name)); + } + } +} diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictResponseTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictResponseTests.cs new file mode 100644 index 00000000..a96c5596 --- /dev/null +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictResponseTests.cs @@ -0,0 +1,137 @@ +/* + * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + * See https://github.com/openiddict/openiddict-core for more information concerning + * the license and the contributors participating to this project. + */ + +using System.Collections.Generic; +using Xunit; + +namespace OpenIddict.Abstractions.Tests.Primitives +{ + public class OpenIddictResponseTests + { + public static IEnumerable Properties + { + get + { + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.AccessToken), + /* name: */ OpenIddictConstants.Parameters.AccessToken, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.Code), + /* name: */ OpenIddictConstants.Parameters.Code, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.DeviceCode), + /* name: */ OpenIddictConstants.Parameters.DeviceCode, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.Error), + /* name: */ OpenIddictConstants.Parameters.Error, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.ErrorDescription), + /* name: */ OpenIddictConstants.Parameters.ErrorDescription, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.ErrorUri), + /* name: */ OpenIddictConstants.Parameters.ErrorUri, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.ExpiresIn), + /* name: */ OpenIddictConstants.Parameters.ExpiresIn, + /* value: */ new OpenIddictParameter((long?) 42) + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.IdToken), + /* name: */ OpenIddictConstants.Parameters.IdToken, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.RefreshToken), + /* name: */ OpenIddictConstants.Parameters.RefreshToken, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.Scope), + /* name: */ OpenIddictConstants.Parameters.Scope, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.State), + /* name: */ OpenIddictConstants.Parameters.State, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.TokenType), + /* name: */ OpenIddictConstants.Parameters.TokenType, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + + yield return new object[] + { + /* property: */ nameof(OpenIddictResponse.UserCode), + /* name: */ OpenIddictConstants.Parameters.UserCode, + /* value: */ new OpenIddictParameter("802A3E3E-DCCA-4EFC-89FA-7D82FE8C27E4") + }; + } + } + + [Theory] + [MemberData(nameof(Properties))] + public void PropertyGetter_ReturnsExpectedParameter(string property, string name, OpenIddictParameter value) + { + // Arrange + var response = new OpenIddictResponse(); + response.SetParameter(name, value); + + // Act and assert + Assert.Equal(value.Value, typeof(OpenIddictResponse).GetProperty(property).GetValue(response)); + } + + [Theory] + [MemberData(nameof(Properties))] + public void PropertySetter_AddsExpectedParameter(string property, string name, OpenIddictParameter value) + { + // Arrange + var response = new OpenIddictResponse(); + + // Act + typeof(OpenIddictResponse).GetProperty(property).SetValue(response, value.Value); + + // Assert + Assert.Equal(value, response.GetParameter(name)); + } + } +}