fix(documents): reject profile changes during submitted CV rendering
This commit is contained in:
@@ -4,6 +4,7 @@ using JobTrackerApi.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Text.Json;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -129,6 +130,65 @@ public sealed class SubmittedApplicationPackageTests
|
||||
storage.Verify(x => x.SnapshotAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Profile_changed_during_render_cannot_publish_old_profile_metadata_with_new_html()
|
||||
{
|
||||
var renderer = new Mock<ICvVariantService>();
|
||||
var (db, service, _) = New("owner-1", renderer);
|
||||
await using var dispose = db;
|
||||
var job = await SeedAsync(db, "owner-1", null);
|
||||
var career = new CareerProfileService(db);
|
||||
var real = new CvVariantService(db, career, new ThemedCvRenderer());
|
||||
renderer.Setup(x => x.RenderAsync("owner-1", It.IsAny<int>(), It.IsAny<CvRenderPerson>(), It.IsAny<CancellationToken>(), It.IsAny<int?>()))
|
||||
.Returns(async (string owner, int id, CvRenderPerson person, CancellationToken ct, int? expected) =>
|
||||
{
|
||||
var changed = JsonSerializer.Deserialize<StructuredCvProfile>("{\"version\":\"1\",\"contact\":{\"fullName\":\"New during capture\",\"headline\":\"Updated canonical profile\"}}", new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!;
|
||||
await career.SaveVersionAsync(owner, changed, "manual", 0, ct);
|
||||
var rendered = await real.RenderAsync(owner, id, person, ct, expected);
|
||||
Assert.Contains("New during capture", rendered!.Html);
|
||||
return rendered;
|
||||
});
|
||||
|
||||
await Assert.ThrowsAsync<DbUpdateConcurrencyException>(() => service.CaptureAsync("owner-1", job.Id, new CvRenderPerson("Ada", null), default));
|
||||
|
||||
Assert.Empty(db.SubmittedApplicationPackages);
|
||||
Assert.Equal(1, (await db.CareerProfiles.SingleAsync()).Version);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task Profile_created_or_removed_during_render_aborts_capture(bool created)
|
||||
{
|
||||
var renderer = new Mock<ICvVariantService>();
|
||||
var (db, service, _) = New("owner-1", renderer);
|
||||
await using var dispose = db;
|
||||
var job = await SeedAsync(db, "owner-1", null);
|
||||
if (created) { db.CareerProfiles.Remove(await db.CareerProfiles.SingleAsync()); await db.SaveChangesAsync(); }
|
||||
var real = new CvVariantService(db, new CareerProfileService(db), new ThemedCvRenderer());
|
||||
renderer.Setup(x => x.RenderAsync("owner-1", It.IsAny<int>(), It.IsAny<CvRenderPerson>(), It.IsAny<CancellationToken>(), It.IsAny<int?>()))
|
||||
.Returns(async (string owner, int id, CvRenderPerson person, CancellationToken ct, int? expected) =>
|
||||
{
|
||||
if (created) db.CareerProfiles.Add(new CareerProfile { OwnerUserId = owner, Version = 1, ProfileJson = "{}" });
|
||||
else db.CareerProfiles.Remove(await db.CareerProfiles.SingleAsync(ct));
|
||||
await db.SaveChangesAsync(ct);
|
||||
return await real.RenderAsync(owner, id, person, ct, expected);
|
||||
});
|
||||
await Assert.ThrowsAsync<DbUpdateConcurrencyException>(() => service.CaptureAsync("owner-1", job.Id, new CvRenderPerson("Ada", null), default));
|
||||
Assert.Empty(db.SubmittedApplicationPackages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Unchanged_absent_legacy_profile_remains_capturable()
|
||||
{
|
||||
var (db, service, _) = New("owner-1");
|
||||
await using var dispose = db;
|
||||
var job = await SeedAsync(db, "owner-1", null);
|
||||
db.CareerProfiles.Remove(await db.CareerProfiles.SingleAsync()); await db.SaveChangesAsync();
|
||||
Assert.NotNull(await service.CaptureAsync("owner-1", job.Id, new CvRenderPerson("Ada", null), default));
|
||||
Assert.Null((await db.SubmittedApplicationPackages.SingleAsync()).CareerProfileJson);
|
||||
}
|
||||
|
||||
private static (JobTrackerContext Db, SubmittedApplicationPackageService Service, Mock<IAttachmentStorage> Storage) New(string userId, Mock<ICvVariantService>? renderOverride = null)
|
||||
{
|
||||
var currentUser = new Mock<ICurrentUserService>();
|
||||
|
||||
Reference in New Issue
Block a user