Files

104 lines
2.9 KiB
C#
Raw Permalink Normal View History

// tests/SpamGuard.Tests/Services/EmailClassifierTests.cs
namespace SpamGuard.Tests.Services;
using System.Net;
using System.Text.Json;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using SpamGuard.Configuration;
using SpamGuard.Models;
using SpamGuard.Services;
using SpamGuard.State;
public class EmailClassifierTests
{
private static SpamGuardOptions DefaultOptions => new()
{
Claude = new ClaudeOptions
{
ApiKey = "test-key",
Model = "claude-sonnet-4-6",
MaxBodyLength = 2000
}
};
private static EmailSummary SampleEmail => new(
Uid: 1,
From: "spammer@sketchy.com",
Subject: "Buy now! Limited offer!",
BodySnippet: "Click here to claim your prize...",
Date: DateTimeOffset.UtcNow
);
[Fact]
public void BuildPrompt_ContainsSenderAndSubjectAndBody()
{
var classifier = new EmailClassifier(
Options.Create(DefaultOptions),
new NullLogger<EmailClassifier>(),
new HttpClient(),
new OverrideStore(Path.GetTempPath())
);
var prompt = classifier.BuildPrompt(SampleEmail);
Assert.Contains("spammer@sketchy.com", prompt);
Assert.Contains("Buy now! Limited offer!", prompt);
Assert.Contains("Click here to claim your prize...", prompt);
}
[Fact]
public void BuildPrompt_TruncatesLongBody()
{
var longBody = new string('x', 5000);
var email = SampleEmail with { BodySnippet = longBody };
var classifier = new EmailClassifier(
Options.Create(DefaultOptions),
new NullLogger<EmailClassifier>(),
new HttpClient(),
new OverrideStore(Path.GetTempPath())
);
var prompt = classifier.BuildPrompt(email);
// Body in prompt should be truncated to MaxBodyLength
Assert.DoesNotContain(longBody, prompt);
}
[Fact]
public void ParseResponse_ValidJson_ReturnsResult()
{
var json = """{"classification": "spam", "confidence": 0.95, "reason": "Unsolicited marketing"}""";
var result = EmailClassifier.ParseResponse(json);
Assert.NotNull(result);
Assert.True(result.IsSpam);
Assert.Equal(0.95, result.Confidence);
Assert.Equal("Unsolicited marketing", result.Reason);
}
[Fact]
public void ParseResponse_InvalidJson_ReturnsNull()
{
var result = EmailClassifier.ParseResponse("not json at all");
Assert.Null(result);
}
[Fact]
public void ParseResponse_JsonWithMarkdownFencing_ReturnsResult()
{
var json = """
```json
{"classification": "legitimate", "confidence": 0.85, "reason": "Normal business email"}
```
""";
var result = EmailClassifier.ParseResponse(json);
Assert.NotNull(result);
Assert.False(result.IsSpam);
}
}