diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-20 15:54:00 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-20 15:54:00 +0800 |
| commit | 3aa0049bb092694b5168d99bc6ac893b1db4740a (patch) | |
| tree | b3cf6a0e21442780cd72e8f6a842a4f3db1cecca /src/LivingVillage.Desktop.Tests | |
| parent | 9724663602b4b1eb755bf334c475dc2c80e4b386 (diff) | |
| download | living-village-3aa0049bb092694b5168d99bc6ac893b1db4740a.tar.gz | |
feat(m6b): add playable menu and save flow
[Change Nature]
- This commit adds the M6b desktop menu and persistence integration.
[New Capability]
- Provide new game, continue, settings, controls, load error, save, load, and exit flows.
- Provide a bounded autoplay flow covering menu navigation and persistence.
[Implementation]
- Add pure menu state transitions and focused M6b coverage.
- Connect menu commands to simulation controls, WorldSave, view resets, and rendering.
[Impact]
- Desktop runtime gains the playable M6b front end without changing out-of-scope files.
- Release focused and solution test suites remain passing.
Diffstat (limited to 'src/LivingVillage.Desktop.Tests')
| -rw-r--r-- | src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj | 1 | ||||
| -rw-r--r-- | src/LivingVillage.Desktop.Tests/M6bTests.fs | 82 |
2 files changed, 83 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj index b8e2055..405e8b5 100644 --- a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj +++ b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj @@ -8,6 +8,7 @@ <ItemGroup> <Compile Include="DesktopTests.fs" /> <Compile Include="M6aTests.fs" /> + <Compile Include="M6bTests.fs" /> </ItemGroup> <ItemGroup> diff --git a/src/LivingVillage.Desktop.Tests/M6bTests.fs b/src/LivingVillage.Desktop.Tests/M6bTests.fs new file mode 100644 index 0000000..6ae0634 --- /dev/null +++ b/src/LivingVillage.Desktop.Tests/M6bTests.fs @@ -0,0 +1,82 @@ +namespace LivingVillage.Desktop.Tests + +open Microsoft.VisualStudio.TestTools.UnitTesting +open LivingVillage.Kernel +open LivingVillage.Desktop + +[<TestClass>] +type M6bMenuTests () = + + [<TestMethod>] + member _.MainMenuHasRequiredOrderAndStartsAtNewGame () = + let state = MenuState.create SimulationControl.initial false + + Assert.AreEqual<MenuPage>(MainMenu, state.Page) + Assert.AreEqual<MenuItem list>( + [ NewGameItem; LoadItem; SettingsItem; ControlsItem; ExitItem ], + MenuState.items state) + Assert.AreEqual<int>(0, state.Selected) + + [<TestMethod>] + member _.SelectionWrapsAndConfirmProducesNewGameCommand () = + let state = MenuState.create SimulationControl.initial false + let wrapped = MenuState.move Up state + let confirmed = MenuState.update Confirm wrapped |> snd + + Assert.AreEqual<MenuItem>(ExitItem, MenuState.selectedItem wrapped) + Assert.AreEqual<MenuCommand>(ExitGame, confirmed) + let newGameState, newGameCommand = MenuState.update Confirm state + Assert.AreEqual<MenuPage>(MainMenu, newGameState.Page) + Assert.AreEqual<MenuCommand>(StartNewGame, newGameCommand) + + [<TestMethod>] + member _.SettingsCanSelectEveryExistingSimulationMode () = + let initial = MenuState.create SimulationControl.initial false + let settings, _ = MenuState.update Confirm (MenuState.move Down (MenuState.move Down initial)) + let oneX, oneXCommand = MenuState.update Confirm settings + let twoX, twoXCommand = MenuState.update Confirm (MenuState.move Down settings) + let fiveX, fiveXCommand = MenuState.update Confirm (MenuState.move Down (MenuState.move Down settings)) + let paused, pausedCommand = MenuState.update Confirm (MenuState.move Down (MenuState.move Down (MenuState.move Down settings))) + + Assert.AreEqual<MenuPage>(Settings, settings.Page) + Assert.AreEqual<MenuCommand>(ApplySettings { Paused = false; Speed = OneX }, oneXCommand) + Assert.AreEqual<MenuCommand>(ApplySettings { Paused = false; Speed = TwoX }, twoXCommand) + Assert.AreEqual<MenuCommand>(ApplySettings { Paused = false; Speed = FiveX }, fiveXCommand) + Assert.AreEqual<MenuCommand>(ApplySettings { Paused = true; Speed = OneX }, pausedCommand) + Assert.AreEqual<MenuPage>(Settings, oneX.Page) + + [<TestMethod>] + member _.EscapeReturnsToPreviousPageAndKeepsCurrentWorld () = + let playing = MenuState.create SimulationControl.initial true |> MenuState.enterGame + let settings = MenuState.openSettings playing + let returned, command = MenuState.update Back settings + let main = MenuState.openMain playing + let continued, continueCommand = MenuState.update Confirm main + + Assert.AreEqual<MenuPage>(Playing, returned.Page) + Assert.AreEqual<MenuCommand>(NoCommand, command) + Assert.IsTrue(returned.HasCurrentWorld) + Assert.AreEqual<MenuPage>(MainMenu, main.Page) + Assert.AreEqual<MenuItem>(ContinueItem, MenuState.selectedItem main) + Assert.AreEqual<MenuPage>(Playing, continued.Page) + Assert.AreEqual<MenuCommand>(ContinueGame, continueCommand) + + [<TestMethod>] + member _.ControlsPageExposesCompleteKeyboardBindings () = + let state = MenuState.openControls (MenuState.create SimulationControl.initial false) + let keys = MenuState.controlRows |> List.map (fun row -> row.Keys) + + Assert.AreEqual<MenuPage>(Controls, state.Page) + Assert.AreEqual<string list>( + [ "WASD"; "E"; "1-6"; "Q"; "TAB"; "C"; "L"; "P"; "F1/F2/F3"; "F6"; "F7"; "ESC"; "UP/DOWN"; "ENTER" ], + keys) + + [<TestMethod>] + member _.LoadFailureIsAnExplicitPageAndBackReturnsToMenu () = + let failed = MenuState.showLoadError "missing save" (MenuState.create SimulationControl.initial false) + let returned, command = MenuState.update Back failed + + Assert.AreEqual<MenuPage>(LoadError, failed.Page) + Assert.AreEqual<string option>(Some "missing save", failed.Error) + Assert.AreEqual<MenuPage>(MainMenu, returned.Page) + Assert.AreEqual<MenuCommand>(NoCommand, command) |
