using System; using System.Collections.Generic; using System.Reflection; using Microsoft.Xna.Framework; using MonoGame.Extended.Screens; namespace MonoGame.Extended.Tests.Screens; [Collection("GraphicsTest")] public sealed class ScreenManagerTests { #region ShowScreen Tests [Fact] public void ShowScreen_FirstScreen_BecomesActive() { ScreenManager manager = new ScreenManager(); TestScreen screen = new TestScreen("Screen1"); manager.ShowScreen(screen); Assert.Equal(screen, manager.ActiveScreen); Assert.True(screen.IsActive); Assert.Single(manager.Screens); } [Fact] public void ShowScreen_SecondScreen_DeactivatesFirstAndBecomesActive() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); manager.ShowScreen(screen1); manager.ShowScreen(screen2); Assert.Equal(screen2, manager.ActiveScreen); Assert.True(screen2.IsActive); Assert.False(screen1.IsActive); Assert.Equal(2, manager.Screens.Count); } [Fact] public void ShowScreen_SetsScreenManagerProperty() { ScreenManager manager = new ScreenManager(); TestScreen screen = new TestScreen("Screen1"); manager.ShowScreen(screen); Assert.Equal(manager, screen.ScreenManager); } [Fact] public void ShowScreen_WithNull_ThrowsArgumentNullException() { ScreenManager manager = new ScreenManager(); Assert.Throws(() => manager.ShowScreen(null)); } #endregion #region CloseScreen Tests [Fact] public void CloseScreen_RemovesActiveAndActivatesPrevious() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.CloseScreen(); Assert.Equal(screen1, manager.ActiveScreen); Assert.True(screen1.IsActive); Assert.True(screen2.DisposeCalled); Assert.Single(manager.Screens); } [Fact] public void CloseScreen_OnLastScreen_LeavesEmptyStack() { ScreenManager manager = new ScreenManager(); TestScreen screen = new TestScreen("Screen1"); manager.ShowScreen(screen); manager.CloseScreen(); Assert.Null(manager.ActiveScreen); Assert.Empty(manager.Screens); Assert.True(screen.DisposeCalled); } [Fact] public void CloseScreen_OnEmptyStack_DoesNotThrow() { ScreenManager manager = new ScreenManager(); manager.CloseScreen(); Assert.Null(manager.ActiveScreen); Assert.Empty(manager.Screens); } #endregion #region ReplaceScreen Tests [Fact] public void ReplaceScreen_ClosesActiveAndShowsNew() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); manager.ShowScreen(screen1); manager.ReplaceScreen(screen2); Assert.Equal(screen2, manager.ActiveScreen); Assert.True(screen2.IsActive); Assert.True(screen1.DisposeCalled); Assert.Single(manager.Screens); } [Fact] public void ReplaceScreen_OnEmptyStack_JustShowsScreen() { ScreenManager manager = new ScreenManager(); TestScreen screen = new TestScreen("Screen1"); manager.ReplaceScreen(screen); Assert.Equal(screen, manager.ActiveScreen); Assert.Single(manager.Screens); } [Fact] public void ReplaceScreen_WithNull_ThrowsArgumentNullException() { ScreenManager manager = new ScreenManager(); Assert.Throws(() => manager.ReplaceScreen(null)); } #endregion #region ClearScreens Tests [Fact] public void ClearScreens_DisposesAllScreensAndClearsStack() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); TestScreen screen3 = new TestScreen("Screen3"); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.ShowScreen(screen3); manager.ClearScreens(); Assert.Null(manager.ActiveScreen); Assert.Empty(manager.Screens); Assert.True(screen1.DisposeCalled); Assert.True(screen2.DisposeCalled); Assert.True(screen3.DisposeCalled); } [Fact] public void ClearScreens_OnEmptyStack_DoesNotThrow() { ScreenManager manager = new ScreenManager(); manager.ClearScreens(); Assert.Null(manager.ActiveScreen); } #endregion #region Update Tests [Fact] public void Update_OnlyUpdatesActiveScreen_ByDefault() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); GameTime gameTime = new GameTime(); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.Update(gameTime); Assert.Equal(0, screen1.UpdateCallCount); Assert.Equal(1, screen2.UpdateCallCount); } [Fact] public void Update_UpdatesInactiveScreens_WhenUpdateWhenInactiveIsTrue() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1") { UpdateWhenInactive = true }; TestScreen screen2 = new TestScreen("Screen2"); GameTime gameTime = new GameTime(); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.Update(gameTime); Assert.Equal(1, screen1.UpdateCallCount); Assert.Equal(1, screen2.UpdateCallCount); } [Fact] public void Update_UpdatesScreensInBottomToTopOrder() { ScreenManager manager = new ScreenManager(); List updateOrder = new List(); TestScreen screen1 = new TestScreen("Screen1") { UpdateWhenInactive = true }; TestScreen screen2 = new TestScreen("Screen2") { UpdateWhenInactive = true }; TestScreen screen3 = new TestScreen("Screen3"); screen1.OnUpdate += name => updateOrder.Add(name); screen2.OnUpdate += name => updateOrder.Add(name); screen3.OnUpdate += name => updateOrder.Add(name); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.ShowScreen(screen3); manager.Update(new GameTime()); Assert.Equal(["Screen1", "Screen2", "Screen3"], updateOrder); } [Fact] public void Update_OnEmptyStack_DoesNotThrow() { ScreenManager manager = new ScreenManager(); manager.Update(new GameTime()); } #endregion #region Draw Tests [Fact] public void Draw_OnlyDrawsActiveScreen_ByDefault() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); GameTime gameTime = new GameTime(); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.Draw(gameTime); Assert.Equal(0, screen1.DrawCallCount); Assert.Equal(1, screen2.DrawCallCount); } [Fact] public void Draw_DrawsInactiveScreens_WhenDrawWhenInactiveIsTrue() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1") { DrawWhenInactive = true }; TestScreen screen2 = new TestScreen("Screen2"); GameTime gameTime = new GameTime(); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.Draw(gameTime); Assert.Equal(1, screen1.DrawCallCount); Assert.Equal(1, screen2.DrawCallCount); } [Fact] public void Draw_DrawsScreensInBottomToTopOrder() { ScreenManager manager = new ScreenManager(); List drawOrder = new List(); TestScreen screen1 = new TestScreen("Screen1") { DrawWhenInactive = true }; TestScreen screen2 = new TestScreen("Screen2") { DrawWhenInactive = true }; TestScreen screen3 = new TestScreen("Screen3"); screen1.OnDraw += name => drawOrder.Add(name); screen2.OnDraw += name => drawOrder.Add(name); screen3.OnDraw += name => drawOrder.Add(name); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.ShowScreen(screen3); manager.Draw(new GameTime()); Assert.Equal(["Screen1", "Screen2", "Screen3"], drawOrder); } [Fact] public void Draw_OnEmptyStack_DoesNotThrow() { ScreenManager manager = new ScreenManager(); manager.Draw(new GameTime()); } #endregion #region Stack Ordering Tests [Fact] public void Screens_ReturnsScreensInBottomToTopOrder() { ScreenManager manager = new ScreenManager(); TestScreen screen1 = new TestScreen("Screen1"); TestScreen screen2 = new TestScreen("Screen2"); TestScreen screen3 = new TestScreen("Screen3"); manager.ShowScreen(screen1); manager.ShowScreen(screen2); manager.ShowScreen(screen3); IReadOnlyList screens = manager.Screens; Assert.Equal(3, screens.Count); Assert.Equal(screen1, screens[0]); Assert.Equal(screen2, screens[1]); Assert.Equal(screen3, screens[2]); } #endregion #region Cache Invalidation Tests [Fact] public void Screens_CachesResultsBetweenCalls() { ScreenManager manager = new ScreenManager(); manager.ShowScreen(new TestScreen("Screen1")); IReadOnlyList screens1 = manager.Screens; IReadOnlyList screens2 = manager.Screens; Assert.Same(screens1, screens2); } [Fact] public void Screens_InvalidatesCacheOnShowScreen() { ScreenManager manager = new ScreenManager(); manager.ShowScreen(new TestScreen("Screen1")); IReadOnlyList screensBefore = manager.Screens; manager.ShowScreen(new TestScreen("Screen2")); IReadOnlyList screensAfter = manager.Screens; Assert.NotSame(screensBefore, screensAfter); Assert.Equal(2, screensAfter.Count); } [Fact] public void Screens_InvalidatesCacheOnCloseScreen() { ScreenManager manager = new ScreenManager(); manager.ShowScreen(new TestScreen("Screen1")); manager.ShowScreen(new TestScreen("Screen2")); IReadOnlyList screensBefore = manager.Screens; manager.CloseScreen(); IReadOnlyList screensAfter = manager.Screens; Assert.NotSame(screensBefore, screensAfter); Assert.Single(screensAfter); } [Fact] public void Screens_InvalidatesCacheOnClearScreens() { ScreenManager manager = new ScreenManager(); manager.ShowScreen(new TestScreen("Screen1")); IReadOnlyList screensBefore = manager.Screens; manager.ClearScreens(); IReadOnlyList screensAfter = manager.Screens; Assert.NotSame(screensBefore, screensAfter); Assert.Empty(screensAfter); } #endregion }