PopupTests.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // Copyright (c) The Avalonia 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;
  4. using System.Collections.Specialized;
  5. using System.Linq;
  6. using Moq;
  7. using Avalonia.Controls.Presenters;
  8. using Avalonia.Controls.Primitives;
  9. using Avalonia.Controls.Templates;
  10. using Avalonia.Layout;
  11. using Avalonia.LogicalTree;
  12. using Avalonia.Platform;
  13. using Avalonia.Styling;
  14. using Avalonia.UnitTests;
  15. using Avalonia.VisualTree;
  16. using Xunit;
  17. namespace Avalonia.Controls.UnitTests.Primitives
  18. {
  19. public class PopupTests
  20. {
  21. [Fact]
  22. public void Setting_Child_Should_Set_Child_Controls_LogicalParent()
  23. {
  24. var target = new Popup();
  25. var child = new Control();
  26. target.Child = child;
  27. Assert.Equal(child.Parent, target);
  28. Assert.Equal(((ILogical)child).LogicalParent, target);
  29. }
  30. [Fact]
  31. public void Clearing_Child_Should_Clear_Child_Controls_Parent()
  32. {
  33. var target = new Popup();
  34. var child = new Control();
  35. target.Child = child;
  36. target.Child = null;
  37. Assert.Null(child.Parent);
  38. Assert.Null(((ILogical)child).LogicalParent);
  39. }
  40. [Fact]
  41. public void Child_Control_Should_Appear_In_LogicalChildren()
  42. {
  43. var target = new Popup();
  44. var child = new Control();
  45. target.Child = child;
  46. Assert.Equal(new[] { child }, target.GetLogicalChildren());
  47. }
  48. [Fact]
  49. public void Clearing_Child_Should_Remove_From_LogicalChildren()
  50. {
  51. var target = new Popup();
  52. var child = new Control();
  53. target.Child = child;
  54. target.Child = null;
  55. Assert.Equal(new ILogical[0], ((ILogical)target).LogicalChildren.ToList());
  56. }
  57. [Fact]
  58. public void Setting_Child_Should_Fire_LogicalChildren_CollectionChanged()
  59. {
  60. var target = new Popup();
  61. var child = new Control();
  62. var called = false;
  63. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  64. called = e.Action == NotifyCollectionChangedAction.Add;
  65. target.Child = child;
  66. Assert.True(called);
  67. }
  68. [Fact]
  69. public void Clearing_Child_Should_Fire_LogicalChildren_CollectionChanged()
  70. {
  71. var target = new Popup();
  72. var child = new Control();
  73. var called = false;
  74. target.Child = child;
  75. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  76. called = e.Action == NotifyCollectionChangedAction.Remove;
  77. target.Child = null;
  78. Assert.True(called);
  79. }
  80. [Fact]
  81. public void Changing_Child_Should_Fire_LogicalChildren_CollectionChanged()
  82. {
  83. var target = new Popup();
  84. var child1 = new Control();
  85. var child2 = new Control();
  86. var called = false;
  87. target.Child = child1;
  88. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true;
  89. target.Child = child2;
  90. Assert.True(called);
  91. }
  92. [Fact]
  93. public void Setting_Child_Should_Not_Set_Childs_VisualParent()
  94. {
  95. var target = new Popup();
  96. var child = new Control();
  97. target.Child = child;
  98. Assert.Null(((IVisual)child).VisualParent);
  99. }
  100. [Fact]
  101. public void PopupRoot_Should_Initially_Be_Null()
  102. {
  103. using (CreateServices())
  104. {
  105. var target = new Popup();
  106. Assert.Null(target.PopupRoot);
  107. }
  108. }
  109. [Fact]
  110. public void PopupRoot_Should_Have_Null_VisualParent()
  111. {
  112. using (CreateServices())
  113. {
  114. var target = new Popup();
  115. target.Open();
  116. Assert.Null(target.PopupRoot.GetVisualParent());
  117. }
  118. }
  119. [Fact]
  120. public void PopupRoot_Should_Have_Popup_As_LogicalParent()
  121. {
  122. using (CreateServices())
  123. {
  124. var target = new Popup();
  125. target.Open();
  126. Assert.Equal(target, target.PopupRoot.Parent);
  127. Assert.Equal(target, target.PopupRoot.GetLogicalParent());
  128. }
  129. }
  130. [Fact]
  131. public void PopupRoot_Should_Be_Detached_From_Logical_Tree_When_Popup_Is_Detached()
  132. {
  133. using (CreateServices())
  134. {
  135. var target = new Popup();
  136. var root = new TestRoot { Child = target };
  137. target.Open();
  138. var popupRoot = (ILogical)target.PopupRoot;
  139. Assert.True(popupRoot.IsAttachedToLogicalTree);
  140. root.Child = null;
  141. Assert.False(((ILogical)target).IsAttachedToLogicalTree);
  142. }
  143. }
  144. [Fact]
  145. public void PopupRoot_Should_Have_Template_Applied()
  146. {
  147. using (CreateServices())
  148. {
  149. var target = new Popup();
  150. var child = new Control();
  151. target.Open();
  152. Assert.Equal(1, target.PopupRoot.GetVisualChildren().Count());
  153. var templatedChild = target.PopupRoot.GetVisualChildren().Single();
  154. Assert.IsType<ContentPresenter>(templatedChild);
  155. Assert.Equal(target.PopupRoot, ((IControl)templatedChild).TemplatedParent);
  156. }
  157. }
  158. [Fact]
  159. public void Templated_Control_With_Popup_In_Template_Should_Set_TemplatedParent()
  160. {
  161. using (CreateServices())
  162. {
  163. PopupContentControl target;
  164. var root = new TestRoot
  165. {
  166. Child = target = new PopupContentControl
  167. {
  168. Content = new Border(),
  169. Template = new FuncControlTemplate<PopupContentControl>(PopupContentControlTemplate),
  170. }
  171. };
  172. target.ApplyTemplate();
  173. var popup = (Popup)target.GetTemplateChildren().First(x => x.Name == "popup");
  174. popup.Open();
  175. var popupRoot = popup.PopupRoot;
  176. var children = popupRoot.GetVisualDescendants().ToList();
  177. var types = children.Select(x => x.GetType().Name).ToList();
  178. Assert.Equal(
  179. new[]
  180. {
  181. "ContentPresenter",
  182. "ContentPresenter",
  183. "Border",
  184. },
  185. types);
  186. var templatedParents = children
  187. .OfType<IControl>()
  188. .Select(x => x.TemplatedParent).ToList();
  189. Assert.Equal(
  190. new object[]
  191. {
  192. popupRoot,
  193. target,
  194. null,
  195. },
  196. templatedParents);
  197. }
  198. }
  199. private static IDisposable CreateServices()
  200. {
  201. var result = AvaloniaLocator.EnterScope();
  202. var styles = new Styles
  203. {
  204. new Style(x => x.OfType<PopupRoot>())
  205. {
  206. Setters = new[]
  207. {
  208. new Setter(TemplatedControl.TemplateProperty, new FuncControlTemplate<PopupRoot>(PopupRootTemplate)),
  209. }
  210. },
  211. };
  212. var globalStyles = new Mock<IGlobalStyles>();
  213. globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
  214. globalStyles.Setup(x => x.Styles).Returns(styles);
  215. var renderInterface = new Mock<IPlatformRenderInterface>();
  216. AvaloniaLocator.CurrentMutable
  217. .Bind<ILayoutManager>().ToTransient<LayoutManager>()
  218. .Bind<IGlobalStyles>().ToFunc(() => globalStyles.Object)
  219. .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
  220. .Bind<IStyler>().ToTransient<Styler>()
  221. .Bind<IPlatformRenderInterface>().ToFunc(() => renderInterface.Object);
  222. return result;
  223. }
  224. private static IControl PopupRootTemplate(PopupRoot control)
  225. {
  226. return new ContentPresenter
  227. {
  228. Name = "PART_ContentPresenter",
  229. [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
  230. };
  231. }
  232. private static IControl PopupContentControlTemplate(PopupContentControl control)
  233. {
  234. return new Popup
  235. {
  236. Name = "popup",
  237. Child = new ContentPresenter
  238. {
  239. [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
  240. }
  241. };
  242. }
  243. private class PopupContentControl : ContentControl
  244. {
  245. }
  246. }
  247. }