diff options
author | 杨宇千 <crupest@outlook.com> | 2020-02-01 00:26:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-01 00:26:35 +0800 |
commit | 7b962cd876719fb871569ba3c97fb5545721a3f8 (patch) | |
tree | f02f8d57440c777d4732bc4439f82e8b25c6732c /Timeline.Tests | |
parent | 289c7e1fada1f4dae6ce5e421e997ebddd55c2df (diff) | |
parent | bcb0a2361467614531a337282da1fd23996924f1 (diff) | |
download | timeline-7b962cd876719fb871569ba3c97fb5545721a3f8.tar.gz timeline-7b962cd876719fb871569ba3c97fb5545721a3f8.tar.bz2 timeline-7b962cd876719fb871569ba3c97fb5545721a3f8.zip |
Merge pull request #56 from crupest/dev
Refactor API to be RESTful.
Diffstat (limited to 'Timeline.Tests')
27 files changed, 691 insertions, 2174 deletions
diff --git a/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs b/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs deleted file mode 100644 index 372ba8a7..00000000 --- a/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs +++ /dev/null @@ -1,388 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging.Abstractions;
-using Moq;
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Threading.Tasks;
-using Timeline.Controllers;
-using Timeline.Filters;
-using Timeline.Models;
-using Timeline.Models.Http;
-using Timeline.Models.Validation;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.Controllers
-{
- public class PersonalTimelineControllerTest : IDisposable
- {
- private readonly Mock<IPersonalTimelineService> _service;
-
- private readonly PersonalTimelineController _controller;
-
- public PersonalTimelineControllerTest()
- {
- _service = new Mock<IPersonalTimelineService>();
- _controller = new PersonalTimelineController(NullLogger<PersonalTimelineController>.Instance, _service.Object);
- }
-
- public void Dispose()
- {
- _controller.Dispose();
- }
-
- [Fact]
- public void AttributeTest()
- {
- static void AssertUsernameParameter(MethodInfo m)
- {
- m.GetParameter("username")
- .Should().BeDecoratedWith<FromRouteAttribute>()
- .And.BeDecoratedWith<UsernameAttribute>();
- }
-
- static void AssertBodyParamter<TBody>(MethodInfo m)
- {
- var p = m.GetParameter("body");
- p.Should().BeDecoratedWith<FromBodyAttribute>();
- p.ParameterType.Should().Be(typeof(TBody));
- }
-
- var type = typeof(PersonalTimelineController);
- type.Should().BeDecoratedWith<ApiControllerAttribute>();
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.TimelineGet));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<HttpGetAttribute>();
- AssertUsernameParameter(m);
- }
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.PostListGet));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<HttpGetAttribute>();
- AssertUsernameParameter(m);
- }
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.PostOperationCreate));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<HttpPostAttribute>();
- AssertUsernameParameter(m);
- AssertBodyParamter<TimelinePostCreateRequest>(m);
- }
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.PostOperationDelete));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<HttpPostAttribute>();
- AssertUsernameParameter(m);
- AssertBodyParamter<TimelinePostDeleteRequest>(m);
- }
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.TimelineChangeProperty));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<SelfOrAdminAttribute>()
- .And.BeDecoratedWith<HttpPostAttribute>();
- AssertUsernameParameter(m);
- AssertBodyParamter<TimelinePropertyChangeRequest>(m);
- }
-
- {
- var m = type.GetMethod(nameof(PersonalTimelineController.TimelineChangeMember));
- m.Should().BeDecoratedWith<CatchTimelineNotExistExceptionAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<SelfOrAdminAttribute>()
- .And.BeDecoratedWith<HttpPostAttribute>();
- AssertUsernameParameter(m);
- AssertBodyParamter<TimelineMemberChangeRequest>(m);
- }
- }
-
- const string authUsername = "authuser";
- private void SetUser(bool administrator)
- {
- _controller.ControllerContext = new ControllerContext
- {
- HttpContext = new DefaultHttpContext
- {
- User = PrincipalHelper.Create(authUsername, administrator)
- }
- };
- }
-
- [Fact]
- public async Task TimelineGet()
- {
- const string username = "username";
- var timelineInfo = new BaseTimelineInfo();
- _service.Setup(s => s.GetTimeline(username)).ReturnsAsync(timelineInfo);
- (await _controller.TimelineGet(username)).Value.Should().Be(timelineInfo);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostListGet_Forbid()
- {
- const string username = "username";
- SetUser(false);
- _service.Setup(s => s.HasReadPermission(username, authUsername)).ReturnsAsync(false);
- var result = (await _controller.PostListGet(username)).Result
- .Should().BeAssignableTo<ObjectResult>()
- .Which;
- result.StatusCode.Should().Be(StatusCodes.Status403Forbidden);
- result.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostListGetForbid);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostListGet_Admin_Success()
- {
- const string username = "username";
- SetUser(true);
- _service.Setup(s => s.GetPosts(username)).ReturnsAsync(new List<TimelinePostInfo>());
- (await _controller.PostListGet(username)).Value
- .Should().BeAssignableTo<IList<TimelinePostInfo>>()
- .Which.Should().NotBeNull().And.BeEmpty();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostListGet_User_Success()
- {
- const string username = "username";
- SetUser(false);
- _service.Setup(s => s.HasReadPermission(username, authUsername)).ReturnsAsync(true);
- _service.Setup(s => s.GetPosts(username)).ReturnsAsync(new List<TimelinePostInfo>());
- (await _controller.PostListGet(username)).Value
- .Should().BeAssignableTo<IList<TimelinePostInfo>>()
- .Which.Should().NotBeNull().And.BeEmpty();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationCreate_Forbid()
- {
- const string username = "username";
- const string content = "cccc";
- SetUser(false);
- _service.Setup(s => s.IsMemberOf(username, authUsername)).ReturnsAsync(false);
- var result = (await _controller.PostOperationCreate(username, new TimelinePostCreateRequest
- {
- Content = content,
- Time = null
- })).Result.Should().NotBeNull().And.BeAssignableTo<ObjectResult>().Which;
- result.StatusCode.Should().Be(StatusCodes.Status403Forbidden);
- result.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostOperationCreateForbid);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationCreate_Admin_Success()
- {
- const string username = "username";
- const string content = "cccc";
- var response = new TimelinePostCreateResponse
- {
- Id = 3,
- Time = DateTime.Now
- };
- SetUser(true);
- _service.Setup(s => s.CreatePost(username, authUsername, content, null)).ReturnsAsync(response);
- var resultValue = (await _controller.PostOperationCreate(username, new TimelinePostCreateRequest
- {
- Content = content,
- Time = null
- })).Value;
- resultValue.Should().NotBeNull()
- .And.BeAssignableTo<TimelinePostCreateResponse>()
- .And.BeEquivalentTo(response);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationCreate_User_Success()
- {
- const string username = "username";
- const string content = "cccc";
- var response = new TimelinePostCreateResponse
- {
- Id = 3,
- Time = DateTime.Now
- };
- SetUser(false);
- _service.Setup(s => s.IsMemberOf(username, authUsername)).ReturnsAsync(true);
- _service.Setup(s => s.CreatePost(username, authUsername, content, null)).ReturnsAsync(response);
- var resultValue = (await _controller.PostOperationCreate(username, new TimelinePostCreateRequest
- {
- Content = content,
- Time = null
- })).Value;
- resultValue.Should().NotBeNull()
- .And.BeAssignableTo<TimelinePostCreateResponse>()
- .And.BeEquivalentTo(response);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationDelete_Forbid()
- {
- const string username = "username";
- const long postId = 2;
- SetUser(false);
- _service.Setup(s => s.HasPostModifyPermission(username, postId, authUsername)).ReturnsAsync(false);
- var result = (await _controller.PostOperationDelete(username, new TimelinePostDeleteRequest
- {
- Id = postId
- })).Should().NotBeNull().And.BeAssignableTo<ObjectResult>().Which;
- result.StatusCode.Should().Be(StatusCodes.Status403Forbidden);
- result.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostOperationDeleteForbid);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationDelete_NotExist()
- {
- const string username = "username";
- const long postId = 2;
- SetUser(true);
- _service.Setup(s => s.DeletePost(username, postId)).ThrowsAsync(new TimelinePostNotExistException());
- var result = (await _controller.PostOperationDelete(username, new TimelinePostDeleteRequest
- {
- Id = postId
- })).Should().NotBeNull().And.BeAssignableTo<ObjectResult>().Which;
- result.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
- result.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostOperationDeleteNotExist);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationDelete_Admin_Success()
- {
- const string username = "username";
- const long postId = 2;
- SetUser(true);
- _service.Setup(s => s.DeletePost(username, postId)).Returns(Task.CompletedTask);
- var result = await _controller.PostOperationDelete(username, new TimelinePostDeleteRequest
- {
- Id = postId
- });
- result.Should().NotBeNull().And.BeAssignableTo<OkResult>();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task PostOperationDelete_User_Success()
- {
- const string username = "username";
- const long postId = 2;
- SetUser(false);
- _service.Setup(s => s.DeletePost(username, postId)).Returns(Task.CompletedTask);
- _service.Setup(s => s.HasPostModifyPermission(username, postId, authUsername)).ReturnsAsync(true);
- var result = await _controller.PostOperationDelete(username, new TimelinePostDeleteRequest
- {
- Id = postId
- });
- result.Should().NotBeNull().And.BeAssignableTo<OkResult>();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task TimelineChangeProperty_Success()
- {
- const string username = "username";
- var req = new TimelinePropertyChangeRequest
- {
- Description = "",
- Visibility = TimelineVisibility.Private
- };
- _service.Setup(s => s.ChangeProperty(username, req)).Returns(Task.CompletedTask);
- var result = await _controller.TimelineChangeProperty(username, req);
- result.Should().NotBeNull().And.BeAssignableTo<OkResult>();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task TimelineChangeMember_Success()
- {
- const string username = "username";
- var add = new List<string> { "aaa" };
- var remove = new List<string> { "rrr" };
- _service.Setup(s => s.ChangeMember(username, add, remove)).Returns(Task.CompletedTask);
- var result = await _controller.TimelineChangeMember(username, new TimelineMemberChangeRequest
- {
- Add = add,
- Remove = remove
- });
- result.Should().NotBeNull().And.BeAssignableTo<OkResult>();
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task TimelineChangeMember_UsernameBadFormat()
- {
- const string username = "username";
- var add = new List<string> { "aaa" };
- var remove = new List<string> { "rrr" };
- _service.Setup(s => s.ChangeMember(username, add, remove)).ThrowsAsync(
- new TimelineMemberOperationUserException("test", new UsernameBadFormatException()));
- var result = await _controller.TimelineChangeMember(username, new TimelineMemberChangeRequest
- {
- Add = add,
- Remove = remove
- });
- result.Should().NotBeNull().And.BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Common.InvalidModel);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task TimelineChangeMember_AddNotExist()
- {
- const string username = "username";
- var add = new List<string> { "aaa" };
- var remove = new List<string> { "rrr" };
- _service.Setup(s => s.ChangeMember(username, add, remove)).ThrowsAsync(
- new TimelineMemberOperationUserException("test", new UserNotExistException()));
- var result = await _controller.TimelineChangeMember(username, new TimelineMemberChangeRequest
- {
- Add = add,
- Remove = remove
- });
- result.Should().NotBeNull().And.BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(ErrorCodes.Http.Timeline.ChangeMemberUserNotExist);
- _service.VerifyAll();
- }
-
- [Fact]
- public async Task TimelineChangeMember_UnknownTimelineMemberOperationUserException()
- {
- const string username = "username";
- var add = new List<string> { "aaa" };
- var remove = new List<string> { "rrr" };
- _service.Setup(s => s.ChangeMember(username, add, remove)).ThrowsAsync(
- new TimelineMemberOperationUserException("test", null));
- await _controller.Awaiting(c => c.TimelineChangeMember(username, new TimelineMemberChangeRequest
- {
- Add = add,
- Remove = remove
- })).Should().ThrowAsync<TimelineMemberOperationUserException>(); // Should rethrow.
- }
- }
-}
diff --git a/Timeline.Tests/Controllers/TokenControllerTest.cs b/Timeline.Tests/Controllers/TokenControllerTest.cs deleted file mode 100644 index 238fc237..00000000 --- a/Timeline.Tests/Controllers/TokenControllerTest.cs +++ /dev/null @@ -1,119 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging.Abstractions;
-using Moq;
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Timeline.Controllers;
-using Timeline.Models.Http;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-using static Timeline.ErrorCodes.Http.Token;
-
-namespace Timeline.Tests.Controllers
-{
- public class TokenControllerTest : IDisposable
- {
- private readonly Mock<IUserService> _mockUserService = new Mock<IUserService>();
- private readonly TestClock _mockClock = new TestClock();
-
-
- private readonly TokenController _controller;
-
- public TokenControllerTest()
- {
- _controller = new TokenController(_mockUserService.Object, NullLogger<TokenController>.Instance, _mockClock);
- }
-
- public void Dispose()
- {
- _controller.Dispose();
- }
-
- [Theory]
- [InlineData(null)]
- [InlineData(100)]
- public async Task Create_Ok(int? expire)
- {
- var mockCurrentTime = DateTime.Now;
- _mockClock.MockCurrentTime = mockCurrentTime;
- var createResult = new CreateTokenResult
- {
- Token = "mocktokenaaaaa",
- User = MockUser.User.Info
- };
- _mockUserService.Setup(s => s.CreateToken("u", "p", expire == null ? null : (DateTime?)mockCurrentTime.AddDays(expire.Value))).ReturnsAsync(createResult);
- var action = await _controller.Create(new CreateTokenRequest
- {
- Username = "u",
- Password = "p",
- Expire = expire
- });
- action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeEquivalentTo(createResult);
- }
-
- [Fact]
- public async Task Create_UserNotExist()
- {
- _mockUserService.Setup(s => s.CreateToken("u", "p", null)).ThrowsAsync(new UserNotExistException("u"));
- var action = await _controller.Create(new CreateTokenRequest
- {
- Username = "u",
- Password = "p",
- Expire = null
- });
- action.Result.Should().BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(Create.BadCredential);
- }
-
- [Fact]
- public async Task Create_BadPassword()
- {
- _mockUserService.Setup(s => s.CreateToken("u", "p", null)).ThrowsAsync(new BadPasswordException("u"));
- var action = await _controller.Create(new CreateTokenRequest
- {
- Username = "u",
- Password = "p",
- Expire = null
- });
- action.Result.Should().BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(Create.BadCredential);
- }
-
- [Fact]
- public async Task Verify_Ok()
- {
- const string token = "aaaaaaaaaaaaaa";
- _mockUserService.Setup(s => s.VerifyToken(token)).ReturnsAsync(MockUser.User.Info);
- var action = await _controller.Verify(new VerifyTokenRequest { Token = token });
- action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeAssignableTo<VerifyTokenResponse>()
- .Which.User.Should().BeEquivalentTo(MockUser.User.Info);
- }
-
- public static IEnumerable<object[]> Verify_BadRequest_Data()
- {
- yield return new object[] { new JwtVerifyException(JwtVerifyException.ErrorCodes.Expired), Verify.Expired };
- yield return new object[] { new JwtVerifyException(JwtVerifyException.ErrorCodes.IdClaimBadFormat), Verify.BadFormat };
- yield return new object[] { new JwtVerifyException(JwtVerifyException.ErrorCodes.OldVersion), Verify.OldVersion };
- yield return new object[] { new UserNotExistException(), Verify.UserNotExist };
- }
-
- [Theory]
- [MemberData(nameof(Verify_BadRequest_Data))]
- public async Task Verify_BadRequest(Exception e, int code)
- {
- const string token = "aaaaaaaaaaaaaa";
- _mockUserService.Setup(s => s.VerifyToken(token)).ThrowsAsync(e);
- var action = await _controller.Verify(new VerifyTokenRequest { Token = token });
- action.Result.Should().BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(code);
- }
- }
-}
diff --git a/Timeline.Tests/Controllers/UserControllerTest.cs b/Timeline.Tests/Controllers/UserControllerTest.cs deleted file mode 100644 index a5ca7a2b..00000000 --- a/Timeline.Tests/Controllers/UserControllerTest.cs +++ /dev/null @@ -1,218 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging.Abstractions;
-using Moq;
-using System;
-using System.Linq;
-using System.Security.Claims;
-using System.Threading.Tasks;
-using Timeline.Controllers;
-using Timeline.Models;
-using Timeline.Models.Http;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-using static Timeline.ErrorCodes.Http.User;
-
-namespace Timeline.Tests.Controllers
-{
- public class UserControllerTest : IDisposable
- {
- private readonly Mock<IUserService> _mockUserService = new Mock<IUserService>();
-
- private readonly UserController _controller;
-
- public UserControllerTest()
- {
- _controller = new UserController(NullLogger<UserController>.Instance, _mockUserService.Object);
- }
-
- public void Dispose()
- {
- _controller.Dispose();
- }
-
- [Fact]
- public async Task GetList_Success()
- {
- var array = MockUser.UserInfoList.ToArray();
- _mockUserService.Setup(s => s.ListUsers()).ReturnsAsync(array);
- var action = await _controller.List();
- action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeEquivalentTo(array);
- }
-
- [Fact]
- public async Task Get_Success()
- {
- const string username = "aaa";
- _mockUserService.Setup(s => s.GetUser(username)).ReturnsAsync(MockUser.User.Info);
- var action = await _controller.Get(username);
- action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeEquivalentTo(MockUser.User.Info);
- }
-
- [Fact]
- public async Task Get_NotFound()
- {
- const string username = "aaa";
- _mockUserService.Setup(s => s.GetUser(username)).Returns(Task.FromResult<UserInfo>(null));
- var action = await _controller.Get(username);
- action.Result.Should().BeAssignableTo<NotFoundObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(Get.NotExist);
- }
-
- [Theory]
- [InlineData(PutResult.Create, true)]
- [InlineData(PutResult.Modify, false)]
- public async Task Put_Success(PutResult result, bool create)
- {
- const string username = "aaa";
- const string password = "ppp";
- const bool administrator = true;
- _mockUserService.Setup(s => s.PutUser(username, password, administrator)).ReturnsAsync(result);
- var action = await _controller.Put(new UserPutRequest
- {
- Password = password,
- Administrator = administrator
- }, username);
- var response = action.Result.Should().BeAssignableTo<ObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonPutResponse>()
- .Which;
- response.Code.Should().Be(0);
- response.Data.Create.Should().Be(create);
- }
-
- [Fact]
- public async Task Patch_Success()
- {
- const string username = "aaa";
- const string password = "ppp";
- const bool administrator = true;
- _mockUserService.Setup(s => s.PatchUser(username, password, administrator)).Returns(Task.CompletedTask);
- var action = await _controller.Patch(new UserPatchRequest
- {
- Password = password,
- Administrator = administrator
- }, username);
- action.Should().BeAssignableTo<OkResult>();
- }
-
- [Fact]
- public async Task Patch_NotExist()
- {
- const string username = "aaa";
- const string password = "ppp";
- const bool administrator = true;
- _mockUserService.Setup(s => s.PatchUser(username, password, administrator)).ThrowsAsync(new UserNotExistException());
- var action = await _controller.Patch(new UserPatchRequest
- {
- Password = password,
- Administrator = administrator
- }, username);
- action.Should().BeAssignableTo<NotFoundObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(Patch.NotExist);
- }
-
- [Fact]
- public async Task Delete_Delete()
- {
- const string username = "aaa";
- _mockUserService.Setup(s => s.DeleteUser(username)).Returns(Task.CompletedTask);
- var action = await _controller.Delete(username);
- var body = action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonDeleteResponse>()
- .Which;
- body.Code.Should().Be(0);
- body.Data.Delete.Should().BeTrue();
- }
-
- [Fact]
- public async Task Delete_NotExist()
- {
- const string username = "aaa";
- _mockUserService.Setup(s => s.DeleteUser(username)).ThrowsAsync(new UserNotExistException());
- var action = await _controller.Delete(username);
- var body = action.Result.Should().BeAssignableTo<OkObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonDeleteResponse>()
- .Which;
- body.Code.Should().Be(0);
- body.Data.Delete.Should().BeFalse();
- }
-
- [Fact]
- public async Task Op_ChangeUsername_Success()
- {
- const string oldUsername = "aaa";
- const string newUsername = "bbb";
- _mockUserService.Setup(s => s.ChangeUsername(oldUsername, newUsername)).Returns(Task.CompletedTask);
- var action = await _controller.ChangeUsername(new ChangeUsernameRequest { OldUsername = oldUsername, NewUsername = newUsername });
- action.Should().BeAssignableTo<OkResult>();
- }
-
- [Theory]
- [InlineData(typeof(UserNotExistException), Op.ChangeUsername.NotExist)]
- [InlineData(typeof(UsernameConfictException), Op.ChangeUsername.AlreadyExist)]
- public async Task Op_ChangeUsername_Failure(Type exceptionType, int code)
- {
- const string oldUsername = "aaa";
- const string newUsername = "bbb";
- _mockUserService.Setup(s => s.ChangeUsername(oldUsername, newUsername)).ThrowsAsync(Activator.CreateInstance(exceptionType) as Exception);
- var action = await _controller.ChangeUsername(new ChangeUsernameRequest { OldUsername = oldUsername, NewUsername = newUsername });
- action.Should().BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(code);
- }
-
- [Fact]
- public async Task Op_ChangePassword_Success()
- {
- const string username = "aaa";
- const string oldPassword = "aaa";
- const string newPassword = "bbb";
- _mockUserService.Setup(s => s.ChangePassword(username, oldPassword, newPassword)).Returns(Task.CompletedTask);
-
- _controller.ControllerContext = new ControllerContext()
- {
- HttpContext = new DefaultHttpContext()
- {
- User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
- {
- new Claim(ClaimTypes.Name, username)
- }, "TestAuthType"))
- }
- };
-
- var action = await _controller.ChangePassword(new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword });
- action.Should().BeAssignableTo<OkResult>();
- }
-
- [Fact]
- public async Task Op_ChangePassword_BadPassword()
- {
- const string username = "aaa";
- const string oldPassword = "aaa";
- const string newPassword = "bbb";
- _mockUserService.Setup(s => s.ChangePassword(username, oldPassword, newPassword)).ThrowsAsync(new BadPasswordException());
-
- _controller.ControllerContext = new ControllerContext()
- {
- HttpContext = new DefaultHttpContext()
- {
- User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
- {
- new Claim(ClaimTypes.Name, username)
- }, "TestAuthType"))
- }
- };
-
- var action = await _controller.ChangePassword(new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword });
- action.Should().BeAssignableTo<BadRequestObjectResult>()
- .Which.Value.Should().BeAssignableTo<CommonResponse>()
- .Which.Code.Should().Be(Op.ChangePassword.BadOldPassword);
- }
- }
-}
diff --git a/Timeline.Tests/Controllers/UserDetailControllerTest.cs b/Timeline.Tests/Controllers/UserDetailControllerTest.cs deleted file mode 100644 index ffd88790..00000000 --- a/Timeline.Tests/Controllers/UserDetailControllerTest.cs +++ /dev/null @@ -1,98 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using Moq;
-using System;
-using System.ComponentModel.DataAnnotations;
-using System.Threading.Tasks;
-using Timeline.Controllers;
-using Timeline.Filters;
-using Timeline.Models.Validation;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.Controllers
-{
- public class UserDetailControllerTest : IDisposable
- {
- private readonly Mock<IUserDetailService> _mockUserDetailService;
- private readonly UserDetailController _controller;
-
- public UserDetailControllerTest()
- {
- _mockUserDetailService = new Mock<IUserDetailService>();
- _controller = new UserDetailController(_mockUserDetailService.Object);
- }
-
- public void Dispose()
- {
- _controller.Dispose();
- }
-
- [Fact]
- public void AttributeTest()
- {
- typeof(UserDetailController).Should().BeDecoratedWith<ApiControllerAttribute>();
-
- var getNickname = typeof(UserDetailController).GetMethod(nameof(UserDetailController.GetNickname));
- getNickname.Should().BeDecoratedWith<HttpGetAttribute>()
- .And.BeDecoratedWith<CatchUserNotExistExceptionAttribute>();
- getNickname.GetParameter("username").Should().BeDecoratedWith<UsernameAttribute>()
- .And.BeDecoratedWith<FromRouteAttribute>();
-
- var putNickname = typeof(UserDetailController).GetMethod(nameof(UserDetailController.PutNickname));
- putNickname.Should().BeDecoratedWith<HttpPutAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<SelfOrAdminAttribute>()
- .And.BeDecoratedWith<CatchUserNotExistExceptionAttribute>();
- putNickname.GetParameter("username").Should().BeDecoratedWith<UsernameAttribute>()
- .And.BeDecoratedWith<FromRouteAttribute>();
- var stringLengthAttributeOnPutBody = putNickname.GetParameter("body").Should().BeDecoratedWith<FromBodyAttribute>()
- .And.BeDecoratedWith<StringLengthAttribute>()
- .Which;
- stringLengthAttributeOnPutBody.MinimumLength.Should().Be(1);
- stringLengthAttributeOnPutBody.MaximumLength.Should().Be(10);
-
- var deleteNickname = typeof(UserDetailController).GetMethod(nameof(UserDetailController.DeleteNickname));
- deleteNickname.Should().BeDecoratedWith<HttpDeleteAttribute>()
- .And.BeDecoratedWith<AuthorizeAttribute>()
- .And.BeDecoratedWith<SelfOrAdminAttribute>()
- .And.BeDecoratedWith<CatchUserNotExistExceptionAttribute>();
- deleteNickname.GetParameter("username").Should().BeDecoratedWith<UsernameAttribute>()
- .And.BeDecoratedWith<FromRouteAttribute>();
- }
-
- [Fact]
- public async Task GetNickname_ShouldWork()
- {
- const string username = "uuu";
- const string nickname = "nnn";
- _mockUserDetailService.Setup(s => s.GetNickname(username)).ReturnsAsync(nickname);
- var actionResult = await _controller.GetNickname(username);
- actionResult.Result.Should().BeAssignableTo<OkObjectResult>(nickname);
- _mockUserDetailService.VerifyAll();
- }
-
- [Fact]
- public async Task PutNickname_ShouldWork()
- {
- const string username = "uuu";
- const string nickname = "nnn";
- _mockUserDetailService.Setup(s => s.SetNickname(username, nickname)).Returns(Task.CompletedTask);
- var actionResult = await _controller.PutNickname(username, nickname);
- actionResult.Should().BeAssignableTo<OkResult>();
- _mockUserDetailService.VerifyAll();
- }
-
- [Fact]
- public async Task DeleteNickname_ShouldWork()
- {
- const string username = "uuu";
- _mockUserDetailService.Setup(s => s.SetNickname(username, null)).Returns(Task.CompletedTask);
- var actionResult = await _controller.DeleteNickname(username);
- actionResult.Should().BeAssignableTo<OkResult>();
- _mockUserDetailService.VerifyAll();
- }
- }
-}
diff --git a/Timeline.Tests/DatabaseTest.cs b/Timeline.Tests/DatabaseTest.cs deleted file mode 100644 index a7b97c16..00000000 --- a/Timeline.Tests/DatabaseTest.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FluentAssertions;
-using System;
-using System.Linq;
-using Timeline.Entities;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests
-{
- public class DatabaseTest : IDisposable
- {
- private readonly TestDatabase _database;
- private readonly DatabaseContext _context;
-
- public DatabaseTest()
- {
- _database = new TestDatabase();
- _context = _database.Context;
- }
-
- public void Dispose()
- {
- _database.Dispose();
- }
-
- [Fact]
- public void DeleteUserShouldAlsoDeleteAvatar()
- {
- var user = _context.Users.First();
- _context.UserAvatars.Count().Should().Be(0);
- _context.UserAvatars.Add(new UserAvatar
- {
- Data = null,
- Type = null,
- ETag = null,
- LastModified = DateTime.Now,
- UserId = user.Id
- });
- _context.SaveChanges();
- _context.UserAvatars.Count().Should().Be(1);
- _context.Users.Remove(user);
- _context.SaveChanges();
- _context.UserAvatars.Count().Should().Be(0);
- }
-
- [Fact]
- public void DeleteUserShouldAlsoDeleteDetail()
- {
- var user = _context.Users.First();
- _context.UserDetails.Count().Should().Be(0);
- _context.UserDetails.Add(new UserDetail
- {
- Nickname = null,
- UserId = user.Id
- });
- _context.SaveChanges();
- _context.UserDetails.Count().Should().Be(1);
- _context.Users.Remove(user);
- _context.SaveChanges();
- _context.UserDetails.Count().Should().Be(0);
- }
- }
-}
diff --git a/Timeline.Tests/ErrorCodeTest.cs b/Timeline.Tests/ErrorCodeTest.cs index 78a58131..258ebf4e 100644 --- a/Timeline.Tests/ErrorCodeTest.cs +++ b/Timeline.Tests/ErrorCodeTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using Timeline.Models.Http;
using Xunit;
using Xunit.Abstractions;
diff --git a/Timeline.Tests/GlobalSuppressions.cs b/Timeline.Tests/GlobalSuppressions.cs index 1d1d294b..0f873033 100644 --- a/Timeline.Tests/GlobalSuppressions.cs +++ b/Timeline.Tests/GlobalSuppressions.cs @@ -12,3 +12,5 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA1816:Dispose methods should call SuppressFinalize", Justification = "Test classes do not need to implement it that way.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2234:Pass system uri objects instead of strings", Justification = "I really don't understand this rule.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Tests do not need make strings resources.")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1054:Uri parameters should not be strings", Justification = "That's unnecessary.")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1056:Uri properties should not be strings", Justification = "That's unnecessary.")]
diff --git a/Timeline.Tests/Helpers/MockUser.cs b/Timeline.Tests/Helpers/MockUser.cs deleted file mode 100644 index 8d738525..00000000 --- a/Timeline.Tests/Helpers/MockUser.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using Timeline.Models; - -namespace Timeline.Tests.Helpers -{ - public class MockUser - { - public MockUser(string username, string password, bool administrator) - { - Info = new UserInfo(username, administrator); - Password = password; - } - - public UserInfo Info { get; set; } - public string Username => Info.Username; - public string Password { get; set; } - public bool Administrator => Info.Administrator; - - public static MockUser User { get; } = new MockUser("user", "userpassword", false); - public static MockUser Admin { get; } = new MockUser("admin", "adminpassword", true); - - public static IReadOnlyList<UserInfo> UserInfoList { get; } = new List<UserInfo> { User.Info, Admin.Info }; - } -} diff --git a/Timeline.Tests/Helpers/ParameterInfoAssertions.cs b/Timeline.Tests/Helpers/ParameterInfoAssertions.cs index e3becee1..d3e5a41e 100644 --- a/Timeline.Tests/Helpers/ParameterInfoAssertions.cs +++ b/Timeline.Tests/Helpers/ParameterInfoAssertions.cs @@ -3,10 +3,7 @@ using FluentAssertions.Execution; using FluentAssertions.Formatting;
using FluentAssertions.Primitives;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Reflection;
-using System.Threading.Tasks;
namespace Timeline.Tests.Helpers
{
diff --git a/Timeline.Tests/Helpers/PrincipalHelper.cs b/Timeline.Tests/Helpers/PrincipalHelper.cs deleted file mode 100644 index 89f3f7b1..00000000 --- a/Timeline.Tests/Helpers/PrincipalHelper.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using System.Security.Claims; -using Timeline.Models; - -namespace Timeline.Tests.Helpers -{ - public static class PrincipalHelper - { - internal const string AuthScheme = "TESTAUTH"; - - internal static ClaimsPrincipal Create(string username, bool administrator) - { - var identity = new ClaimsIdentity(AuthScheme); - identity.AddClaim(new Claim(identity.NameClaimType, username, ClaimValueTypes.String)); - identity.AddClaims(UserRoleConvert.ToArray(administrator).Select(role => new Claim(identity.RoleClaimType, role, ClaimValueTypes.String))); - - var principal = new ClaimsPrincipal(); - principal.AddIdentity(identity); - - return principal; - } - } -} diff --git a/Timeline.Tests/Helpers/ResponseAssertions.cs b/Timeline.Tests/Helpers/ResponseAssertions.cs index 301ceef6..f01a0677 100644 --- a/Timeline.Tests/Helpers/ResponseAssertions.cs +++ b/Timeline.Tests/Helpers/ResponseAssertions.cs @@ -3,6 +3,7 @@ using FluentAssertions.Execution; using FluentAssertions.Formatting;
using FluentAssertions.Primitives;
using System;
+using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Text;
@@ -124,6 +125,13 @@ namespace Timeline.Tests.Helpers return assertions.HaveJsonBody<CommonResponse>(because, becauseArgs);
}
+ public static void HaveCommonBody(this HttpResponseMessageAssertions assertions, int code, string message = null, params object[] messageArgs)
+ {
+ message = string.IsNullOrEmpty(message) ? "" : ", " + string.Format(CultureInfo.CurrentCulture, message, messageArgs);
+ var body = assertions.HaveCommonBody("Response body should be CommonResponse{0}", message).Which;
+ body.Code.Should().Be(code, "Response body code is not the specified one{0}", message);
+ }
+
public static AndWhichConstraint<HttpResponseMessageAssertions, CommonDataResponse<TData>> HaveCommonDataBody<TData>(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs)
{
return assertions.HaveJsonBody<CommonDataResponse<TData>>(because, becauseArgs);
@@ -152,9 +160,9 @@ namespace Timeline.Tests.Helpers message = string.IsNullOrEmpty(message) ? "" : ", " + message;
assertions.HaveStatusCode(400, "Invalid Model Error must have 400 status code{0}", message)
.And.HaveCommonBody("Invalid Model Error must have CommonResponse body{0}", message)
- .Which.Code.Should().Be(ErrorCodes.Http.Common.InvalidModel,
+ .Which.Code.Should().Be(ErrorCodes.Common.InvalidModel,
"Invalid Model Error must have code {0} in body{1}",
- ErrorCodes.Http.Common.InvalidModel, message);
+ ErrorCodes.Common.InvalidModel, message);
}
}
}
diff --git a/Timeline.Tests/Helpers/TestApplication.cs b/Timeline.Tests/Helpers/TestApplication.cs index d18f2848..bc5deeec 100644 --- a/Timeline.Tests/Helpers/TestApplication.cs +++ b/Timeline.Tests/Helpers/TestApplication.cs @@ -1,4 +1,6 @@ using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.AspNetCore.TestHost;
+using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
@@ -8,19 +10,31 @@ namespace Timeline.Tests.Helpers {
public class TestApplication : IDisposable
{
- public TestDatabase Database { get; } = new TestDatabase();
+ public SqliteConnection DatabaseConnection { get; }
+
public WebApplicationFactory<Startup> Factory { get; }
public TestApplication(WebApplicationFactory<Startup> factory)
{
+ DatabaseConnection = new SqliteConnection("Data Source=:memory:;");
+ DatabaseConnection.Open();
+
+ var options = new DbContextOptionsBuilder<DevelopmentDatabaseContext>()
+ .UseSqlite(DatabaseConnection)
+ .Options;
+
+ using (var context = new DevelopmentDatabaseContext(options))
+ {
+ context.Database.EnsureCreated();
+ }
+
Factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
- services.AddEntityFrameworkSqlite();
services.AddDbContext<DatabaseContext, DevelopmentDatabaseContext>(options =>
{
- options.UseSqlite(Database.Connection);
+ options.UseSqlite(DatabaseConnection);
});
});
});
@@ -28,7 +42,8 @@ namespace Timeline.Tests.Helpers public void Dispose()
{
- Database.Dispose();
+ DatabaseConnection.Close();
+ DatabaseConnection.Dispose();
}
}
}
diff --git a/Timeline.Tests/Helpers/TestClock.cs b/Timeline.Tests/Helpers/TestClock.cs deleted file mode 100644 index 12b320d3..00000000 --- a/Timeline.Tests/Helpers/TestClock.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Timeline.Services; - -namespace Timeline.Tests.Helpers -{ - public class TestClock : IClock - { - public DateTime? MockCurrentTime { get; set; } = null; - - public DateTime GetCurrentTime() - { - return MockCurrentTime.GetValueOrDefault(DateTime.Now); - } - } -} diff --git a/Timeline.Tests/Helpers/TestDatabase.cs b/Timeline.Tests/Helpers/TestDatabase.cs deleted file mode 100644 index 9560f353..00000000 --- a/Timeline.Tests/Helpers/TestDatabase.cs +++ /dev/null @@ -1,89 +0,0 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using Timeline.Entities; -using Timeline.Models; -using Timeline.Services; - -namespace Timeline.Tests.Helpers -{ - public class TestDatabase : IDisposable - { - // currently password service is thread safe, so we share a static one. - private static PasswordService PasswordService { get; } = new PasswordService(); - - private static User CreateEntityFromMock(MockUser user) - { - return new User - { - Name = user.Username, - EncryptedPassword = PasswordService.HashPassword(user.Password), - RoleString = UserRoleConvert.ToString(user.Administrator), - Avatar = null - }; - } - - private static IEnumerable<User> CreateDefaultMockEntities() - { - // emmmmmmm. Never reuse the user instances because EF Core uses them, which will cause strange things. - yield return CreateEntityFromMock(MockUser.User); - yield return CreateEntityFromMock(MockUser.Admin); - } - - private static void InitDatabase(DatabaseContext context) - { - context.Database.EnsureCreated(); - context.Users.AddRange(CreateDefaultMockEntities()); - context.SaveChanges(); - } - - public SqliteConnection Connection { get; } - public DatabaseContext Context { get; } - - public TestDatabase() - { - Connection = new SqliteConnection("Data Source=:memory:;"); - Connection.Open(); - - var options = new DbContextOptionsBuilder<DevelopmentDatabaseContext>() - .UseSqlite(Connection) - .Options; - - Context = new DevelopmentDatabaseContext(options); - - InitDatabase(Context); - } - - private List<MockUser> _extraMockUsers; - - public IReadOnlyList<MockUser> ExtraMockUsers => _extraMockUsers; - - public void CreateExtraMockUsers(int count) - { - if (count <= 0) - throw new ArgumentOutOfRangeException(nameof(count), count, "Additional user count must be bigger than 0."); - if (_extraMockUsers != null) - throw new InvalidOperationException("Already create mock users."); - - _extraMockUsers = new List<MockUser>(); - for (int i = 0; i < count; i++) - { - _extraMockUsers.Add(new MockUser($"user{i}", $"password", false)); - } - - Context.AddRange(_extraMockUsers.Select(u => CreateEntityFromMock(u))); - Context.SaveChanges(); - } - - public void Dispose() - { - Context.Dispose(); - - Connection.Close(); - Connection.Dispose(); - } - - } -} diff --git a/Timeline.Tests/Helpers/UseCultureAttribute.cs b/Timeline.Tests/Helpers/UseCultureAttribute.cs deleted file mode 100644 index 017d77a8..00000000 --- a/Timeline.Tests/Helpers/UseCultureAttribute.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Globalization; -using System.Reflection; -using System.Threading; -using Xunit.Sdk; - - -namespace Timeline.Tests.Helpers -{ - // Copied from https://github.com/xunit/samples.xunit/blob/master/UseCulture/UseCultureAttribute.cs - - /// <summary> - /// Apply this attribute to your test method to replace the - /// <see cref="Thread.CurrentThread" /> <see cref="CultureInfo.CurrentCulture" /> and - /// <see cref="CultureInfo.CurrentUICulture" /> with another culture. - /// </summary> - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - public class UseCultureAttribute : BeforeAfterTestAttribute - { - readonly Lazy<CultureInfo> culture; - readonly Lazy<CultureInfo> uiCulture; - - CultureInfo originalCulture; - CultureInfo originalUICulture; - - /// <summary> - /// Replaces the culture and UI culture of the current thread with - /// <paramref name="culture" /> - /// </summary> - /// <param name="culture">The name of the culture.</param> - /// <remarks> - /// <para> - /// This constructor overload uses <paramref name="culture" /> for both - /// <see cref="Culture" /> and <see cref="UICulture" />. - /// </para> - /// </remarks> - public UseCultureAttribute(string culture) - : this(culture, culture) { } - - /// <summary> - /// Replaces the culture and UI culture of the current thread with - /// <paramref name="culture" /> and <paramref name="uiCulture" /> - /// </summary> - /// <param name="culture">The name of the culture.</param> - /// <param name="uiCulture">The name of the UI culture.</param> - public UseCultureAttribute(string culture, string uiCulture) - { - this.culture = new Lazy<CultureInfo>(() => new CultureInfo(culture, false)); - this.uiCulture = new Lazy<CultureInfo>(() => new CultureInfo(uiCulture, false)); - } - - /// <summary> - /// Gets the culture. - /// </summary> - public CultureInfo Culture { get { return culture.Value; } } - - /// <summary> - /// Gets the UI culture. - /// </summary> - public CultureInfo UICulture { get { return uiCulture.Value; } } - - /// <summary> - /// Stores the current <see cref="Thread.CurrentPrincipal" /> - /// <see cref="CultureInfo.CurrentCulture" /> and <see cref="CultureInfo.CurrentUICulture" /> - /// and replaces them with the new cultures defined in the constructor. - /// </summary> - /// <param name="methodUnderTest">The method under test</param> - public override void Before(MethodInfo methodUnderTest) - { - originalCulture = Thread.CurrentThread.CurrentCulture; - originalUICulture = Thread.CurrentThread.CurrentUICulture; - - Thread.CurrentThread.CurrentCulture = Culture; - Thread.CurrentThread.CurrentUICulture = UICulture; - - CultureInfo.CurrentCulture.ClearCachedData(); - CultureInfo.CurrentUICulture.ClearCachedData(); - } - - /// <summary> - /// Restores the original <see cref="CultureInfo.CurrentCulture" /> and - /// <see cref="CultureInfo.CurrentUICulture" /> to <see cref="Thread.CurrentPrincipal" /> - /// </summary> - /// <param name="methodUnderTest">The method under test</param> - public override void After(MethodInfo methodUnderTest) - { - Thread.CurrentThread.CurrentCulture = originalCulture; - Thread.CurrentThread.CurrentUICulture = originalUICulture; - - CultureInfo.CurrentCulture.ClearCachedData(); - CultureInfo.CurrentUICulture.ClearCachedData(); - } - } -} diff --git a/Timeline.Tests/IntegratedTests/AuthorizationTest.cs b/Timeline.Tests/IntegratedTests/AuthorizationTest.cs index 0bc094af..4aa6b3ae 100644 --- a/Timeline.Tests/IntegratedTests/AuthorizationTest.cs +++ b/Timeline.Tests/IntegratedTests/AuthorizationTest.cs @@ -22,7 +22,7 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task UnauthenticationTest()
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
var response = await client.GetAsync(AuthorizeUrl);
response.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
}
@@ -48,7 +48,7 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task AdminAuthorizationTest()
{
- using var client = await CreateClientAsAdmin();
+ using var client = await CreateClientAsAdministrator();
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 deleted file mode 100644 index 855179af..00000000 --- a/Timeline.Tests/IntegratedTests/I18nTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using System;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading.Tasks;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.IntegratedTests
-{
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1054:Uri parameters should not be strings")]
- public class I18nTest : IntegratedTestBase
- {
- private readonly HttpClient _client;
-
- public I18nTest(WebApplicationFactory<Startup> factory)
- : base(factory)
- {
- _client = Factory.CreateDefaultClient();
- }
-
- protected override void OnDispose()
- {
- _client.Dispose();
- }
-
- private const string DirectUrl = "testing/i18n/direct";
- private const string LocalizerUrl = "testing/i18n/localizer";
-
- [Theory]
- [InlineData(DirectUrl)]
- [InlineData(LocalizerUrl)]
- public async Task DefaultShouldReturnEnglish(string url)
- {
- (await _client.GetStringAsync(url)).Should().ContainEquivalentOf("English");
- }
-
- [Theory]
- [InlineData(DirectUrl, "en", true)]
- [InlineData(LocalizerUrl, "en", true)]
- [InlineData(DirectUrl, "en-US", true)]
- [InlineData(LocalizerUrl, "en-US", true)]
- [InlineData(DirectUrl, "zh", false)]
- [InlineData(LocalizerUrl, "zh", false)]
- public async Task ShouldWork(string url, string acceptLanguage, bool english)
- {
- var request = new HttpRequestMessage
- {
- Method = HttpMethod.Get,
- RequestUri = new Uri(url, UriKind.RelativeOrAbsolute)
- };
- request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(acceptLanguage));
- var body = await (await _client.SendAsync(request)).Content.ReadAsStringAsync();
- body.Should().ContainEquivalentOf(english ? "English" : "中文");
- request.Dispose();
- }
- }
-}
diff --git a/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs index 242a452d..dfde2ea5 100644 --- a/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs +++ b/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs @@ -1,51 +1,82 @@ -using Microsoft.AspNetCore.Mvc.Testing; +using AutoMapper;
+using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection;
using System; -using System.Collections.Generic; +using System.Collections.Generic;
using System.Net.Http; using System.Threading.Tasks; using Timeline.Models.Http; +using Timeline.Services;
using Timeline.Tests.Helpers; using Xunit; namespace Timeline.Tests.IntegratedTests { - public enum AuthType - { - None, - User, - Admin - } - - public static class AuthTypeExtensions + public abstract class IntegratedTestBase : IClassFixture<WebApplicationFactory<Startup>>, IDisposable { - 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.") - }; + static IntegratedTestBase()
+ {
+ FluentAssertions.AssertionOptions.AssertEquivalencyUsing(options =>
+ options.Excluding(m => m.RuntimeType == typeof(UserInfoLinks)));
} - public static string GetUsername(this AuthType authType) => authType.GetMockUser().Username; - } - - public abstract class IntegratedTestBase : IClassFixture<WebApplicationFactory<Startup>>, IDisposable - { protected TestApplication TestApp { get; } protected WebApplicationFactory<Startup> Factory => TestApp.Factory; - public IntegratedTestBase(WebApplicationFactory<Startup> factory) + public IntegratedTestBase(WebApplicationFactory<Startup> factory) : this(factory, 1) + { + + }
+
+ public IntegratedTestBase(WebApplicationFactory<Startup> factory, int userCount) { + if (userCount < 0) + throw new ArgumentOutOfRangeException(nameof(userCount), userCount, "User count can't be negative."); + TestApp = new TestApplication(factory); + + using (var scope = Factory.Services.CreateScope())
+ {
+ var users = new List<User>()
+ {
+ new User
+ {
+ Username = "admin",
+ Password = "adminpw",
+ Administrator = true,
+ Nickname = "administrator"
+ }
+ };
+
+ for (int i = 1; i <= userCount; i++)
+ {
+ users.Add(new User
+ {
+ Username = $"user{i}",
+ Password = $"user{i}pw",
+ Administrator = false,
+ Nickname = $"imuser{i}"
+ });
+ }
+
+ var userInfoList = new List<UserInfo>();
+
+ var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
+ var mapper = scope.ServiceProvider.GetRequiredService<IMapper>();
+
+ foreach (var user in users)
+ {
+ userService.CreateUser(user).Wait();
+ userInfoList.Add(mapper.Map<UserInfo>(user));
+ }
+
+ UserInfos = userInfoList;
+ }
} protected virtual void OnDispose() { - } public void Dispose() @@ -54,14 +85,9 @@ namespace Timeline.Tests.IntegratedTests TestApp.Dispose(); } - protected void CreateExtraMockUsers(int count) - { - TestApp.Database.CreateExtraMockUsers(count); - } - - protected IReadOnlyList<MockUser> ExtraMockUsers => TestApp.Database.ExtraMockUsers; + public IReadOnlyList<UserInfo> UserInfos { get; } - public Task<HttpClient> CreateClientWithNoAuth() + public Task<HttpClient> CreateDefaultClient() { return Task.FromResult(Factory.CreateDefaultClient()); } @@ -77,18 +103,24 @@ namespace Timeline.Tests.IntegratedTests return client; } - public Task<HttpClient> CreateClientAs(MockUser user) + public Task<HttpClient> CreateClientAs(int userNumber) { - if (user == null) - return CreateClientWithNoAuth(); - return CreateClientWithCredential(user.Username, user.Password); + if (userNumber < 0) + return CreateDefaultClient(); + if (userNumber == 0) + return CreateClientWithCredential("admin", "adminpw"); + else + return CreateClientWithCredential($"user{userNumber}", $"user{userNumber}pw"); } - public Task<HttpClient> CreateClientAs(AuthType authType) => CreateClientAs(authType.GetMockUser()); - - - public Task<HttpClient> CreateClientAsUser() => CreateClientAs(MockUser.User); - public Task<HttpClient> CreateClientAsAdmin() => CreateClientAs(MockUser.Admin); - + public Task<HttpClient> CreateClientAsAdministrator()
+ {
+ return CreateClientAs(0);
+ }
+
+ public Task<HttpClient> CreateClientAsUser()
+ {
+ return CreateClientAs(1);
+ } } } diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs index c5d0addd..81446fd8 100644 --- a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; -using Timeline.Models; using Timeline.Models.Http; using Timeline.Tests.Helpers; using Xunit; @@ -15,7 +14,7 @@ namespace Timeline.Tests.IntegratedTests public class PersonalTimelineTest : IntegratedTestBase { public PersonalTimelineTest(WebApplicationFactory<Startup> factory) - : base(factory) + : base(factory, 3) { } @@ -23,14 +22,82 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task TimelineGet_Should_Work() { - using var client = await CreateClientWithNoAuth(); - var res = await client.GetAsync("users/user/timeline"); + using var client = await CreateDefaultClient(); + var res = await client.GetAsync("users/user1/timeline"); var body = res.Should().HaveStatusCode(200) .And.HaveJsonBody<BaseTimelineInfo>().Which; - body.Owner.Should().Be("user"); + body.Owner.Should().BeEquivalentTo(UserInfos[1]); body.Visibility.Should().Be(TimelineVisibility.Register); body.Description.Should().Be(""); body.Members.Should().NotBeNull().And.BeEmpty(); + }
+
+ [Fact] + public async Task InvalidModel_BadUsername() + { + using var client = await CreateClientAsAdministrator(); + {
+ var res = await client.GetAsync("users/user!!!/timeline"); + res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PatchAsJsonAsync("users/user!!!/timeline", new TimelinePatchRequest { }); + res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PutAsync("users/user!!!/timeline/members/user1", null); + res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.DeleteAsync("users/user!!!/timeline/members/user1"); + res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.GetAsync("users/user!!!/timeline/posts"); + res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user!!!/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); + res.Should().BeInvalidModel();
+ } + {
+ var res = await client.DeleteAsync("users/user!!!/timeline/posts/123");
+ res.Should().BeInvalidModel();
+ } + }
+
+ [Fact] + public async Task NotFound() + { + using var client = await CreateClientAsAdministrator(); + {
+ var res = await client.GetAsync("users/usernotexist/timeline"); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PatchAsJsonAsync("users/usernotexist/timeline", new TimelinePatchRequest { }); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PutAsync("users/usernotexist/timeline/members/user1", null); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.DeleteAsync("users/usernotexist/timeline/members/user1"); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.GetAsync("users/usernotexist/timeline/posts"); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/usernotexist/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); + res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ } + {
+ var res = await client.DeleteAsync("users/usernotexist/timeline/posts/123");
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ } } [Fact] @@ -40,7 +107,7 @@ namespace Timeline.Tests.IntegratedTests async Task AssertDescription(string description) { - var res = await client.GetAsync("users/user/timeline"); + var res = await client.GetAsync("users/user1/timeline"); var body = res.Should().HaveStatusCode(200) .And.HaveJsonBody<BaseTimelineInfo>() .Which.Description.Should().Be(description); @@ -50,21 +117,24 @@ namespace Timeline.Tests.IntegratedTests await AssertDescription(""); { - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Description = mockDescription }); - res.Should().HaveStatusCode(200); + var res = await client.PatchAsJsonAsync("users/user1/timeline", + new TimelinePatchRequest { Description = mockDescription }); + res.Should().HaveStatusCode(200) + .And.HaveJsonBody<BaseTimelineInfo>().Which.Description.Should().Be(mockDescription); await AssertDescription(mockDescription); } { - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Description = null }); - res.Should().HaveStatusCode(200); + var res = await client.PatchAsJsonAsync("users/user1/timeline", + new TimelinePatchRequest { Description = null }); + res.Should().HaveStatusCode(200) + .And.HaveJsonBody<BaseTimelineInfo>().Which.Description.Should().Be(mockDescription); await AssertDescription(mockDescription); } { - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Description = "" }); - res.Should().HaveStatusCode(200); + var res = await client.PatchAsJsonAsync("users/user1/timeline", + new TimelinePatchRequest { Description = "" }); + res.Should().HaveStatusCode(200) + .And.HaveJsonBody<BaseTimelineInfo>().Which.Description.Should().Be(""); await AssertDescription(""); } } @@ -72,11 +142,10 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Member_Should_Work() { - const string getUrl = "users/user/timeline"; - const string changeUrl = "users/user/timeline/op/member"; + const string getUrl = "users/user1/timeline"; using var client = await CreateClientAsUser(); - async Task AssertMembers(IList<string> members) + async Task AssertMembers(IList<UserInfo> members) { var res = await client.GetAsync(getUrl); res.Should().HaveStatusCode(200) @@ -94,90 +163,86 @@ namespace Timeline.Tests.IntegratedTests await AssertEmptyMembers(); { - var res = await client.PostAsJsonAsync(changeUrl, - new TimelineMemberChangeRequest { Add = new List<string> { "admin", "usernotexist" } }); - res.Should().HaveStatusCode(400) - .And.HaveCommonBody() - .Which.Code.Should().Be(ErrorCodes.Http.Timeline.ChangeMemberUserNotExist); - } - { - var res = await client.PostAsJsonAsync(changeUrl, - new TimelineMemberChangeRequest { Remove = new List<string> { "admin", "usernotexist" } }); + var res = await client.PutAsync("/users/user1/timeline/members/usernotexist", null); res.Should().HaveStatusCode(400) - .And.HaveCommonBody() - .Which.Code.Should().Be(ErrorCodes.Http.Timeline.ChangeMemberUserNotExist); + .And.HaveCommonBody(ErrorCodes.TimelineController.MemberPut_NotExist); } + await AssertEmptyMembers(); { - var res = await client.PostAsJsonAsync(changeUrl, - new TimelineMemberChangeRequest { Add = new List<string> { "admin" }, Remove = new List<string> { "admin" } }); + var res = await client.PutAsync("/users/user1/timeline/members/user2", null); res.Should().HaveStatusCode(200); - await AssertEmptyMembers(); } + await AssertMembers(new List<UserInfo> { UserInfos[2] }); { - var res = await client.PostAsJsonAsync(changeUrl, - new TimelineMemberChangeRequest { Add = new List<string> { "admin" } }); - res.Should().HaveStatusCode(200); - await AssertMembers(new List<string> { "admin" }); - } + var res = await client.DeleteAsync("/users/user1/timeline/members/user2"); + res.Should().BeDelete(true); + }
+ await AssertEmptyMembers(); { - var res = await client.PostAsJsonAsync(changeUrl, - new TimelineMemberChangeRequest { Remove = new List<string> { "admin" } }); - res.Should().HaveStatusCode(200); - await AssertEmptyMembers(); + var res = await client.DeleteAsync("/users/user1/timeline/members/users2"); + res.Should().BeDelete(false); } + await AssertEmptyMembers(); } [Theory] - [InlineData(AuthType.None, 200, 401, 401, 401, 401)] - [InlineData(AuthType.User, 200, 200, 403, 200, 403)] - [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) + [InlineData(-1, 200, 401, 401, 401, 401)] + [InlineData(1, 200, 200, 403, 200, 403)] + [InlineData(0, 200, 200, 200, 200, 200)] + public async Task Permission_Timeline(int userNumber, int get, int opPatchUser, int opPatchAdmin, int opMemberUser, int opMemberAdmin) { - using var client = await CreateClientAs(authType); + using var client = await CreateClientAs(userNumber); { - var res = await client.GetAsync("users/user/timeline"); + var res = await client.GetAsync("users/user1/timeline"); res.Should().HaveStatusCode(get); } { - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Description = "hahaha" }); - res.Should().HaveStatusCode(opPropertyUser); + var res = await client.PatchAsJsonAsync("users/user1/timeline", new TimelinePatchRequest { Description = "hahaha" }); + res.Should().HaveStatusCode(opPatchUser); } { - var res = await client.PostAsJsonAsync("users/admin/timeline/op/property", - new TimelinePropertyChangeRequest { Description = "hahaha" }); - res.Should().HaveStatusCode(opPropertyAdmin); + var res = await client.PatchAsJsonAsync("users/admin/timeline", new TimelinePatchRequest { Description = "hahaha" }); + res.Should().HaveStatusCode(opPatchAdmin); } { - var res = await client.PostAsJsonAsync("users/user/timeline/op/member", - new TimelineMemberChangeRequest { Add = new List<string> { "admin" } }); + var res = await client.PutAsync("users/user1/timeline/members/user2", null); + res.Should().HaveStatusCode(opMemberUser); + }
+
+ { + var res = await client.DeleteAsync("users/user1/timeline/members/user2"); res.Should().HaveStatusCode(opMemberUser); } { - var res = await client.PostAsJsonAsync("users/admin/timeline/op/member", - new TimelineMemberChangeRequest { Add = new List<string> { "user" } }); + var res = await client.PutAsync("users/admin/timeline/members/user2", null); + res.Should().HaveStatusCode(opMemberAdmin); + }
+
+ { + var res = await client.DeleteAsync("users/admin/timeline/members/user2"); res.Should().HaveStatusCode(opMemberAdmin); } } [Fact] - public async Task Permission_GetPost() + public async Task Visibility_Test() { - const string userUrl = "users/user/timeline/posts"; + const string userUrl = "users/user1/timeline/posts"; const string adminUrl = "users/admin/timeline/posts"; - { + {
+
using var client = await CreateClientAsUser(); - var res = await client.PostAsync("users/user/timeline/op/property", - new StringContent(@"{""visibility"":""abcdefg""}", System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json)); + using var content = new StringContent(@"{""visibility"":""abcdefg""}", System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json); + var res = await client.PatchAsync("users/user1/timeline", content); res.Should().BeInvalidModel(); } { // default visibility is registered { - using var client = await CreateClientWithNoAuth(); + using var client = await CreateDefaultClient(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(403); } @@ -192,12 +257,12 @@ namespace Timeline.Tests.IntegratedTests { // change visibility to public { using var client = await CreateClientAsUser(); - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Public }); + var res = await client.PatchAsJsonAsync("users/user1/timeline", + new TimelinePatchRequest { Visibility = TimelineVisibility.Public }); res.Should().HaveStatusCode(200); } { - using var client = await CreateClientWithNoAuth(); + using var client = await CreateDefaultClient(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(200); } @@ -205,20 +270,20 @@ namespace Timeline.Tests.IntegratedTests { // change visibility to private { - using var client = await CreateClientAsAdmin(); + using var client = await CreateClientAsAdministrator(); { - var res = await client.PostAsJsonAsync("users/user/timeline/op/property", - new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Private }); + var res = await client.PatchAsJsonAsync("users/user1/timeline", + new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); res.Should().HaveStatusCode(200); } { - var res = await client.PostAsJsonAsync("users/admin/timeline/op/property", - new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Private }); + var res = await client.PatchAsJsonAsync("users/admin/timeline", + new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); res.Should().HaveStatusCode(200); } } { - using var client = await CreateClientWithNoAuth(); + using var client = await CreateDefaultClient(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(403); } @@ -228,14 +293,13 @@ namespace Timeline.Tests.IntegratedTests res.Should().HaveStatusCode(403); } { // admin can read user's - using var client = await CreateClientAsAdmin(); + using var client = await CreateClientAsAdministrator(); var res = await client.GetAsync(userUrl); res.Should().HaveStatusCode(200); } { // add member - using var client = await CreateClientAsAdmin(); - var res = await client.PostAsJsonAsync("users/admin/timeline/op/member", - new TimelineMemberChangeRequest { Add = new List<string> { "user" } }); + using var client = await CreateClientAsAdministrator(); + var res = await client.PutAsync("/users/admin/timeline/members/user1", null); res.Should().HaveStatusCode(200); } { // now user can read admin's @@ -250,19 +314,16 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Permission_Post_Create() { - CreateExtraMockUsers(1); - using (var client = await CreateClientAsUser()) { - var res = await client.PostAsJsonAsync("users/user/timeline/op/member", - new TimelineMemberChangeRequest { Add = new List<string> { "user0" } }); + var res = await client.PutAsync("users/user1/timeline/members/user2", null); res.Should().HaveStatusCode(200); } - using (var client = await CreateClientWithNoAuth()) + using (var client = await CreateDefaultClient()) { { // no auth should get 401 - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); res.Should().HaveStatusCode(401); } @@ -271,30 +332,30 @@ namespace Timeline.Tests.IntegratedTests using (var client = await CreateClientAsUser()) { { // post self's - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); res.Should().HaveStatusCode(200); } { // post other not as a member should get 403 - var res = await client.PostAsJsonAsync("users/admin/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/admin/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); res.Should().HaveStatusCode(403); } } - using (var client = await CreateClientAsAdmin()) + using (var client = await CreateClientAsAdministrator()) { { // post as admin - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); res.Should().HaveStatusCode(200); } } - using (var client = await CreateClientAs(ExtraMockUsers[0])) + using (var client = await CreateClientAs(2)) { { // post as member - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); res.Should().HaveStatusCode(200); } @@ -304,69 +365,66 @@ namespace Timeline.Tests.IntegratedTests [Fact] public async Task Permission_Post_Delete() { - CreateExtraMockUsers(2); - - async Task<long> CreatePost(MockUser auth, string timeline) + async Task<long> CreatePost(int userNumber) { - using var client = await CreateClientAs(auth); - var res = await client.PostAsJsonAsync($"users/{timeline}/timeline/postop/create", + using var client = await CreateClientAs(userNumber); + var res = await client.PostAsJsonAsync($"users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa" }); return res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostCreateResponse>() + .And.HaveJsonBody<TimelinePostInfo>() .Which.Id; } using (var client = await CreateClientAsUser()) { - var res = await client.PostAsJsonAsync("users/user/timeline/op/member", - new TimelineMemberChangeRequest { Add = new List<string> { "user0", "user1" } }); - res.Should().HaveStatusCode(200); + {
+ var res = await client.PutAsync("users/user1/timeline/members/user2", null);
+ res.Should().HaveStatusCode(200); + }
+ {
+ var res = await client.PutAsync("users/user1/timeline/members/user3", null);
+ res.Should().HaveStatusCode(200); + } } { // no auth should get 401 - using var client = await CreateClientWithNoAuth(); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = 12 }); + using var client = await CreateDefaultClient(); + var res = await client.DeleteAsync("users/user1/timeline/posts/12"); res.Should().HaveStatusCode(401); } { // self can delete self - var postId = await CreatePost(MockUser.User, "user"); + var postId = await CreatePost(1); using var client = await CreateClientAsUser(); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = postId }); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{postId}"); res.Should().HaveStatusCode(200); } { // admin can delete any - var postId = await CreatePost(MockUser.User, "user"); - using var client = await CreateClientAsAdmin(); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = postId }); + var postId = await CreatePost(1); + using var client = await CreateClientAsAdministrator(); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{postId}"); res.Should().HaveStatusCode(200); } { // owner can delete other - var postId = await CreatePost(ExtraMockUsers[0], "user"); + var postId = await CreatePost(2); using var client = await CreateClientAsUser(); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = postId }); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{postId}"); res.Should().HaveStatusCode(200); } { // author can delete self - var postId = await CreatePost(ExtraMockUsers[0], "user"); - using var client = await CreateClientAs(ExtraMockUsers[0]); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = postId }); + var postId = await CreatePost(2); + using var client = await CreateClientAs(2); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{postId}"); res.Should().HaveStatusCode(200); } { // otherwise is forbidden - var postId = await CreatePost(ExtraMockUsers[0], "user"); - using var client = await CreateClientAs(ExtraMockUsers[1]); - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = postId }); + var postId = await CreatePost(2); + using var client = await CreateClientAs(3); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{postId}"); res.Should().HaveStatusCode(403); } } @@ -377,96 +435,69 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAsUser(); { - var res = await client.GetAsync("users/user/timeline/posts"); + var res = await client.GetAsync("users/user1/timeline/posts"); res.Should().HaveStatusCode(200) .And.HaveJsonBody<TimelinePostInfo[]>() .Which.Should().NotBeNull().And.BeEmpty(); } { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = null }); res.Should().BeInvalidModel(); } const string mockContent = "aaa"; - TimelinePostCreateResponse createRes; + TimelinePostInfo createRes; { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = mockContent }); var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostCreateResponse>() + .And.HaveJsonBody<TimelinePostInfo>() .Which; body.Should().NotBeNull(); + body.Content.Should().Be(mockContent); + body.Author.Should().BeEquivalentTo(UserInfos[1]); createRes = body; } { - var res = await client.GetAsync("users/user/timeline/posts"); + var res = await client.GetAsync("users/user1/timeline/posts"); res.Should().HaveStatusCode(200) .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo( - new TimelinePostInfo - { - Id = createRes.Id, - Author = "user", - Content = mockContent, - Time = createRes.Time - }); + .Which.Should().NotBeNull().And.BeEquivalentTo(createRes); } const string mockContent2 = "bbb"; var mockTime2 = DateTime.Now.AddDays(-1); - TimelinePostCreateResponse createRes2; + TimelinePostInfo createRes2; { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = mockContent2, Time = mockTime2 }); var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostCreateResponse>() + .And.HaveJsonBody<TimelinePostInfo>() .Which; - body.Should().NotBeNull(); + body.Should().NotBeNull();
+ body.Content.Should().Be(mockContent2); + body.Author.Should().BeEquivalentTo(UserInfos[1]); + body.Time.Should().BeCloseTo(mockTime2, 1000); createRes2 = body; } { - var res = await client.GetAsync("users/user/timeline/posts"); + var res = await client.GetAsync("users/user1/timeline/posts"); res.Should().HaveStatusCode(200) .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo( - new TimelinePostInfo - { - Id = createRes.Id, - Author = "user", - Content = mockContent, - Time = createRes.Time - }, - new TimelinePostInfo - { - Id = createRes2.Id, - Author = "user", - Content = mockContent2, - Time = createRes2.Time - }); + .Which.Should().NotBeNull().And.BeEquivalentTo(createRes, createRes2); } { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = createRes.Id }); - res.Should().HaveStatusCode(200); + var res = await client.DeleteAsync($"users/user1/timeline/posts/{createRes.Id}"); + res.Should().BeDelete(true); } { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete", - new TimelinePostDeleteRequest { Id = 30000 }); - res.Should().HaveStatusCode(400) - .And.HaveCommonBody() - .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostOperationDeleteNotExist); + var res = await client.DeleteAsync("users/user1/timeline/posts/30000"); + res.Should().BeDelete(false); } { - var res = await client.GetAsync("users/user/timeline/posts"); + var res = await client.GetAsync("users/user1/timeline/posts"); res.Should().HaveStatusCode(200) .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo( - new TimelinePostInfo - { - Id = createRes2.Id, - Author = "user", - Content = mockContent2, - Time = createRes2.Time - }); + .Which.Should().NotBeNull().And.BeEquivalentTo(createRes2); } } } @@ -478,10 +509,10 @@ namespace Timeline.Tests.IntegratedTests async Task<long> CreatePost(DateTime time) { - var res = await client.PostAsJsonAsync("users/user/timeline/postop/create", + var res = await client.PostAsJsonAsync("users/user1/timeline/posts", new TimelinePostCreateRequest { Content = "aaa", Time = time }); return res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostCreateResponse>() + .And.HaveJsonBody<TimelinePostInfo>() .Which.Id; } @@ -491,7 +522,7 @@ namespace Timeline.Tests.IntegratedTests var id2 = await CreatePost(now); { - var res = await client.GetAsync("users/user/timeline/posts"); + var res = await client.GetAsync("users/user1/timeline/posts"); res.Should().HaveStatusCode(200) .And.HaveJsonBody<TimelinePostInfo[]>() .Which.Select(p => p.Id).Should().Equal(id1, id2, id0); diff --git a/Timeline.Tests/IntegratedTests/TokenTest.cs b/Timeline.Tests/IntegratedTests/TokenTest.cs index e62228fc..928d546c 100644 --- a/Timeline.Tests/IntegratedTests/TokenTest.cs +++ b/Timeline.Tests/IntegratedTests/TokenTest.cs @@ -8,7 +8,6 @@ using Timeline.Models.Http; using Timeline.Services;
using Timeline.Tests.Helpers;
using Xunit;
-using static Timeline.ErrorCodes.Http.Token;
namespace Timeline.Tests.IntegratedTests
{
@@ -42,7 +41,7 @@ namespace Timeline.Tests.IntegratedTests [MemberData(nameof(CreateToken_InvalidModel_Data))]
public async Task CreateToken_InvalidModel(string username, string password, int expire)
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
(await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest
{
Username = username,
@@ -54,37 +53,37 @@ namespace Timeline.Tests.IntegratedTests public static IEnumerable<object[]> CreateToken_UserCredential_Data()
{
yield return new[] { "usernotexist", "p" };
- yield return new[] { MockUser.User.Username, "???" };
+ yield return new[] { "user1", "???" };
}
[Theory]
[MemberData(nameof(CreateToken_UserCredential_Data))]
public async void CreateToken_UserCredential(string username, string password)
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
var response = await client.PostAsJsonAsync(CreateTokenUrl,
new CreateTokenRequest { Username = username, Password = password });
response.Should().HaveStatusCode(400)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Create.BadCredential);
+ .Which.Code.Should().Be(ErrorCodes.TokenController.Create_BadCredential);
}
[Fact]
public async Task CreateToken_Success()
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
var response = await client.PostAsJsonAsync(CreateTokenUrl,
- new CreateTokenRequest { Username = MockUser.User.Username, Password = MockUser.User.Password });
+ new CreateTokenRequest { Username = "user1", Password = "user1pw" });
var body = response.Should().HaveStatusCode(200)
.And.HaveJsonBody<CreateTokenResponse>().Which;
body.Token.Should().NotBeNullOrWhiteSpace();
- body.User.Should().BeEquivalentTo(MockUser.User.Info);
+ body.User.Should().BeEquivalentTo(UserInfos[1]);
}
[Fact]
public async Task VerifyToken_InvalidModel()
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
(await client.PostAsJsonAsync(VerifyTokenUrl,
new VerifyTokenRequest { Token = null })).Should().BeInvalidModel();
}
@@ -92,51 +91,51 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task VerifyToken_BadFormat()
{
- using var client = await CreateClientWithNoAuth();
+ using var client = await CreateDefaultClient();
var response = await client.PostAsJsonAsync(VerifyTokenUrl,
new VerifyTokenRequest { Token = "bad token hahaha" });
response.Should().HaveStatusCode(400)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Verify.BadFormat);
+ .Which.Code.Should().Be(ErrorCodes.TokenController.Verify_BadFormat);
}
[Fact]
public async Task VerifyToken_OldVersion()
{
- using var client = await CreateClientWithNoAuth();
- var token = (await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password)).Token;
+ using var client = await CreateDefaultClient();
+ var token = (await CreateUserTokenAsync(client, "user1", "user1pw")).Token;
- using (var scope = Factory.Server.Host.Services.CreateScope()) // UserService is scoped.
+ using (var scope = Factory.Services.CreateScope()) // UserService is scoped.
{
// create a user for test
var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
- await userService.PatchUser(MockUser.User.Username, null, null);
+ await userService.ModifyUser("user1", new User { Password = "user1pw" });
}
(await client.PostAsJsonAsync(VerifyTokenUrl,
new VerifyTokenRequest { Token = token }))
.Should().HaveStatusCode(400)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Verify.OldVersion);
+ .Which.Code.Should().Be(ErrorCodes.TokenController.Verify_OldVersion);
}
[Fact]
public async Task VerifyToken_UserNotExist()
{
- using var client = await CreateClientWithNoAuth();
- var token = (await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password)).Token;
+ using var client = await CreateDefaultClient();
+ var token = (await CreateUserTokenAsync(client, "user1", "user1pw")).Token;
using (var scope = Factory.Server.Host.Services.CreateScope()) // UserService is scoped.
{
var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
- await userService.DeleteUser(MockUser.User.Username);
+ await userService.DeleteUser("user1");
}
(await client.PostAsJsonAsync(VerifyTokenUrl,
new VerifyTokenRequest { Token = token }))
.Should().HaveStatusCode(400)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Verify.UserNotExist);
+ .Which.Code.Should().Be(ErrorCodes.TokenController.Verify_UserNotExist);
}
//[Fact]
@@ -160,13 +159,13 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task VerifyToken_Success()
{
- using var client = await CreateClientWithNoAuth();
- var createTokenResult = await CreateUserTokenAsync(client, MockUser.User.Username, MockUser.User.Password);
+ using var client = await CreateDefaultClient();
+ var createTokenResult = await CreateUserTokenAsync(client, "user1", "user1pw");
var response = await client.PostAsJsonAsync(VerifyTokenUrl,
new VerifyTokenRequest { Token = createTokenResult.Token });
response.Should().HaveStatusCode(200)
.And.HaveJsonBody<VerifyTokenResponse>()
- .Which.User.Should().BeEquivalentTo(MockUser.User.Info);
+ .Which.User.Should().BeEquivalentTo(UserInfos[1]);
}
}
}
diff --git a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs index 25a7b675..fa0120f1 100644 --- a/Timeline.Tests/IntegratedTests/UserAvatarTest.cs +++ b/Timeline.Tests/IntegratedTests/UserAvatarTest.cs @@ -13,11 +13,10 @@ using System.Net; using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
+using Timeline.Models.Http;
using Timeline.Services;
using Timeline.Tests.Helpers;
using Xunit;
-using static Timeline.ErrorCodes.Http.Common;
-using static Timeline.ErrorCodes.Http.UserAvatar;
namespace Timeline.Tests.IntegratedTests
{
@@ -30,7 +29,6 @@ namespace Timeline.Tests.IntegratedTests }
[Fact]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpMessageRequest should be disposed ???")]
public async Task Test()
{
Avatar mockAvatar = new Avatar
@@ -45,13 +43,13 @@ namespace Timeline.Tests.IntegratedTests var res = await client.GetAsync("users/usernotexist/avatar");
res.Should().HaveStatusCode(404)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Get.UserNotExist);
+ .Which.Code.Should().Be(ErrorCodes.UserCommon.NotExist);
}
var env = Factory.Server.Host.Services.GetRequiredService<IWebHostEnvironment>();
var defaultAvatarData = await File.ReadAllBytesAsync(Path.Combine(env.ContentRootPath, "default-avatar.png"));
- async Task GetReturnDefault(string username = "user")
+ async Task GetReturnDefault(string username = "user1")
{
var res = await client.GetAsync($"users/{username}/avatar");
res.Should().HaveStatusCode(200);
@@ -62,7 +60,7 @@ namespace Timeline.Tests.IntegratedTests EntityTagHeaderValue eTag;
{
- var res = await client.GetAsync($"users/user/avatar");
+ var res = await client.GetAsync($"users/user1/avatar");
res.Should().HaveStatusCode(200);
res.Content.Headers.ContentType.MediaType.Should().Be("image/png");
var body = await res.Content.ReadAsByteArrayAsync();
@@ -77,21 +75,21 @@ namespace Timeline.Tests.IntegratedTests await GetReturnDefault("admin");
{
- var request = new HttpRequestMessage()
+ using var request = new HttpRequestMessage()
{
- RequestUri = new Uri(client.BaseAddress, "users/user/avatar"),
+ RequestUri = new Uri(client.BaseAddress, "users/user1/avatar"),
Method = HttpMethod.Get,
};
request.Headers.TryAddWithoutValidation("If-None-Match", "\"dsdfd");
var res = await client.SendAsync(request);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Header.IfNonMatch.BadFormat);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.IfNonMatch_BadFormat);
}
{
- var request = new HttpRequestMessage()
+ using var request = new HttpRequestMessage()
{
- RequestUri = new Uri(client.BaseAddress, "users/user/avatar"),
+ RequestUri = new Uri(client.BaseAddress, "users/user1/avatar"),
Method = HttpMethod.Get,
};
request.Headers.TryAddWithoutValidation("If-None-Match", "\"aaa\"");
@@ -100,9 +98,9 @@ namespace Timeline.Tests.IntegratedTests }
{
- var request = new HttpRequestMessage()
+ using var request = new HttpRequestMessage()
{
- RequestUri = new Uri(client.BaseAddress, "users/user/avatar"),
+ RequestUri = new Uri(client.BaseAddress, "users/user1/avatar"),
Method = HttpMethod.Get,
};
request.Headers.Add("If-None-Match", eTag.ToString());
@@ -111,85 +109,85 @@ namespace Timeline.Tests.IntegratedTests }
{
- var content = new ByteArrayContent(new[] { (byte)0x00 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00 });
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Http.Filter.Header.ContentLength.Missing); ;
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentLength_Missing); ;
}
{
- var content = new ByteArrayContent(new[] { (byte)0x00 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00 });
content.Headers.ContentLength = 1;
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Http.Filter.Header.ContentType.Missing);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentType_Missing);
}
{
- var content = new ByteArrayContent(new[] { (byte)0x00 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00 });
content.Headers.ContentLength = 0;
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Http.Filter.Header.ContentLength.Zero);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Header.ContentLength_Zero);
}
{
- var res = await client.PutByteArrayAsync("users/user/avatar", new[] { (byte)0x00 }, "image/notaccept");
+ var res = await client.PutByteArrayAsync("users/user1/avatar", new[] { (byte)0x00 }, "image/notaccept");
res.Should().HaveStatusCode(HttpStatusCode.UnsupportedMediaType);
}
{
- var content = new ByteArrayContent(new[] { (byte)0x00 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00 });
content.Headers.ContentLength = 1000 * 1000 * 11;
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Content.TooBig);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Content.TooBig);
}
{
- var content = new ByteArrayContent(new[] { (byte)0x00 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00 });
content.Headers.ContentLength = 2;
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Content.UnmatchedLength_Smaller);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Content.UnmatchedLength_Smaller);
}
{
- var content = new ByteArrayContent(new[] { (byte)0x00, (byte)0x01 });
+ using var content = new ByteArrayContent(new[] { (byte)0x00, (byte)0x01 });
content.Headers.ContentLength = 1;
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
- var res = await client.PutAsync("users/user/avatar", content);
+ var res = await client.PutAsync("users/user1/avatar", content);
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Content.UnmatchedLength_Bigger);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Content.UnmatchedLength_Bigger);
}
{
- var res = await client.PutByteArrayAsync("users/user/avatar", new[] { (byte)0x00 }, "image/png");
+ var res = await client.PutByteArrayAsync("users/user1/avatar", new[] { (byte)0x00 }, "image/png");
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Put.BadFormat_CantDecode);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.UserAvatar.BadFormat_CantDecode);
}
{
- var res = await client.PutByteArrayAsync("users/user/avatar", mockAvatar.Data, "image/jpeg");
+ var res = await client.PutByteArrayAsync("users/user1/avatar", mockAvatar.Data, "image/jpeg");
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Put.BadFormat_UnmatchedFormat);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.UserAvatar.BadFormat_UnmatchedFormat);
}
{
- var res = await client.PutByteArrayAsync("users/user/avatar", ImageHelper.CreatePngWithSize(100, 200), "image/png");
+ var res = await client.PutByteArrayAsync("users/user1/avatar", ImageHelper.CreatePngWithSize(100, 200), "image/png");
res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody().Which.Code.Should().Be(Put.BadFormat_BadSize);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.UserAvatar.BadFormat_BadSize);
}
{
- var res = await client.PutByteArrayAsync("users/user/avatar", mockAvatar.Data, mockAvatar.Type);
+ var res = await client.PutByteArrayAsync("users/user1/avatar", mockAvatar.Data, mockAvatar.Type);
res.Should().HaveStatusCode(HttpStatusCode.OK);
- var res2 = await client.GetAsync("users/user/avatar");
+ var res2 = await client.GetAsync("users/user1/avatar");
res2.Should().HaveStatusCode(200);
res2.Content.Headers.ContentType.MediaType.Should().Be(mockAvatar.Type);
var body = await res2.Content.ReadAsByteArrayAsync();
@@ -205,40 +203,40 @@ namespace Timeline.Tests.IntegratedTests foreach ((var mimeType, var format) in formats)
{
- var res = await client.PutByteArrayAsync("users/user/avatar", ImageHelper.CreateImageWithSize(100, 100, format), mimeType);
+ var res = await client.PutByteArrayAsync("users/user1/avatar", ImageHelper.CreateImageWithSize(100, 100, format), mimeType);
res.Should().HaveStatusCode(HttpStatusCode.OK);
}
{
var res = await client.PutByteArrayAsync("users/admin/avatar", new[] { (byte)0x00 }, "image/png");
res.Should().HaveStatusCode(HttpStatusCode.Forbidden)
- .And.HaveCommonBody().Which.Code.Should().Be(Put.Forbid);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Forbid);
}
{
var res = await client.DeleteAsync("users/admin/avatar");
res.Should().HaveStatusCode(HttpStatusCode.Forbidden)
- .And.HaveCommonBody().Which.Code.Should().Be(Delete.Forbid);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.Common.Forbid);
}
for (int i = 0; i < 2; i++) // double delete should work.
{
- var res = await client.DeleteAsync("users/user/avatar");
+ var res = await client.DeleteAsync("users/user1/avatar");
res.Should().HaveStatusCode(200);
await GetReturnDefault();
}
}
// Authorization check.
- using (var client = await CreateClientAsAdmin())
+ using (var client = await CreateClientAsAdministrator())
{
{
- var res = await client.PutByteArrayAsync("users/user/avatar", mockAvatar.Data, mockAvatar.Type);
+ var res = await client.PutByteArrayAsync("users/user1/avatar", mockAvatar.Data, mockAvatar.Type);
res.Should().HaveStatusCode(HttpStatusCode.OK);
}
{
- var res = await client.DeleteAsync("users/user/avatar");
+ var res = await client.DeleteAsync("users/user1/avatar");
res.Should().HaveStatusCode(HttpStatusCode.OK);
}
@@ -246,18 +244,18 @@ namespace Timeline.Tests.IntegratedTests var res = await client.PutByteArrayAsync("users/usernotexist/avatar", new[] { (byte)0x00 }, "image/png");
res.Should().HaveStatusCode(400)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Put.UserNotExist);
+ .Which.Code.Should().Be(ErrorCodes.UserCommon.NotExist);
}
{
var res = await client.DeleteAsync("users/usernotexist/avatar");
res.Should().HaveStatusCode(400)
- .And.HaveCommonBody().Which.Code.Should().Be(Delete.UserNotExist);
+ .And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.UserCommon.NotExist);
}
}
// bad username check
- using (var client = await CreateClientAsAdmin())
+ using (var client = await CreateClientAsAdministrator())
{
{
var res = await client.GetAsync("users/u!ser/avatar");
diff --git a/Timeline.Tests/IntegratedTests/UserDetailTest.cs b/Timeline.Tests/IntegratedTests/UserDetailTest.cs deleted file mode 100644 index 932c287e..00000000 --- a/Timeline.Tests/IntegratedTests/UserDetailTest.cs +++ /dev/null @@ -1,153 +0,0 @@ -using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using System.Net;
-using System.Net.Http.Headers;
-using System.Net.Mime;
-using System.Threading.Tasks;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.IntegratedTests
-{
- public class UserDetailTest : IntegratedTestBase
- {
- public UserDetailTest(WebApplicationFactory<Startup> factory)
- : base(factory)
- {
-
- }
-
- [Fact]
- public async Task PermissionTest()
- {
- { // unauthorize
- using var client = await CreateClientWithNoAuth();
- { // GET
- var res = await client.GetAsync($"users/{MockUser.User.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- { // PUT
- var res = await client.PutStringAsync($"users/{MockUser.User.Username}/nickname", "aaa");
- res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
- }
- { // DELETE
- var res = await client.DeleteAsync($"users/{MockUser.User.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
- }
- }
- { // user
- using var client = await CreateClientAsUser();
- { // GET
- var res = await client.GetAsync($"users/{MockUser.User.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- { // PUT self
- var res = await client.PutStringAsync($"users/{MockUser.User.Username}/nickname", "aaa");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- { // PUT other
- var res = await client.PutStringAsync($"users/{MockUser.Admin.Username}/nickname", "aaa");
- res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
- }
- { // DELETE self
- var res = await client.DeleteAsync($"users/{MockUser.User.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- { // DELETE other
- var res = await client.DeleteAsync($"users/{MockUser.Admin.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
- }
- }
- { // user
- using var client = await CreateClientAsAdmin();
- { // PUT other
- var res = await client.PutStringAsync($"users/{MockUser.User.Username}/nickname", "aaa");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- { // DELETE other
- var res = await client.DeleteAsync($"users/{MockUser.User.Username}/nickname");
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- }
- }
-
- [Fact]
- public async Task FunctionTest()
- {
- var url = $"users/{MockUser.User.Username}/nickname";
- var userNotExistUrl = "users/usernotexist/nickname";
- {
- using var client = await CreateClientAsUser();
- {
- var res = await client.GetAsync(userNotExistUrl);
- res.Should().HaveStatusCode(HttpStatusCode.NotFound)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(ErrorCodes.Http.Filter.User.NotExist);
-
- }
- {
- var res = await client.GetAsync(url);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- res.Content.Headers.ContentType.Should().Be(new MediaTypeHeaderValue(MediaTypeNames.Text.Plain) { CharSet = "utf-8" });
- var body = await res.Content.ReadAsStringAsync();
- body.Should().Be(MockUser.User.Username);
- }
- {
- var res = await client.PutStringAsync(url, "");
- res.Should().BeInvalidModel();
- }
- {
- var res = await client.PutStringAsync(url, new string('a', 11));
- res.Should().BeInvalidModel();
- }
- var nickname1 = "nnn";
- var nickname2 = "nn2";
- {
- var res = await client.PutStringAsync(url, nickname1);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- (await client.GetStringAsync(url)).Should().Be(nickname1);
- }
- {
- var res = await client.PutStringAsync(url, nickname2);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- (await client.GetStringAsync(url)).Should().Be(nickname2);
- }
- {
- var res = await client.DeleteAsync(url);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- (await client.GetStringAsync(url)).Should().Be(MockUser.User.Username);
- }
- {
- var res = await client.DeleteAsync(url);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- }
- }
- {
- using var client = await CreateClientAsAdmin();
- {
- var res = await client.PutStringAsync(userNotExistUrl, "aaa");
- res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(ErrorCodes.Http.Filter.User.NotExist);
- }
- {
- var res = await client.DeleteAsync(userNotExistUrl);
- res.Should().HaveStatusCode(HttpStatusCode.BadRequest)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(ErrorCodes.Http.Filter.User.NotExist);
- }
- var nickname = "nnn";
- {
- var res = await client.PutStringAsync(url, nickname);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- (await client.GetStringAsync(url)).Should().Be(nickname);
- }
- {
- var res = await client.DeleteAsync(url);
- res.Should().HaveStatusCode(HttpStatusCode.OK);
- (await client.GetStringAsync(url)).Should().Be(MockUser.User.Username);
- }
- }
- }
- }
-}
diff --git a/Timeline.Tests/IntegratedTests/UserTest.cs b/Timeline.Tests/IntegratedTests/UserTest.cs index abfea18e..8ce76299 100644 --- a/Timeline.Tests/IntegratedTests/UserTest.cs +++ b/Timeline.Tests/IntegratedTests/UserTest.cs @@ -1,13 +1,12 @@ using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using System.Collections.Generic;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
-using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Tests.Helpers;
using Xunit;
-using static Timeline.ErrorCodes.Http.User;
namespace Timeline.Tests.IntegratedTests
{
@@ -20,218 +19,395 @@ namespace Timeline.Tests.IntegratedTests }
[Fact]
- public async Task Get_List_Success()
+ public async Task GetList_NoAuth()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.GetAsync("users");
+ using var client = await CreateDefaultClient();
+ var res = await client.GetAsync("/users");
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<UserInfo[]>()
- .Which.Should().BeEquivalentTo(MockUser.UserInfoList);
+ .Which.Should().BeEquivalentTo(UserInfos);
}
[Fact]
- public async Task Get_Single_Success()
+ public async Task GetList_User()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.GetAsync("users/" + MockUser.User.Username);
+ using var client = await CreateClientAsUser();
+ var res = await client.GetAsync("/users");
res.Should().HaveStatusCode(200)
- .And.HaveJsonBody<UserInfo>()
- .Which.Should().BeEquivalentTo(MockUser.User.Info);
+ .And.HaveJsonBody<UserInfo[]>()
+ .Which.Should().BeEquivalentTo(UserInfos);
}
[Fact]
- public async Task Get_InvalidModel()
+ public async Task GetList_Admin()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.GetAsync("users/aaa!a");
- res.Should().BeInvalidModel();
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.GetAsync("/users");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo[]>()
+ .Which.Should().BeEquivalentTo(UserInfos);
}
[Fact]
- public async Task Get_Users_404()
+ public async Task Get_NoAuth()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.GetAsync("users/usernotexist");
- res.Should().HaveStatusCode(404)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(Get.NotExist);
+ using var client = await CreateDefaultClient();
+ var res = await client.GetAsync($"/users/admin");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which.Should().BeEquivalentTo(UserInfos[0]);
}
- public static IEnumerable<object[]> Put_InvalidModel_Data()
+ [Fact]
+ public async Task Get_User()
{
- yield return new object[] { "aaa", null, false };
- yield return new object[] { "aaa", "p", null };
- yield return new object[] { "aa!a", "p", false };
+ using var client = await CreateClientAsUser();
+ var res = await client.GetAsync($"/users/admin");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which.Should().BeEquivalentTo(UserInfos[0]);
}
- [Theory]
- [MemberData(nameof(Put_InvalidModel_Data))]
- public async Task Put_InvalidModel(string username, string password, bool? administrator)
+ [Fact]
+ public async Task Get_Admin()
{
- using var client = await CreateClientAsAdmin();
- (await client.PutAsJsonAsync("users/" + username,
- new UserPutRequest { Password = password, Administrator = administrator }))
- .Should().BeInvalidModel();
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.GetAsync($"/users/user1");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which.Should().BeEquivalentTo(UserInfos[1]);
}
- private async Task CheckAdministrator(HttpClient client, string username, bool administrator)
+ [Fact]
+ public async Task Get_InvalidModel()
{
- var res = await client.GetAsync("users/" + username);
- res.Should().HaveStatusCode(200)
- .And.HaveJsonBody<UserInfo>()
- .Which.Administrator.Should().Be(administrator);
+ using var client = await CreateClientAsUser();
+ var res = await client.GetAsync("/users/aaa!a");
+ res.Should().BeInvalidModel();
}
[Fact]
- public async Task Put_Modiefied()
+ public async Task Get_404()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.PutAsJsonAsync("users/" + MockUser.User.Username, new UserPutRequest
+ using var client = await CreateClientAsUser();
+ var res = await client.GetAsync("/users/usernotexist");
+ res.Should().HaveStatusCode(404)
+ .And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+
+ [Fact]
+ public async Task Patch_User()
+ {
+ using var client = await CreateClientAsUser();
+ {
+ var res = await client.PatchAsJsonAsync("/users/user1",
+ new UserPatchRequest { Nickname = "aaa" });
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which.Nickname.Should().Be("aaa");
+ }
+
{
- Password = "password",
- Administrator = false
- });
- res.Should().BePut(false);
- await CheckAdministrator(client, MockUser.User.Username, false);
+ var res = await client.GetAsync("/users/user1");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which.Nickname.Should().Be("aaa");
+ }
}
[Fact]
- public async Task Put_Created()
+ public async Task Patch_Admin()
{
- using var client = await CreateClientAsAdmin();
- const string username = "puttest";
- const string url = "users/" + username;
+ using var client = await CreateClientAsAdministrator();
+ using var userClient = await CreateClientAsUser();
+
+ {
+ var res = await client.PatchAsJsonAsync("/users/user1",
+ new UserPatchRequest
+ {
+ Username = "newuser",
+ Password = "newpw",
+ Administrator = true,
+ Nickname = "aaa"
+ });
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which;
+ body.Administrator.Should().Be(true);
+ body.Nickname.Should().Be("aaa");
+ }
+
+ {
+ var res = await client.GetAsync("/users/newuser");
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>()
+ .Which;
+ body.Administrator.Should().Be(true);
+ body.Nickname.Should().Be("aaa");
+ }
+
+ {
+ // Token should expire.
+ var res = await userClient.GetAsync("/testing/auth/Authorize");
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
+ }
- var res = await client.PutAsJsonAsync(url, new UserPutRequest
{
- Password = "password",
- Administrator = false
- });
- res.Should().BePut(true);
- await CheckAdministrator(client, username, false);
+ // Check password.
+ (await CreateClientWithCredential("newuser", "newpw")).Dispose();
+ }
}
[Fact]
public async Task Patch_NotExist()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.PatchAsJsonAsync("users/usernotexist", new UserPatchRequest { });
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.PatchAsJsonAsync("/users/usernotexist", new UserPatchRequest { });
res.Should().HaveStatusCode(404)
.And.HaveCommonBody()
- .Which.Code.Should().Be(Patch.NotExist);
+ .Which.Code.Should().Be(ErrorCodes.UserCommon.NotExist);
}
[Fact]
public async Task Patch_InvalidModel()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.PatchAsJsonAsync("users/aaa!a", new UserPatchRequest { });
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.PatchAsJsonAsync("/users/aaa!a", new UserPatchRequest { });
+ res.Should().BeInvalidModel();
+ }
+
+ public static IEnumerable<object[]> Patch_InvalidModel_Body_Data()
+ {
+ yield return new[] { new UserPatchRequest { Username = "aaa!a" } };
+ yield return new[] { new UserPatchRequest { Password = "" } };
+ yield return new[] { new UserPatchRequest { Nickname = new string('a', 50) } };
+ }
+
+ [Theory]
+ [MemberData(nameof(Patch_InvalidModel_Body_Data))]
+ public async Task Patch_InvalidModel_Body(UserPatchRequest body)
+ {
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.PatchAsJsonAsync("/users/user1", body);
res.Should().BeInvalidModel();
}
[Fact]
- public async Task Patch_Success()
+ public async Task Patch_UsernameConflict()
{
- using var client = await CreateClientAsAdmin();
- {
- var res = await client.PatchAsJsonAsync("users/" + MockUser.User.Username,
- new UserPatchRequest { Administrator = false });
- res.Should().HaveStatusCode(200);
- await CheckAdministrator(client, MockUser.User.Username, false);
- }
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { Username = "admin" });
+ res.Should().HaveStatusCode(400)
+ .And.HaveCommonBody(ErrorCodes.UserController.UsernameConflict);
}
[Fact]
- public async Task Delete_InvalidModel()
+ public async Task Patch_NoAuth_Unauthorized()
{
- using var client = await CreateClientAsAdmin();
- var url = "users/aaa!a";
- var res = await client.DeleteAsync(url);
- res.Should().BeInvalidModel();
+ using var client = await CreateDefaultClient();
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { Nickname = "aaa" });
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
+ }
+
+ [Fact]
+ public async Task Patch_User_Forbid()
+ {
+ using var client = await CreateClientAsUser();
+ var res = await client.PatchAsJsonAsync("/users/admin", new UserPatchRequest { Nickname = "aaa" });
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
+ }
+
+ [Fact]
+ public async Task Patch_Username_Forbid()
+ {
+ using var client = await CreateClientAsUser();
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { Username = "aaa" });
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
+ }
+
+ [Fact]
+ public async Task Patch_Password_Forbid()
+ {
+ using var client = await CreateClientAsUser();
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { Password = "aaa" });
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
+ }
+
+ [Fact]
+ public async Task Patch_Administrator_Forbid()
+ {
+ using var client = await CreateClientAsUser();
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { Administrator = true });
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
}
[Fact]
public async Task Delete_Deleted()
{
- using var client = await CreateClientAsAdmin();
- var url = "users/" + MockUser.User.Username;
- var res = await client.DeleteAsync(url);
- res.Should().BeDelete(true);
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.DeleteAsync("/users/user1");
+ res.Should().BeDelete(true);
+ }
- var res2 = await client.GetAsync(url);
- res2.Should().HaveStatusCode(404);
+ {
+ var res = await client.GetAsync("/users/user1");
+ res.Should().HaveStatusCode(404);
+ }
}
[Fact]
public async Task Delete_NotExist()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.DeleteAsync("users/usernotexist");
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.DeleteAsync("/users/usernotexist");
res.Should().BeDelete(false);
}
- private const string changeUsernameUrl = "userop/changeusername";
+ [Fact]
+ public async Task Delete_InvalidModel()
+ {
+ using var client = await CreateClientAsAdministrator();
+ var res = await client.DeleteAsync("/users/aaa!a");
+ res.Should().BeInvalidModel();
+ }
- public static IEnumerable<object[]> Op_ChangeUsername_InvalidModel_Data()
+ [Fact]
+ public async Task Delete_NoAuth_Unauthorized()
{
- yield return new[] { null, "uuu" };
- yield return new[] { "uuu", null };
- yield return new[] { "a!a", "uuu" };
- yield return new[] { "uuu", "a!a" };
+ using var client = await CreateDefaultClient();
+ var res = await client.DeleteAsync("/users/aaa!a");
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
}
- [Theory]
- [MemberData(nameof(Op_ChangeUsername_InvalidModel_Data))]
- public async Task Op_ChangeUsername_InvalidModel(string oldUsername, string newUsername)
+ [Fact]
+ public async Task Delete_User_Forbid()
{
- using var client = await CreateClientAsAdmin();
- (await client.PostAsJsonAsync(changeUsernameUrl,
- new ChangeUsernameRequest { OldUsername = oldUsername, NewUsername = newUsername }))
- .Should().BeInvalidModel();
+ using var client = await CreateClientAsUser();
+ var res = await client.DeleteAsync("/users/aaa!a");
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
}
+ private const string createUserUrl = "/userop/createuser";
+
[Fact]
- public async Task Op_ChangeUsername_UserNotExist()
+ public async Task Op_CreateUser()
{
- using var client = await CreateClientAsAdmin();
- var res = await client.PostAsJsonAsync(changeUsernameUrl,
- new ChangeUsernameRequest { OldUsername = "usernotexist", NewUsername = "newUsername" });
- res.Should().HaveStatusCode(400)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(Op.ChangeUsername.NotExist);
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.PostAsJsonAsync(createUserUrl, new CreateUserRequest
+ {
+ Username = "aaa",
+ Password = "bbb",
+ Administrator = true,
+ Nickname = "ccc"
+ });
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>().Which;
+ body.Username.Should().Be("aaa");
+ body.Nickname.Should().Be("ccc");
+ body.Administrator.Should().BeTrue();
+ }
+ {
+ var res = await client.GetAsync("users/aaa");
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<UserInfo>().Which;
+ body.Username.Should().Be("aaa");
+ body.Nickname.Should().Be("ccc");
+ body.Administrator.Should().BeTrue();
+ }
+ {
+ // Test password.
+ (await CreateClientWithCredential("aaa", "bbb")).Dispose();
+ }
+ }
+
+ public static IEnumerable<object[]> Op_CreateUser_InvalidModel_Data()
+ {
+ yield return new[] { new CreateUserRequest { Username = "aaa", Password = "bbb" } };
+ yield return new[] { new CreateUserRequest { Username = "aaa", Administrator = true } };
+ yield return new[] { new CreateUserRequest { Password = "bbb", Administrator = true } };
+ yield return new[] { new CreateUserRequest { Username = "a!a", Password = "bbb", Administrator = true } };
+ yield return new[] { new CreateUserRequest { Username = "aaa", Password = "", Administrator = true } };
+ yield return new[] { new CreateUserRequest { Username = "aaa", Password = "bbb", Administrator = true, Nickname = new string('a', 40) } };
+ }
+
+ [Theory]
+ [MemberData(nameof(Op_CreateUser_InvalidModel_Data))]
+ public async Task Op_CreateUser_InvalidModel(CreateUserRequest body)
+ {
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.PostAsJsonAsync(createUserUrl, body);
+ res.Should().BeInvalidModel();
+ }
}
[Fact]
- public async Task Op_ChangeUsername_UserAlreadyExist()
+ public async Task Op_CreateUser_UsernameConflict()
{
- 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)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(Op.ChangeUsername.AlreadyExist);
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.PostAsJsonAsync(createUserUrl, new CreateUserRequest
+ {
+ Username = "user1",
+ Password = "bbb",
+ Administrator = false
+ });
+ res.Should().HaveStatusCode(400)
+ .And.HaveCommonBody(ErrorCodes.UserController.UsernameConflict);
+ }
}
- private async Task TestLogin(string username, string password)
+ [Fact]
+ public async Task Op_CreateUser_NoAuth_Unauthorized()
{
- using var client = await CreateClientWithNoAuth();
- var response = await client.PostAsJsonAsync("token/create", new CreateTokenRequest { Username = username, Password = password });
- response.Should().HaveStatusCode(200)
- .And.HaveJsonBody<CreateTokenResponse>();
+ using var client = await CreateDefaultClient();
+ {
+ var res = await client.PostAsJsonAsync(createUserUrl, new CreateUserRequest
+ {
+ Username = "aaa",
+ Password = "bbb",
+ Administrator = false
+ });
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
+ }
}
[Fact]
- public async Task Op_ChangeUsername_Success()
+ public async Task Op_CreateUser_User_Forbid()
{
- 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 TestLogin(newUsername, MockUser.User.Password);
+ using var client = await CreateClientAsUser();
+ {
+ var res = await client.PostAsJsonAsync(createUserUrl, new CreateUserRequest
+ {
+ Username = "aaa",
+ Password = "bbb",
+ Administrator = false
+ });
+ res.Should().HaveStatusCode(HttpStatusCode.Forbidden);
+ }
}
- private const string changePasswordUrl = "userop/changepassword";
+ private const string changePasswordUrl = "/userop/changepassword";
+
+ [Fact]
+ public async Task Op_ChangePassword()
+ {
+ using var client = await CreateClientAsUser();
+ {
+ var res = await client.PostAsJsonAsync(changePasswordUrl,
+ new ChangePasswordRequest { OldPassword = "user1pw", NewPassword = "newpw" });
+ res.Should().HaveStatusCode(200);
+ }
+ {
+ var res = await client.PatchAsJsonAsync("/users/user1", new UserPatchRequest { });
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
+ }
+ {
+ (await CreateClientWithCredential("user1", "newpw")).Dispose();
+ }
+ }
public static IEnumerable<object[]> Op_ChangePassword_InvalidModel_Data()
{
@@ -244,9 +420,9 @@ namespace Timeline.Tests.IntegratedTests public async Task Op_ChangePassword_InvalidModel(string oldPassword, string newPassword)
{
using var client = await CreateClientAsUser();
- (await client.PostAsJsonAsync(changePasswordUrl,
- new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword }))
- .Should().BeInvalidModel();
+ var res = await client.PostAsJsonAsync(changePasswordUrl,
+ new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword });
+ res.Should().BeInvalidModel();
}
[Fact]
@@ -255,19 +431,15 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser();
var res = await client.PostAsJsonAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "???", NewPassword = "???" });
res.Should().HaveStatusCode(400)
- .And.HaveCommonBody()
- .Which.Code.Should().Be(Op.ChangePassword.BadOldPassword);
+ .And.HaveCommonBody(ErrorCodes.UserController.ChangePassword_BadOldPassword);
}
[Fact]
- public async Task Op_ChangePassword_Success()
+ public async Task Op_ChangePassword_NoAuth_Unauthorized()
{
- 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 TestLogin(MockUser.User.Username, newPassword);
+ using var client = await CreateDefaultClient();
+ var res = await client.PostAsJsonAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "???", NewPassword = "???" });
+ res.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
}
}
}
diff --git a/Timeline.Tests/Services/UserAvatarServiceTest.cs b/Timeline.Tests/Services/UserAvatarServiceTest.cs deleted file mode 100644 index 2729aa6f..00000000 --- a/Timeline.Tests/Services/UserAvatarServiceTest.cs +++ /dev/null @@ -1,280 +0,0 @@ -using FluentAssertions;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging.Abstractions;
-using Moq;
-using SixLabors.ImageSharp.Formats.Png;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Timeline.Entities;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.Services
-{
- public class UserAvatarValidatorTest : IClassFixture<UserAvatarValidator>
- {
- private readonly UserAvatarValidator _validator;
-
- public UserAvatarValidatorTest(UserAvatarValidator validator)
- {
- _validator = validator;
- }
-
- [Fact]
- public void CantDecode()
- {
- Avatar avatar = new Avatar
- {
- Data = Encoding.ASCII.GetBytes("This is not a image."),
- Type = "image/png"
- };
- _validator.Awaiting(v => v.Validate(avatar))
- .Should().Throw<AvatarFormatException>()
- .Where(e => e.Avatar == avatar && e.Error == AvatarFormatException.ErrorReason.CantDecode);
- }
-
- [Fact]
- public void UnmatchedFormat()
- {
- Avatar avatar = new Avatar
- {
- Data = ImageHelper.CreatePngWithSize(100, 100),
- Type = "image/jpeg"
- };
- _validator.Awaiting(v => v.Validate(avatar))
- .Should().Throw<AvatarFormatException>()
- .Where(e => e.Avatar == avatar && e.Error == AvatarFormatException.ErrorReason.UnmatchedFormat);
- }
-
- [Fact]
- public void BadSize()
- {
- Avatar avatar = new Avatar
- {
- Data = ImageHelper.CreatePngWithSize(100, 200),
- Type = PngFormat.Instance.DefaultMimeType
- };
- _validator.Awaiting(v => v.Validate(avatar))
- .Should().Throw<AvatarFormatException>()
- .Where(e => e.Avatar == avatar && e.Error == AvatarFormatException.ErrorReason.BadSize);
- }
-
- [Fact]
- public void Success()
- {
- Avatar avatar = new Avatar
- {
- Data = ImageHelper.CreatePngWithSize(100, 100),
- Type = PngFormat.Instance.DefaultMimeType
- };
- _validator.Awaiting(v => v.Validate(avatar))
- .Should().NotThrow();
- }
- }
-
- public class UserAvatarServiceTest : IDisposable
- {
- private UserAvatar CreateMockAvatarEntity(string key) => new UserAvatar
- {
- Type = $"image/test{key}",
- Data = Encoding.ASCII.GetBytes($"mock{key}"),
- ETag = $"etag{key}",
- LastModified = DateTime.Now
- };
-
- private AvatarInfo CreateMockAvatarInfo(string key) => new AvatarInfo
- {
- Avatar = new Avatar
- {
- Type = $"image/test{key}",
- Data = Encoding.ASCII.GetBytes($"mock{key}")
- },
- LastModified = DateTime.Now
- };
-
- private Avatar CreateMockAvatar(string key) => new Avatar
- {
- Type = $"image/test{key}",
- Data = Encoding.ASCII.GetBytes($"mock{key}")
- };
-
- private static Avatar ToAvatar(UserAvatar entity)
- {
- return new Avatar
- {
- Data = entity.Data,
- Type = entity.Type
- };
- }
-
- private static AvatarInfo ToAvatarInfo(UserAvatar entity)
- {
- return new AvatarInfo
- {
- Avatar = ToAvatar(entity),
- LastModified = entity.LastModified
- };
- }
-
- private readonly Mock<IDefaultUserAvatarProvider> _mockDefaultAvatarProvider;
- private readonly Mock<IUserAvatarValidator> _mockValidator;
- private readonly Mock<IETagGenerator> _mockETagGenerator;
- private readonly Mock<IClock> _mockClock;
-
- private readonly TestDatabase _database;
-
- private readonly UserAvatarService _service;
-
- public UserAvatarServiceTest()
- {
- _mockDefaultAvatarProvider = new Mock<IDefaultUserAvatarProvider>();
- _mockValidator = new Mock<IUserAvatarValidator>();
- _mockETagGenerator = new Mock<IETagGenerator>();
- _mockClock = new Mock<IClock>();
-
- _database = new TestDatabase();
-
- _service = new UserAvatarService(NullLogger<UserAvatarService>.Instance, _database.Context, _mockDefaultAvatarProvider.Object, _mockValidator.Object, _mockETagGenerator.Object, _mockClock.Object);
- }
-
- public void Dispose()
- {
- _database.Dispose();
- }
-
- [Theory]
- [InlineData(null, typeof(ArgumentNullException))]
- [InlineData("", typeof(UsernameBadFormatException))]
- [InlineData("a!a", typeof(UsernameBadFormatException))]
- [InlineData("usernotexist", typeof(UserNotExistException))]
- public async Task GetAvatarETag_ShouldThrow(string username, Type exceptionType)
- {
- await _service.Awaiting(s => s.GetAvatarETag(username)).Should().ThrowAsync(exceptionType);
- }
-
- [Fact]
- public async Task GetAvatarETag_ShouldReturn_Default()
- {
- const string etag = "aaaaaa";
- _mockDefaultAvatarProvider.Setup(p => p.GetDefaultAvatarETag()).ReturnsAsync(etag);
- (await _service.GetAvatarETag(MockUser.User.Username)).Should().Be(etag);
- }
-
- [Fact]
- public async Task GetAvatarETag_ShouldReturn_Data()
- {
- string username = MockUser.User.Username;
- var mockAvatarEntity = CreateMockAvatarEntity("aaa");
- {
- var context = _database.Context;
- var user = await context.Users.Where(u => u.Name == username).Include(u => u.Avatar).SingleAsync();
- user.Avatar = mockAvatarEntity;
- await context.SaveChangesAsync();
- }
- (await _service.GetAvatarETag(username)).Should().BeEquivalentTo(mockAvatarEntity.ETag);
- }
-
- [Theory]
- [InlineData(null, typeof(ArgumentNullException))]
- [InlineData("", typeof(UsernameBadFormatException))]
- [InlineData("a!a", typeof(UsernameBadFormatException))]
- [InlineData("usernotexist", typeof(UserNotExistException))]
- public async Task GetAvatar_ShouldThrow(string username, Type exceptionType)
- {
- await _service.Awaiting(s => s.GetAvatar(username)).Should().ThrowAsync(exceptionType);
-
- }
-
- [Fact]
- public async Task GetAvatar_ShouldReturn_Default()
- {
- var mockAvatar = CreateMockAvatarInfo("aaa");
- _mockDefaultAvatarProvider.Setup(p => p.GetDefaultAvatar()).ReturnsAsync(mockAvatar);
- string username = MockUser.User.Username;
- (await _service.GetAvatar(username)).Should().BeEquivalentTo(mockAvatar);
- }
-
- [Fact]
- public async Task GetAvatar_ShouldReturn_Data()
- {
- string username = MockUser.User.Username;
- var mockAvatarEntity = CreateMockAvatarEntity("aaa");
- {
- var context = _database.Context;
- var user = await context.Users.Where(u => u.Name == username).Include(u => u.Avatar).SingleAsync();
- user.Avatar = mockAvatarEntity;
- await context.SaveChangesAsync();
- }
-
- (await _service.GetAvatar(username)).Should().BeEquivalentTo(ToAvatarInfo(mockAvatarEntity));
- }
-
- public static IEnumerable<object[]> SetAvatar_ShouldThrow_Data()
- {
- yield return new object[] { null, null, typeof(ArgumentNullException) };
- yield return new object[] { "", null, typeof(UsernameBadFormatException) };
- yield return new object[] { "u!u", null, typeof(UsernameBadFormatException) };
- yield return new object[] { null, new Avatar { Type = null, Data = new[] { (byte)0x00 } }, typeof(ArgumentException) };
- yield return new object[] { null, new Avatar { Type = "", Data = new[] { (byte)0x00 } }, typeof(ArgumentException) };
- yield return new object[] { null, new Avatar { Type = "aaa", Data = null }, typeof(ArgumentException) };
- yield return new object[] { "usernotexist", null, typeof(UserNotExistException) };
- }
-
- [Theory]
- [MemberData(nameof(SetAvatar_ShouldThrow_Data))]
- public async Task SetAvatar_ShouldThrow(string username, Avatar avatar, Type exceptionType)
- {
- await _service.Awaiting(s => s.SetAvatar(username, avatar)).Should().ThrowAsync(exceptionType);
- }
-
- [Fact]
- public async Task SetAvatar_Should_Work()
- {
- string username = MockUser.User.Username;
-
- var user = await _database.Context.Users.Where(u => u.Name == username).Include(u => u.Avatar).SingleAsync();
-
- var avatar1 = CreateMockAvatar("aaa");
- var avatar2 = CreateMockAvatar("bbb");
-
- string etag1 = "etagaaa";
- string etag2 = "etagbbb";
-
- DateTime dateTime1 = DateTime.Now.AddSeconds(2);
- DateTime dateTime2 = DateTime.Now.AddSeconds(10);
- DateTime dateTime3 = DateTime.Now.AddSeconds(20);
-
- // create
- _mockETagGenerator.Setup(g => g.Generate(avatar1.Data)).ReturnsAsync(etag1);
- _mockClock.Setup(c => c.GetCurrentTime()).Returns(dateTime1);
- await _service.SetAvatar(username, avatar1);
- user.Avatar.Should().NotBeNull();
- user.Avatar.Type.Should().Be(avatar1.Type);
- user.Avatar.Data.Should().Equal(avatar1.Data);
- user.Avatar.ETag.Should().Be(etag1);
- user.Avatar.LastModified.Should().Be(dateTime1);
-
- // modify
- _mockETagGenerator.Setup(g => g.Generate(avatar2.Data)).ReturnsAsync(etag2);
- _mockClock.Setup(c => c.GetCurrentTime()).Returns(dateTime2);
- await _service.SetAvatar(username, avatar2);
- user.Avatar.Should().NotBeNull();
- user.Avatar.Type.Should().Be(avatar2.Type);
- user.Avatar.Data.Should().Equal(avatar2.Data);
- user.Avatar.ETag.Should().Be(etag2);
- user.Avatar.LastModified.Should().Be(dateTime2);
-
- // delete
- _mockClock.Setup(c => c.GetCurrentTime()).Returns(dateTime3);
- await _service.SetAvatar(username, null);
- user.Avatar.Type.Should().BeNull();
- user.Avatar.Data.Should().BeNull();
- user.Avatar.ETag.Should().BeNull();
- user.Avatar.LastModified.Should().Be(dateTime3);
- }
- }
-}
diff --git a/Timeline.Tests/Services/UserDetailServiceTest.cs b/Timeline.Tests/Services/UserDetailServiceTest.cs deleted file mode 100644 index 9a869c89..00000000 --- a/Timeline.Tests/Services/UserDetailServiceTest.cs +++ /dev/null @@ -1,107 +0,0 @@ -using FluentAssertions;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging.Abstractions;
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Timeline.Entities;
-using Timeline.Services;
-using Timeline.Tests.Helpers;
-using Xunit;
-
-namespace Timeline.Tests.Services
-{
- public class UserDetailServiceTest : IDisposable
- {
- private readonly TestDatabase _testDatabase;
-
- private readonly UserDetailService _service;
-
- public UserDetailServiceTest()
- {
- _testDatabase = new TestDatabase();
- _service = new UserDetailService(_testDatabase.Context, NullLogger<UserDetailService>.Instance);
- }
-
- public void Dispose()
- {
- _testDatabase.Dispose();
- }
-
- [Theory]
- [InlineData(null, typeof(ArgumentNullException))]
- [InlineData("", typeof(UsernameBadFormatException))]
- [InlineData("a!a", typeof(UsernameBadFormatException))]
- [InlineData("usernotexist", typeof(UserNotExistException))]
- public async Task GetNickname_ShouldThrow(string username, Type exceptionType)
- {
- await _service.Awaiting(s => s.GetNickname(username)).Should().ThrowAsync(exceptionType);
- }
-
- [Fact]
- public async Task GetNickname_ShouldReturnUsername()
- {
- var result = await _service.GetNickname(MockUser.User.Username);
- result.Should().Be(MockUser.User.Username);
- }
-
- [Fact]
- public async Task GetNickname_ShouldReturnData()
- {
- const string nickname = "aaaaaa";
- {
- var context = _testDatabase.Context;
- var userId = (await context.Users.Where(u => u.Name == MockUser.User.Username).Select(u => new { u.Id }).SingleAsync()).Id;
- context.UserDetails.Add(new UserDetail
- {
- Nickname = nickname,
- UserId = userId
- });
- await context.SaveChangesAsync();
- }
- var result = await _service.GetNickname(MockUser.User.Username);
- result.Should().Be(nickname);
- }
-
- [Theory]
- [InlineData(null, typeof(ArgumentNullException))]
- [InlineData("", typeof(UsernameBadFormatException))]
- [InlineData("a!a", typeof(UsernameBadFormatException))]
- [InlineData("usernotexist", typeof(UserNotExistException))]
- public async Task SetNickname_ShouldThrow(string username, Type exceptionType)
- {
- await _service.Awaiting(s => s.SetNickname(username, null)).Should().ThrowAsync(exceptionType);
- }
-
- [Fact]
- public async Task SetNickname_ShouldThrow_ArgumentException()
- {
- await _service.Awaiting(s => s.SetNickname("uuu", new string('a', 50))).Should().ThrowAsync<ArgumentException>();
- }
-
- [Fact]
- public async Task SetNickname_ShouldWork()
- {
- var username = MockUser.User.Username;
- var user = await _testDatabase.Context.Users.Where(u => u.Name == username).Include(u => u.Detail).SingleAsync();
-
- var nickname1 = "nickname1";
- var nickname2 = "nickname2";
-
- await _service.SetNickname(username, null);
- user.Detail.Should().BeNull();
-
- await _service.SetNickname(username, nickname1);
- user.Detail.Should().NotBeNull();
- user.Detail.Nickname.Should().Be(nickname1);
-
- await _service.SetNickname(username, nickname2);
- user.Detail.Should().NotBeNull();
- user.Detail.Nickname.Should().Be(nickname2);
-
- await _service.SetNickname(username, null);
- user.Detail.Should().NotBeNull();
- user.Detail.Nickname.Should().BeNull();
- }
- }
-}
diff --git a/Timeline.Tests/Timeline.Tests.csproj b/Timeline.Tests/Timeline.Tests.csproj index 0845d1ab..40e8cda2 100644 --- a/Timeline.Tests/Timeline.Tests.csproj +++ b/Timeline.Tests/Timeline.Tests.csproj @@ -7,18 +7,17 @@ </PropertyGroup>
<ItemGroup>
- <PackageReference Include="coverlet.collector" Version="1.1.0">
+ <PackageReference Include="coverlet.collector" Version="1.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
- <PackageReference Include="FluentAssertions" Version="5.9.0" />
+ <PackageReference Include="FluentAssertions" Version="5.10.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
- <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="xunit" Version="2.4.1" />
diff --git a/Timeline.Tests/UsernameValidatorUnitTest.cs b/Timeline.Tests/UsernameValidatorUnitTest.cs index e0f4633f..0f844452 100644 --- a/Timeline.Tests/UsernameValidatorUnitTest.cs +++ b/Timeline.Tests/UsernameValidatorUnitTest.cs @@ -5,7 +5,6 @@ using Xunit; namespace Timeline.Tests
{
- [UseCulture("en")]
public class UsernameValidatorUnitTest : IClassFixture<UsernameValidator>
{
private readonly UsernameValidator _validator;
@@ -23,12 +22,6 @@ namespace Timeline.Tests }
[Fact]
- public void Null()
- {
- FailAndMessage(null).Should().ContainEquivalentOf("null");
- }
-
- [Fact]
public void NotString()
{
var (result, message) = _validator.Validate(123);
@@ -59,6 +52,7 @@ namespace Timeline.Tests }
[Theory]
+ [InlineData(null)]
[InlineData("abc")]
[InlineData("-abc")]
[InlineData("_abc")]
@@ -69,7 +63,6 @@ namespace Timeline.Tests [InlineData("a-b_c")]
public void Success(string value)
{
-
var (result, _) = _validator.Validate(value);
result.Should().BeTrue();
}
|