Rename Project concept to Novel across the stack
Renames the domain concept from Project to Novel throughout the backend (entities, DTOs, services, endpoints, ProjectAccessService/Permission, ProjectId foreign keys), MCP server (tool names and routes), and the React/Vite frontend (types, hooks, routes, components). Adds a new EF Core migration (RenameProjectToNovel) using RenameTable/RenameColumn to preserve existing data instead of dropping/recreating tables. Updates CLAUDE.md's structure section to reference Novels/ instead of Projects/.
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
using Novelly.Api.Beats;
|
||||
using Novelly.Api.Chapters;
|
||||
using Novelly.Api.Characters;
|
||||
using Novelly.Api.Projects;
|
||||
using Novelly.Api.Novels;
|
||||
|
||||
namespace Novelly.Api.Tests;
|
||||
|
||||
[TestFixture]
|
||||
public class BeatServiceTests : ServiceTestFixture
|
||||
{
|
||||
private Guid _projectId;
|
||||
private Guid _novelId;
|
||||
private Guid _chapterId;
|
||||
|
||||
protected override void OnSetUp()
|
||||
{
|
||||
_projectId = Projects.CreateAsync(new CreateProjectRequest("The Salt Road")).Result.Id;
|
||||
_chapterId = Chapters.CreateAsync(_projectId, new CreateChapterRequest("Landfall")).Result.Id;
|
||||
_novelId = Novels.CreateAsync(new CreateNovelRequest("The Salt Road")).Result.Id;
|
||||
_chapterId = Chapters.CreateAsync(_novelId, new CreateChapterRequest("Landfall")).Result.Id;
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -100,8 +100,8 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task A_beat_can_carry_several_characters()
|
||||
{
|
||||
var ines = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Ines"));
|
||||
var mara = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Mara"));
|
||||
var ines = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Ines"));
|
||||
var mara = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Mara"));
|
||||
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest(
|
||||
"She burns the atlas",
|
||||
@@ -117,22 +117,22 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task A_beat_cannot_borrow_a_character_from_another_project()
|
||||
public async Task A_beat_cannot_borrow_a_character_from_another_novel()
|
||||
{
|
||||
var other = await Projects.CreateAsync(new CreateProjectRequest("Other Book"));
|
||||
var other = await Novels.CreateAsync(new CreateNovelRequest("Other Book"));
|
||||
var stranger = await Characters.CreateAsync(other.Id, new CreateCharacterRequest("Stranger"));
|
||||
|
||||
Assert.That(
|
||||
async () => await Beats.CreateAsync(
|
||||
_chapterId, new CreateBeatRequest("A beat", CharacterIds: [stranger.Id])),
|
||||
Throws.TypeOf<InvalidOperationException>().With.Message.Contains("same project"));
|
||||
Throws.TypeOf<InvalidOperationException>().With.Message.Contains("same novel"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Assigning_a_character_to_several_beats_leaves_their_other_characters_alone()
|
||||
{
|
||||
var ines = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Ines"));
|
||||
var mara = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Mara"));
|
||||
var ines = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Ines"));
|
||||
var mara = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Mara"));
|
||||
var first = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First", CharacterIds: [ines.Id]));
|
||||
var second = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("Second"));
|
||||
|
||||
@@ -153,7 +153,7 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task Assigning_a_character_already_on_a_beat_does_not_duplicate_it()
|
||||
{
|
||||
var ines = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Ines"));
|
||||
var ines = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Ines"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First", CharacterIds: [ines.Id]));
|
||||
|
||||
var assigned = await Beats.AssignCharacterAsync(
|
||||
@@ -163,9 +163,9 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Assigning_a_character_from_another_project_returns_null()
|
||||
public async Task Assigning_a_character_from_another_novel_returns_null()
|
||||
{
|
||||
var other = await Projects.CreateAsync(new CreateProjectRequest("Other Book"));
|
||||
var other = await Novels.CreateAsync(new CreateNovelRequest("Other Book"));
|
||||
var stranger = await Characters.CreateAsync(other.Id, new CreateCharacterRequest("Stranger"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First"));
|
||||
|
||||
@@ -177,7 +177,7 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task Assigning_to_an_unknown_beat_returns_null_rather_than_partially_applying()
|
||||
{
|
||||
var ines = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Ines"));
|
||||
var ines = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Ines"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First"));
|
||||
|
||||
var result = await Beats.AssignCharacterAsync(
|
||||
@@ -190,7 +190,7 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task Moving_beats_appends_them_to_the_end_of_the_target_chapter()
|
||||
{
|
||||
var other = await Chapters.CreateAsync(_projectId, new CreateChapterRequest("Second landfall"));
|
||||
var other = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Second landfall"));
|
||||
await Beats.CreateAsync(other.Id, new CreateBeatRequest("Already there"));
|
||||
var first = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First"));
|
||||
var second = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("Second"));
|
||||
@@ -216,9 +216,9 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Moving_to_a_chapter_in_another_project_returns_null()
|
||||
public async Task Moving_to_a_chapter_in_another_novel_returns_null()
|
||||
{
|
||||
var other = await Projects.CreateAsync(new CreateProjectRequest("Other Book"));
|
||||
var other = await Novels.CreateAsync(new CreateNovelRequest("Other Book"));
|
||||
var otherChapter = await Chapters.CreateAsync(other.Id, new CreateChapterRequest("Elsewhere"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First"));
|
||||
|
||||
@@ -228,7 +228,7 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task Moving_an_unknown_beat_returns_null_rather_than_partially_applying()
|
||||
{
|
||||
var other = await Chapters.CreateAsync(_projectId, new CreateChapterRequest("Second landfall"));
|
||||
var other = await Chapters.CreateAsync(_novelId, new CreateChapterRequest("Second landfall"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest("First"));
|
||||
|
||||
var result = await Beats.MoveAsync(_chapterId, new MoveBeatsRequest(other.Id, [beat.Id, Guid.NewGuid()]));
|
||||
@@ -265,7 +265,7 @@ public class BeatServiceTests : ServiceTestFixture
|
||||
[Test]
|
||||
public async Task An_empty_CharacterIds_list_clears_a_beats_characters_since_null_means_leave_it_alone()
|
||||
{
|
||||
var ines = await Characters.CreateAsync(_projectId, new CreateCharacterRequest("Ines"));
|
||||
var ines = await Characters.CreateAsync(_novelId, new CreateCharacterRequest("Ines"));
|
||||
var beat = await Beats.CreateAsync(_chapterId, new CreateBeatRequest(
|
||||
"She burns the atlas", CharacterIds: [ines.Id]));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user