feat(progression): snapshots, ports, in-memory adapters (slice 5)
flat snapshot record per aggregate - separate files mean saving a run doesn't rewrite the Profile, deleting a slot is deleting a file, and a corrupt slot doesn't cost achievements or best times. snapshots hold primitives so Restore re-runs the value-object factories; a serialiser building LevelId directly would bypass every guard. LoadResult has three outcomes: Absent != Corrupt. Collapsing them is the bug where a version bump made ContinueGame overwrite the save. Profile.Restore writes collections directly - replaying UnlockAchievement would re-fire popups and Steam pushes on every load. 44 tests.
This commit is contained in:
47
progression.tests/PlaythroughStoreTests.cs
Normal file
47
progression.tests/PlaythroughStoreTests.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace Mr.BrickAdventures.Progression.Tests;
|
||||
|
||||
public class PlaythroughStoreTests
|
||||
{
|
||||
private static readonly PlaythroughId Id =
|
||||
PlaythroughId.Of(new Guid("33333333-3333-3333-3333-333333333333"));
|
||||
|
||||
private static Campaign OneLevel() => Campaign.Of(new[] { LevelId.Of("village_1") });
|
||||
|
||||
[Fact]
|
||||
public void A_playthrough_that_was_never_saved_is_absent_not_an_error()
|
||||
{
|
||||
var store = new InMemoryPlaythroughStore();
|
||||
|
||||
var result = store.Load(Id);
|
||||
|
||||
Assert.Equal(LoadOutcome.Absent, result.Outcome);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_playthrough_that_cannot_be_read_is_corrupt_and_not_mistaken_for_absent()
|
||||
{
|
||||
// This is the version-bump bug. LoadGame returns false for both "no file" and "version
|
||||
// mismatch", ContinueGame reads that as no save, calls StartNewGame, and overwrites the
|
||||
// player's file. Absent means "offer a new game"; Corrupt means "say something went wrong".
|
||||
var store = new InMemoryPlaythroughStore();
|
||||
store.Save(Playthrough.StartNew(Id, OneLevel(), Lives.Of(3)));
|
||||
store.Corrupt(Id);
|
||||
|
||||
var result = store.Load(Id);
|
||||
|
||||
Assert.Equal(LoadOutcome.Corrupt, result.Outcome);
|
||||
Assert.NotEqual(LoadOutcome.Absent, result.Outcome);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_saved_playthrough_loads_back()
|
||||
{
|
||||
var store = new InMemoryPlaythroughStore();
|
||||
store.Save(Playthrough.StartNew(Id, OneLevel(), Lives.Of(2)));
|
||||
|
||||
var result = store.Load(Id);
|
||||
|
||||
Assert.Equal(LoadOutcome.Loaded, result.Outcome);
|
||||
Assert.Equal(2, result.Value!.Lives.Value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user