using Microsoft.EntityFrameworkCore; using Novelly.Api.Beats; using Novelly.Api.Chapters; using Novelly.Api.Common; using Novelly.Api.Novels; namespace Novelly.Api.Tests; [TestFixture] public class ChapterServiceTests : ServiceTestFixture { private Guid _novelId; protected override void OnSetUp() { _novelId = Novels.CreateAsync(new CreateNovelRequest("The Salt Road")).Result.Id; } [Test] public async Task Setting_a_number_that_already_exists_is_still_stored_as_given() { var first = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall", Number: 5)); var second = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("The Harbour", Number: 5)); Assert.Multiple(() => { Assert.That(first.Number, Is.EqualTo(5)); Assert.That(second.Number, Is.EqualTo(5)); }); } [Test] public async Task Updating_leaves_omitted_fields_alone_and_clears_notes_on_empty_string() { var chapter = await Chapters.CreateAsync(_novelId, new CreateChapterRequest( "Landfall", Summary: "The ship makes shore.", Notes: "Check the tide tables.")); var renamed = (await Chapters.UpdateAsync(chapter.Id, new UpdateChapterRequest(Title: "First Landfall")))!; Assert.Multiple(() => { Assert.That(renamed.Title, Is.EqualTo("First Landfall")); Assert.That(renamed.Summary, Is.EqualTo("The ship makes shore.")); Assert.That(renamed.Notes, Is.EqualTo("Check the tide tables.")); }); var cleared = (await Chapters.UpdateAsync(chapter.Id, new UpdateChapterRequest(Notes: "")))!; Assert.Multiple(() => { Assert.That(cleared.Notes, Is.Null); Assert.That(cleared.Summary, Is.EqualTo("The ship makes shore.")); }); } [Test] public async Task Deleting_a_chapter_takes_its_beats_with_it() { var chapter = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall")); await Beats.CreateAsync(chapter.Id, new CreateBeatRequest("She finds the map")); await Chapters.DeleteAsync(chapter.Id); using var verification = Db.CreateContext(); Assert.That(await verification.Beats.CountAsync(), Is.EqualTo(0)); } [Test] public async Task Creating_a_chapter_under_a_missing_novel_returns_null_rather_than_throwing() => Assert.That( await Chapters.CreateAsync(Guid.NewGuid(), new CreateChapterRequest("Landfall")), Is.Null); [Test] public async Task Reading_a_missing_chapter_returns_null_rather_than_throwing() => Assert.That(await Chapters.GetAsync(Guid.NewGuid()), Is.Null); [Test] public async Task Deleting_a_missing_chapter_returns_false_rather_than_throwing() => Assert.That(await Chapters.DeleteAsync(Guid.NewGuid()), Is.False); [Test] public async Task A_chapter_defaults_to_a_body_chapter() { var chapter = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall")); Assert.That(chapter!.Kind, Is.EqualTo(ChapterKind.Body)); } [Test] public async Task Front_matter_does_not_consume_a_chapter_number() { var foreword = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Foreword", Number: 1, Kind: ChapterKind.FrontMatter)); var first = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall", Number: 2)); var second = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("The Harbour", Number: 3)); var displayNumbers = ChapterNumbering.DisplayNumbers(await Chapters.ListAsync(_novelId)); Assert.Multiple(() => { Assert.That(displayNumbers.ContainsKey(foreword!.Id), Is.False); Assert.That(displayNumbers[first!.Id], Is.EqualTo(1)); Assert.That(displayNumbers[second!.Id], Is.EqualTo(2)); }); } [Test] public async Task Back_matter_is_listed_last_but_carries_no_chapter_number() { var body = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall", Number: 1)); var afterword = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Afterword", Number: 2, Kind: ChapterKind.BackMatter)); var afterwordDisplayNumber = await Chapters.DisplayNumberAsync(afterword!); var bodyDisplayNumber = await Chapters.DisplayNumberAsync(body!); Assert.Multiple(() => { Assert.That(afterwordDisplayNumber, Is.Null); Assert.That(bodyDisplayNumber, Is.EqualTo(1)); }); } [Test] public async Task Changing_a_chapter_to_front_matter_drops_it_from_the_chapter_count() { var chapter = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Prologue", Number: 1)); var other = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall", Number: 2)); var updated = await Chapters.UpdateAsync(chapter!.Id, new UpdateChapterRequest(Kind: ChapterKind.FrontMatter)); var updatedDisplayNumber = await Chapters.DisplayNumberAsync(updated!); var otherDisplayNumber = await Chapters.DisplayNumberAsync(other!); Assert.Multiple(() => { Assert.That(updatedDisplayNumber, Is.Null); Assert.That(otherDisplayNumber, Is.EqualTo(1)); }); } }