ControlTests.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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.Generic;
  5. using System.Reactive.Linq;
  6. using Moq;
  7. using Avalonia.Styling;
  8. using Avalonia.UnitTests;
  9. using Xunit;
  10. namespace Avalonia.Controls.UnitTests
  11. {
  12. public class ControlTests
  13. {
  14. [Fact]
  15. public void Classes_Should_Initially_Be_Empty()
  16. {
  17. var target = new Control();
  18. Assert.Equal(0, target.Classes.Count);
  19. }
  20. [Fact]
  21. public void Setting_Parent_Should_Also_Set_InheritanceParent()
  22. {
  23. var parent = new Decorator();
  24. var target = new TestControl();
  25. parent.Child = target;
  26. Assert.Equal(parent, target.Parent);
  27. Assert.Equal(parent, target.InheritanceParent);
  28. }
  29. [Fact]
  30. public void Setting_Parent_Should_Not_Set_InheritanceParent_If_Already_Set()
  31. {
  32. var parent = new Decorator();
  33. var inheritanceParent = new Decorator();
  34. var target = new TestControl();
  35. ((ISetInheritanceParent)target).SetParent(inheritanceParent);
  36. parent.Child = target;
  37. Assert.Equal(parent, target.Parent);
  38. Assert.Equal(inheritanceParent, target.InheritanceParent);
  39. }
  40. [Fact]
  41. public void InheritanceParent_Should_Be_Cleared_When_Removed_From_Parent()
  42. {
  43. var parent = new Decorator();
  44. var target = new TestControl();
  45. parent.Child = target;
  46. parent.Child = null;
  47. Assert.Null(target.InheritanceParent);
  48. }
  49. [Fact]
  50. public void InheritanceParent_Should_Be_Cleared_When_Removed_From_Parent_When_Has_Different_InheritanceParent()
  51. {
  52. var parent = new Decorator();
  53. var inheritanceParent = new Decorator();
  54. var target = new TestControl();
  55. ((ISetInheritanceParent)target).SetParent(inheritanceParent);
  56. parent.Child = target;
  57. parent.Child = null;
  58. Assert.Null(target.InheritanceParent);
  59. }
  60. [Fact]
  61. public void AttachedToLogicalParent_Should_Be_Called_When_Added_To_Tree()
  62. {
  63. var root = new TestRoot();
  64. var parent = new Border();
  65. var child = new Border();
  66. var grandchild = new Border();
  67. var parentRaised = false;
  68. var childRaised = false;
  69. var grandchildRaised = false;
  70. parent.AttachedToLogicalTree += (s, e) => parentRaised = true;
  71. child.AttachedToLogicalTree += (s, e) => childRaised = true;
  72. grandchild.AttachedToLogicalTree += (s, e) => grandchildRaised = true;
  73. parent.Child = child;
  74. child.Child = grandchild;
  75. Assert.False(parentRaised);
  76. Assert.False(childRaised);
  77. Assert.False(grandchildRaised);
  78. root.Child = parent;
  79. Assert.True(parentRaised);
  80. Assert.True(childRaised);
  81. Assert.True(grandchildRaised);
  82. }
  83. [Fact]
  84. public void AttachedToLogicalParent_Should_Be_Called_Before_Parent_Change_Signalled()
  85. {
  86. var root = new TestRoot();
  87. var child = new Border();
  88. var raised = new List<string>();
  89. child.AttachedToLogicalTree += (s, e) =>
  90. {
  91. Assert.Equal(root, child.Parent);
  92. raised.Add("attached");
  93. };
  94. child.GetObservable(Control.ParentProperty).Skip(1).Subscribe(_ => raised.Add("parent"));
  95. root.Child = child;
  96. Assert.Equal(new[] { "attached", "parent" }, raised);
  97. }
  98. [Fact]
  99. public void DetachedToLogicalParent_Should_Be_Called_When_Removed_From_Tree()
  100. {
  101. var root = new TestRoot();
  102. var parent = new Border();
  103. var child = new Border();
  104. var grandchild = new Border();
  105. var parentRaised = false;
  106. var childRaised = false;
  107. var grandchildRaised = false;
  108. parent.Child = child;
  109. child.Child = grandchild;
  110. root.Child = parent;
  111. parent.DetachedFromLogicalTree += (s, e) => parentRaised = true;
  112. child.DetachedFromLogicalTree += (s, e) => childRaised = true;
  113. grandchild.DetachedFromLogicalTree += (s, e) => grandchildRaised = true;
  114. root.Child = null;
  115. Assert.True(parentRaised);
  116. Assert.True(childRaised);
  117. Assert.True(grandchildRaised);
  118. }
  119. [Fact]
  120. public void Adding_Tree_To_IStyleRoot_Should_Style_Controls()
  121. {
  122. using (AvaloniaLocator.EnterScope())
  123. {
  124. var root = new TestRoot();
  125. var parent = new Border();
  126. var child = new Border();
  127. var grandchild = new Control();
  128. var styler = new Mock<IStyler>();
  129. AvaloniaLocator.CurrentMutable.Bind<IStyler>().ToConstant(styler.Object);
  130. parent.Child = child;
  131. child.Child = grandchild;
  132. styler.Verify(x => x.ApplyStyles(It.IsAny<IStyleable>()), Times.Never());
  133. root.Child = parent;
  134. styler.Verify(x => x.ApplyStyles(parent), Times.Once());
  135. styler.Verify(x => x.ApplyStyles(child), Times.Once());
  136. styler.Verify(x => x.ApplyStyles(grandchild), Times.Once());
  137. }
  138. }
  139. [Fact]
  140. public void Styles_Not_Applied_Until_Initialization_Finished()
  141. {
  142. using (AvaloniaLocator.EnterScope())
  143. {
  144. var root = new TestRoot();
  145. var child = new Border();
  146. var styler = new Mock<IStyler>();
  147. AvaloniaLocator.CurrentMutable.Bind<IStyler>().ToConstant(styler.Object);
  148. ((ISupportInitialize)child).BeginInit();
  149. root.Child = child;
  150. styler.Verify(x => x.ApplyStyles(It.IsAny<IStyleable>()), Times.Never());
  151. ((ISupportInitialize)child).EndInit();
  152. styler.Verify(x => x.ApplyStyles(child), Times.Once());
  153. }
  154. }
  155. [Fact]
  156. public void Adding_To_Logical_Tree_Should_Register_With_NameScope()
  157. {
  158. using (AvaloniaLocator.EnterScope())
  159. {
  160. var root = new TestRoot();
  161. var child = new Border();
  162. child.Name = "foo";
  163. root.Child = child;
  164. Assert.Same(root.FindControl<Border>("foo"), child);
  165. }
  166. }
  167. [Fact]
  168. public void Name_Cannot_Be_Set_After_Added_To_Logical_Tree()
  169. {
  170. using (AvaloniaLocator.EnterScope())
  171. {
  172. var root = new TestRoot();
  173. var child = new Border();
  174. root.Child = child;
  175. Assert.Throws<InvalidOperationException>(() => child.Name = "foo");
  176. }
  177. }
  178. [Fact]
  179. public void Name_Can_Be_Set_While_Initializing()
  180. {
  181. using (AvaloniaLocator.EnterScope())
  182. {
  183. var root = new TestRoot();
  184. var child = new Border();
  185. ((ISupportInitialize)child).BeginInit();
  186. root.Child = child;
  187. child.Name = "foo";
  188. Assert.Null(root.FindControl<Border>("foo"));
  189. ((ISupportInitialize)child).EndInit();
  190. Assert.Same(root.FindControl<Border>("foo"), child);
  191. }
  192. }
  193. [Fact]
  194. public void StyleDetach_Is_Triggered_When_Control_Removed_From_Logical_Tree()
  195. {
  196. using (AvaloniaLocator.EnterScope())
  197. {
  198. var root = new TestRoot();
  199. var child = new Border();
  200. root.Child = child;
  201. bool styleDetachTriggered = false;
  202. ((IStyleable)child).StyleDetach.Subscribe(_ => styleDetachTriggered = true);
  203. root.Child = null;
  204. Assert.True(styleDetachTriggered);
  205. }
  206. }
  207. [Fact]
  208. public void EndInit_Should_Raise_Initialized()
  209. {
  210. var root = new TestRoot();
  211. var target = new Border();
  212. var called = false;
  213. target.Initialized += (s, e) => called = true;
  214. ((ISupportInitialize)target).BeginInit();
  215. root.Child = target;
  216. ((ISupportInitialize)target).EndInit();
  217. Assert.True(called);
  218. Assert.True(target.IsInitialized);
  219. }
  220. [Fact]
  221. public void Attaching_To_Visual_Tree_Should_Raise_Initialized()
  222. {
  223. var root = new TestRoot();
  224. var target = new Border();
  225. var called = false;
  226. target.Initialized += (s, e) => called = true;
  227. root.Child = target;
  228. Assert.True(called);
  229. Assert.True(target.IsInitialized);
  230. }
  231. private class TestControl : Control
  232. {
  233. public new IAvaloniaObject InheritanceParent => base.InheritanceParent;
  234. }
  235. }
  236. }