Harden CV rewrite diagnostics and preview PDFs
This commit is contained in:
@@ -556,6 +556,129 @@ public sealed class ProfileCvControllerTests
|
||||
Assert.Equal("Warwickshire College, UK", structured.Education[0].Location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Rewrite_section_returns_ai_service_unavailable_detail_when_ai_health_is_unhealthy()
|
||||
{
|
||||
var user = new ApplicationUser { Id = "user-1", ProfileCvText = "Professional Summary\nBuilt backend systems." };
|
||||
var userManager = CreateUserManager();
|
||||
userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
|
||||
var aiService = new Mock<ISummarizerService>();
|
||||
aiService
|
||||
.Setup(x => x.SummarizeSectionAsync(It.IsAny<string>(), It.IsAny<string>(), 1800, 400))
|
||||
.ReturnsAsync(string.Empty);
|
||||
aiService
|
||||
.Setup(x => x.GetMetricsAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new AiServiceMetrics(
|
||||
Healthy: false,
|
||||
Model: "distilbart",
|
||||
Device: "cpu",
|
||||
GpuAvailable: false,
|
||||
GpuName: null,
|
||||
OcrAvailable: true,
|
||||
OcrLanguages: "eng",
|
||||
OllamaConfigured: true,
|
||||
OllamaReachable: true,
|
||||
OllamaModel: "qwen2.5:7b",
|
||||
OllamaModelAvailable: true,
|
||||
OllamaVersion: "0.6.0",
|
||||
OllamaInstalledModels: new List<string> { "qwen2.5:7b" },
|
||||
OllamaLoadedModels: new List<string>(),
|
||||
OllamaLoadedCount: 0,
|
||||
HealthLatencyMs: 21,
|
||||
ProbeLatencyMs: null,
|
||||
LastProbeAt: null,
|
||||
LastProbeSuccessAt: null,
|
||||
LastProbeFailureAt: null,
|
||||
ProbeFailures: 1,
|
||||
Requests: 1,
|
||||
CacheHits: 0,
|
||||
CacheMisses: 1,
|
||||
Failures: 1,
|
||||
AverageLatencyMs: 21,
|
||||
OcrRequests: 0,
|
||||
OcrFailures: 0,
|
||||
AverageOcrLatencyMs: null,
|
||||
LastOcrSuccessAt: null,
|
||||
LastOcrFailureAt: null,
|
||||
LastSuccessAt: null,
|
||||
LastFailureAt: DateTimeOffset.UtcNow,
|
||||
LastError: "Model loading is disabled by AI_SERVICE_SKIP_MODEL_LOAD."));
|
||||
|
||||
await using var db = CreateDb();
|
||||
var controller = CreateController(userManager.Object, aiService.Object, db, CreatePaths());
|
||||
|
||||
var result = await controller.RewriteSection(new ProfileCvController.RewriteSectionRequest());
|
||||
|
||||
var objectResult = Assert.IsType<ObjectResult>(result);
|
||||
Assert.Equal(StatusCodes.Status502BadGateway, objectResult.StatusCode);
|
||||
var payload = Assert.IsType<ProfileCvController.CvRewriteFailureDto>(objectResult.Value);
|
||||
Assert.Equal("ai-service-unavailable", payload.Code);
|
||||
Assert.Contains("could not rewrite", payload.Message, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("unavailable", payload.Detail ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("AI_SERVICE_SKIP_MODEL_LOAD", payload.LastAiError ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Rewrite_section_returns_rewrite_empty_detail_when_ai_health_is_healthy()
|
||||
{
|
||||
var user = new ApplicationUser { Id = "user-1", ProfileCvText = "Professional Summary\nBuilt backend systems." };
|
||||
var userManager = CreateUserManager();
|
||||
userManager.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
|
||||
var aiService = new Mock<ISummarizerService>();
|
||||
aiService
|
||||
.Setup(x => x.SummarizeSectionAsync(It.IsAny<string>(), It.IsAny<string>(), 1800, 400))
|
||||
.ReturnsAsync(string.Empty);
|
||||
aiService
|
||||
.Setup(x => x.GetMetricsAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new AiServiceMetrics(
|
||||
Healthy: true,
|
||||
Model: "distilbart",
|
||||
Device: "cpu",
|
||||
GpuAvailable: false,
|
||||
GpuName: null,
|
||||
OcrAvailable: true,
|
||||
OcrLanguages: "eng",
|
||||
OllamaConfigured: true,
|
||||
OllamaReachable: true,
|
||||
OllamaModel: "qwen2.5:7b",
|
||||
OllamaModelAvailable: true,
|
||||
OllamaVersion: "0.6.0",
|
||||
OllamaInstalledModels: new List<string> { "qwen2.5:7b" },
|
||||
OllamaLoadedModels: new List<string>(),
|
||||
OllamaLoadedCount: 0,
|
||||
HealthLatencyMs: 21,
|
||||
ProbeLatencyMs: null,
|
||||
LastProbeAt: null,
|
||||
LastProbeSuccessAt: null,
|
||||
LastProbeFailureAt: null,
|
||||
ProbeFailures: 0,
|
||||
Requests: 1,
|
||||
CacheHits: 0,
|
||||
CacheMisses: 1,
|
||||
Failures: 0,
|
||||
AverageLatencyMs: 21,
|
||||
OcrRequests: 0,
|
||||
OcrFailures: 0,
|
||||
AverageOcrLatencyMs: null,
|
||||
LastOcrSuccessAt: null,
|
||||
LastOcrFailureAt: null,
|
||||
LastSuccessAt: DateTimeOffset.UtcNow,
|
||||
LastFailureAt: null,
|
||||
LastError: null));
|
||||
|
||||
await using var db = CreateDb();
|
||||
var controller = CreateController(userManager.Object, aiService.Object, db, CreatePaths());
|
||||
|
||||
var result = await controller.RewriteSection(new ProfileCvController.RewriteSectionRequest());
|
||||
|
||||
var objectResult = Assert.IsType<ObjectResult>(result);
|
||||
Assert.Equal(StatusCodes.Status502BadGateway, objectResult.StatusCode);
|
||||
var payload = Assert.IsType<ProfileCvController.CvRewriteFailureDto>(objectResult.Value);
|
||||
Assert.Equal("rewrite-empty", payload.Code);
|
||||
Assert.Contains("empty", payload.Message, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Contains("no usable text", payload.Detail ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Rewrite_section_can_target_saved_job_context_and_whole_cv()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user