From ed8bae9cf7fd22300678d718cfee1913209f2cd0 Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 20 Nov 2019 00:28:53 +0800 Subject: Clean and refactor tests. --- .../IntegratedTests/AuthorizationTest.cs | 23 ++------ Timeline.Tests/IntegratedTests/I18nTest.cs | 16 ++--- .../IntegratedTests/IntegratedTestBase.cs | 65 ++++++++++++++++++++- .../IntegratedTests/PersonalTimelineTest.cs | 62 +++++++++----------- Timeline.Tests/IntegratedTests/TokenTest.cs | 46 +++++++-------- Timeline.Tests/IntegratedTests/UserAvatarTest.cs | 21 ++----- Timeline.Tests/IntegratedTests/UserDetailTest.cs | 25 +++----- Timeline.Tests/IntegratedTests/UserTest.cs | 68 ++++++++++------------ 8 files changed, 169 insertions(+), 157 deletions(-) (limited to 'Timeline.Tests/IntegratedTests') diff --git a/Timeline.Tests/IntegratedTests/AuthorizationTest.cs b/Timeline.Tests/IntegratedTests/AuthorizationTest.cs index a31d98f5..0bc094af 100644 --- a/Timeline.Tests/IntegratedTests/AuthorizationTest.cs +++ b/Timeline.Tests/IntegratedTests/AuthorizationTest.cs @@ -1,28 +1,17 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; -using System; using System.Net; using System.Threading.Tasks; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; using Xunit; namespace Timeline.Tests.IntegratedTests { - public class AuthorizationTest : IClassFixture>, IDisposable + public class AuthorizationTest : IntegratedTestBase { - private readonly TestApplication _testApp; - private readonly WebApplicationFactory _factory; - public AuthorizationTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _factory = _testApp.Factory; - } - - public void Dispose() - { - _testApp.Dispose(); } private const string BaseUrl = "testing/auth/"; @@ -33,7 +22,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task UnauthenticationTest() { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var response = await client.GetAsync(AuthorizeUrl); response.Should().HaveStatusCode(HttpStatusCode.Unauthorized); } @@ -41,7 +30,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task AuthenticationTest() { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var response = await client.GetAsync(AuthorizeUrl); response.Should().HaveStatusCode(HttpStatusCode.OK); } @@ -49,7 +38,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task UserAuthorizationTest() { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var response1 = await client.GetAsync(UserUrl); response1.Should().HaveStatusCode(HttpStatusCode.OK); var response2 = await client.GetAsync(AdminUrl); @@ -59,7 +48,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task AdminAuthorizationTest() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var response1 = await client.GetAsync(UserUrl); response1.Should().HaveStatusCode(HttpStatusCode.OK); var response2 = await client.GetAsync(AdminUrl); diff --git a/Timeline.Tests/IntegratedTests/I18nTest.cs b/Timeline.Tests/IntegratedTests/I18nTest.cs index 67bbea5c..855179af 100644 --- a/Timeline.Tests/IntegratedTests/I18nTest.cs +++ b/Timeline.Tests/IntegratedTests/I18nTest.cs @@ -1,32 +1,28 @@ -using Microsoft.AspNetCore.Mvc.Testing; +using FluentAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Timeline.Tests.Helpers; using Xunit; -using FluentAssertions; namespace Timeline.Tests.IntegratedTests { [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1054:Uri parameters should not be strings")] - public class I18nTest : IClassFixture>, IDisposable + public class I18nTest : IntegratedTestBase { - private readonly TestApplication _testApp; private readonly HttpClient _client; public I18nTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _client = _testApp.Factory.CreateDefaultClient(); + _client = Factory.CreateDefaultClient(); } - public void Dispose() + protected override void OnDispose() { _client.Dispose(); - _testApp.Dispose(); } private const string DirectUrl = "testing/i18n/direct"; diff --git a/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs index 2dfaf82e..242a452d 100644 --- a/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs +++ b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs @@ -1,14 +1,37 @@ using Microsoft.AspNetCore.Mvc.Testing; using System; using System.Collections.Generic; -using System.Linq; +using System.Net.Http; using System.Threading.Tasks; +using Timeline.Models.Http; using Timeline.Tests.Helpers; -using Timeline.Tests.Mock.Data; using Xunit; namespace Timeline.Tests.IntegratedTests { + public enum AuthType + { + None, + User, + Admin + } + + public static class AuthTypeExtensions + { + public static MockUser GetMockUser(this AuthType authType) + { + return authType switch + { + AuthType.None => null, + AuthType.User => MockUser.User, + AuthType.Admin => MockUser.Admin, + _ => throw new InvalidOperationException("Unknown auth type.") + }; + } + + public static string GetUsername(this AuthType authType) => authType.GetMockUser().Username; + } + public abstract class IntegratedTestBase : IClassFixture>, IDisposable { protected TestApplication TestApp { get; } @@ -20,8 +43,14 @@ namespace Timeline.Tests.IntegratedTests TestApp = new TestApplication(factory); } - public virtual void Dispose() + protected virtual void OnDispose() + { + + } + + public void Dispose() { + OnDispose(); TestApp.Dispose(); } @@ -31,5 +60,35 @@ namespace Timeline.Tests.IntegratedTests } protected IReadOnlyList ExtraMockUsers => TestApp.Database.ExtraMockUsers; + + public Task CreateClientWithNoAuth() + { + return Task.FromResult(Factory.CreateDefaultClient()); + } + + public async Task CreateClientWithCredential(string username, string password) + { + var client = Factory.CreateDefaultClient(); + var response = await client.PostAsJsonAsync("/token/create", + new CreateTokenRequest { Username = username, Password = password }); + var token = response.Should().HaveStatusCode(200) + .And.HaveJsonBody().Which.Token; + client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); + return client; + } + + public Task CreateClientAs(MockUser user) + { + if (user == null) + return CreateClientWithNoAuth(); + return CreateClientWithCredential(user.Username, user.Password); + } + + public Task CreateClientAs(AuthType authType) => CreateClientAs(authType.GetMockUser()); + + + public Task CreateClientAsUser() => CreateClientAs(MockUser.User); + public Task CreateClientAsAdmin() => CreateClientAs(MockUser.Admin); + } } diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs index 705675f9..9dae4c3e 100644 --- a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs @@ -1,17 +1,12 @@ using FluentAssertions; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Testing; using System; using System.Collections.Generic; -using System.Linq; using System.Net.Http; -using System.Text.Json; using System.Threading.Tasks; using Timeline.Models; using Timeline.Models.Http; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Timeline.Tests.Mock.Data; using Xunit; namespace Timeline.Tests.IntegratedTests @@ -27,7 +22,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task TimelineGet_Should_Work() { - using var client = Factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var res = await client.GetAsync("users/user/timeline"); var body = res.Should().HaveStatusCode(200) .And.HaveJsonBody().Which; @@ -40,7 +35,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Description_Should_Work() { - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); async Task AssertDescription(string description) { @@ -78,7 +73,7 @@ namespace Timeline.Tests.IntegratedTests { const string getUrl = "users/user/timeline"; const string changeUrl = "users/user/timeline/op/member"; - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); async Task AssertMembers(IList members) { @@ -137,7 +132,7 @@ namespace Timeline.Tests.IntegratedTests [InlineData(AuthType.Admin, 200, 200, 200, 200, 200)] public async Task Permission_Timeline(AuthType authType, int get, int opPropertyUser, int opPropertyAdmin, int opMemberUser, int opMemberAdmin) { - using var client = await Factory.CreateClientAs(authType); + using var client = await CreateClientAs(authType); { var res = await client.GetAsync("users/user/timeline"); res.Should().HaveStatusCode(get); @@ -175,13 +170,13 @@ namespace Timeline.Tests.IntegratedTests const string adminUrl = "users/admin/timeline/posts"; { // default visibility is registered { - using var client = Factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(403); } { - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.GetAsync(adminUrl); res.Should().HaveStatusCode(200); } @@ -189,13 +184,13 @@ namespace Timeline.Tests.IntegratedTests { // change visibility to public { - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.PostAsJsonAsync("users/user/timeline/op/property", new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Public }); res.Should().HaveStatusCode(200); } { - using var client = Factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(200); } @@ -203,7 +198,7 @@ namespace Timeline.Tests.IntegratedTests { // change visibility to private { - using var client = await Factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); { var res = await client.PostAsJsonAsync("users/user/timeline/op/property", new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Private }); @@ -216,28 +211,28 @@ namespace Timeline.Tests.IntegratedTests } } { - using var client = Factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(403); } { // user can't read admin's - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.GetAsync(adminUrl); res.Should().HaveStatusCode(403); } { // admin can read user's - using var client = await Factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(200); } { // add member - using var client = await Factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PostAsJsonAsync("users/admin/timeline/op/member", new TimelineMemberChangeRequest { Add = new List { "user" } }); res.Should().HaveStatusCode(200); } { // now user can read admin's - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.GetAsync(adminUrl); res.Should().HaveStatusCode(200); } @@ -250,14 +245,14 @@ namespace Timeline.Tests.IntegratedTests { CreateExtraMockUsers(1); - using (var client = await Factory.CreateClientAsUser()) + using (var client = await CreateClientAsUser()) { var res = await client.PostAsJsonAsync("users/user/timeline/op/member", new TimelineMemberChangeRequest { Add = new List { "user0" } }); res.Should().HaveStatusCode(200); } - using (var client = Factory.CreateDefaultClient()) + using (var client = await CreateClientWithNoAuth()) { { // no auth should get 401 var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", @@ -266,7 +261,7 @@ namespace Timeline.Tests.IntegratedTests } } - using (var client = await Factory.CreateClientAsUser()) + using (var client = await CreateClientAsUser()) { { // post self's var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", @@ -280,7 +275,7 @@ namespace Timeline.Tests.IntegratedTests } } - using (var client = await Factory.CreateClientAsAdmin()) + using (var client = await CreateClientAsAdmin()) { { // post as admin var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", @@ -289,7 +284,7 @@ namespace Timeline.Tests.IntegratedTests } } - using (var client = await Factory.CreateClientAs(ExtraMockUsers[0])) + using (var client = await CreateClientAs(ExtraMockUsers[0])) { { // post as member var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", @@ -306,7 +301,7 @@ namespace Timeline.Tests.IntegratedTests async Task CreatePost(MockUser auth, string timeline) { - using var client = await Factory.CreateClientAs(auth); + using var client = await CreateClientAs(auth); var res = await client.PostAsJsonAsync($"users/{timeline}/timeline/postop/create", new TimelinePostCreateRequest { Content = "aaa" }); return res.Should().HaveStatusCode(200) @@ -314,7 +309,7 @@ namespace Timeline.Tests.IntegratedTests .Which.Id; } - using (var client = await Factory.CreateClientAsUser()) + using (var client = await CreateClientAsUser()) { var res = await client.PostAsJsonAsync("users/user/timeline/op/member", new TimelineMemberChangeRequest { Add = new List { "user0", "user1" } }); @@ -322,7 +317,7 @@ namespace Timeline.Tests.IntegratedTests } { // no auth should get 401 - using var client = Factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = 12 }); res.Should().HaveStatusCode(401); @@ -330,7 +325,7 @@ namespace Timeline.Tests.IntegratedTests { // self can delete self var postId = await CreatePost(MockUser.User, "user"); - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = postId }); res.Should().HaveStatusCode(200); @@ -338,7 +333,7 @@ namespace Timeline.Tests.IntegratedTests { // admin can delete any var postId = await CreatePost(MockUser.User, "user"); - using var client = await Factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = postId }); res.Should().HaveStatusCode(200); @@ -346,7 +341,7 @@ namespace Timeline.Tests.IntegratedTests { // owner can delete other var postId = await CreatePost(ExtraMockUsers[0], "user"); - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = postId }); res.Should().HaveStatusCode(200); @@ -354,7 +349,7 @@ namespace Timeline.Tests.IntegratedTests { // author can delete self var postId = await CreatePost(ExtraMockUsers[0], "user"); - using var client = await Factory.CreateClientAs(ExtraMockUsers[0]); + using var client = await CreateClientAs(ExtraMockUsers[0]); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = postId }); res.Should().HaveStatusCode(200); @@ -362,7 +357,7 @@ namespace Timeline.Tests.IntegratedTests { // otherwise is forbidden var postId = await CreatePost(ExtraMockUsers[0], "user"); - using var client = await Factory.CreateClientAs(ExtraMockUsers[1]); + using var client = await CreateClientAs(ExtraMockUsers[1]); var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", new TimelinePostDeleteRequest { Id = postId }); res.Should().HaveStatusCode(403); @@ -373,7 +368,7 @@ namespace Timeline.Tests.IntegratedTests public async Task Post_Op_Should_Work() { { - using var client = await Factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); { var res = await client.GetAsync("users/user/timeline/posts"); res.Should().HaveStatusCode(200) @@ -459,6 +454,7 @@ namespace Timeline.Tests.IntegratedTests Time = createRes2.Time }); } + // TODO! Add post not exist tests. } } } diff --git a/Timeline.Tests/IntegratedTests/TokenTest.cs b/Timeline.Tests/IntegratedTests/TokenTest.cs index 111e8d8e..e62228fc 100644 --- a/Timeline.Tests/IntegratedTests/TokenTest.cs +++ b/Timeline.Tests/IntegratedTests/TokenTest.cs @@ -1,37 +1,33 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; -using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Timeline.Models.Http; using Timeline.Services; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Timeline.Tests.Mock.Data; using Xunit; using static Timeline.ErrorCodes.Http.Token; namespace Timeline.Tests.IntegratedTests { - public class TokenTest : IClassFixture>, IDisposable + public class TokenTest : IntegratedTestBase { private const string CreateTokenUrl = "token/create"; private const string VerifyTokenUrl = "token/verify"; - private readonly TestApplication _testApp; - private readonly WebApplicationFactory _factory; - public TokenTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _factory = _testApp.Factory; + } - public void Dispose() + private static async Task CreateUserTokenAsync(HttpClient client, string username, string password, int? expireOffset = null) { - _testApp.Dispose(); + var response = await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, Password = password, Expire = expireOffset }); + return response.Should().HaveStatusCode(200) + .And.HaveJsonBody().Which; } public static IEnumerable CreateToken_InvalidModel_Data() @@ -46,7 +42,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(CreateToken_InvalidModel_Data))] public async Task CreateToken_InvalidModel(string username, string password, int expire) { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); (await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, @@ -65,7 +61,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(CreateToken_UserCredential_Data))] public async void CreateToken_UserCredential(string username, string password) { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var response = await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, Password = password }); response.Should().HaveStatusCode(400) @@ -76,7 +72,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task CreateToken_Success() { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var response = await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = MockUser.User.Username, Password = MockUser.User.Password }); var body = response.Should().HaveStatusCode(200) @@ -88,7 +84,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task VerifyToken_InvalidModel() { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); (await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = null })).Should().BeInvalidModel(); } @@ -96,7 +92,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task VerifyToken_BadFormat() { - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); var response = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = "bad token hahaha" }); response.Should().HaveStatusCode(400) @@ -107,10 +103,10 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task VerifyToken_OldVersion() { - using var client = _factory.CreateDefaultClient(); - var token = (await client.CreateUserTokenAsync(MockUser.User.Username, MockUser.User.Password)).Token; + using var client = await CreateClientWithNoAuth(); + var token = (await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password)).Token; - using (var scope = _factory.Server.Host.Services.CreateScope()) // UserService is scoped. + using (var scope = Factory.Server.Host.Services.CreateScope()) // UserService is scoped. { // create a user for test var userService = scope.ServiceProvider.GetRequiredService(); @@ -127,10 +123,10 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task VerifyToken_UserNotExist() { - using var client = _factory.CreateDefaultClient(); - var token = (await client.CreateUserTokenAsync(MockUser.User.Username, MockUser.User.Password)).Token; + using var client = await CreateClientWithNoAuth(); + var token = (await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password)).Token; - using (var scope = _factory.Server.Host.Services.CreateScope()) // UserService is scoped. + using (var scope = Factory.Server.Host.Services.CreateScope()) // UserService is scoped. { var userService = scope.ServiceProvider.GetRequiredService(); await userService.DeleteUser(MockUser.User.Username); @@ -146,7 +142,7 @@ namespace Timeline.Tests.IntegratedTests //[Fact] //public async Task VerifyToken_Expired() //{ - // using (var client = _factory.CreateDefaultClient()) + // using (var client = await CreateClientWithNoAuth()) // { // // I can only control the token expired time but not current time // // because verify logic is encapsuled in other library. @@ -164,8 +160,8 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task VerifyToken_Success() { - using var client = _factory.CreateDefaultClient(); - var createTokenResult = await client.CreateUserTokenAsync(MockUser.User.Username, MockUser.User.Password); + using var client = await CreateClientWithNoAuth(); + var createTokenResult = await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password); var response = await client.PostAsJsonAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = createTokenResult.Token }); response.Should().HaveStatusCode(200) diff --git a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs index 2310fc66..25a7b675 100644 --- a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs +++ b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs @@ -15,27 +15,18 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Timeline.Services; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; using Xunit; using static Timeline.ErrorCodes.Http.Common; using static Timeline.ErrorCodes.Http.UserAvatar; namespace Timeline.Tests.IntegratedTests { - public class UserAvatarTest : IClassFixture>, IDisposable + public class UserAvatarTest : IntegratedTestBase { - private readonly TestApplication _testApp; - private readonly WebApplicationFactory _factory; - public UserAvatarTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _factory = _testApp.Factory; - } - public void Dispose() - { - _testApp.Dispose(); } [Fact] @@ -48,7 +39,7 @@ namespace Timeline.Tests.IntegratedTests Type = PngFormat.Instance.DefaultMimeType }; - using (var client = await _factory.CreateClientAsUser()) + using (var client = await CreateClientAsUser()) { { var res = await client.GetAsync("users/usernotexist/avatar"); @@ -57,7 +48,7 @@ namespace Timeline.Tests.IntegratedTests .Which.Code.Should().Be(Get.UserNotExist); } - var env = _factory.Server.Host.Services.GetRequiredService(); + var env = Factory.Server.Host.Services.GetRequiredService(); var defaultAvatarData = await File.ReadAllBytesAsync(Path.Combine(env.ContentRootPath, "default-avatar.png")); async Task GetReturnDefault(string username = "user") @@ -239,7 +230,7 @@ namespace Timeline.Tests.IntegratedTests } // Authorization check. - using (var client = await _factory.CreateClientAsAdmin()) + using (var client = await CreateClientAsAdmin()) { { var res = await client.PutByteArrayAsync("users/user/avatar", mockAvatar.Data, mockAvatar.Type); @@ -266,7 +257,7 @@ namespace Timeline.Tests.IntegratedTests } // bad username check - using (var client = await _factory.CreateClientAsAdmin()) + using (var client = await CreateClientAsAdmin()) { { var res = await client.GetAsync("users/u!ser/avatar"); diff --git a/Timeline.Tests/IntegratedTests/UserDetailTest.cs b/Timeline.Tests/IntegratedTests/UserDetailTest.cs index 8f2b6925..932c287e 100644 --- a/Timeline.Tests/IntegratedTests/UserDetailTest.cs +++ b/Timeline.Tests/IntegratedTests/UserDetailTest.cs @@ -1,38 +1,27 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; -using System; using System.Net; using System.Net.Http.Headers; using System.Net.Mime; using System.Threading.Tasks; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Timeline.Tests.Mock.Data; using Xunit; namespace Timeline.Tests.IntegratedTests { - public class UserDetailTest : IClassFixture>, IDisposable + public class UserDetailTest : IntegratedTestBase { - private readonly TestApplication _testApp; - private readonly WebApplicationFactory _factory; - public UserDetailTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _factory = _testApp.Factory; - } - public void Dispose() - { - _testApp.Dispose(); } [Fact] public async Task PermissionTest() { { // unauthorize - using var client = _factory.CreateDefaultClient(); + using var client = await CreateClientWithNoAuth(); { // GET var res = await client.GetAsync($"users/{MockUser.User.Username}/nickname"); res.Should().HaveStatusCode(HttpStatusCode.OK); @@ -47,7 +36,7 @@ namespace Timeline.Tests.IntegratedTests } } { // user - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); { // GET var res = await client.GetAsync($"users/{MockUser.User.Username}/nickname"); res.Should().HaveStatusCode(HttpStatusCode.OK); @@ -70,7 +59,7 @@ namespace Timeline.Tests.IntegratedTests } } { // user - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); { // PUT other var res = await client.PutStringAsync($"users/{MockUser.User.Username}/nickname", "aaa"); res.Should().HaveStatusCode(HttpStatusCode.OK); @@ -88,7 +77,7 @@ namespace Timeline.Tests.IntegratedTests var url = $"users/{MockUser.User.Username}/nickname"; var userNotExistUrl = "users/usernotexist/nickname"; { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); { var res = await client.GetAsync(userNotExistUrl); res.Should().HaveStatusCode(HttpStatusCode.NotFound) @@ -134,7 +123,7 @@ namespace Timeline.Tests.IntegratedTests } } { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); { var res = await client.PutStringAsync(userNotExistUrl, "aaa"); res.Should().HaveStatusCode(HttpStatusCode.BadRequest) diff --git a/Timeline.Tests/IntegratedTests/UserTest.cs b/Timeline.Tests/IntegratedTests/UserTest.cs index 7e99ddba..abfea18e 100644 --- a/Timeline.Tests/IntegratedTests/UserTest.cs +++ b/Timeline.Tests/IntegratedTests/UserTest.cs @@ -1,39 +1,28 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; -using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Timeline.Models; using Timeline.Models.Http; using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Timeline.Tests.Mock.Data; using Xunit; using static Timeline.ErrorCodes.Http.User; namespace Timeline.Tests.IntegratedTests { - public class UserTest : IClassFixture>, IDisposable + public class UserTest : IntegratedTestBase { - private readonly TestApplication _testApp; - private readonly WebApplicationFactory _factory; - public UserTest(WebApplicationFactory factory) + : base(factory) { - _testApp = new TestApplication(factory); - _factory = _testApp.Factory; - } - public void Dispose() - { - _testApp.Dispose(); } [Fact] public async Task Get_List_Success() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.GetAsync("users"); res.Should().HaveStatusCode(200) .And.HaveJsonBody() @@ -43,7 +32,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Get_Single_Success() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.GetAsync("users/" + MockUser.User.Username); res.Should().HaveStatusCode(200) .And.HaveJsonBody() @@ -53,7 +42,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Get_InvalidModel() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.GetAsync("users/aaa!a"); res.Should().BeInvalidModel(); } @@ -61,7 +50,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Get_Users_404() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.GetAsync("users/usernotexist"); res.Should().HaveStatusCode(404) .And.HaveCommonBody() @@ -79,7 +68,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(Put_InvalidModel_Data))] public async Task Put_InvalidModel(string username, string password, bool? administrator) { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); (await client.PutAsJsonAsync("users/" + username, new UserPutRequest { Password = password, Administrator = administrator })) .Should().BeInvalidModel(); @@ -96,7 +85,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Put_Modiefied() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PutAsJsonAsync("users/" + MockUser.User.Username, new UserPutRequest { Password = "password", @@ -109,7 +98,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Put_Created() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); const string username = "puttest"; const string url = "users/" + username; @@ -125,7 +114,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Patch_NotExist() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PatchAsJsonAsync("users/usernotexist", new UserPatchRequest { }); res.Should().HaveStatusCode(404) .And.HaveCommonBody() @@ -135,7 +124,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Patch_InvalidModel() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PatchAsJsonAsync("users/aaa!a", new UserPatchRequest { }); res.Should().BeInvalidModel(); } @@ -143,7 +132,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Patch_Success() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); { var res = await client.PatchAsJsonAsync("users/" + MockUser.User.Username, new UserPatchRequest { Administrator = false }); @@ -155,7 +144,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Delete_InvalidModel() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var url = "users/aaa!a"; var res = await client.DeleteAsync(url); res.Should().BeInvalidModel(); @@ -164,7 +153,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Delete_Deleted() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var url = "users/" + MockUser.User.Username; var res = await client.DeleteAsync(url); res.Should().BeDelete(true); @@ -176,7 +165,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Delete_NotExist() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.DeleteAsync("users/usernotexist"); res.Should().BeDelete(false); } @@ -195,7 +184,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(Op_ChangeUsername_InvalidModel_Data))] public async Task Op_ChangeUsername_InvalidModel(string oldUsername, string newUsername) { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); (await client.PostAsJsonAsync(changeUsernameUrl, new ChangeUsernameRequest { OldUsername = oldUsername, NewUsername = newUsername })) .Should().BeInvalidModel(); @@ -204,7 +193,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Op_ChangeUsername_UserNotExist() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PostAsJsonAsync(changeUsernameUrl, new ChangeUsernameRequest { OldUsername = "usernotexist", NewUsername = "newUsername" }); res.Should().HaveStatusCode(400) @@ -215,7 +204,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Op_ChangeUsername_UserAlreadyExist() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); var res = await client.PostAsJsonAsync(changeUsernameUrl, new ChangeUsernameRequest { OldUsername = MockUser.User.Username, NewUsername = MockUser.Admin.Username }); res.Should().HaveStatusCode(400) @@ -223,15 +212,23 @@ namespace Timeline.Tests.IntegratedTests .Which.Code.Should().Be(Op.ChangeUsername.AlreadyExist); } + private async Task TestLogin(string username, string password) + { + using var client = await CreateClientWithNoAuth(); + var response = await client.PostAsJsonAsync("token/create", new CreateTokenRequest { Username = username, Password = password }); + response.Should().HaveStatusCode(200) + .And.HaveJsonBody(); + } + [Fact] public async Task Op_ChangeUsername_Success() { - using var client = await _factory.CreateClientAsAdmin(); + using var client = await CreateClientAsAdmin(); const string newUsername = "hahaha"; var res = await client.PostAsJsonAsync(changeUsernameUrl, new ChangeUsernameRequest { OldUsername = MockUser.User.Username, NewUsername = newUsername }); res.Should().HaveStatusCode(200); - await client.CreateUserTokenAsync(newUsername, MockUser.User.Password); + await TestLogin(newUsername, MockUser.User.Password); } private const string changePasswordUrl = "userop/changepassword"; @@ -246,7 +243,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(Op_ChangePassword_InvalidModel_Data))] public async Task Op_ChangePassword_InvalidModel(string oldPassword, string newPassword) { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); (await client.PostAsJsonAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword })) .Should().BeInvalidModel(); @@ -255,7 +252,7 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Op_ChangePassword_BadOldPassword() { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); var res = await client.PostAsJsonAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "???", NewPassword = "???" }); res.Should().HaveStatusCode(400) .And.HaveCommonBody() @@ -265,13 +262,12 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Op_ChangePassword_Success() { - using var client = await _factory.CreateClientAsUser(); + using var client = await CreateClientAsUser(); const string newPassword = "new"; var res = await client.PostAsJsonAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = MockUser.User.Password, NewPassword = newPassword }); res.Should().HaveStatusCode(200); - await _factory.CreateDefaultClient() // don't use client above, because it sets authorization header - .CreateUserTokenAsync(MockUser.User.Username, newPassword); + await TestLogin(MockUser.User.Username, newPassword); } } } -- cgit v1.2.3