Added tests, need to go through them manually to check if they make sense and are correct later
This commit is contained in:
@@ -0,0 +1,157 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Lutra.API.IntegrationTests.Infrastructure;
|
||||||
|
using Lutra.Application.Supermarkten;
|
||||||
|
using Lutra.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Lutra.API.IntegrationTests.Controllers;
|
||||||
|
|
||||||
|
public class SupermarktenControllerTests(LutraApiFactory factory)
|
||||||
|
: IntegrationTestBase(factory)
|
||||||
|
{
|
||||||
|
// ── GET /api/supermarkten ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsOk_WithEmptyList_WhenNoDataExists()
|
||||||
|
{
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body.Should().NotBeNull();
|
||||||
|
body!.Supermarkten.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsSeededSupermarkt()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Albert Heijn",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body!.Supermarkten.Should().HaveCount(1);
|
||||||
|
body.Supermarkten.First().Naam.Should().Be("Albert Heijn");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsAllSeededSupermarkten()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Albert Heijn",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Jumbo",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Picnic",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body!.Supermarkten.Should().HaveCount(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GET /api/supermarkten — pagination ────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_Pagination_ReturnsCorrectPage()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Albert Heijn",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Jumbo",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Picnic",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten?skip=1&take=1");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body!.Supermarkten.Should().HaveCount(1);
|
||||||
|
// Handler orders by Naam ascending, so skip=1 skips "Albert Heijn" and returns "Jumbo".
|
||||||
|
body.Supermarkten.First().Naam.Should().Be("Jumbo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_Pagination_ReturnsEmptyList_WhenSkipExceedsTotalCount()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Albert Heijn",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten?skip=10&take=50");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body!.Supermarkten.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GET /api/supermarkten — sorting ───────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsSupermarkten_OrderedByNaamAscending()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Picnic",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Albert Heijn",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
var namen = body!.Supermarkten.Select(s => s.Naam).ToList();
|
||||||
|
namen.Should().BeInAscendingOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Soft-delete behaviour ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_DoesNotReturn_SoftDeletedSupermarkt()
|
||||||
|
{
|
||||||
|
await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Verwijderd",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow,
|
||||||
|
DeletedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/supermarkten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetSupermarkten.Response>();
|
||||||
|
body!.Supermarkten.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Lutra.API.IntegrationTests.Infrastructure;
|
||||||
|
using Lutra.API.Requests;
|
||||||
|
using Lutra.Application.Verspakketten;
|
||||||
|
using Lutra.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Lutra.API.IntegrationTests.Controllers;
|
||||||
|
|
||||||
|
public class VerspakkettenControllerTests(LutraApiFactory factory)
|
||||||
|
: IntegrationTestBase(factory)
|
||||||
|
{
|
||||||
|
// ── GET /api/verspakketten ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsOk_WithEmptyList_WhenNoDataExists()
|
||||||
|
{
|
||||||
|
var response = await Client.GetAsync("/api/verspakketten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetVerspakketten.Response>();
|
||||||
|
body.Should().NotBeNull();
|
||||||
|
body!.Verspakketten.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_ReturnsSeededVerspakket()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Lente Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/verspakketten");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetVerspakketten.Response>();
|
||||||
|
body!.Verspakketten.Should().HaveCount(1);
|
||||||
|
body.Verspakketten.First().Naam.Should().Be("Lente Pakket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GET /api/verspakketten/{id} ───────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetById_ReturnsNotFound_WhenVerspakketDoesNotExist()
|
||||||
|
{
|
||||||
|
var response = await Client.GetAsync($"/api/verspakketten/{Guid.NewGuid()}");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetById_ReturnsVerspakket_WhenItExists()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Jumbo",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
var verspakket = await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Zomer Pakket", AantalPersonen = 4,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync($"/api/verspakketten/{verspakket.Id}");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetVerspakket.Response>();
|
||||||
|
body!.Verspakket.Should().NotBeNull();
|
||||||
|
body.Verspakket!.Naam.Should().Be("Zomer Pakket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── POST /api/verspakketten ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Post_CreatesVerspakket_AndReturns201()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Picnic",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var command = new CreateVerspakket.Command("Herfst Pakket", 1499, 3, supermarkt.Id);
|
||||||
|
var response = await Client.PostAsJsonAsync("/api/verspakketten", command);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<CreateVerspakket.Response>();
|
||||||
|
body!.Id.Should().NotBeEmpty();
|
||||||
|
response.Headers.Location.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Post_ReturnsBadRequest_WhenSupermarktDoesNotExist()
|
||||||
|
{
|
||||||
|
var command = new CreateVerspakket.Command("Winter Pakket", 999, 2, Guid.NewGuid());
|
||||||
|
var response = await Client.PostAsJsonAsync("/api/verspakketten", command);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── PUT /api/verspakketten/{id} ───────────────────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Update_ReturnsNoContent_WhenVerspakketExists()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
var verspakket = await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Oud Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var request = new UpdateVerspakketRequest("Nieuw Pakket", 1999, 3, supermarkt.Id);
|
||||||
|
var response = await Client.PutAsJsonAsync($"/api/verspakketten/{verspakket.Id}", request);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Update_ReturnsNotFound_WhenVerspakketDoesNotExist()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var request = new UpdateVerspakketRequest("Pakket", 999, 2, supermarkt.Id);
|
||||||
|
var response = await Client.PutAsJsonAsync($"/api/verspakketten/{Guid.NewGuid()}", request);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Update_ReturnsBadRequest_WhenSupermarktDoesNotExist()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
var verspakket = await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var request = new UpdateVerspakketRequest("Pakket", 999, 2, Guid.NewGuid());
|
||||||
|
var response = await Client.PutAsJsonAsync($"/api/verspakketten/{verspakket.Id}", request);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GET /api/verspakketten — pagination & sorting ─────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_Pagination_ReturnsCorrectPage()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Aardappel Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Broccoli Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Courgette Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/verspakketten?skip=1&take=1");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetVerspakketten.Response>();
|
||||||
|
body!.Verspakketten.Should().HaveCount(1);
|
||||||
|
body.Verspakketten.First().Naam.Should().Be("Broccoli Pakket");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Get_SortDescending_ReturnsItemsInReverseOrder()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "AH",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Aardappel Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Zomerpakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/api/verspakketten?sortDirection=Descending");
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<GetVerspakketten.Response>();
|
||||||
|
body!.Verspakketten.First().Naam.Should().Be("Zomerpakket");
|
||||||
|
body.Verspakketten.Last().Naam.Should().Be("Aardappel Pakket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── POST /api/verspakketten/{id}/beoordelingen ────────────────────────────
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AddBeoordeling_ReturnsBadRequest_WhenVerspakketDoesNotExist()
|
||||||
|
{
|
||||||
|
var command = new AddBeoordeling.Command(Guid.NewGuid(), 8, 7, true, "Heerlijk!");
|
||||||
|
var response = await Client.PostAsJsonAsync($"/api/verspakketten/{command.VerspakketId}/beoordelingen", command);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AddBeoordeling_Returns201_WhenVerspakketExists()
|
||||||
|
{
|
||||||
|
var supermarkt = await SeedAsync(new Supermarkt
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Lidl",
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
var verspakket = await SeedAsync(new Verspakket
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(), Naam = "Basis Pakket", AantalPersonen = 2,
|
||||||
|
SupermarktId = supermarkt.Id,
|
||||||
|
CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
var command = new AddBeoordeling.Command(verspakket.Id, 8, 7, true, "Heerlijk!");
|
||||||
|
var response = await Client.PostAsJsonAsync($"/api/verspakketten/{verspakket.Id}/beoordelingen", command);
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||||
|
var body = await response.Content.ReadFromJsonAsync<AddBeoordeling.Response>();
|
||||||
|
body!.Id.Should().NotBeEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Lutra.Application.Interfaces;
|
||||||
|
using Lutra.Infrastructure.Sql;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Lutra.API.IntegrationTests.Infrastructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for integration tests. Provides a shared factory and helper methods
|
||||||
|
/// to seed and reset the database between tests.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class IntegrationTestBase : IClassFixture<LutraApiFactory>, IAsyncLifetime
|
||||||
|
{
|
||||||
|
protected readonly LutraApiFactory Factory;
|
||||||
|
protected readonly HttpClient Client;
|
||||||
|
|
||||||
|
protected IntegrationTestBase(LutraApiFactory factory)
|
||||||
|
{
|
||||||
|
Factory = factory;
|
||||||
|
Client = factory.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Seed data or perform setup before each test.</summary>
|
||||||
|
public virtual Task InitializeAsync()
|
||||||
|
{
|
||||||
|
Factory.EnsureSchemaCreated();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Reset database state after each test.</summary>
|
||||||
|
public async Task DisposeAsync()
|
||||||
|
{
|
||||||
|
using var scope = Factory.Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<ILutraDbContext>() as LutraDbContext;
|
||||||
|
if (db is not null)
|
||||||
|
{
|
||||||
|
db.Beoordelingen.RemoveRange(db.Beoordelingen);
|
||||||
|
db.Verspaketten.RemoveRange(db.Verspaketten);
|
||||||
|
db.Supermarkten.RemoveRange(db.Supermarkten);
|
||||||
|
await db.SaveChangesAsync(CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<T> SeedAsync<T>(T entity) where T : class
|
||||||
|
{
|
||||||
|
using var scope = Factory.Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<ILutraDbContext>() as LutraDbContext;
|
||||||
|
db!.Set<T>().Add(entity);
|
||||||
|
await db.SaveChangesAsync(CancellationToken.None);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using Lutra.Application.Interfaces;
|
||||||
|
using Lutra.Infrastructure.Sql;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
|
namespace Lutra.API.IntegrationTests.Infrastructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom WebApplicationFactory that replaces the PostgreSQL database with SQLite in-memory
|
||||||
|
/// so that integration tests can run without a live database server.
|
||||||
|
/// A single SqliteConnection is kept open for the lifetime of the factory so that
|
||||||
|
/// all DI scopes share the same in-memory database.
|
||||||
|
/// </summary>
|
||||||
|
public class LutraApiFactory : WebApplicationFactory<Program>
|
||||||
|
{
|
||||||
|
// Opened immediately so it is ready when ConfigureWebHost runs.
|
||||||
|
private readonly SqliteConnection _connection = new("Data Source=:memory:");
|
||||||
|
private bool _schemaCreated;
|
||||||
|
|
||||||
|
public LutraApiFactory()
|
||||||
|
{
|
||||||
|
_connection.Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Ensures the SQLite schema is created. Call once before the first test.</summary>
|
||||||
|
public void EnsureSchemaCreated()
|
||||||
|
{
|
||||||
|
if (_schemaCreated) return;
|
||||||
|
|
||||||
|
using var scope = Services.CreateScope();
|
||||||
|
var db = (LutraDbContext)scope.ServiceProvider.GetRequiredService<ILutraDbContext>();
|
||||||
|
db.Database.EnsureCreated();
|
||||||
|
_schemaCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
|
{
|
||||||
|
builder.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
// EF Core 10 stores provider configuration in IDbContextOptionsConfiguration<T>
|
||||||
|
// descriptors (one per AddDbContext call). All four registration types must be
|
||||||
|
// removed so neither Npgsql options nor its provider services survive into the
|
||||||
|
// SQLite registration.
|
||||||
|
services.RemoveAll<ILutraDbContext>();
|
||||||
|
services.RemoveAll<LutraDbContext>();
|
||||||
|
services.RemoveAll<DbContextOptions<LutraDbContext>>();
|
||||||
|
services.RemoveAll<DbContextOptions>();
|
||||||
|
services.RemoveAll(typeof(IDbContextOptionsConfiguration<LutraDbContext>));
|
||||||
|
|
||||||
|
// Register SQLite using the shared open connection.
|
||||||
|
services.AddDbContext<ILutraDbContext, LutraDbContext>(options =>
|
||||||
|
options.UseSqlite(_connection));
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.UseEnvironment("Testing");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (disposing)
|
||||||
|
_connection.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="10.0.0">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.9.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.6" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.6" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Lutra.API\Lutra.API.csproj" />
|
||||||
|
<ProjectReference Include="..\Lutra.Infrastructure\Lutra.Infrastructure.Sql.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -85,12 +85,28 @@ namespace Lutra.API.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
[HttpPut("{id:guid}")]
|
[HttpPut("{id:guid}")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateVerspakketRequest request)
|
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateVerspakketRequest request)
|
||||||
{
|
{
|
||||||
var command = new UpdateVerspakket.Command(id, request.Naam, request.PrijsInCenten, request.AantalPersonen, request.SupermarktId);
|
try
|
||||||
await mediator.SendCommandAsync<UpdateVerspakket.Command, UpdateVerspakket.Response>(command);
|
{
|
||||||
return NoContent();
|
var command = new UpdateVerspakket.Command(id, request.Naam, request.PrijsInCenten, request.AantalPersonen, request.SupermarktId);
|
||||||
|
await mediator.SendCommandAsync<UpdateVerspakket.Command, UpdateVerspakket.Response>(command);
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex) when (ex.Message.StartsWith($"Verspakket with id '{id}'"))
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.9.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||||
|
<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" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Lutra.Application\Lutra.Application.csproj" />
|
||||||
|
<ProjectReference Include="..\Lutra.Domain\Lutra.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using Lutra.Application.Interfaces;
|
||||||
|
using Lutra.Application.Verspakketten;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Moq;
|
||||||
|
using Moq.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Lutra.Application.UnitTests.Verspakketten;
|
||||||
|
|
||||||
|
public class AddBeoordelingHandlerTests
|
||||||
|
{
|
||||||
|
private readonly Mock<ILutraDbContext> _contextMock;
|
||||||
|
private readonly AddBeoordeling.Handler _handler;
|
||||||
|
|
||||||
|
public AddBeoordelingHandlerTests()
|
||||||
|
{
|
||||||
|
_contextMock = new Mock<ILutraDbContext>();
|
||||||
|
_handler = new AddBeoordeling.Handler(_contextMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_VerspakketExists_AddsBeoordeling()
|
||||||
|
{
|
||||||
|
var verspakketId = Guid.NewGuid();
|
||||||
|
var verspakketten = new List<Domain.Entities.Verspakket>
|
||||||
|
{
|
||||||
|
new() { Id = verspakketId, Naam = "Test", AantalPersonen = 2, SupermarktId = Guid.NewGuid(), CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow }
|
||||||
|
};
|
||||||
|
|
||||||
|
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(verspakketten);
|
||||||
|
_contextMock.Setup(c => c.Beoordelingen).ReturnsDbSet(new List<Domain.Entities.Beoordeling>());
|
||||||
|
_contextMock.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(1);
|
||||||
|
|
||||||
|
var command = new AddBeoordeling.Command(verspakketId, 8, 7, true, "Lekker!");
|
||||||
|
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
result.Id.Should().NotBeEmpty();
|
||||||
|
_contextMock.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_VerspakketNotFound_ThrowsInvalidOperationException()
|
||||||
|
{
|
||||||
|
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(new List<Domain.Entities.Verspakket>());
|
||||||
|
|
||||||
|
var command = new AddBeoordeling.Command(Guid.NewGuid(), 8, 7, true, null);
|
||||||
|
|
||||||
|
var act = () => _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
await act.Should().ThrowAsync<InvalidOperationException>()
|
||||||
|
.WithMessage("*was not found*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_VerspakketDeleted_ThrowsInvalidOperationException()
|
||||||
|
{
|
||||||
|
var verspakketId = Guid.NewGuid();
|
||||||
|
var verspakketten = new List<Domain.Entities.Verspakket>
|
||||||
|
{
|
||||||
|
new() { Id = verspakketId, Naam = "Deleted", AantalPersonen = 2, SupermarktId = Guid.NewGuid(), CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow, DeletedAt = DateTime.UtcNow }
|
||||||
|
};
|
||||||
|
|
||||||
|
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(verspakketten);
|
||||||
|
|
||||||
|
var command = new AddBeoordeling.Command(verspakketId, 8, 7, true, null);
|
||||||
|
|
||||||
|
var act = () => _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
await act.Should().ThrowAsync<InvalidOperationException>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using Lutra.Application.Interfaces;
|
||||||
|
using Lutra.Application.Verspakketten;
|
||||||
|
using Moq;
|
||||||
|
using Moq.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Lutra.Application.UnitTests.Verspakketten;
|
||||||
|
|
||||||
|
public class CreateVerspakketHandlerTests
|
||||||
|
{
|
||||||
|
private readonly Mock<ILutraDbContext> _contextMock;
|
||||||
|
private readonly CreateVerspakket.Handler _handler;
|
||||||
|
|
||||||
|
public CreateVerspakketHandlerTests()
|
||||||
|
{
|
||||||
|
_contextMock = new Mock<ILutraDbContext>();
|
||||||
|
_handler = new CreateVerspakket.Handler(_contextMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_SupermarktExists_CreatesVerspakket()
|
||||||
|
{
|
||||||
|
var supermarktId = Guid.NewGuid();
|
||||||
|
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);
|
||||||
|
|
||||||
|
var command = new CreateVerspakket.Command("Lente Pakket", 1299, 2, supermarktId);
|
||||||
|
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
result.Id.Should().NotBeEmpty();
|
||||||
|
_contextMock.Verify(c => c.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_SupermarktNotFound_ThrowsInvalidOperationException()
|
||||||
|
{
|
||||||
|
_contextMock.Setup(c => c.Supermarkten).ReturnsDbSet(new List<Domain.Entities.Supermarkt>());
|
||||||
|
|
||||||
|
var command = new CreateVerspakket.Command("Lente Pakket", 1299, 2, Guid.NewGuid());
|
||||||
|
|
||||||
|
var act = () => _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
await act.Should().ThrowAsync<InvalidOperationException>()
|
||||||
|
.WithMessage("*was not found*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_CreatesVerspakketWithCorrectProperties()
|
||||||
|
{
|
||||||
|
var supermarktId = Guid.NewGuid();
|
||||||
|
var supermarkten = new List<Domain.Entities.Supermarkt>
|
||||||
|
{
|
||||||
|
new() { Id = supermarktId, Naam = "Jumbo", CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow }
|
||||||
|
};
|
||||||
|
|
||||||
|
Domain.Entities.Verspakket? savedVerspakket = null;
|
||||||
|
_contextMock.Setup(c => c.Supermarkten).ReturnsDbSet(supermarkten);
|
||||||
|
_contextMock.Setup(c => c.Verspaketten).ReturnsDbSet(new List<Domain.Entities.Verspakket>());
|
||||||
|
_contextMock
|
||||||
|
.Setup(c => c.Verspaketten.AddAsync(It.IsAny<Domain.Entities.Verspakket>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Callback<Domain.Entities.Verspakket, CancellationToken>((v, _) => savedVerspakket = v);
|
||||||
|
_contextMock.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(1);
|
||||||
|
|
||||||
|
var command = new CreateVerspakket.Command("Zomer Pakket", 999, 4, supermarktId);
|
||||||
|
|
||||||
|
await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
savedVerspakket.Should().NotBeNull();
|
||||||
|
savedVerspakket!.Naam.Should().Be("Zomer Pakket");
|
||||||
|
savedVerspakket.PrijsInCenten.Should().Be(999);
|
||||||
|
savedVerspakket.AantalPersonen.Should().Be(4);
|
||||||
|
savedVerspakket.SupermarktId.Should().Be(supermarktId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,36 +15,118 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.AppHost", "Lutra.AppH
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.Infrastructure.Migrator", "Lutra.Infrastructure.Migrator\Lutra.Infrastructure.Migrator.csproj", "{6582486C-CEB7-78BF-D043-E0C3C0D6A923}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.Infrastructure.Migrator", "Lutra.Infrastructure.Migrator\Lutra.Infrastructure.Migrator.csproj", "{6582486C-CEB7-78BF-D043-E0C3C0D6A923}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.Application.UnitTests", "Lutra.Application.UnitTests\Lutra.Application.UnitTests.csproj", "{923A138F-A7A1-4254-A95F-447977B7AAC0}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.API.IntegrationTests", "Lutra.API.IntegrationTests\Lutra.API.IntegrationTests.csproj", "{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lutra.Infrastructure", "Lutra.Infrastructure", "{DF712D4B-6D10-CA62-6EF1-190F54D65E10}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{22B74CFE-E9D0-42F3-96E3-818D014E1A2E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{CD66D294-FB25-4CA1-8DCA-7EF3DDDFE0C5}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|Any CPU.Build.0 = Release|Any CPU
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{DACBC33C-A76A-483A-8535-AA62D33D4977}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{0D9E0DD9-E914-483F-8046-8A57B510E984}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{923A138F-A7A1-4254-A95F-447977B7AAC0}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E1B105D6-DCC2-42F5-9CB9-3A295804DCF6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user