feat(cv): redesign document editing with revision-safe letters and writing tools
This commit is contained in:
@@ -66,6 +66,43 @@ public sealed class AiWorkspaceTests
|
||||
|
||||
private static AiGenerateRequest Req(string module, string? mode = null) => new(module, mode, null);
|
||||
|
||||
private static async Task SeedLinkedProfileAsync(JobTrackerContext db, int jobId, StructuredCvProfile? profile = null, CvVariantSettings? settings = null, string profileOwner = "user-1")
|
||||
{
|
||||
db.CareerProfiles.Add(new CareerProfile { OwnerUserId = profileOwner, ProfileJson = StructuredCvProfileJson.Serialize(profile ?? new StructuredCvProfile { Skills = { "C#" } }) });
|
||||
db.CvVariants.Add(new CvVariant {
|
||||
OwnerUserId = "user-1", JobApplicationId = jobId, Name = "Source CV", PublicSlug = Guid.NewGuid().ToString("N"),
|
||||
SettingsJson = CvVariantSettingsJson.Serialize(settings ?? new()), Version = 1,
|
||||
CreatedAtUtc = DateTimeOffset.UtcNow, UpdatedAtUtc = DateTimeOffset.UtcNow,
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("generate", "no-linked-cv")]
|
||||
[InlineData("improve", "no-linked-cv")]
|
||||
[InlineData("grammar", "identity-only")]
|
||||
[InlineData("shorten", "hidden-facts")]
|
||||
[InlineData("generate", "foreign-profile")]
|
||||
public async Task Letter_requires_owned_visible_career_facts_before_inference_even_with_draft_and_advert(string action, string source)
|
||||
{
|
||||
var (db, svc, ai) = New("user-1");
|
||||
await using var _ = db;
|
||||
var jobId = await SeedJobAsync(db, "user-1");
|
||||
if (source != "no-linked-cv")
|
||||
{
|
||||
var profile = new StructuredCvProfile { Contact = new StructuredCvContact { FullName = "Ada Example", Headline = "Engineer" } };
|
||||
var settings = new CvVariantSettings();
|
||||
if (source == "hidden-facts") { profile.Skills.Add("C#"); settings.Sections.Add(new() { Key = "skills", Hidden = true }); }
|
||||
if (source == "foreign-profile") profile.Skills.Add("Foreign profile skill");
|
||||
await SeedLinkedProfileAsync(db, jobId, profile, settings, source == "foreign-profile" ? "user-2" : "user-1");
|
||||
}
|
||||
var error = await Assert.ThrowsAsync<ArgumentException>(() => svc.GenerateAsync("user-1", jobId,
|
||||
"Unverified legacy fallback claiming 99 years experience", "Ada", new("cover-letter", "professional", "Invent impressive results", "en", "An existing unverified letter draft", action), "p", default));
|
||||
Assert.Equal("cover_letter_source_required", error.Message);
|
||||
Assert.Equal(0, ai.Calls);
|
||||
Assert.Empty(await db.AiInteractions.IgnoreQueryFilters().ToListAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Generate_stores_an_interaction_and_returns_it()
|
||||
{
|
||||
@@ -107,6 +144,7 @@ public sealed class AiWorkspaceTests
|
||||
var (db, svc, _) = New("user-1");
|
||||
await using var _ = db;
|
||||
var jobId = await SeedJobAsync(db, "user-1");
|
||||
await SeedLinkedProfileAsync(db, jobId);
|
||||
|
||||
var res = await svc.GenerateAsync("user-1", jobId, "cv", "Ada", Req("cover-letter", "banana"), "p", default);
|
||||
|
||||
@@ -209,6 +247,7 @@ public sealed class AiWorkspaceTests
|
||||
await using var _ = db;
|
||||
ai.Next = " ";
|
||||
var jobId = await SeedJobAsync(db, "user-1");
|
||||
await SeedLinkedProfileAsync(db, jobId);
|
||||
await Assert.ThrowsAsync<AiUnavailableException>(() => svc.GenerateAsync("user-1", jobId, "cv", "Ada", Req("cover-letter"), "p", default));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user