mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
6d1c53beeb
Large refactor that renames/moves core types into a new Govor.Domain surface and reorganizes the Application layer. Models, configurations, migrations and many files moved from Govor.Core/Govor.Data to Govor.Domain; numerous Application services, interfaces and implementations were relocated or added (authentication, friends, messages, medias, push notifications, user sessions, storage, synching, private chats, etc.). Tests updated to use Govor.Domain namespaces and adjusted project references (removed Govor.Data reference from API tests). Also updated API, Hub and mapping code and project files to reflect the new structure and naming. This is primarily a codebase-wide namespace and module reorganization to establish a Domain project and restructure application services.
362 lines
13 KiB
C#
362 lines
13 KiB
C#
using System.Text;
|
|
using AutoFixture;
|
|
using Govor.API.Controllers;
|
|
using Govor.Application.Interfaces.Infrastructure.Extensions;
|
|
using Govor.Application.Interfaces.Medias;
|
|
using Govor.Contracts.Requests;
|
|
using Govor.Domain.Models.Messages;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
using Moq;
|
|
|
|
namespace Govor.API.Tests.IntegrationTests.Controllers;
|
|
|
|
[TestFixture]
|
|
public class MediaControllerTests
|
|
{
|
|
private Fixture _fixture;
|
|
private Mock<ICurrentUserService> _currentUserMock;
|
|
private Mock<ILogger<MediaController>> _loggerMock;
|
|
private Mock<IMediaService> _mockMedia;
|
|
private Mock<IAccesserToDownloadMedia> _mockAccesser;
|
|
private MediaController _controller;
|
|
private Guid _userId = Guid.NewGuid();
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
_fixture = new Fixture();
|
|
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => _fixture.Behaviors.Remove(b));
|
|
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
|
|
|
_currentUserMock = new Mock<ICurrentUserService>();
|
|
_loggerMock = new Mock<ILogger<MediaController>>();
|
|
_mockAccesser = new Mock<IAccesserToDownloadMedia>();
|
|
_mockMedia = new Mock<IMediaService>();
|
|
|
|
_currentUserMock.Setup(f => f.GetCurrentUserId()).Returns(_userId);
|
|
|
|
_controller = new MediaController(
|
|
_loggerMock.Object,
|
|
_mockMedia.Object,
|
|
_mockAccesser.Object,
|
|
_currentUserMock.Object);
|
|
}
|
|
|
|
// Tests for Upload action
|
|
[Test]
|
|
public async Task Upload_ValidRequest_ReturnsOkResult()
|
|
{
|
|
// Arrange
|
|
var content = "fake file content";
|
|
var fileName = "testfile.txt";
|
|
var fileBytes = System.Text.Encoding.UTF8.GetBytes(content);
|
|
var stream = new MemoryStream(fileBytes);
|
|
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(fileBytes.Length);
|
|
formFileMock.Setup(f => f.FileName).Returns(fileName);
|
|
formFileMock.Setup(f => f.OpenReadStream()).Returns(stream);
|
|
formFileMock.Setup(f => f.CopyToAsync(It.IsAny<Stream>(), default))
|
|
.Returns<Stream, CancellationToken>((target, _) => stream.CopyToAsync(target));
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.Type, MediaType.Image)
|
|
.With(r => r.MimeType, "image/png")
|
|
.With(r => r.EncryptedKey, "secret")
|
|
.Create();
|
|
|
|
var uploadResult = _fixture.Create<MediaUploadResult>();
|
|
|
|
_mockMedia.Setup(f => f.UploadMediaAsync(It.IsAny<Media>()))
|
|
.ReturnsAsync(uploadResult);
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<OkObjectResult>());
|
|
|
|
var okResult = result as OkObjectResult;
|
|
var value = okResult?.Value as MediaUploadResult;
|
|
|
|
Assert.That(value, Is.Not.Null);
|
|
Assert.That(value!.Url, Is.EqualTo(uploadResult.Url));
|
|
Assert.That(value.MediaId, Is.EqualTo(uploadResult.MediaId));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_InvalidModelState_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
_controller.ModelState.AddModelError("Error", "Invalid model state");
|
|
var content = "fake file content";
|
|
var fileName = "testfile.txt";
|
|
var fileBytes = System.Text.Encoding.UTF8.GetBytes(content);
|
|
var stream = new MemoryStream(fileBytes);
|
|
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(fileBytes.Length);
|
|
formFileMock.Setup(f => f.FileName).Returns(fileName);
|
|
formFileMock.Setup(f => f.OpenReadStream()).Returns(stream);
|
|
formFileMock.Setup(f => f.CopyToAsync(It.IsAny<Stream>(), default))
|
|
.Returns<Stream, CancellationToken>((target, _) => stream.CopyToAsync(target));
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.Type, MediaType.Image)
|
|
.With(r => r.MimeType, "image/png")
|
|
.With(r => r.EncryptedKey, "secret")
|
|
.Create();
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_NoFileUploaded_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, (IFormFile)null)
|
|
.Create();
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
var badRequestResult = result as BadRequestObjectResult;
|
|
Assert.That(badRequestResult?.Value, Is.EqualTo("No file uploaded"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_EmptyFile_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(0);
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.Create();
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
var badRequestResult = result as BadRequestObjectResult;
|
|
Assert.That(badRequestResult?.Value, Is.EqualTo("No file uploaded"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_FileTooLarge_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(20_000_001); // Just over 20MB
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.Create();
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
var badRequestResult = result as BadRequestObjectResult;
|
|
Assert.That(badRequestResult?.Value, Is.EqualTo("File is too large"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_MissingMimeType_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(1000);
|
|
formFileMock.Setup(f => f.FileName).Returns("testfile.txt");
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.MimeType, string.Empty)
|
|
.Create();
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
var badRequestResult = result as BadRequestObjectResult;
|
|
Assert.That(badRequestResult?.Value, Is.EqualTo("Missing MIME type"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_UnauthorizedAccess_ReturnsUnauthorized()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(1000);
|
|
formFileMock.Setup(f => f.FileName).Returns("testfile.txt");
|
|
formFileMock.Setup(f => f.OpenReadStream()).Returns(new MemoryStream(new byte[1000]));
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.MimeType, "text/plain")
|
|
.Create();
|
|
|
|
_mockMedia.Setup(f => f.UploadMediaAsync(It.IsAny<Media>()))
|
|
.ThrowsAsync(new UnauthorizedAccessException("Access denied"));
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<ForbidResult>());
|
|
var forbidResult = result as ForbidResult;
|
|
Assert.That(forbidResult.AuthenticationSchemes.First(), Is.EqualTo("Access denied"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_InvalidOperation_ReturnsBadRequest()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(1000);
|
|
formFileMock.Setup(f => f.FileName).Returns("testfile.txt");
|
|
formFileMock.Setup(f => f.OpenReadStream()).Returns(new MemoryStream(new byte[1000]));
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.MimeType, "text/plain")
|
|
.Create();
|
|
|
|
_mockMedia.Setup(f => f.UploadMediaAsync(It.IsAny<Media>()))
|
|
.ThrowsAsync(new InvalidOperationException("Invalid operation"));
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<BadRequestObjectResult>());
|
|
var badRequestResult = result as BadRequestObjectResult;
|
|
Assert.That(badRequestResult?.Value, Is.EqualTo("Invalid operation"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Upload_GeneralException_ReturnsInternalServerError()
|
|
{
|
|
// Arrange
|
|
var formFileMock = new Mock<IFormFile>();
|
|
formFileMock.Setup(f => f.Length).Returns(1000);
|
|
formFileMock.Setup(f => f.FileName).Returns("testfile.txt");
|
|
formFileMock.Setup(f => f.OpenReadStream()).Returns(new MemoryStream(new byte[1000]));
|
|
|
|
var uploadRequest = _fixture.Build<MediaUploadRequest>()
|
|
.With(r => r.FromFile, formFileMock.Object)
|
|
.With(r => r.MimeType, "text/plain")
|
|
.Create();
|
|
|
|
_mockMedia.Setup(f => f.UploadMediaAsync(It.IsAny<Media>()))
|
|
.ThrowsAsync(new Exception("Something went wrong"));
|
|
|
|
// Act
|
|
var result = await _controller.Upload(uploadRequest);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<ObjectResult>());
|
|
var objectResult = result as ObjectResult;
|
|
Assert.That(objectResult.StatusCode, Is.EqualTo(500));
|
|
}
|
|
|
|
// Tests for Download action
|
|
[Test]
|
|
public async Task Download_HasAccessAndMediaExists_ReturnsFile()
|
|
{
|
|
// Arrange
|
|
var mediaId = Guid.NewGuid();
|
|
var media = _fixture.Build<Media>()
|
|
.With(m => m.Data, Encoding.UTF8.GetBytes("fake file content"))
|
|
.With(m => m.MimeType, "application/octet-stream") // Ensure MimeType is set
|
|
.With(m => m.FileName, "testfile.txt")
|
|
.Create();
|
|
|
|
_mockAccesser.Setup(f => f.HasAccessAsync(mediaId, _userId)).ReturnsAsync(true);
|
|
_mockMedia.Setup(f => f.GetMediaByIdAsync(mediaId)).ReturnsAsync(media);
|
|
|
|
// Act
|
|
var result = await _controller.Download(mediaId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<FileContentResult>());
|
|
var fileResult = result as FileContentResult;
|
|
Assert.That(fileResult?.FileContents, Is.EqualTo(media.Data));
|
|
Assert.That(fileResult?.ContentType, Is.EqualTo(media.MimeType)); // Changed MineType to MimeType
|
|
Assert.That(fileResult?.FileDownloadName, Is.EqualTo(Path.GetFileName(media.FileName)));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Download_NoAccess_ReturnsForbid()
|
|
{
|
|
// Arrange
|
|
var mediaId = Guid.NewGuid();
|
|
|
|
_mockAccesser.Setup(f => f.HasAccessAsync(mediaId, _userId)).ReturnsAsync(false);
|
|
|
|
// Act
|
|
var result = await _controller.Download(mediaId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<ForbidResult>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task Download_MediaNotFound_ReturnsNotFound()
|
|
{
|
|
// Arrange
|
|
var mediaId = Guid.NewGuid();
|
|
|
|
_mockAccesser.Setup(f => f.HasAccessAsync(mediaId, _userId)).ReturnsAsync(true);
|
|
_mockMedia.Setup(f => f.GetMediaByIdAsync(mediaId))
|
|
.ThrowsAsync(new KeyNotFoundException("Media not found"));
|
|
|
|
// Act
|
|
var result = await _controller.Download(mediaId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<NotFoundObjectResult>());
|
|
var notFoundResult = result as NotFoundObjectResult;
|
|
Assert.That(notFoundResult?.Value, Is.EqualTo("Media not found"));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Download_GeneralException_ReturnsInternalServerError()
|
|
{
|
|
// Arrange
|
|
var mediaId = Guid.NewGuid();
|
|
|
|
_mockAccesser.Setup(f => f.HasAccessAsync(mediaId, _userId)).ReturnsAsync(true);
|
|
_mockMedia.Setup(f => f.GetMediaByIdAsync(mediaId))
|
|
.ThrowsAsync(new Exception("Something went wrong"));
|
|
|
|
// Act
|
|
var result = await _controller.Download(mediaId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.InstanceOf<ObjectResult>());
|
|
var objectResult = result as ObjectResult;
|
|
Assert.That(objectResult.StatusCode, Is.EqualTo(500));
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
_controller.Dispose();
|
|
}
|
|
} |