fixes and tweaks
This commit is contained in:
@@ -8,13 +8,19 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="8.9.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="Moq.EntityFrameworkCore" Version="10.0.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
using FluentAssertions;
|
||||
using Lutra.Application.Interfaces;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
using Lutra.Application.Verspakketten;
|
||||
using Moq;
|
||||
using Moq.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.UnitTests.Verspakketten;
|
||||
|
||||
public class CreateVerspakketWithFotosHandlerTests
|
||||
{
|
||||
private readonly Mock<ILutraDbContext> _contextMock;
|
||||
private readonly CreateVerspakket.Handler _handler;
|
||||
|
||||
// 1x1 white PNG as base64
|
||||
private const string ValidBase64Png = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI6QAAAABJRU5ErkJggg==";
|
||||
|
||||
public CreateVerspakketWithFotosHandlerTests()
|
||||
{
|
||||
_contextMock = new Mock<ILutraDbContext>();
|
||||
_handler = new CreateVerspakket.Handler(_contextMock.Object);
|
||||
}
|
||||
|
||||
private void SetupContext(Guid supermarktId)
|
||||
{
|
||||
var supermarkten = new List<Domain.Entities.Supermarkt>
|
||||
{
|
||||
new() { Id = supermarktId, Naam = "AH", CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow }
|
||||
};
|
||||
_contextMock.Setup(c => c.Supermarkten).ReturnsDbSet(supermarkten);
|
||||
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(new List<Domain.Entities.Verspakket>());
|
||||
_contextMock.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithFotos_CreatesVerspakketWithFotos()
|
||||
{
|
||||
var supermarktId = Guid.NewGuid();
|
||||
SetupContext(supermarktId);
|
||||
|
||||
Domain.Entities.Verspakket? saved = null;
|
||||
_contextMock
|
||||
.Setup(c => c.Verspaketten.AddAsync(It.IsAny<Domain.Entities.Verspakket>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<Domain.Entities.Verspakket, CancellationToken>((v, _) => saved = v);
|
||||
|
||||
var fotos = new List<VerspakketFoto>
|
||||
{
|
||||
new(ValidBase64Png, IsMainImage: true),
|
||||
new(ValidBase64Png, IsMainImage: false)
|
||||
};
|
||||
|
||||
var command = new CreateVerspakket.Command("Lente Pakket", 999, 2, supermarktId, null, fotos);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
saved.Should().NotBeNull();
|
||||
saved!.Fotos.Should().HaveCount(2);
|
||||
saved.Fotos.Count(f => f.IsMainImage).Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithoutFotos_CreatesVerspakketWithNoFotos()
|
||||
{
|
||||
var supermarktId = Guid.NewGuid();
|
||||
SetupContext(supermarktId);
|
||||
|
||||
Domain.Entities.Verspakket? saved = null;
|
||||
_contextMock
|
||||
.Setup(c => c.Verspaketten.AddAsync(It.IsAny<Domain.Entities.Verspakket>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<Domain.Entities.Verspakket, CancellationToken>((v, _) => saved = v);
|
||||
|
||||
var command = new CreateVerspakket.Command("Herfst Pakket", 799, 2, supermarktId, null);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
saved.Should().NotBeNull();
|
||||
saved!.Fotos.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_FotoBase64Decoded_StoresCorrectBytes()
|
||||
{
|
||||
var supermarktId = Guid.NewGuid();
|
||||
SetupContext(supermarktId);
|
||||
|
||||
Domain.Entities.Verspakket? saved = null;
|
||||
_contextMock
|
||||
.Setup(c => c.Verspaketten.AddAsync(It.IsAny<Domain.Entities.Verspakket>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<Domain.Entities.Verspakket, CancellationToken>((v, _) => saved = v);
|
||||
|
||||
var fotos = new List<VerspakketFoto> { new(ValidBase64Png, IsMainImage: false) };
|
||||
var command = new CreateVerspakket.Command("Pakket", null, 1, supermarktId, null, fotos);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
var foto = saved!.Fotos.Single();
|
||||
foto.Data.Should().BeEquivalentTo(Convert.FromBase64String(ValidBase64Png));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using FluentAssertions;
|
||||
using Lutra.Application.Interfaces;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
using Lutra.Application.Verspakketten;
|
||||
using Moq;
|
||||
using Moq.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.UnitTests.Verspakketten;
|
||||
|
||||
public class UpdateVerspakketHandlerTests
|
||||
{
|
||||
private readonly Mock<ILutraDbContext> _contextMock;
|
||||
private readonly UpdateVerspakket.Handler _handler;
|
||||
|
||||
private const string ValidBase64Png = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI6QAAAABJRU5ErkJggg==";
|
||||
|
||||
public UpdateVerspakketHandlerTests()
|
||||
{
|
||||
_contextMock = new Mock<ILutraDbContext>();
|
||||
_handler = new UpdateVerspakket.Handler(_contextMock.Object);
|
||||
}
|
||||
|
||||
private (Guid verspakketId, Guid supermarktId) SetupContext(
|
||||
List<Domain.Entities.VerspakketFoto>? existingFotos = null)
|
||||
{
|
||||
var supermarktId = Guid.NewGuid();
|
||||
var verspakketId = Guid.NewGuid();
|
||||
|
||||
var supermarkten = new List<Domain.Entities.Supermarkt>
|
||||
{
|
||||
new() { Id = supermarktId, Naam = "AH", CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
var verspakket = new Domain.Entities.Verspakket
|
||||
{
|
||||
Id = verspakketId,
|
||||
Naam = "Oud Pakket",
|
||||
PrijsInCenten = 500,
|
||||
AantalPersonen = 2,
|
||||
SupermarktId = supermarktId,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
ModifiedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
foreach (var foto in existingFotos ?? [])
|
||||
verspakket.AddFoto(foto);
|
||||
|
||||
_contextMock.Setup(c => c.Supermarkten).ReturnsDbSet(supermarkten);
|
||||
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(new List<Domain.Entities.Verspakket> { verspakket });
|
||||
_contextMock.Setup(c => c.VerspakketFotos).ReturnsDbSet(existingFotos ?? []);
|
||||
_contextMock.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(1);
|
||||
|
||||
return (verspakketId, supermarktId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithoutFotos_UpdatesFieldsOnly()
|
||||
{
|
||||
var (verspakketId, supermarktId) = SetupContext();
|
||||
|
||||
var command = new UpdateVerspakket.Command(verspakketId, "Nieuw Pakket", 1200, 4, supermarktId);
|
||||
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
result.Should().NotBeNull();
|
||||
_contextMock.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithFotos_ReplacesFotos()
|
||||
{
|
||||
var oldFotoId = Guid.NewGuid();
|
||||
var existingFotos = new List<Domain.Entities.VerspakketFoto>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = oldFotoId,
|
||||
Data = [0x00],
|
||||
IsMainImage = true,
|
||||
VerspakketId = Guid.NewGuid(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
ModifiedAt = DateTime.UtcNow
|
||||
}
|
||||
};
|
||||
|
||||
var (verspakketId, supermarktId) = SetupContext(existingFotos);
|
||||
|
||||
var newFotos = new List<VerspakketFoto>
|
||||
{
|
||||
new(ValidBase64Png, IsMainImage: true),
|
||||
new(ValidBase64Png, IsMainImage: false)
|
||||
};
|
||||
|
||||
var command = new UpdateVerspakket.Command(verspakketId, "Pakket", 999, 2, supermarktId, newFotos);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
_contextMock.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NullFotos_DoesNotTouchFotos()
|
||||
{
|
||||
var (verspakketId, supermarktId) = SetupContext();
|
||||
|
||||
var command = new UpdateVerspakket.Command(verspakketId, "Pakket", 800, 3, supermarktId, null);
|
||||
|
||||
await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// VerspakketFotos.RemoveRange should NOT be called when Fotos is null
|
||||
_contextMock.Verify(
|
||||
c => c.VerspakketFotos.RemoveRange(It.IsAny<IEnumerable<Domain.Entities.VerspakketFoto>>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_VerspakketNotFound_ThrowsInvalidOperationException()
|
||||
{
|
||||
var supermarktId = Guid.NewGuid();
|
||||
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(new List<Domain.Entities.Verspakket>());
|
||||
_contextMock.Setup(c => c.Supermarkten).ReturnsDbSet(new List<Domain.Entities.Supermarkt>());
|
||||
|
||||
var command = new UpdateVerspakket.Command(Guid.NewGuid(), "Pakket", 800, 2, supermarktId);
|
||||
|
||||
var act = () => _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
await act.Should().ThrowAsync<InvalidOperationException>().WithMessage("*was not found*");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_InvalidAantalPersonen_ThrowsArgumentException()
|
||||
{
|
||||
var (verspakketId, supermarktId) = SetupContext();
|
||||
|
||||
var command = new UpdateVerspakket.Command(verspakketId, "Pakket", 800, 0, supermarktId);
|
||||
|
||||
var act = () => _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
await act.Should().ThrowAsync<ArgumentException>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user