using Microsoft.EntityFrameworkCore; using PageManager.Api.Data; using PageManager.Api.Data.Models; using PageManager.Api.Services; namespace PageManager.Api.Tests.Unit.Services; public class ImportServiceTests : IDisposable { private readonly AppDbContext _db; private readonly ImportService _sut; public ImportServiceTests() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; _db = new AppDbContext(options); _sut = new ImportService(_db); } public void Dispose() => _db.Dispose(); // ── Sources ─────────────────────────────────────────────────────────────── [Fact] public async Task GetSourcesAsync_ReturnsMappedDtos() { _db.ImportSources.Add(new ImportSource { Id = "s1", Name = "My Books", Type = ImportSourceType.Folder, Path = "/books", Enabled = true }); await _db.SaveChangesAsync(); var result = (await _sut.GetSourcesAsync()).ToArray(); result.Should().HaveCount(1); result[0].Id.Should().Be("s1"); result[0].Name.Should().Be("My Books"); result[0].Type.Should().Be("folder"); result[0].Enabled.Should().BeTrue(); } [Fact] public async Task UpdateSourceAsync_Found_TogglesEnabled() { _db.ImportSources.Add(new ImportSource { Id = "s1", Name = "Lib", Type = ImportSourceType.Folder, Path = "/", Enabled = true }); await _db.SaveChangesAsync(); var result = await _sut.UpdateSourceAsync("s1", false); result.Should().NotBeNull(); result!.Enabled.Should().BeFalse(); (await _db.ImportSources.FindAsync("s1"))!.Enabled.Should().BeFalse(); } [Fact] public async Task UpdateSourceAsync_NotFound_ReturnsNull() { var result = await _sut.UpdateSourceAsync("missing", true); result.Should().BeNull(); } // ── Queue ───────────────────────────────────────────────────────────────── [Fact] public async Task GetQueueAsync_ReturnsMappedDtos() { _db.ImportQueueItems.Add(new ImportQueueItem { Id = "q1", Filename = "book.epub", SizeBytes = 1024, DownloadedBytes = 512, Status = QueueItemStatus.Downloading, Source = "https://example.com", }); await _db.SaveChangesAsync(); var result = (await _sut.GetQueueAsync()).ToArray(); result.Should().HaveCount(1); result[0].Id.Should().Be("q1"); result[0].Status.Should().Be("downloading"); } [Fact] public async Task RemoveQueueItemAsync_Found_RemovesAndReturnsTrue() { _db.ImportQueueItems.Add(new ImportQueueItem { Id = "q1", Filename = "f.epub", Status = QueueItemStatus.Completed }); await _db.SaveChangesAsync(); var result = await _sut.RemoveQueueItemAsync("q1"); result.Should().BeTrue(); _db.ImportQueueItems.Should().BeEmpty(); } [Fact] public async Task RemoveQueueItemAsync_NotFound_ReturnsFalse() { (await _sut.RemoveQueueItemAsync("missing")).Should().BeFalse(); } [Fact] public async Task RetryQueueItemAsync_FailedItem_SetsStatusToQueued() { _db.ImportQueueItems.Add(new ImportQueueItem { Id = "q1", Filename = "f.epub", Status = QueueItemStatus.Failed, Error = "timeout", }); await _db.SaveChangesAsync(); var result = await _sut.RetryQueueItemAsync("q1"); result.Should().BeTrue(); var item = await _db.ImportQueueItems.FindAsync("q1"); item!.Status.Should().Be(QueueItemStatus.Queued); item.Error.Should().BeNull(); } [Fact] public async Task RetryQueueItemAsync_NonFailedItem_ReturnsFalse() { _db.ImportQueueItems.Add(new ImportQueueItem { Id = "q1", Filename = "f.epub", Status = QueueItemStatus.Completed }); await _db.SaveChangesAsync(); (await _sut.RetryQueueItemAsync("q1")).Should().BeFalse(); } }