145 lines
5.5 KiB
C#
145 lines
5.5 KiB
C#
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Wiki.Application.Encyclopedia;
|
|
using Wiki.Core.Model;
|
|
|
|
namespace Wiki.Application.Tests;
|
|
|
|
public class FoldArticleUseCaseTests
|
|
{
|
|
private static readonly EncyclopediaSettings Settings = new(16000, 10, 300_000, [], null) { CandidateArticles = 2 };
|
|
|
|
private static FoldArticleUseCase UseCase(FakeTextModel model) =>
|
|
new(model, Settings, NullLogger<FoldArticleUseCase>.Instance);
|
|
|
|
private static PlannedArticle Article(string slug, params string[] sources) =>
|
|
new(slug, "Titel " + slug, "Title " + slug, ArticleCategory.System, "Scope " + slug, sources);
|
|
|
|
private static Dictionary<string, Document> Notes(params string[] slugs) =>
|
|
slugs.ToDictionary(s => s, s => TestNotes.Note(s));
|
|
|
|
[Fact]
|
|
public async Task Fold_Into()
|
|
{
|
|
var thin = Article("valve", "a");
|
|
var model = new FakeTextModel().Reply("""{"into":"heating"}""");
|
|
|
|
var target = await UseCase(model).FoldAsync(thin, Notes("a"), [Article("heating", "h"), Article("garden", "g")], CancellationToken.None);
|
|
|
|
Assert.Equal("heating", target);
|
|
Assert.Equal(Settings.FoldMaxTokens, model.Calls[0].MaxTokens);
|
|
Assert.StartsWith("[fold]", model.Calls[0].System);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_ListsAtMostFoldMinSources()
|
|
{
|
|
var model = new FakeTextModel().Reply("""{"keep":true}""");
|
|
var thin = Article("valve", "a", "b", "c", "d");
|
|
var notes = new Dictionary<string, Document>
|
|
{
|
|
["a"] = TestNotes.Note("a", title: "Na"), ["b"] = TestNotes.Note("b", title: "Nb"),
|
|
["c"] = TestNotes.Note("c", title: "Nc"), ["d"] = TestNotes.Note("d", title: "Nd"),
|
|
};
|
|
|
|
await UseCase(model).FoldAsync(thin, notes, [Article("heating", "h")], CancellationToken.None);
|
|
|
|
Assert.Contains("Nc", model.Calls[0].User);
|
|
Assert.DoesNotContain("Nd", model.Calls[0].User);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_Keep_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Reply("""{"keep":true}""");
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_TargetNotNearby_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Reply("""{"into":"elsewhere"}""");
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_TargetBeyondCandidateCap_IsNull()
|
|
{
|
|
var nearby = new[] { Article("n1", "1"), Article("n2", "2"), Article("n3", "3") };
|
|
var model = new FakeTextModel().Reply("""{"into":"n3"}""");
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), nearby, CancellationToken.None));
|
|
Assert.DoesNotContain("n3 | ", model.Calls[0].User);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_IntoItself_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Reply("""{"into":"valve"}""");
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("valve", "a"), Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_NoNearby_NoCall()
|
|
{
|
|
var model = new FakeTextModel();
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [], CancellationToken.None));
|
|
Assert.Empty(model.Calls);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_Truncated_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Reply("""{"into":"heating"}""", truncated: true);
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_NotJson_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Reply("hm");
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_BadRequest_IsNull()
|
|
{
|
|
var model = new FakeTextModel().Throw(new HttpRequestException("bad", null, System.Net.HttpStatusCode.BadRequest));
|
|
|
|
Assert.Null(await UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fold_ModelUnavailable_Propagates()
|
|
{
|
|
var model = new FakeTextModel().Throw(new ModelUnavailableException("down"));
|
|
|
|
await Assert.ThrowsAsync<ModelUnavailableException>(() =>
|
|
UseCase(model).FoldAsync(Article("valve", "a"), Notes("a"), [Article("heating", "h")], CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsThin_Thresholds()
|
|
{
|
|
var s = new EncyclopediaSettings(16000, 10, 300_000, [], null);
|
|
var notes = new Dictionary<string, Document>
|
|
{
|
|
["a"] = TestNotes.Note("a", 1000),
|
|
["b"] = TestNotes.Note("b", 1000),
|
|
["c"] = TestNotes.Note("c", 1000),
|
|
["big"] = TestNotes.Note("big", 4000),
|
|
};
|
|
|
|
Assert.True(FoldArticleUseCase.IsThin(Article("x", "a", "b"), notes, s));
|
|
Assert.False(FoldArticleUseCase.IsThin(Article("x", "a", "b", "c"), notes, s));
|
|
Assert.False(FoldArticleUseCase.IsThin(Article("x", "big"), notes, s));
|
|
Assert.False(FoldArticleUseCase.IsThin(Article("x", "a", "b", "ghost"), notes, s));
|
|
Assert.True(FoldArticleUseCase.IsThin(Article("x", "a"), notes, s));
|
|
}
|
|
}
|