Add genre feature; extract ConfirmModal for reusable confirm dialogs
Genres seed on boot, are editable per project, and gate agent config errors more gracefully. ConfirmModal replaces ad-hoc confirm prompts across chapters, tags, and characters pages.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using Novelly.Api.Projects;
|
||||
|
||||
namespace Novelly.Api.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public class GenreServiceTests : ServiceTestFixture
|
||||
{
|
||||
[Test]
|
||||
public async Task The_genre_list_arrives_seeded_and_alphabetical()
|
||||
{
|
||||
var listed = await Genres.ListAsync();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(listed, Is.Not.Empty);
|
||||
Assert.That(listed.Select(g => g.Name), Has.Member("Fantasy").And.Member("Literary Fiction"));
|
||||
Assert.That(listed.Select(g => g.Name), Is.Ordered);
|
||||
Assert.That(listed.Select(g => g.Id), Is.Unique);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task A_project_can_be_filed_under_a_genre_off_the_list()
|
||||
{
|
||||
var fantasy = (await Genres.ListAsync()).First(g => g.Name == "Fantasy");
|
||||
|
||||
var project = await Projects.CreateAsync(new CreateProjectRequest("The Salt Road", Genre: fantasy.Name));
|
||||
|
||||
Assert.That(project.Genre, Is.EqualTo("Fantasy"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task A_project_can_still_carry_a_genre_that_is_not_on_the_list()
|
||||
{
|
||||
var project = await Projects.CreateAsync(
|
||||
new CreateProjectRequest("The Salt Road", Genre: "Nautical Gothic"));
|
||||
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
Assert.That(project.Genre, Is.EqualTo("Nautical Gothic"));
|
||||
Assert.That((await Genres.ListAsync()).Select(g => g.Name), Has.No.Member("Nautical Gothic"));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Novelly.Api.Beats;
|
||||
using Novelly.Api.Chapters;
|
||||
using Novelly.Api.Characters;
|
||||
using Novelly.Api.Genres;
|
||||
using Novelly.Api.Projects;
|
||||
using Novelly.Api.Questions;
|
||||
using Novelly.Api.Tags;
|
||||
@@ -17,6 +18,7 @@ public abstract class ServiceTestFixture
|
||||
protected BeatService Beats { get; private set; } = null!;
|
||||
protected CharacterArcService Arcs { get; private set; } = null!;
|
||||
protected OpenQuestionService Questions { get; private set; } = null!;
|
||||
protected GenreService Genres { get; private set; } = null!;
|
||||
|
||||
protected CapturingLogger<ProjectService> ProjectLogs { get; private set; } = null!;
|
||||
protected CapturingLogger<CharacterService> CharacterLogs { get; private set; } = null!;
|
||||
@@ -25,6 +27,7 @@ public abstract class ServiceTestFixture
|
||||
protected CapturingLogger<TagService> TagLogs { get; private set; } = null!;
|
||||
protected CapturingLogger<CharacterArcService> ArcLogs { get; private set; } = null!;
|
||||
protected CapturingLogger<OpenQuestionService> QuestionLogs { get; private set; } = null!;
|
||||
protected CapturingLogger<GenreService> GenreLogs { get; private set; } = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetUpFixture()
|
||||
@@ -38,6 +41,7 @@ public abstract class ServiceTestFixture
|
||||
BeatLogs = new CapturingLogger<BeatService>();
|
||||
ArcLogs = new CapturingLogger<CharacterArcService>();
|
||||
QuestionLogs = new CapturingLogger<OpenQuestionService>();
|
||||
GenreLogs = new CapturingLogger<GenreService>();
|
||||
|
||||
Tags = new TagService(Db.Context, TagLogs, new CreateTagRequestValidator(), new UpdateTagRequestValidator());
|
||||
Projects = new ProjectService(Db.Context, ProjectLogs, new CreateProjectRequestValidator(), new UpdateProjectRequestValidator());
|
||||
@@ -54,6 +58,7 @@ public abstract class ServiceTestFixture
|
||||
Questions = new OpenQuestionService(
|
||||
Db.Context, QuestionLogs,
|
||||
new CreateOpenQuestionRequestValidator(), new UpdateOpenQuestionRequestValidator(), new ResolveOpenQuestionRequestValidator());
|
||||
Genres = new GenreService(Db.Context, GenreLogs);
|
||||
|
||||
OnSetUp();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user