using Theriapolis.Core; using Theriapolis.Core.Persistence; using Theriapolis.Core.Rules.Quests; using Xunit; namespace Theriapolis.Tests.Quests; /// /// Phase 6 M4 — capture/restore round-trip for quest engine state. /// public sealed class QuestSnapshotTests { [Fact] public void CaptureAndRestore_RoundTripActiveAndCompleted() { var engine = new QuestEngine(); engine.AdoptActive(new QuestState { QuestId = "q1", CurrentStep = "step_a", Status = QuestStatus.Active, StartedAt = 100, StepStartedAt = 150, }); engine.Get("q1")!.Journal.Add("started q1"); engine.AdoptCompleted(new QuestState { QuestId = "q2", CurrentStep = "", Status = QuestStatus.Completed, StartedAt = 0, StepStartedAt = 200, }); engine.Journal.Add("global event 1"); var snap = QuestCodec.Capture(engine); Assert.Single(snap.Active); Assert.Single(snap.Completed); Assert.Single(snap.Journal); var rebuilt = new QuestEngine(); QuestCodec.Restore(rebuilt, snap); Assert.True(rebuilt.IsActive("q1")); Assert.True(rebuilt.IsCompleted("q2")); Assert.Single(rebuilt.Journal); Assert.Equal("step_a", rebuilt.Get("q1")!.CurrentStep); Assert.Contains("started q1", rebuilt.Get("q1")!.Journal); } [Fact] public void SaveCodec_RoundTripsQuestEngineState() { var engine = new QuestEngine(); engine.AdoptActive(new QuestState { QuestId = "main_act_i_001_arrival", CurrentStep = "find_magistrate", Status = QuestStatus.Active, StartedAt = 500, StepStartedAt = 700, }); engine.Journal.Add("Arrived in Millhaven"); var body = new SaveBody(); body.Player.Name = "Tester"; body.QuestEngineState = QuestCodec.Capture(engine); var header = new SaveHeader { Version = C.SAVE_SCHEMA_VERSION, WorldSeedHex = "0xCAFE" }; var bytes = SaveCodec.Serialize(header, body); var (h2, b2) = SaveCodec.Deserialize(bytes); Assert.Equal(C.SAVE_SCHEMA_VERSION, h2.Version); Assert.Single(b2.QuestEngineState.Active); Assert.Equal("find_magistrate", b2.QuestEngineState.Active[0].CurrentStep); Assert.Single(b2.QuestEngineState.Journal); } [Fact] public void EmptyEngineState_OmitsTagFromSave() { // No active/completed/journal → no TAG_QUESTS section written. var body = new SaveBody { Player = { Name = "Empty" } }; var bytes = SaveCodec.Serialize(new SaveHeader(), body); var (_, b2) = SaveCodec.Deserialize(bytes); Assert.Empty(b2.QuestEngineState.Active); Assert.Empty(b2.QuestEngineState.Completed); Assert.Empty(b2.QuestEngineState.Journal); } }