From f34d9ccfa729c5367c5169d8461f74df11a5b2fb Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 13 Nov 2020 16:10:12 +0800 Subject: test: Add integrated tests for permission api. --- .../IntegratedTests/UserPermissionTest.cs | 308 +++++++++++++++++++++ BackEnd/Timeline/Controllers/UserController.cs | 4 +- BackEnd/Timeline/GlobalSuppressions.cs | 4 +- .../Resources/Services/UserService.Designer.cs | 4 +- .../Timeline/Resources/Services/UserService.resx | 4 +- BackEnd/Timeline/Services/UserPermissionService.cs | 2 +- 6 files changed, 316 insertions(+), 10 deletions(-) create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs diff --git a/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs new file mode 100644 index 00000000..cf27a6c6 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs @@ -0,0 +1,308 @@ +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http.Json; +using System.Threading.Tasks; +using Timeline.Models.Http; +using Timeline.Services; +using Xunit; + +namespace Timeline.Tests.IntegratedTests +{ + public class UserPermissionTest : IntegratedTestBase + { + public UserPermissionTest() : base(3) { } + + [Fact] + public async Task RootUserShouldReturnAllPermissions() + { + using var client = await CreateDefaultClient(); + var res = await client.GetAsync("users/admin"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); + } + + [Fact] + public async Task NonRootUserShouldReturnNonPermissions() + { + using var client = await CreateDefaultClient(); + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEmpty(); + } + + public static IEnumerable EveryPermissionTestData() + { + return Enum.GetValues().Select(p => new object[] { p }); + } + + [Theory] + [MemberData(nameof(EveryPermissionTestData))] + public async Task ModifyRootUserPermissionShouldHaveNoEffect(UserPermission permission) + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.DeleteAsync($"users/admin/permissions/{permission}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/admin"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); + } + + { + var res = await client.PutAsync($"users/admin/permissions/{permission}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/admin"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); + } + } + + [Theory] + [MemberData(nameof(EveryPermissionTestData))] + public async Task ModifyUserPermissionShouldWork(UserPermission permission) + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(permission.ToString()); + } + + { + var res = await client.DeleteAsync($"users/user1/permissions/{permission}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEmpty(); + } + } + + [Theory] + [MemberData(nameof(EveryPermissionTestData))] + public async Task PutExistPermissionShouldHaveNoEffect(UserPermission permission) + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(permission.ToString()); + } + + { + var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(permission.ToString()); + } + } + + [Theory] + [MemberData(nameof(EveryPermissionTestData))] + public async Task DeleteNonExistPermissionShouldHaveNoEffect(UserPermission permission) + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.DeleteAsync($"users/user1/permissions/{permission}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEmpty(); + } + } + + [Fact] + public async Task AGeneralTest() + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.AllTimelineManagement}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(UserPermission.AllTimelineManagement.ToString()); + } + + { + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(UserPermission.AllTimelineManagement.ToString(), + UserPermission.HighlightTimelineManangement.ToString()); + } + + { + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.UserManagement}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo( + UserPermission.AllTimelineManagement.ToString(), + UserPermission.HighlightTimelineManangement.ToString(), + UserPermission.UserManagement.ToString()); + } + + { + var res = await client.DeleteAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo( + UserPermission.AllTimelineManagement.ToString(), + UserPermission.UserManagement.ToString()); + } + + { + var res = await client.DeleteAsync($"users/user1/permissions/{UserPermission.AllTimelineManagement}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(UserPermission.UserManagement.ToString()); + } + + { + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}", null); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo( + UserPermission.HighlightTimelineManangement.ToString(), UserPermission.UserManagement.ToString()); + } + + { + var res = await client.DeleteAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEquivalentTo(UserPermission.UserManagement.ToString()); + } + + { + var res = await client.DeleteAsync($"users/user1/permissions/{UserPermission.UserManagement}"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + } + + { + var res = await client.GetAsync("users/user1"); + res.StatusCode.Should().Be(HttpStatusCode.OK); + var body = await res.Content.ReadFromJsonAsync(); + body.Permissions.Should().BeEmpty(); + } + } + + [Theory] + [InlineData("users/user1/permissions/aaa")] + [InlineData("users/!!!/permissions/UserManagement")] + public async Task InvalidModel(string url) + { + using var client = await CreateClientAsAdministrator(); + + { + var res = await client.PutAsync(url, null); + res.StatusCode.Should().Be(HttpStatusCode.BadRequest); + var body = await res.Content.ReadFromJsonAsync(); + body.Code.Should().Be(ErrorCodes.Common.InvalidModel); + } + + { + var res = await client.DeleteAsync(url); + res.StatusCode.Should().Be(HttpStatusCode.BadRequest); + var body = await res.Content.ReadFromJsonAsync(); + body.Code.Should().Be(ErrorCodes.Common.InvalidModel); + } + } + + [Fact] + public async Task UserNotExist() + { + using var client = await CreateClientAsAdministrator(); + + const string url = "users/user123/permissions/UserManagement"; + + { + var res = await client.PutAsync(url, null); + res.StatusCode.Should().Be(HttpStatusCode.NotFound); + var body = await res.Content.ReadFromJsonAsync(); + body.Code.Should().Be(ErrorCodes.UserCommon.NotExist); + } + + { + var res = await client.DeleteAsync(url); + res.StatusCode.Should().Be(HttpStatusCode.NotFound); + var body = await res.Content.ReadFromJsonAsync(); + body.Code.Should().Be(ErrorCodes.UserCommon.NotExist); + } + } + } +} diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs index c5d1d4de..bbdb5d57 100644 --- a/BackEnd/Timeline/Controllers/UserController.cs +++ b/BackEnd/Timeline/Controllers/UserController.cs @@ -200,7 +200,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task PutUserPermission([FromRoute] string username, [FromRoute] UserPermission permission) + public async Task PutUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission) { try { @@ -220,7 +220,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task DeleteUserPermission([FromRoute] string username, [FromRoute] UserPermission permission) + public async Task DeleteUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission) { try { diff --git a/BackEnd/Timeline/GlobalSuppressions.cs b/BackEnd/Timeline/GlobalSuppressions.cs index 2b0da576..155ed9ff 100644 --- a/BackEnd/Timeline/GlobalSuppressions.cs +++ b/BackEnd/Timeline/GlobalSuppressions.cs @@ -5,10 +5,8 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "This is not a UI application.")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1034:Nested types should not be visible", Justification = "This is not bad.")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "No need to check the null because it's ASP.Net's duty.", Scope = "namespaceanddescendants", Target = "Timeline.Controllers")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Migrations code are auto generated.", Scope = "namespaceanddescendants", Target = "Timeline.Migrations")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Generated error response identifiers.", Scope = "type", Target = "Timeline.Models.Http.ErrorResponse")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1724:Type names should not match namespaces", Justification = "Generated error response identifiers.", Scope = "type", Target = "Timeline.Models.Http.ErrorResponse")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Generated error response.", Scope = "type", Target = "Timeline.Models.Http.ErrorResponse")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1056:Uri properties should not be strings", Justification = "That's unnecessary.")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Adundant")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Redundant")] diff --git a/BackEnd/Timeline/Resources/Services/UserService.Designer.cs b/BackEnd/Timeline/Resources/Services/UserService.Designer.cs index cdf7f390..564dd26c 100644 --- a/BackEnd/Timeline/Resources/Services/UserService.Designer.cs +++ b/BackEnd/Timeline/Resources/Services/UserService.Designer.cs @@ -70,7 +70,7 @@ namespace Timeline.Resources.Services { } /// - /// Looks up a localized string similar to Nickname is of bad format, because {}.. + /// Looks up a localized string similar to Nickname is of bad format, because {0}.. /// internal static string ExceptionNicknameBadFormat { get { @@ -106,7 +106,7 @@ namespace Timeline.Resources.Services { } /// - /// Looks up a localized string similar to Username is of bad format, because {}.. + /// Looks up a localized string similar to Username is of bad format, because {0}.. /// internal static string ExceptionUsernameBadFormat { get { diff --git a/BackEnd/Timeline/Resources/Services/UserService.resx b/BackEnd/Timeline/Resources/Services/UserService.resx index 09bd4abb..1f3c0011 100644 --- a/BackEnd/Timeline/Resources/Services/UserService.resx +++ b/BackEnd/Timeline/Resources/Services/UserService.resx @@ -121,7 +121,7 @@ New username is of bad format. - Nickname is of bad format, because {}. + Nickname is of bad format, because {0}. Old username is of bad format. @@ -133,7 +133,7 @@ Password can't be null. - Username is of bad format, because {}. + Username is of bad format, because {0}. A user with given username already exists. diff --git a/BackEnd/Timeline/Services/UserPermissionService.cs b/BackEnd/Timeline/Services/UserPermissionService.cs index deedf0a6..ff09b4ee 100644 --- a/BackEnd/Timeline/Services/UserPermissionService.cs +++ b/BackEnd/Timeline/Services/UserPermissionService.cs @@ -70,7 +70,7 @@ namespace Timeline.Services /// A string list. public List ToStringList() { - return _permissions.Select(p => p.ToString().ToUpperInvariant()).ToList(); + return _permissions.Select(p => p.ToString()).ToList(); } /// -- cgit v1.2.3