feat(cv): redesign document editing with revision-safe letters and writing tools

This commit is contained in:
cesnimda
2026-10-25 22:44:14 +01:00
parent 01e10996c5
commit 2bfaf6c14b
57 changed files with 2859 additions and 118 deletions
@@ -15,6 +15,39 @@ public sealed class MigrationChainTests
{
private const string SnapshotMigration = "20260711181039_SyncModelSnapshot";
[Fact]
public async Task Letter_document_upgrade_adds_nullable_fields_without_rewriting_old_letters_or_frozen_bytes()
{
await using var connection = new SqliteConnection("Data Source=:memory:");
await connection.OpenAsync();
await using var db = Context(connection);
var migrator = db.GetService<IMigrator>();
await migrator.MigrateAsync("20261023090000_AddJobRevision");
await ExecuteAsync(connection, """
INSERT INTO Companies (Name) VALUES ('Letter migration fixture');
INSERT INTO JobApplications
(CompanyId, JobTitle, Status, ResponseReceived, OwnerUserId, SavedAt, CoverLetterText,
HasResume, HasCoverLetter, HasPortfolio, HasOtherAttachment, IsDeleted, Version)
VALUES (1, 'Durable role', 'Saved', 0, 'rd21-owner', '2026-10-25', ' old body ', 0, 0, 0, 0, 0, 7);
INSERT INTO CoverLetterVersions (OwnerUserId, JobApplicationId, Version, Text, Source, CreatedAtUtc)
VALUES ('rd21-owner', 1, 3, ' historical letter ', 'ai', '2026-10-25');
INSERT INTO SubmittedApplicationPackages (OwnerUserId, JobApplicationId, Version, CoverLetterText, RenderedCvHtml, ApplicationMaterialJson, CreatedAtUtc)
VALUES ('rd21-owner', 1, 1, ' frozen old letter ', '<p>old exact CV</p>', '{}', '2026-10-25');
""");
await migrator.MigrateAsync();
Assert.Equal(" old body ", await ScalarAsync<string>(connection, "SELECT CoverLetterText FROM JobApplications WHERE Id=1;"));
Assert.Equal(7L, await ScalarAsync<long>(connection, "SELECT Version FROM JobApplications WHERE Id=1;"));
Assert.Equal(" historical letter ", await ScalarAsync<string>(connection, "SELECT Text FROM CoverLetterVersions WHERE Version=3;"));
Assert.Equal("<p>old exact CV</p>", await ScalarAsync<string>(connection, "SELECT RenderedCvHtml FROM SubmittedApplicationPackages WHERE Id=1;"));
Assert.Equal(1L, await ScalarAsync<long>(connection, "SELECT COUNT(*) FROM JobApplications WHERE CoverLetterDocumentSettingsJson IS NULL;"));
Assert.Equal(1L, await ScalarAsync<long>(connection, "SELECT COUNT(*) FROM CoverLetterVersions WHERE DocumentSettingsJson IS NULL;"));
Assert.Equal(1L, await ScalarAsync<long>(connection, "SELECT COUNT(*) FROM SubmittedApplicationPackages WHERE RenderedCoverLetterHtml IS NULL AND CoverLetterDocumentSettingsJson IS NULL;"));
await migrator.MigrateAsync("20261023090000_AddJobRevision");
Assert.Equal(" frozen old letter ", await ScalarAsync<string>(connection, "SELECT CoverLetterText FROM SubmittedApplicationPackages WHERE Id=1;"));
await migrator.MigrateAsync();
Assert.Empty(await db.Database.GetPendingMigrationsAsync());
}
[Fact]
public async Task Rd21_revision_upgrade_and_rollback_preserve_existing_job_content()
{