feat(progression): use cases (slice 6)
ProgressionService holds the loaded Profile, active Playthrough and active Attempt, so "exactly one active Attempt" has a testable home. EnterLevel always announces LevelStarted - the reason ghost recording and splits never worked on level 1 or after a Continue. Refuses unreachable levels. Does not touch campaign position, so a Replay leaves it alone. SkillCatalogue returns null for a skill with no authored upgrades, killing the Upgrades[0].Cost overrun. PurchaseSkill reads the current level from the ledger first, so one Attempt can unlock then upgrade. HandlePlayerDeath now persists - death was free if you quit. SkillLevel.First/Next driven out here by a real caller. 53 tests.
This commit is contained in:
@@ -156,4 +156,18 @@ public class PlaythroughTests
|
||||
Assert.False(playthrough.HasCleared(First));
|
||||
Assert.Equal(First, playthrough.CurrentLevel);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Committing_an_attempt_that_overspent_the_bank_is_an_impossible_state()
|
||||
{
|
||||
// PurchaseSkill's affordability check makes this unreachable through the application layer.
|
||||
// Asserted directly so the guard is covered rather than being dead code nobody has run — if
|
||||
// it ever fires, the bug is a missing affordability check, not this line.
|
||||
var campaign = TwoLevels();
|
||||
var playthrough = StartWith(Lives.Of(3));
|
||||
var attempt = new Attempt(First);
|
||||
attempt.TryRecordPurchase(SkillId.Of("brick_throw"), SkillLevel.First, Coins.Of(999));
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => playthrough.SettleCompletion(attempt, campaign));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user