feat(progression): read surface and change announcements (slice 10a)
reads for the UI: TotalCoins, Lives, IsRunOver, CurrentLevel, LevelOf/IsOwned/CanAfford, HasCleared. The read half of candidate 01 - callers get a narrow surface instead of reaching into state. new domain events LivesChanged / TotalCoinsChanged / SkillSetChanged, announced by comparing against the last announced value, so an operation can neither forget to announce nor announce something unchanged. HandlePlayerDeath now clears the spent attempt - it was still counting towards TotalCoins after its ledger had been discarded. republisher and EventBus extended; SkillSetChanged is what SkillManager will reconcile against instead of the non-atomic call pairs. 65 tests.
This commit is contained in:
@@ -21,6 +21,7 @@ public class ProgressionServiceTests
|
||||
startingLives: Lives.Of(3));
|
||||
|
||||
service.StartPlaythrough(Id);
|
||||
service.DrainEvents(); // setup announces; tests assert about the operation under test
|
||||
return service;
|
||||
}
|
||||
|
||||
@@ -84,6 +85,7 @@ public class ProgressionServiceTests
|
||||
TwoLevels(), Skills(), Lives.Of(3));
|
||||
service.StartPlaythrough(Id);
|
||||
service.EnterLevel(First);
|
||||
service.DrainEvents(); // setup announces; tests assert about the operation under test
|
||||
return service;
|
||||
}
|
||||
|
||||
@@ -167,4 +169,33 @@ public class ProgressionServiceTests
|
||||
Assert.Equal(Second, reloaded.CurrentLevel);
|
||||
Assert.Equal(LevelTime.Of(30.0), profileStore.Load().Value!.BestTimeFor(First));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Picking_up_a_coin_announces_the_new_total_so_the_hud_never_polls()
|
||||
{
|
||||
// CoinsChanged is emitted from four places today and subscribed by nobody, while Hud rebuilds
|
||||
// three translated strings every frame in _Process. One announcement, one read path.
|
||||
var service = ServiceWithSkills();
|
||||
|
||||
service.RecordCoinsFound(Coins.Of(7));
|
||||
|
||||
var announced = service.DrainEvents().OfType<TotalCoinsChanged>().Single();
|
||||
Assert.Equal(Coins.Of(7), announced.Total);
|
||||
Assert.Equal(Coins.Of(7), service.TotalCoins);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dying_announces_both_the_remaining_lives_and_the_coins_reverting_to_the_bank()
|
||||
{
|
||||
var service = ServiceWithSkills();
|
||||
service.RecordCoinsFound(Coins.Of(40));
|
||||
|
||||
service.HandlePlayerDeath();
|
||||
|
||||
var events = service.DrainEvents();
|
||||
Assert.Equal(2, events.OfType<LivesChanged>().Single().Remaining.Value);
|
||||
// The attempt is discarded, so the 40 found coins were never banked.
|
||||
Assert.Equal(Coins.Zero, events.OfType<TotalCoinsChanged>().Last().Total);
|
||||
Assert.Equal(Coins.Zero, service.TotalCoins);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user