feat: add application draft saving modes and reminder grouping

This commit is contained in:
cesnimda
2026-03-22 18:37:55 +01:00
parent 9188039e9d
commit 8041b43f47
7 changed files with 174 additions and 9 deletions
@@ -0,0 +1,34 @@
using System.Reflection;
using JobTrackerApi.Controllers;
using Xunit;
namespace JobTrackerApi.Tests;
public sealed class JobApplicationsControllerTests
{
[Fact]
public void Application_package_record_exposes_expected_fields()
{
var type = typeof(JobApplicationsController).GetNestedType("GenerateApplicationPackageDto", BindingFlags.Public | BindingFlags.NonPublic);
Assert.NotNull(type);
var props = type!.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToHashSet();
Assert.Contains("TailoredCvText", props);
Assert.Contains("CoverLetterDraft", props);
Assert.Contains("ApplicationAnswerDraft", props);
Assert.Contains("RecruiterMessageDraft", props);
Assert.Contains("KeyPoints", props);
}
[Fact]
public void Save_application_drafts_request_supports_cover_letter_and_notes()
{
var type = typeof(JobApplicationsController).GetNestedType("SaveApplicationDraftsRequest", BindingFlags.Public | BindingFlags.NonPublic);
Assert.NotNull(type);
var ctor = type!.GetConstructors().Single();
var parameters = ctor.GetParameters().Select(x => x.Name).ToArray();
Assert.Contains("coverLetterText", parameters);
Assert.Contains("notes", parameters);
}
}
@@ -0,0 +1,73 @@
using System.Security.Claims;
using System.Text;
using JobTrackerApi.Controllers;
using JobTrackerApi.Models;
using JobTrackerApi.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
namespace JobTrackerApi.Tests;
public sealed class ProfileCvControllerTests
{
[Fact]
public async Task Upload_rejects_unsupported_extension()
{
var user = new ApplicationUser();
var userManager = CreateUserManager();
userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
var controller = new ProfileCvController(userManager.Object)
{
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext() }
};
var file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("hello")), 0, 5, "file", "resume.exe");
var result = await controller.Upload(file);
var badRequest = Assert.IsType<BadRequestObjectResult>(result);
Assert.Contains("supported", StringComparison.OrdinalIgnoreCase, badRequest.Value?.ToString());
}
[Fact]
public async Task Upload_accepts_markdown_cv_and_saves_text()
{
var user = new ApplicationUser();
var userManager = CreateUserManager();
userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
userManager.Setup(x => x.UpdateAsync(user)).ReturnsAsync(IdentityResult.Success);
var controller = new ProfileCvController(userManager.Object)
{
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext() }
};
var file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("# CV\nBuilt APIs and UIs")), 0, 23, "file", "resume.md");
var result = await controller.Upload(file);
Assert.IsType<OkObjectResult>(result);
Assert.Contains("Built APIs", user.ProfileCvText);
}
private static Mock<UserManager<ApplicationUser>> CreateUserManager()
{
var store = new Mock<IUserStore<ApplicationUser>>();
return new Mock<UserManager<ApplicationUser>>(
store.Object,
Options.Create(new IdentityOptions()),
new PasswordHasher<ApplicationUser>(),
Array.Empty<IUserValidator<ApplicationUser>>(),
Array.Empty<IPasswordValidator<ApplicationUser>>(),
new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(),
null!,
new NullLogger<UserManager<ApplicationUser>>()
);
}
}