using System.Text; using AutoMapper; using Govor.API.Controllers; using Govor.API.Hubs; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Application.Interfaces.Medias; using Govor.Application.Profiles; using Govor.Contracts.DTOs; using Govor.Contracts.Requests; using Govor.Core.Models; using Govor.Core.Models.Messages; using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Moq; using Newtonsoft.Json.Linq; namespace Govor.API.Tests; [TestFixture] public class ProfileControllerTests { private Mock> _mockLogger = null!; private Mock _mockMediaService = null!; private Mock _mockProfileService = null!; private Mock _mockCurrentUserService = null!; private Mock> _mockProfileHubContext = null!; private Mock _mockClients = null!; private Mock _mockClientProxy = null!; private Mock _mockMapper = null!; private ProfileController _controller = null!; private Guid _userId; [SetUp] public void SetUp() { _mockLogger = new Mock>(); _mockMediaService = new Mock(); _mockProfileService = new Mock(); _mockCurrentUserService = new Mock(); _mockMapper = new Mock(); _mockProfileHubContext = new Mock>(); _mockClients = new Mock(); _mockClientProxy = new Mock(); _mockProfileHubContext.Setup(x => x.Clients).Returns(_mockClients.Object); _mockClients.Setup(x => x.All).Returns(_mockClientProxy.Object); _mockClientProxy.Setup(x => x.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); _controller = new ProfileController( _mockLogger.Object, _mockMediaService.Object, _mockProfileService.Object, _mockCurrentUserService.Object, _mockProfileHubContext.Object, _mockMapper.Object); _userId = Guid.NewGuid(); _mockCurrentUserService.Setup(x => x.GetCurrentUserId()).Returns(_userId); } [Test] public async Task UploadAvatar_ReturnsBadRequest_WhenFileIsEmpty() { // Arrange var request = new AvatarUploadRequest { FromFile = null }; // Act var result = await _controller.UploadAvatar(request); // Assert Assert.That(result, Is.InstanceOf()); var badRequestResult = (BadRequestObjectResult)result; Assert.That(badRequestResult.Value, Is.EqualTo("File is empty.")); _mockMediaService.Verify(s => s.UploadMediaAsync(It.IsAny()), Times.Never); } [Test] public async Task UploadAvatar_ReturnsBadRequest_WhenFileLengthIsZero() { // Arrange var mockFile = new Mock(); mockFile.Setup(f => f.Length).Returns(0); var request = new AvatarUploadRequest { FromFile = mockFile.Object }; // Act var result = await _controller.UploadAvatar(request); // Assert Assert.That(result, Is.InstanceOf()); var badRequestResult = (BadRequestObjectResult)result; Assert.That(badRequestResult.Value, Is.EqualTo("File is empty.")); _mockMediaService.Verify(s => s.UploadMediaAsync(It.IsAny()), Times.Never); } [Test] public async Task UploadAvatar_ReturnsOkAndPerformsAllActions_WhenFileIsValid() { // Arrange var mediaId = Guid.NewGuid(); var expectedMediaInfo = new MediaUploadResult(mediaId, $"/media/{mediaId}"); var fileName = "test_avatar.jpg"; var fileContent = "This is a test image content"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent)); var mockFile = new Mock(); mockFile.Setup(f => f.FileName).Returns(fileName); mockFile.Setup(f => f.Length).Returns(stream.Length); mockFile.Setup(f => f.OpenReadStream()).Returns(stream); mockFile.Setup(f => f.CopyToAsync(It.IsAny(), It.IsAny())) .Callback((s, t) => stream.CopyTo(s)); // Для ReadFileAsync var request = new AvatarUploadRequest { FromFile = mockFile.Object, Type = MediaType.Image, MimeType = "image/jpeg" }; _mockMediaService.Setup(s => s.UploadMediaAsync(It.IsAny())) .ReturnsAsync(expectedMediaInfo); _mockProfileService.Setup(s => s.SetNewIcon(_userId, mediaId)) .Returns(Task.CompletedTask); // Act var result = await _controller.UploadAvatar(request); // Assert Assert.That(result, Is.InstanceOf()); var okResult = (OkObjectResult)result; Assert.That(okResult.StatusCode, Is.EqualTo(200)); Assert.That(okResult.Value, Is.EqualTo(expectedMediaInfo)); mockFile.Verify(f => f.CopyToAsync(It.IsAny(), It.IsAny()), Times.Once); _mockMediaService.Verify(s => s.UploadMediaAsync(It.Is(m => m.OwnerId == _userId && m.OwnerType == MediaOwnerType.Avatar && m.FileName == fileName )), Times.Once); _mockProfileService.Verify(s => s.SetNewIcon(_userId, mediaId), Times.Once); _mockClientProxy.Verify( c => c.SendCoreAsync("AvatarUpdated", It.Is( args => args.Length == 1 && JObject.FromObject(args[0]!).Value("userId") == _userId && JObject.FromObject(args[0]!).Value("iconId") == mediaId ), It.IsAny()), Times.Once, "Hub SendAsync must be called to notify clients." ); } [Test] public async Task UploadAvatar_ReturnsInternalServerError_WhenMediaServiceFails() { // Arrange var mockFile = new Mock(); mockFile.Setup(f => f.Length).Returns(100); mockFile.Setup(f => f.OpenReadStream()).Returns(new MemoryStream(Encoding.UTF8.GetBytes("test"))); var request = new AvatarUploadRequest { FromFile = mockFile.Object }; _mockMediaService.Setup(s => s.UploadMediaAsync(It.IsAny())) .ThrowsAsync(new System.Exception("Simulated upload failure")); // Act var result = await _controller.UploadAvatar(request); // Assert Assert.That(result, Is.InstanceOf()); var objectResult = (ObjectResult)result; Assert.That(objectResult.StatusCode, Is.EqualTo(500)); _mockProfileService.Verify(s => s.SetNewIcon(It.IsAny(), It.IsAny()), Times.Never); _mockClientProxy.Verify( c => c.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never, "The Hub should not be called in case of a service error." ); } [Test] public async Task DowloadProfile_ReturnsOk_WhenProfileExists() { // Arrange var userProfile = new UserProfile { Id = _userId, Username = "test_user", Description = "test description", IconId = Guid.NewGuid() }; var userProfileDto = new UserProfileDto { Id = _userId, Username = "test_user", Description = "test description", IconId = userProfile.IconId }; _mockProfileService.Setup(s => s.GetUserProfileAsync(_userId)) .ReturnsAsync(userProfile); _mockMapper.Setup(m => m.Map(userProfile)) .Returns(userProfileDto); // Act var result = await _controller.DownloadProfile(); // Assert var okResult = result as OkObjectResult; Assert.That(okResult, Is.Not.Null); Assert.That(okResult!.StatusCode, Is.EqualTo(200)); Assert.That(okResult.Value, Is.EqualTo(userProfileDto)); } [Test] public async Task DowloadProfile_ReturnsForbid_WhenUnauthorizedAccessExceptionThrown() { // Arrange _mockProfileService.Setup(s => s.GetUserProfileAsync(_userId)) .ThrowsAsync(new UnauthorizedAccessException("Access denied")); // Act var result = await _controller.DownloadProfile(); // Assert Assert.That(result, Is.InstanceOf()); } [Test] public async Task DowloadProfile_ReturnsBadRequest_WhenNotFoundExceptionThrown() { // Arrange _mockProfileService.Setup(s => s.GetUserProfileAsync(_userId)) .ThrowsAsync(new NotFoundException("Cannot find profile")); // Act var result = await _controller.DownloadProfile(); // Assert var notFoundResult = result as NotFoundObjectResult; Assert.That(notFoundResult, Is.Not.Null); Assert.That(notFoundResult!.Value, Is.EqualTo("Profile not found")); } [Test] public async Task DowloadProfile_Returns500_WhenUnexpectedExceptionThrown() { // Arrange _mockProfileService.Setup(s => s.GetUserProfileAsync(_userId)) .ThrowsAsync(new Exception("Unexpected error")); // Act var result = await _controller.DownloadProfile(); // Assert var objectResult = result as ObjectResult; Assert.That(objectResult, Is.Not.Null); Assert.That(objectResult!.StatusCode, Is.EqualTo(500)); Assert.That(objectResult.Value, Is.EqualTo("Unexpected Error! Please try again later.")); } }