Files
Wiki/test/Wiki.Application.Tests/EncyclopediaStateTests.cs
T

101 lines
4.0 KiB
C#

using Wiki.Application.Encyclopedia;
using Wiki.Core.Model;
namespace Wiki.Application.Tests;
public class EncyclopediaStateTests
{
private static readonly DateTimeOffset At = new(2026, 10, 24, 3, 0, 0, TimeSpan.Zero);
[Fact]
public void EncyclopediaStateJson_RoundTrip()
{
var state = new EncyclopediaState(
new Dictionary<string, SubjectAttempt>
{
["heating"] = new("abc", AttemptOutcome.Written, At),
["sauna"] = new("def", AttemptOutcome.Rejected, At),
},
new Dictionary<string, DateTimeOffset>(),
new Dictionary<string, string>());
var read = EncyclopediaStateJson.Read(EncyclopediaStateJson.Write(state));
Assert.Equal(state.Subjects, read.Subjects);
}
[Fact]
public void RoundTrip_FailedBatchesAndKept()
{
var state = new EncyclopediaState(
new Dictionary<string, SubjectAttempt>(),
new Dictionary<string, DateTimeOffset> { ["fp1"] = At },
new Dictionary<string, string> { ["heating"] = "fp2" });
var read = EncyclopediaStateJson.Read(EncyclopediaStateJson.Write(state));
Assert.Equal(state.FailedBatches, read.FailedBatches);
Assert.Equal(state.KeptArticles, read.KeptArticles);
}
[Fact]
public void Read_OldJsonWithFailedPlan_IgnoresIt()
{
var read = EncyclopediaStateJson.Read("""{"subjects":{},"failedPlan":{"noteSetFingerprint":"x","at":"2026-10-24T03:00:00+00:00"}}""");
Assert.Empty(read.Subjects);
Assert.Empty(read.FailedBatches);
Assert.Empty(read.KeptArticles);
Assert.DoesNotContain("failedPlan", EncyclopediaStateJson.Write(read));
}
[Fact]
public void BatchFingerprint_ChangesWhenANoteChanges()
{
var ab = EncyclopediaState.BatchFingerprint([TestNotes.Note("a", hash: "1"), TestNotes.Note("b", hash: "2")]);
var ba = EncyclopediaState.BatchFingerprint([TestNotes.Note("b", hash: "2"), TestNotes.Note("a", hash: "1")]);
var changed = EncyclopediaState.BatchFingerprint([TestNotes.Note("a", hash: "1"), TestNotes.Note("b", hash: "3")]);
var fewer = EncyclopediaState.BatchFingerprint([TestNotes.Note("a", hash: "1")]);
Assert.Equal(ab, ba);
Assert.NotEqual(ab, changed);
Assert.NotEqual(ab, fewer);
Assert.Matches("^[0-9a-f]{64}$", ab);
}
[Fact]
public void EncyclopediaStateJson_Malformed_ReadsEmpty()
{
var read = EncyclopediaStateJson.Read("{{{ nope");
Assert.Empty(read.Subjects);
}
[Fact]
public void EncyclopediaStateJson_NullEntry_Dropped()
{
var read = EncyclopediaStateJson.Read("""{"subjects":{"a":null,"b":{"fingerprint":"f","outcome":"written","at":"2026-10-24T03:00:00+00:00"}},"failedPlan":null}""");
Assert.Equal(["b"], read.Subjects.Keys);
}
[Fact]
public void Empty_DoesNotShareMutableState()
{
((Dictionary<string, SubjectAttempt>)EncyclopediaState.Empty.Subjects)["x"] = new("f", AttemptOutcome.Written, At);
Assert.Empty(EncyclopediaState.Empty.Subjects);
}
[Fact]
public void SubjectFingerprint_ChangesWithSourceHashOrTitle()
{
var planned = new PlannedArticle("heating", "Heizung", "Heating", ArticleCategory.System, "", ["a", "b"]);
var notes = new[] { TestNotes.Note("a", hash: "1"), TestNotes.Note("b", hash: "2") };
var baseline = EncyclopediaState.SubjectFingerprint(planned, notes);
Assert.Equal(baseline, EncyclopediaState.SubjectFingerprint(planned, notes));
Assert.Matches("^[0-9a-f]{64}$", baseline);
var changedHash = new[] { notes[0], TestNotes.Note("b", hash: "3") };
Assert.NotEqual(baseline, EncyclopediaState.SubjectFingerprint(planned, changedHash));
Assert.NotEqual(baseline, EncyclopediaState.SubjectFingerprint(planned with { TitleDe = "Heizungsanlage" }, notes));
Assert.NotEqual(baseline, EncyclopediaState.SubjectFingerprint(planned with { Scope = "Only boilers" }, notes));
}
}