WindowTests.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using Avalonia.Layout;
  5. using Avalonia.Platform;
  6. using Avalonia.Rendering;
  7. using Avalonia.UnitTests;
  8. using Moq;
  9. using Xunit;
  10. namespace Avalonia.Controls.UnitTests
  11. {
  12. public class WindowTests
  13. {
  14. [Fact]
  15. public void Setting_Title_Should_Set_Impl_Title()
  16. {
  17. var windowImpl = new Mock<IWindowImpl>();
  18. var windowingPlatform = new MockWindowingPlatform(() => windowImpl.Object);
  19. using (UnitTestApplication.Start(new TestServices(windowingPlatform: windowingPlatform)))
  20. {
  21. var target = new Window();
  22. target.Title = "Hello World";
  23. windowImpl.Verify(x => x.SetTitle("Hello World"));
  24. }
  25. }
  26. [Fact]
  27. public void IsVisible_Should_Initially_Be_False()
  28. {
  29. using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
  30. {
  31. var window = new Window();
  32. Assert.False(window.IsVisible);
  33. }
  34. }
  35. [Fact]
  36. public void IsVisible_Should_Be_True_After_Show()
  37. {
  38. using (UnitTestApplication.Start(TestServices.StyledWindow))
  39. {
  40. var window = new Window();
  41. window.Show();
  42. Assert.True(window.IsVisible);
  43. }
  44. }
  45. [Fact]
  46. public void IsVisible_Should_Be_True_After_ShowDialog()
  47. {
  48. using (UnitTestApplication.Start(TestServices.StyledWindow))
  49. {
  50. var parent = new Window();
  51. parent.Show();
  52. var window = new Window();
  53. var task = window.ShowDialog(parent);
  54. Assert.True(window.IsVisible);
  55. }
  56. }
  57. [Fact]
  58. public void IsVisible_Should_Be_False_After_Hide()
  59. {
  60. using (UnitTestApplication.Start(TestServices.StyledWindow))
  61. {
  62. var window = new Window();
  63. window.Show();
  64. window.Hide();
  65. Assert.False(window.IsVisible);
  66. }
  67. }
  68. [Fact]
  69. public void IsVisible_Should_Be_False_After_Close()
  70. {
  71. using (UnitTestApplication.Start(TestServices.StyledWindow))
  72. {
  73. var window = new Window();
  74. window.Show();
  75. window.Close();
  76. Assert.False(window.IsVisible);
  77. }
  78. }
  79. [Fact]
  80. public void IsVisible_Should_Be_False_After_Impl_Signals_Close()
  81. {
  82. var windowImpl = new Mock<IWindowImpl>();
  83. windowImpl.SetupProperty(x => x.Closed);
  84. windowImpl.Setup(x => x.Scaling).Returns(1);
  85. var services = TestServices.StyledWindow.With(
  86. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
  87. using (UnitTestApplication.Start(services))
  88. {
  89. var window = new Window();
  90. window.Show();
  91. windowImpl.Object.Closed();
  92. Assert.False(window.IsVisible);
  93. }
  94. }
  95. [Fact]
  96. public void Closing_Should_Only_Be_Invoked_Once()
  97. {
  98. using (UnitTestApplication.Start(TestServices.StyledWindow))
  99. {
  100. var window = new Window();
  101. var count = 0;
  102. window.Closing +=
  103. (sender, e) =>
  104. {
  105. count++;
  106. };
  107. window.Show();
  108. window.Close();
  109. Assert.Equal(1, count);
  110. }
  111. }
  112. [Fact]
  113. public void Showing_Should_Start_Renderer()
  114. {
  115. using (UnitTestApplication.Start(TestServices.StyledWindow))
  116. {
  117. var renderer = new Mock<IRenderer>();
  118. var target = new Window(CreateImpl(renderer));
  119. target.Show();
  120. renderer.Verify(x => x.Start(), Times.Once);
  121. }
  122. }
  123. [Fact]
  124. public void ShowDialog_Should_Start_Renderer()
  125. {
  126. using (UnitTestApplication.Start(TestServices.StyledWindow))
  127. {
  128. var parent = Mock.Of<Window>();
  129. var renderer = new Mock<IRenderer>();
  130. var target = new Window(CreateImpl(renderer));
  131. target.ShowDialog<object>(parent);
  132. renderer.Verify(x => x.Start(), Times.Once);
  133. }
  134. }
  135. [Fact]
  136. public void ShowDialog_Should_Raise_Opened()
  137. {
  138. using (UnitTestApplication.Start(TestServices.StyledWindow))
  139. {
  140. var parent = Mock.Of<Window>();
  141. var target = new Window();
  142. var raised = false;
  143. target.Opened += (s, e) => raised = true;
  144. target.ShowDialog<object>(parent);
  145. Assert.True(raised);
  146. }
  147. }
  148. [Fact]
  149. public void Hiding_Should_Stop_Renderer()
  150. {
  151. using (UnitTestApplication.Start(TestServices.StyledWindow))
  152. {
  153. var renderer = new Mock<IRenderer>();
  154. var target = new Window(CreateImpl(renderer));
  155. target.Show();
  156. target.Hide();
  157. renderer.Verify(x => x.Stop(), Times.Once);
  158. }
  159. }
  160. [Fact]
  161. public async Task ShowDialog_With_ValueType_Returns_Default_When_Closed()
  162. {
  163. using (UnitTestApplication.Start(TestServices.StyledWindow))
  164. {
  165. var parent = new Mock<Window>();
  166. var windowImpl = new Mock<IWindowImpl>();
  167. windowImpl.SetupProperty(x => x.Closed);
  168. windowImpl.Setup(x => x.Scaling).Returns(1);
  169. var target = new Window(windowImpl.Object);
  170. var task = target.ShowDialog<bool>(parent.Object);
  171. windowImpl.Object.Closed();
  172. var result = await task;
  173. Assert.False(result);
  174. }
  175. }
  176. [Fact]
  177. public void Calling_Show_On_Closed_Window_Should_Throw()
  178. {
  179. using (UnitTestApplication.Start(TestServices.StyledWindow))
  180. {
  181. var target = new Window();
  182. target.Show();
  183. target.Close();
  184. var openedRaised = false;
  185. target.Opened += (s, e) => openedRaised = true;
  186. var ex = Assert.Throws<InvalidOperationException>(() => target.Show());
  187. Assert.Equal("Cannot re-show a closed window.", ex.Message);
  188. Assert.False(openedRaised);
  189. }
  190. }
  191. [Fact]
  192. public async Task Calling_ShowDialog_On_Closed_Window_Should_Throw()
  193. {
  194. using (UnitTestApplication.Start(TestServices.StyledWindow))
  195. {
  196. var parent = new Mock<Window>();
  197. var windowImpl = new Mock<IWindowImpl>();
  198. windowImpl.SetupProperty(x => x.Closed);
  199. windowImpl.Setup(x => x.Scaling).Returns(1);
  200. var target = new Window(windowImpl.Object);
  201. var task = target.ShowDialog<bool>(parent.Object);
  202. windowImpl.Object.Closed();
  203. await task;
  204. var openedRaised = false;
  205. target.Opened += (s, e) => openedRaised = true;
  206. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => target.ShowDialog<bool>(parent.Object));
  207. Assert.Equal("Cannot re-show a closed window.", ex.Message);
  208. Assert.False(openedRaised);
  209. }
  210. }
  211. [Fact]
  212. public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
  213. {
  214. var screen1 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true);
  215. var screen2 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1366, 768)), new PixelRect(new PixelSize(1366, 728)), false);
  216. var screens = new Mock<IScreenImpl>();
  217. screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object });
  218. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  219. windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
  220. windowImpl.Setup(x => x.Scaling).Returns(1);
  221. windowImpl.Setup(x => x.Screen).Returns(screens.Object);
  222. using (UnitTestApplication.Start(TestServices.StyledWindow))
  223. {
  224. var window = new Window(windowImpl.Object);
  225. window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
  226. window.Position = new PixelPoint(60, 40);
  227. window.Show();
  228. var expectedPosition = new PixelPoint(
  229. (int)(screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2),
  230. (int)(screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2));
  231. Assert.Equal(window.Position, expectedPosition);
  232. }
  233. }
  234. [Fact]
  235. public void Window_Should_Be_Centered_Relative_To_Owner_When_WindowStartupLocation_Is_CenterOwner()
  236. {
  237. var parentWindowImpl = MockWindowingPlatform.CreateWindowMock();
  238. parentWindowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
  239. parentWindowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080));
  240. parentWindowImpl.Setup(x => x.Scaling).Returns(1);
  241. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  242. windowImpl.Setup(x => x.ClientSize).Returns(new Size(320, 200));
  243. windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080));
  244. windowImpl.Setup(x => x.Scaling).Returns(1);
  245. var parentWindowServices = TestServices.StyledWindow.With(
  246. windowingPlatform: new MockWindowingPlatform(() => parentWindowImpl.Object));
  247. var windowServices = TestServices.StyledWindow.With(
  248. windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
  249. using (UnitTestApplication.Start(parentWindowServices))
  250. {
  251. var parentWindow = new Window();
  252. parentWindow.Position = new PixelPoint(60, 40);
  253. parentWindow.Show();
  254. using (UnitTestApplication.Start(windowServices))
  255. {
  256. var window = new Window();
  257. window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
  258. window.Position = new PixelPoint(60, 40);
  259. window.Owner = parentWindow;
  260. window.Show();
  261. var expectedPosition = new PixelPoint(
  262. (int)(parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2),
  263. (int)(parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2));
  264. Assert.Equal(window.Position, expectedPosition);
  265. }
  266. }
  267. }
  268. public class SizingTests
  269. {
  270. [Fact]
  271. public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual()
  272. {
  273. using (UnitTestApplication.Start(TestServices.StyledWindow))
  274. {
  275. var child = new ChildControl();
  276. var target = new Window
  277. {
  278. Width = 100,
  279. Height = 50,
  280. SizeToContent = SizeToContent.Manual,
  281. Content = child
  282. };
  283. Show(target);
  284. Assert.Equal(1, child.MeasureSizes.Count);
  285. Assert.Equal(new Size(100, 50), child.MeasureSizes[0]);
  286. }
  287. }
  288. [Fact]
  289. public void Child_Should_Be_Measured_With_ClientSize_If_SizeToContent_Is_Manual_And_No_Width_Height_Specified()
  290. {
  291. using (UnitTestApplication.Start(TestServices.StyledWindow))
  292. {
  293. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  294. windowImpl.Setup(x => x.ClientSize).Returns(new Size(550, 450));
  295. var child = new ChildControl();
  296. var target = new Window(windowImpl.Object)
  297. {
  298. SizeToContent = SizeToContent.Manual,
  299. Content = child
  300. };
  301. Show(target);
  302. Assert.Equal(1, child.MeasureSizes.Count);
  303. Assert.Equal(new Size(550, 450), child.MeasureSizes[0]);
  304. }
  305. }
  306. [Fact]
  307. public void Child_Should_Be_Measured_With_Infinity_If_SizeToContent_Is_WidthAndHeight()
  308. {
  309. using (UnitTestApplication.Start(TestServices.StyledWindow))
  310. {
  311. var child = new ChildControl();
  312. var target = new Window
  313. {
  314. Width = 100,
  315. Height = 50,
  316. SizeToContent = SizeToContent.WidthAndHeight,
  317. Content = child
  318. };
  319. Show(target);
  320. Assert.Equal(1, child.MeasureSizes.Count);
  321. Assert.Equal(Size.Infinity, child.MeasureSizes[0]);
  322. }
  323. }
  324. [Fact]
  325. public void Should_Not_Have_Offset_On_Bounds_When_Content_Larger_Than_Max_Window_Size()
  326. {
  327. // Issue #3784.
  328. using (UnitTestApplication.Start(TestServices.StyledWindow))
  329. {
  330. var windowImpl = MockWindowingPlatform.CreateWindowMock();
  331. var clientSize = new Size(200, 200);
  332. var maxClientSize = new Size(480, 480);
  333. windowImpl.Setup(x => x.Resize(It.IsAny<Size>())).Callback<Size>(size =>
  334. {
  335. clientSize = size.Constrain(maxClientSize);
  336. windowImpl.Object.Resized?.Invoke(clientSize);
  337. });
  338. windowImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
  339. var child = new Canvas
  340. {
  341. Width = 400,
  342. Height = 800,
  343. };
  344. var target = new Window(windowImpl.Object)
  345. {
  346. SizeToContent = SizeToContent.WidthAndHeight,
  347. Content = child
  348. };
  349. Show(target);
  350. Assert.Equal(new Size(400, 480), target.Bounds.Size);
  351. // Issue #3784 causes this to be (0, 160) which makes no sense as Window has no
  352. // parent control to be offset against.
  353. Assert.Equal(new Point(0, 0), target.Bounds.Position);
  354. }
  355. }
  356. [Fact]
  357. public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_WidthAndHeight()
  358. {
  359. using (UnitTestApplication.Start(TestServices.StyledWindow))
  360. {
  361. var child = new Canvas
  362. {
  363. Width = 400,
  364. Height = 800,
  365. };
  366. var target = new Window()
  367. {
  368. SizeToContent = SizeToContent.WidthAndHeight,
  369. Content = child
  370. };
  371. Show(target);
  372. Assert.Equal(400, target.Width);
  373. Assert.Equal(800, target.Height);
  374. }
  375. }
  376. [Fact]
  377. public void SizeToContent_Should_Not_Be_Lost_On_Show()
  378. {
  379. using (UnitTestApplication.Start(TestServices.StyledWindow))
  380. {
  381. var child = new Canvas
  382. {
  383. Width = 400,
  384. Height = 800,
  385. };
  386. var target = new Window()
  387. {
  388. SizeToContent = SizeToContent.WidthAndHeight,
  389. Content = child
  390. };
  391. Show(target);
  392. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  393. }
  394. }
  395. [Fact]
  396. public void Width_Height_Should_Be_Updated_When_SizeToContent_Is_WidthAndHeight()
  397. {
  398. using (UnitTestApplication.Start(TestServices.StyledWindow))
  399. {
  400. var child = new Canvas
  401. {
  402. Width = 400,
  403. Height = 800,
  404. };
  405. var target = new Window()
  406. {
  407. SizeToContent = SizeToContent.WidthAndHeight,
  408. Content = child
  409. };
  410. Show(target);
  411. Assert.Equal(400, target.Width);
  412. Assert.Equal(800, target.Height);
  413. child.Width = 410;
  414. target.LayoutManager.ExecuteLayoutPass();
  415. Assert.Equal(410, target.Width);
  416. Assert.Equal(800, target.Height);
  417. Assert.Equal(SizeToContent.WidthAndHeight, target.SizeToContent);
  418. }
  419. }
  420. [Fact]
  421. public void Setting_Width_Should_Resize_WindowImpl()
  422. {
  423. // Issue #3796
  424. using (UnitTestApplication.Start(TestServices.StyledWindow))
  425. {
  426. var target = new Window()
  427. {
  428. Width = 400,
  429. Height = 800,
  430. };
  431. Show(target);
  432. Assert.Equal(400, target.Width);
  433. Assert.Equal(800, target.Height);
  434. target.Width = 410;
  435. target.LayoutManager.ExecuteLayoutPass();
  436. var windowImpl = Mock.Get(target.PlatformImpl);
  437. windowImpl.Verify(x => x.Resize(new Size(410, 800)));
  438. Assert.Equal(410, target.Width);
  439. }
  440. }
  441. protected virtual void Show(Window window)
  442. {
  443. window.Show();
  444. }
  445. }
  446. public class DialogSizingTests : SizingTests
  447. {
  448. protected override void Show(Window window)
  449. {
  450. var owner = new Window();
  451. window.ShowDialog(owner);
  452. }
  453. }
  454. private IWindowImpl CreateImpl(Mock<IRenderer> renderer)
  455. {
  456. return Mock.Of<IWindowImpl>(x =>
  457. x.Scaling == 1 &&
  458. x.CreateRenderer(It.IsAny<IRenderRoot>()) == renderer.Object);
  459. }
  460. private class ChildControl : Control
  461. {
  462. public List<Size> MeasureSizes { get; } = new List<Size>();
  463. protected override Size MeasureOverride(Size availableSize)
  464. {
  465. MeasureSizes.Add(availableSize);
  466. return base.MeasureOverride(availableSize);
  467. }
  468. }
  469. }
  470. }