feat: complete phase 2 UX improvements
This commit is contained in:
@@ -40,7 +40,7 @@ public sealed class ProfileCvControllerTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Upload_stores_cv_artifact_and_extraction_run_metadata()
|
||||
public async Task Upload_waits_for_review_then_accept_merges_and_applies()
|
||||
{
|
||||
var user = new ApplicationUser { Id = "user-1" };
|
||||
var userManager = CreateUserManager();
|
||||
@@ -81,21 +81,55 @@ public sealed class ProfileCvControllerTests
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
var artifact = await db.CvUploadArtifacts.SingleAsync();
|
||||
var run = await db.CvExtractionRuns.SingleAsync();
|
||||
var parsed = StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson);
|
||||
Assert.Equal("user-1", artifact.OwnerUserId);
|
||||
Assert.Equal("resume.md", artifact.OriginalFileName);
|
||||
Assert.True(System.IO.File.Exists(artifact.StoragePath));
|
||||
Assert.Equal("applied", run.Status);
|
||||
Assert.Equal("pending_review", run.Status);
|
||||
Assert.Equal("upload", run.Trigger);
|
||||
Assert.Equal(artifact.Id, run.ArtifactId);
|
||||
Assert.Null(user.ProfileCvStructureJson);
|
||||
Assert.Null(user.CurrentCvExtractionRunId);
|
||||
|
||||
Assert.IsType<OkObjectResult>(await controller.GetRunDiff(run.Id));
|
||||
Assert.IsType<OkObjectResult>(await controller.AcceptRun(run.Id));
|
||||
|
||||
var parsed = StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson);
|
||||
Assert.Equal("applied", run.Status);
|
||||
Assert.Equal(run.Id, user.CurrentCvExtractionRunId);
|
||||
Assert.Equal(artifact.Id, user.CurrentCvUploadArtifactId);
|
||||
Assert.Equal(1, user.CurrentCvProfileVersion);
|
||||
Assert.Equal(run.Id, parsed.Metadata.AppliedExtractionRunId);
|
||||
Assert.True(parsed.Metadata.ProfileVersion >= 1);
|
||||
Assert.Contains(parsed.Metadata.Fields.Keys, key => key == "contact.fullName" || key == "summary");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DiscardRun_leaves_profile_unchanged()
|
||||
{
|
||||
var user = new ApplicationUser { Id = "user-1", ProfileCvStructureJson = StructuredCvProfileJson.Serialize(new StructuredCvProfile { Skills = { "C#" } }) };
|
||||
var userManager = CreateUserManager();
|
||||
userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
|
||||
var aiService = new Mock<ISummarizerService>();
|
||||
await using var db = CreateDb();
|
||||
db.CvExtractionRuns.Add(new CvExtractionRun
|
||||
{
|
||||
OwnerUserId = user.Id,
|
||||
Trigger = "upload",
|
||||
Status = "pending_review",
|
||||
ParserVersion = "test",
|
||||
NormalizerVersion = "test",
|
||||
LlmPromptVersion = "test",
|
||||
StructuredProfileJson = StructuredCvProfileJson.Serialize(new StructuredCvProfile { Skills = { "Docker" } }),
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
var run = await db.CvExtractionRuns.SingleAsync();
|
||||
var controller = CreateController(userManager.Object, aiService.Object, db, CreatePaths());
|
||||
|
||||
Assert.IsType<NoContentResult>(await controller.DiscardRun(run.Id));
|
||||
|
||||
Assert.Equal("discarded", run.Status);
|
||||
Assert.Equal(new[] { "C#" }, StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson).Skills);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetRuns_returns_latest_extraction_runs()
|
||||
{
|
||||
@@ -186,10 +220,10 @@ public sealed class ProfileCvControllerTests
|
||||
|
||||
var run = await db.CvExtractionRuns.SingleAsync();
|
||||
Assert.Equal("reprocess", run.Trigger);
|
||||
Assert.Equal("applied", run.Status);
|
||||
Assert.Equal(2, user.CurrentCvProfileVersion);
|
||||
Assert.Equal(run.Id, user.CurrentCvExtractionRunId);
|
||||
Assert.Equal("# Connor Babbington\n\n## Professional Summary\nRefined profile", user.ProfileCvText);
|
||||
Assert.Equal("pending_review", run.Status);
|
||||
Assert.Equal(1, user.CurrentCvProfileVersion);
|
||||
Assert.Null(user.CurrentCvExtractionRunId);
|
||||
Assert.Null(user.ProfileCvText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -268,9 +302,10 @@ public sealed class ProfileCvControllerTests
|
||||
var result = await controller.Upload(file);
|
||||
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
Assert.Equal(reconstructed, user.ProfileCvText);
|
||||
var savedRun = await db.CvExtractionRuns.SingleAsync();
|
||||
Assert.Equal(reconstructed, savedRun.NormalizedText);
|
||||
|
||||
var structured = StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson);
|
||||
var structured = StructuredCvProfileJson.Deserialize(savedRun.StructuredProfileJson);
|
||||
Assert.Equal("Connor Babbington", structured.Contact.FullName);
|
||||
Assert.Single(structured.Summary);
|
||||
Assert.Single(structured.Jobs);
|
||||
@@ -326,10 +361,11 @@ public sealed class ProfileCvControllerTests
|
||||
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
normalizer.Verify(x => x.NormalizeAsync(It.Is<string>(text => text.Contains("Warwickshire County Council", StringComparison.Ordinal)), It.IsAny<CancellationToken>()), Times.Once);
|
||||
var structured = StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson);
|
||||
var savedRun = await db.CvExtractionRuns.SingleAsync();
|
||||
var structured = StructuredCvProfileJson.Deserialize(savedRun.StructuredProfileJson);
|
||||
Assert.Equal("Connor Babbington", structured.Contact.FullName);
|
||||
Assert.Contains("# Skills", user.ProfileCvText ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("Warwickshire County Council", user.ProfileCvText ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("# Skills", savedRun.NormalizedText ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("Warwickshire County Council", savedRun.NormalizedText ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -366,7 +402,8 @@ public sealed class ProfileCvControllerTests
|
||||
var result = await controller.Upload(file);
|
||||
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
var structured = StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson);
|
||||
var savedRun = await db.CvExtractionRuns.SingleAsync();
|
||||
var structured = StructuredCvProfileJson.Deserialize(savedRun.StructuredProfileJson);
|
||||
Assert.Equal("Connor Babbington", structured.Contact.FullName);
|
||||
Assert.Equal("connor.babbington@cesnimda.co.uk", structured.Contact.Email);
|
||||
Assert.Equal("+47 41 33 44 70", structured.Contact.Phone);
|
||||
@@ -965,8 +1002,10 @@ public sealed class ProfileCvControllerTests
|
||||
var result = await controller.Upload(file);
|
||||
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
Assert.Contains("Built APIs", user.ProfileCvText);
|
||||
Assert.Equal("Connor Babbington", StructuredCvProfileJson.Deserialize(user.ProfileCvStructureJson).Contact.FullName);
|
||||
var run = await db.CvExtractionRuns.SingleAsync();
|
||||
Assert.Contains("Built APIs", run.NormalizedText);
|
||||
Assert.Equal("Connor Babbington", StructuredCvProfileJson.Deserialize(run.StructuredProfileJson).Contact.FullName);
|
||||
Assert.Equal("pending_review", run.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user