116 lines
4.6 KiB
C#
116 lines
4.6 KiB
C#
using JobTrackerApi.Controllers;
|
|
using JobTrackerApi.Data;
|
|
using JobTrackerApi.Models;
|
|
using JobTrackerApi.Services;
|
|
using JobTrackerApi.Tests.TestSupport;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace JobTrackerApi.Tests;
|
|
|
|
// JobApplication.HasResume/HasCoverLetter/HasPortfolio/HasOtherAttachment are derived from
|
|
// Attachment rows (backlog Wave 3), not manually settable. These tests exercise the single
|
|
// place they're written: AttachmentsController's Purpose-change and Delete paths.
|
|
public sealed class AttachmentFlagsRecomputeTests
|
|
{
|
|
[Fact]
|
|
public async Task Changing_purpose_to_resume_sets_HasResume()
|
|
{
|
|
await using var db = TestHostFactory.CreateInMemoryDb();
|
|
var (job, attachment) = await SeedJobWithAttachmentAsync(db, purpose: "other");
|
|
var controller = CreateController(db, Path.GetDirectoryName(attachment.FilePath));
|
|
|
|
var result = await controller.Rename(attachment.Id, new AttachmentsController.UpdateAttachmentRequest(null, "resume", null), CancellationToken.None);
|
|
|
|
Assert.IsType<NoContentResult>(result);
|
|
var updated = await db.JobApplications.SingleAsync(j => j.Id == job.Id);
|
|
Assert.True(updated.HasResume);
|
|
Assert.True(updated.HasOtherAttachment == false);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Deleting_the_only_resume_attachment_clears_HasResume()
|
|
{
|
|
await using var db = TestHostFactory.CreateInMemoryDb();
|
|
var (job, attachment) = await SeedJobWithAttachmentAsync(db, purpose: "resume");
|
|
var controller = CreateController(db, Path.GetDirectoryName(attachment.FilePath));
|
|
|
|
var result = await controller.Delete(attachment.Id, CancellationToken.None);
|
|
|
|
Assert.IsType<NoContentResult>(result);
|
|
var updated = await db.JobApplications.SingleAsync(j => j.Id == job.Id);
|
|
Assert.False(updated.HasResume);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Attachment_with_case_study_purpose_counts_as_other()
|
|
{
|
|
await using var db = TestHostFactory.CreateInMemoryDb();
|
|
var (job, attachment) = await SeedJobWithAttachmentAsync(db, purpose: "resume");
|
|
var controller = CreateController(db, Path.GetDirectoryName(attachment.FilePath));
|
|
|
|
await controller.Rename(attachment.Id, new AttachmentsController.UpdateAttachmentRequest(null, "case-study", null), CancellationToken.None);
|
|
|
|
var updated = await db.JobApplications.SingleAsync(j => j.Id == job.Id);
|
|
Assert.False(updated.HasResume);
|
|
Assert.True(updated.HasOtherAttachment);
|
|
}
|
|
|
|
private static async Task<(JobApplication Job, Attachment Attachment)> SeedJobWithAttachmentAsync(JobTrackerContext db, string purpose)
|
|
{
|
|
var company = new Company { Name = "Acme", OwnerUserId = "user-1" };
|
|
db.Companies.Add(company);
|
|
await db.SaveChangesAsync();
|
|
|
|
var job = new JobApplication { JobTitle = "Backend Developer", CompanyId = company.Id, OwnerUserId = "user-1" };
|
|
db.JobApplications.Add(job);
|
|
await db.SaveChangesAsync();
|
|
|
|
var attachment = new Attachment
|
|
{
|
|
JobApplicationId = job.Id,
|
|
FileName = "file.pdf",
|
|
FilePath = Path.Combine(Path.GetTempPath(), $"jobtracker-attachment-test-{Guid.NewGuid():N}.pdf"),
|
|
FileType = "application/pdf",
|
|
FileSize = 100,
|
|
Purpose = purpose,
|
|
};
|
|
db.Attachments.Add(attachment);
|
|
await db.SaveChangesAsync();
|
|
|
|
job.HasResume = purpose == "resume";
|
|
job.HasOtherAttachment = purpose is not ("resume" or "cover-letter" or "portfolio");
|
|
await db.SaveChangesAsync();
|
|
|
|
return (job, attachment);
|
|
}
|
|
|
|
private static AttachmentsController CreateController(JobTrackerContext db, string? attachmentsRoot)
|
|
{
|
|
var tempRoot = Path.Combine(Path.GetTempPath(), $"jobtracker-attachments-tests-{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(tempRoot);
|
|
|
|
var config = new ConfigurationBuilder()
|
|
.AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["Data:Root"] = tempRoot,
|
|
["Data:AttachmentsRoot"] = attachmentsRoot,
|
|
})
|
|
.Build();
|
|
|
|
var env = new Mock<IHostEnvironment>();
|
|
env.SetupGet(x => x.ContentRootPath).Returns(tempRoot);
|
|
var paths = new AppPaths(config, env.Object);
|
|
|
|
return new AttachmentsController(paths, db)
|
|
{
|
|
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext() }
|
|
};
|
|
}
|
|
}
|