Files
2026-03-15 22:31:31 +02:00

159 lines
6.3 KiB
C#

using System.Net;
using System.Net.Http.Json;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using PageManager.Api.Api.Dtos;
using PageManager.Api.Data;
using PageManager.Api.Data.Models;
using PageManager.Api.Tests.Integration.Fixtures;
namespace PageManager.Api.Tests.Integration;
[Collection("Postgres")]
public class ImportControllerTests : IAsyncLifetime
{
private readonly TestWebAppFactory _factory;
private readonly HttpClient _client;
public ImportControllerTests(PostgresFixture postgres)
{
_factory = new TestWebAppFactory(postgres);
_client = _factory.CreateClient();
}
public async Task InitializeAsync()
{
using var scope = _factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions
.ExecuteSqlRawAsync(db.Database,
"TRUNCATE import_queue_items, import_sources RESTART IDENTITY CASCADE");
}
public Task DisposeAsync()
{
_client.Dispose();
_factory.Dispose();
return Task.CompletedTask;
}
// ── GET /api/sources ──────────────────────────────────────────────────────
[Fact]
public async Task GetSources_EmptyDb_Returns200WithEmptyArray()
{
var response = await _client.GetAsync("/api/sources");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var sources = await response.Content.ReadFromJsonAsync<ImportSourceDto[]>();
sources.Should().BeEmpty();
}
[Fact]
public async Task GetSources_SeededSource_ReturnsMappedDto()
{
await SeedSourceAsync(name: "My Library", type: ImportSourceType.Folder, path: "/books");
var response = await _client.GetAsync("/api/sources");
var sources = await response.Content.ReadFromJsonAsync<ImportSourceDto[]>();
sources.Should().HaveCount(1);
sources![0].Name.Should().Be("My Library");
sources[0].Type.Should().Be("folder");
sources[0].Enabled.Should().BeTrue();
}
// ── PATCH /api/sources/{id} ───────────────────────────────────────────────
[Fact]
public async Task UpdateSource_Found_Returns200WithUpdatedEnabled()
{
var id = await SeedSourceAsync();
var response = await _client.PatchAsJsonAsync($"/api/sources/{id}", new { enabled = false });
response.StatusCode.Should().Be(HttpStatusCode.OK);
var dto = await response.Content.ReadFromJsonAsync<ImportSourceDto>();
dto!.Enabled.Should().BeFalse();
}
[Fact]
public async Task UpdateSource_NotFound_Returns404()
{
var response = await _client.PatchAsJsonAsync("/api/sources/missing-id", new { enabled = false });
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
// ── GET /api/queue ────────────────────────────────────────────────────────
[Fact]
public async Task GetQueue_EmptyDb_Returns200WithEmptyArray()
{
var response = await _client.GetAsync("/api/queue");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var items = await response.Content.ReadFromJsonAsync<QueueItemDto[]>();
items.Should().BeEmpty();
}
// ── DELETE /api/queue/{id} ────────────────────────────────────────────────
[Fact]
public async Task RemoveQueueItem_Found_Returns204()
{
var id = await SeedQueueItemAsync();
var response = await _client.DeleteAsync($"/api/queue/{id}");
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
}
[Fact]
public async Task RemoveQueueItem_NotFound_Returns404()
{
var response = await _client.DeleteAsync("/api/queue/missing-id");
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
// ── POST /api/queue/{id}/retry ────────────────────────────────────────────
[Fact]
public async Task RetryQueueItem_FailedItem_Returns204()
{
var id = await SeedQueueItemAsync(status: QueueItemStatus.Failed);
var response = await _client.PostAsync($"/api/queue/{id}/retry", null);
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
}
[Fact]
public async Task RetryQueueItem_NonFailedItem_Returns404()
{
var id = await SeedQueueItemAsync(status: QueueItemStatus.Completed);
var response = await _client.PostAsync($"/api/queue/{id}/retry", null);
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
// ── Helpers ───────────────────────────────────────────────────────────────
private async Task<string> SeedSourceAsync(
string name = "Test Source",
ImportSourceType type = ImportSourceType.Folder,
string path = "/test")
{
using var scope = _factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var source = new ImportSource { Name = name, Type = type, Path = path };
db.ImportSources.Add(source);
await db.SaveChangesAsync();
return source.Id;
}
private async Task<string> SeedQueueItemAsync(
string filename = "book.epub",
QueueItemStatus status = QueueItemStatus.Queued)
{
using var scope = _factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var item = new ImportQueueItem { Filename = filename, Status = status, Source = "https://example.com" };
db.ImportQueueItems.Add(item);
await db.SaveChangesAsync();
return item.Id;
}
}