TopLevelTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Copyright (c) The Perspex Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System.Reactive;
  4. using System.Reactive.Subjects;
  5. using Moq;
  6. using Perspex.Controls.Presenters;
  7. using Perspex.Controls.Templates;
  8. using Perspex.Input;
  9. using Perspex.Input.Raw;
  10. using Perspex.Layout;
  11. using Perspex.Platform;
  12. using Perspex.Rendering;
  13. using Perspex.Styling;
  14. using Ploeh.AutoFixture;
  15. using Ploeh.AutoFixture.AutoMoq;
  16. using Xunit;
  17. namespace Perspex.Controls.UnitTests
  18. {
  19. public class TopLevelTests
  20. {
  21. [Fact]
  22. public void ClientSize_Should_Be_Set_On_Construction()
  23. {
  24. using (PerspexLocator.EnterScope())
  25. {
  26. RegisterServices();
  27. var impl = new Mock<ITopLevelImpl>();
  28. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  29. var target = new TestTopLevel(impl.Object);
  30. Assert.Equal(new Size(123, 456), target.ClientSize);
  31. }
  32. }
  33. [Fact]
  34. public void Width_Should_Not_Be_Set_On_Construction()
  35. {
  36. using (PerspexLocator.EnterScope())
  37. {
  38. RegisterServices();
  39. var impl = new Mock<ITopLevelImpl>();
  40. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  41. var target = new TestTopLevel(impl.Object);
  42. Assert.Equal(double.NaN, target.Width);
  43. }
  44. }
  45. [Fact]
  46. public void Height_Should_Not_Be_Set_On_Construction()
  47. {
  48. using (PerspexLocator.EnterScope())
  49. {
  50. RegisterServices();
  51. var impl = new Mock<ITopLevelImpl>();
  52. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  53. var target = new TestTopLevel(impl.Object);
  54. Assert.Equal(double.NaN, target.Height);
  55. }
  56. }
  57. [Fact]
  58. public void Layout_Pass_Should_Not_Be_Automatically_Scheduled()
  59. {
  60. using (PerspexLocator.EnterScope())
  61. {
  62. RegisterServices();
  63. var impl = new Mock<ITopLevelImpl>();
  64. var target = new TestTopLevel(impl.Object);
  65. // The layout pass should be scheduled by the derived class.
  66. var layoutManagerMock = Mock.Get(target.LayoutManager);
  67. layoutManagerMock.Verify(x => x.ExecuteLayoutPass(), Times.Never);
  68. }
  69. }
  70. [Fact]
  71. public void Bounds_Should_Be_Set_After_Layout_Pass()
  72. {
  73. using (PerspexLocator.EnterScope())
  74. {
  75. RegisterServices();
  76. PerspexLocator.CurrentMutable.Bind<ILayoutManager>().ToConstant(new LayoutManager());
  77. var impl = new Mock<ITopLevelImpl>();
  78. impl.SetupProperty(x => x.ClientSize);
  79. impl.SetupProperty(x => x.Resized);
  80. var target = new TestTopLevel(impl.Object)
  81. {
  82. Template = new ControlTemplate<TestTopLevel>(x =>
  83. new ContentPresenter
  84. {
  85. [~ContentPresenter.ContentProperty] = x[~ContentControl.ContentProperty],
  86. }),
  87. Content = new TextBlock
  88. {
  89. Width = 321,
  90. Height = 432,
  91. }
  92. };
  93. target.LayoutManager.ExecuteLayoutPass();
  94. Assert.Equal(new Rect(0, 0, 321, 432), target.Bounds);
  95. }
  96. }
  97. [Fact]
  98. public void Impl_ClientSize_Should_Be_Set_After_Layout_Pass()
  99. {
  100. using (PerspexLocator.EnterScope())
  101. {
  102. RegisterServices();
  103. PerspexLocator.CurrentMutable.Bind<ILayoutManager>().ToConstant(new LayoutManager());
  104. var impl = new Mock<ITopLevelImpl>();
  105. var target = new TestTopLevel(impl.Object)
  106. {
  107. Template = new ControlTemplate<TestTopLevel>(x =>
  108. new ContentPresenter
  109. {
  110. [~ContentPresenter.ContentProperty] = x[~ContentControl.ContentProperty],
  111. }),
  112. Content = new TextBlock
  113. {
  114. Width = 321,
  115. Height = 432,
  116. }
  117. };
  118. target.LayoutManager.ExecuteLayoutPass();
  119. impl.VerifySet(x => x.ClientSize = new Size(321, 432));
  120. }
  121. }
  122. [Fact]
  123. public void Width_And_Height_Should_Not_Be_Set_After_Layout_Pass()
  124. {
  125. using (PerspexLocator.EnterScope())
  126. {
  127. RegisterServices();
  128. var impl = new Mock<ITopLevelImpl>();
  129. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  130. var target = new TestTopLevel(impl.Object);
  131. target.LayoutManager.ExecuteLayoutPass();
  132. Assert.Equal(double.NaN, target.Width);
  133. Assert.Equal(double.NaN, target.Height);
  134. }
  135. }
  136. [Fact]
  137. public void Render_Should_Be_Scheduled_After_Layout_Pass()
  138. {
  139. using (PerspexLocator.EnterScope())
  140. {
  141. RegisterServices();
  142. var completed = new Subject<Unit>();
  143. var layoutManagerMock = Mock.Get(PerspexLocator.Current.GetService<ILayoutManager>());
  144. layoutManagerMock.Setup(x => x.LayoutCompleted).Returns(completed);
  145. var impl = new Mock<ITopLevelImpl>();
  146. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  147. var target = new TestTopLevel(impl.Object);
  148. completed.OnNext(Unit.Default);
  149. var renderManagerMock = Mock.Get(PerspexLocator.Current.GetService<IRenderQueueManager>());
  150. renderManagerMock.Verify(x => x.InvalidateRender(target));
  151. }
  152. }
  153. [Fact]
  154. public void Width_And_Height_Should_Be_Set_After_Window_Resize_Notification()
  155. {
  156. using (PerspexLocator.EnterScope())
  157. {
  158. RegisterServices();
  159. var impl = new Mock<ITopLevelImpl>();
  160. impl.SetupAllProperties();
  161. impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
  162. // The user has resized the window, so we can no longer auto-size.
  163. var target = new TestTopLevel(impl.Object);
  164. impl.Object.Resized(new Size(100, 200));
  165. Assert.Equal(100, target.Width);
  166. Assert.Equal(200, target.Height);
  167. }
  168. }
  169. [Fact]
  170. public void Activate_Should_Call_Impl_Activate()
  171. {
  172. using (PerspexLocator.EnterScope())
  173. {
  174. RegisterServices();
  175. var impl = new Mock<ITopLevelImpl>();
  176. var target = new TestTopLevel(impl.Object);
  177. target.Activate();
  178. impl.Verify(x => x.Activate());
  179. }
  180. }
  181. [Fact]
  182. public void Impl_Activate_Should_Call_Raise_Activated_Event()
  183. {
  184. using (PerspexLocator.EnterScope())
  185. {
  186. RegisterServices();
  187. var impl = new Mock<ITopLevelImpl>();
  188. impl.SetupAllProperties();
  189. bool raised = false;
  190. var target = new TestTopLevel(impl.Object);
  191. target.Activated += (s, e) => raised = true;
  192. impl.Object.Activated();
  193. Assert.True(raised);
  194. }
  195. }
  196. [Fact]
  197. public void Impl_Close_Should_Call_Raise_Closed_Event()
  198. {
  199. using (PerspexLocator.EnterScope())
  200. {
  201. RegisterServices();
  202. var impl = new Mock<ITopLevelImpl>();
  203. impl.SetupAllProperties();
  204. bool raised = false;
  205. var target = new TestTopLevel(impl.Object);
  206. target.Closed += (s, e) => raised = true;
  207. impl.Object.Closed();
  208. Assert.True(raised);
  209. }
  210. }
  211. [Fact]
  212. public void Impl_Deactivate_Should_Call_Raise_Activated_Event()
  213. {
  214. using (PerspexLocator.EnterScope())
  215. {
  216. RegisterServices();
  217. var impl = new Mock<ITopLevelImpl>();
  218. impl.SetupAllProperties();
  219. bool raised = false;
  220. var target = new TestTopLevel(impl.Object);
  221. target.Deactivated += (s, e) => raised = true;
  222. impl.Object.Deactivated();
  223. Assert.True(raised);
  224. }
  225. }
  226. [Fact]
  227. public void Impl_Input_Should_Pass_Input_To_InputManager()
  228. {
  229. using (PerspexLocator.EnterScope())
  230. {
  231. RegisterServices();
  232. var impl = new Mock<ITopLevelImpl>();
  233. impl.SetupAllProperties();
  234. var target = new TestTopLevel(impl.Object);
  235. var input = new RawKeyEventArgs(
  236. new Mock<IKeyboardDevice>().Object,
  237. 0,
  238. RawKeyEventType.KeyDown,
  239. Key.A, InputModifiers.None);
  240. impl.Object.Input(input);
  241. var inputManagerMock = Mock.Get(InputManager.Instance);
  242. inputManagerMock.Verify(x => x.Process(input));
  243. }
  244. }
  245. private void RegisterServices()
  246. {
  247. var fixture = new Fixture().Customize(new AutoMoqCustomization());
  248. var l = PerspexLocator.CurrentMutable;
  249. var formattedText = fixture.Create<IFormattedTextImpl>();
  250. var globalStyles = new Mock<IGlobalStyles>();
  251. var layoutManager = fixture.Create<ILayoutManager>();
  252. var renderInterface = fixture.Create<IPlatformRenderInterface>();
  253. var renderManager = fixture.Create<IRenderQueueManager>();
  254. var windowImpl = new Mock<IWindowImpl>();
  255. var theme = new Styles();
  256. globalStyles.Setup(x => x.Styles).Returns(theme);
  257. PerspexLocator.CurrentMutable
  258. .Bind<IInputManager>().ToConstant(new Mock<IInputManager>().Object)
  259. .Bind<IFocusManager>().ToConstant(new Mock<IFocusManager>().Object)
  260. .Bind<IGlobalStyles>().ToConstant(globalStyles.Object)
  261. .Bind<ILayoutManager>().ToConstant(layoutManager)
  262. .Bind<IPlatformRenderInterface>().ToConstant(renderInterface)
  263. .Bind<IPlatformThreadingInterface>().ToConstant(new Mock<IPlatformThreadingInterface>().Object)
  264. .Bind<IRenderQueueManager>().ToConstant(renderManager)
  265. .Bind<IStyler>().ToConstant(new Styler());
  266. }
  267. private class TestTopLevel : TopLevel
  268. {
  269. public TestTopLevel(ITopLevelImpl impl)
  270. : base(impl)
  271. {
  272. }
  273. }
  274. }
  275. }