[FA-misc] Refresh button, UI mostly gold
All checks were successful
CI / build-backend (pull_request) Successful in 1m45s
CI / build-frontend (pull_request) Successful in 39s

This commit is contained in:
gamer147
2025-12-09 09:11:39 -05:00
parent 81e4e88ad4
commit e70c39ea75
12 changed files with 476 additions and 26 deletions

View File

@@ -162,4 +162,138 @@ public class NovelUpdateServiceTests
}
private record NovelCreateResult(Novel Novel, Chapter Chapter);
#region UpdateImage Tests
[Fact]
public async Task UpdateImage_sets_NewPath_on_image_without_chapter()
{
// Arrange
using var dbContext = CreateDbContext();
var image = new Image
{
OriginalPath = "http://original/cover.jpg",
NewPath = null
};
dbContext.Images.Add(image);
await dbContext.SaveChangesAsync();
var adapter = Substitute.For<ISourceAdapter>();
var eventBus = Substitute.For<IEventBus>();
var service = CreateService(dbContext, adapter, eventBus);
var newUrl = "https://cdn.example.com/uploaded/cover.jpg";
// Act
await service.UpdateImage(image.Id, newUrl);
// Assert
var updatedImage = await dbContext.Images.FindAsync(image.Id);
updatedImage!.NewPath.Should().Be(newUrl);
updatedImage.OriginalPath.Should().Be("http://original/cover.jpg");
}
[Fact]
public async Task UpdateImage_updates_chapter_body_html_with_new_url()
{
// Arrange
using var dbContext = CreateDbContext();
var source = new Source { Name = "Demo", Key = "demo", Url = "http://demo" };
var (novel, chapter) = CreateNovelWithSingleChapter(dbContext, source);
var image = new Image
{
OriginalPath = "http://original/image.jpg",
NewPath = null,
Chapter = chapter
};
chapter.Images.Add(image);
await dbContext.SaveChangesAsync();
// Set up the chapter body with an img tag referencing the image by ID (as PullChapterContents does)
var pendingUrl = "https://pending/placeholder.jpg";
var bodyHtml = $"<p>Content</p><img src=\"{pendingUrl}\" alt=\"{image.Id}\" />";
chapter.Body.Texts.Add(new LocalizationText
{
Language = Language.En,
Text = bodyHtml
});
await dbContext.SaveChangesAsync();
var adapter = Substitute.For<ISourceAdapter>();
var eventBus = Substitute.For<IEventBus>();
var service = CreateService(dbContext, adapter, eventBus, pendingUrl);
var newUrl = "https://cdn.example.com/uploaded/image.jpg";
// Act
await service.UpdateImage(image.Id, newUrl);
// Assert
var updatedImage = await dbContext.Images
.Include(i => i.Chapter)
.ThenInclude(c => c.Body)
.ThenInclude(b => b.Texts)
.FirstAsync(i => i.Id == image.Id);
updatedImage.NewPath.Should().Be(newUrl);
var updatedBodyText = updatedImage.Chapter!.Body.Texts.Single().Text;
var doc = new HtmlDocument();
doc.LoadHtml(updatedBodyText);
var imgNode = doc.DocumentNode.SelectSingleNode("//img");
imgNode.Should().NotBeNull();
imgNode!.GetAttributeValue("src", string.Empty).Should().Be(newUrl);
}
[Fact]
public async Task UpdateImage_does_not_modify_other_images_in_chapter_body()
{
// Arrange
using var dbContext = CreateDbContext();
var source = new Source { Name = "Demo", Key = "demo", Url = "http://demo" };
var (novel, chapter) = CreateNovelWithSingleChapter(dbContext, source);
var image1 = new Image { OriginalPath = "http://original/img1.jpg", Chapter = chapter };
var image2 = new Image { OriginalPath = "http://original/img2.jpg", Chapter = chapter };
chapter.Images.Add(image1);
chapter.Images.Add(image2);
await dbContext.SaveChangesAsync();
var pendingUrl = "https://pending/placeholder.jpg";
var bodyHtml = $"<p>Content</p><img src=\"{pendingUrl}\" alt=\"{image1.Id}\" /><img src=\"{pendingUrl}\" alt=\"{image2.Id}\" />";
chapter.Body.Texts.Add(new LocalizationText
{
Language = Language.En,
Text = bodyHtml
});
await dbContext.SaveChangesAsync();
var adapter = Substitute.For<ISourceAdapter>();
var eventBus = Substitute.For<IEventBus>();
var service = CreateService(dbContext, adapter, eventBus, pendingUrl);
var newUrl = "https://cdn.example.com/uploaded/img1.jpg";
// Act - only update image1
await service.UpdateImage(image1.Id, newUrl);
// Assert
var updatedChapter = await dbContext.Chapters
.Include(c => c.Body)
.ThenInclude(b => b.Texts)
.FirstAsync(c => c.Id == chapter.Id);
var updatedBodyText = updatedChapter.Body.Texts.Single().Text;
var doc = new HtmlDocument();
doc.LoadHtml(updatedBodyText);
var img1Node = doc.DocumentNode.SelectSingleNode($"//img[@alt='{image1.Id}']");
var img2Node = doc.DocumentNode.SelectSingleNode($"//img[@alt='{image2.Id}']");
img1Node!.GetAttributeValue("src", string.Empty).Should().Be(newUrl);
img2Node!.GetAttributeValue("src", string.Empty).Should().Be(pendingUrl);
}
#endregion
}