WindowTests.cs 20 KB

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