AllViewsTests.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. using System.Reflection;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class AllViewsTests (ITestOutputHelper output)
  5. {
  6. // TODO: Update all these tests to use AllViews like AllViews_Center_Properly does
  7. public static TheoryData<View, string> AllViews => TestHelpers.GetAllViewsTheoryData ();
  8. [Theory]
  9. [MemberData (nameof (AllViews))]
  10. public void AllViews_Center_Properly (View view, string viewName)
  11. {
  12. // See https://github.com/gui-cs/Terminal.Gui/issues/3156
  13. if (view == null)
  14. {
  15. output.WriteLine ($"Ignoring {viewName} - It's a Generic");
  16. Application.Shutdown ();
  17. return;
  18. }
  19. view.X = Pos.Center ();
  20. view.Y = Pos.Center ();
  21. // Turn off AutoSize
  22. view.AutoSize = false;
  23. // Ensure the view has positive dimensions
  24. view.Width = 10;
  25. view.Height = 10;
  26. var frame = new View { X = 0, Y = 0, Width = 50, Height = 50 };
  27. frame.Add (view);
  28. frame.BeginInit ();
  29. frame.EndInit ();
  30. frame.LayoutSubviews ();
  31. // What's the natural width/height?
  32. int expectedX = (frame.Frame.Width - view.Frame.Width) / 2;
  33. int expectedY = (frame.Frame.Height - view.Frame.Height) / 2;
  34. Assert.True (
  35. view.Frame.Left == expectedX,
  36. $"{view} did not center horizontally. Expected: {expectedX}. Actual: {view.Frame.Left}"
  37. );
  38. Assert.True (
  39. view.Frame.Top == expectedY,
  40. $"{view} did not center vertically. Expected: {expectedY}. Actual: {view.Frame.Top}"
  41. );
  42. Application.Shutdown ();
  43. }
  44. [Fact]
  45. public void AllViews_Enter_Leave_Events ()
  46. {
  47. foreach (Type type in GetAllViewClasses ())
  48. {
  49. output.WriteLine ($"Testing {type.Name}");
  50. Application.Init (new FakeDriver ());
  51. Toplevel top = new ();
  52. View vType = CreateViewFromType (type, type.GetConstructor (Array.Empty<Type> ()));
  53. if (vType == null)
  54. {
  55. output.WriteLine ($"Ignoring {type} - It's a Generic");
  56. top.Dispose ();
  57. Application.Shutdown ();
  58. continue;
  59. }
  60. vType.AutoSize = false;
  61. vType.X = 0;
  62. vType.Y = 0;
  63. vType.Width = 10;
  64. vType.Height = 1;
  65. var view = new View
  66. {
  67. X = 0,
  68. Y = 1,
  69. Width = 10,
  70. Height = 1,
  71. CanFocus = true
  72. };
  73. var vTypeEnter = 0;
  74. var vTypeLeave = 0;
  75. var viewEnter = 0;
  76. var viewLeave = 0;
  77. vType.Enter += (s, e) => vTypeEnter++;
  78. vType.Leave += (s, e) => vTypeLeave++;
  79. view.Enter += (s, e) => viewEnter++;
  80. view.Leave += (s, e) => viewLeave++;
  81. top.Add (vType, view);
  82. Application.Begin (top);
  83. if (!vType.CanFocus || (vType is Toplevel && ((Toplevel)vType).Modal))
  84. {
  85. top.Dispose ();
  86. Application.Shutdown ();
  87. continue;
  88. }
  89. if (vType is TextView)
  90. {
  91. top.NewKeyDownEvent (Key.Tab.WithCtrl);
  92. }
  93. else if (vType is DatePicker)
  94. {
  95. for (var i = 0; i < 4; i++)
  96. {
  97. top.NewKeyDownEvent (Key.Tab.WithCtrl);
  98. }
  99. }
  100. else
  101. {
  102. top.NewKeyDownEvent (Key.Tab);
  103. }
  104. top.NewKeyDownEvent (Key.Tab);
  105. Assert.Equal (2, vTypeEnter);
  106. Assert.Equal (1, vTypeLeave);
  107. Assert.Equal (1, viewEnter);
  108. Assert.Equal (1, viewLeave);
  109. top.Dispose ();
  110. Application.Shutdown ();
  111. }
  112. }
  113. [Fact]
  114. public void AllViews_Tests_All_Constructors ()
  115. {
  116. Application.Init (new FakeDriver ());
  117. foreach (Type type in GetAllViewClasses ())
  118. {
  119. Assert.True (Test_All_Constructors_Of_Type (type));
  120. }
  121. Application.Shutdown ();
  122. }
  123. public static List<Type> GetAllViewClasses ()
  124. {
  125. return typeof (View).Assembly.GetTypes ()
  126. .Where (
  127. myType => myType.IsClass
  128. && !myType.IsAbstract
  129. && myType.IsPublic
  130. && myType.IsSubclassOf (typeof (View))
  131. )
  132. .ToList ();
  133. }
  134. //[Fact]
  135. //public void AllViews_HotKey_Works ()
  136. //{
  137. // foreach (var type in GetAllViewClasses ()) {
  138. // _output.WriteLine ($"Testing {type.Name}");
  139. // var view = GetTypeInitializer (type, type.GetConstructor (Array.Empty<Type> ()));
  140. // view.HotKeySpecifier = (Rune)'^';
  141. // view.Text = "^text";
  142. // Assert.Equal(Key.T, view.HotKey);
  143. // }
  144. //}
  145. public bool Test_All_Constructors_Of_Type (Type type)
  146. {
  147. foreach (ConstructorInfo ctor in type.GetConstructors ())
  148. {
  149. View view = CreateViewFromType (type, ctor);
  150. if (view != null)
  151. {
  152. Assert.True (type.FullName == view.GetType ().FullName);
  153. }
  154. }
  155. return true;
  156. }
  157. // BUGBUG: This is a hack. We should figure out how to dynamically
  158. // create the right type of argument for the constructor.
  159. private static void AddArguments (Type paramType, List<object> pTypes)
  160. {
  161. if (paramType == typeof (Rectangle))
  162. {
  163. pTypes.Add (Rectangle.Empty);
  164. }
  165. else if (paramType == typeof (string))
  166. {
  167. pTypes.Add (string.Empty);
  168. }
  169. else if (paramType == typeof (int))
  170. {
  171. pTypes.Add (0);
  172. }
  173. else if (paramType == typeof (bool))
  174. {
  175. pTypes.Add (true);
  176. }
  177. else if (paramType.Name == "IList")
  178. {
  179. pTypes.Add (new List<object> ());
  180. }
  181. else if (paramType.Name == "View")
  182. {
  183. var top = new Toplevel ();
  184. var view = new View ();
  185. top.Add (view);
  186. pTypes.Add (view);
  187. }
  188. else if (paramType.Name == "View[]")
  189. {
  190. pTypes.Add (new View [] { });
  191. }
  192. else if (paramType.Name == "Stream")
  193. {
  194. pTypes.Add (new MemoryStream ());
  195. }
  196. else if (paramType.Name == "String")
  197. {
  198. pTypes.Add (string.Empty);
  199. }
  200. else if (paramType.Name == "TreeView`1[T]")
  201. {
  202. pTypes.Add (string.Empty);
  203. }
  204. else
  205. {
  206. pTypes.Add (null);
  207. }
  208. }
  209. private static View CreateViewFromType (Type type, ConstructorInfo ctor)
  210. {
  211. View viewType = null;
  212. if (type.IsGenericType && type.IsTypeDefinition)
  213. {
  214. List<Type> gTypes = new ();
  215. foreach (Type args in type.GetGenericArguments ())
  216. {
  217. gTypes.Add (typeof (object));
  218. }
  219. type = type.MakeGenericType (gTypes.ToArray ());
  220. Assert.IsType (type, (View)Activator.CreateInstance (type));
  221. }
  222. else
  223. {
  224. ParameterInfo [] paramsInfo = ctor.GetParameters ();
  225. Type paramType;
  226. List<object> pTypes = new ();
  227. if (type.IsGenericType)
  228. {
  229. foreach (Type args in type.GetGenericArguments ())
  230. {
  231. paramType = args.GetType ();
  232. if (args.Name == "T")
  233. {
  234. pTypes.Add (typeof (object));
  235. }
  236. else
  237. {
  238. AddArguments (paramType, pTypes);
  239. }
  240. }
  241. }
  242. foreach (ParameterInfo p in paramsInfo)
  243. {
  244. paramType = p.ParameterType;
  245. if (p.HasDefaultValue)
  246. {
  247. pTypes.Add (p.DefaultValue);
  248. }
  249. else
  250. {
  251. AddArguments (paramType, pTypes);
  252. }
  253. }
  254. if (type.IsGenericType && !type.IsTypeDefinition)
  255. {
  256. viewType = (View)Activator.CreateInstance (type);
  257. Assert.IsType (type, viewType);
  258. }
  259. else
  260. {
  261. viewType = (View)ctor.Invoke (pTypes.ToArray ());
  262. Assert.IsType (type, viewType);
  263. }
  264. }
  265. return viewType;
  266. }
  267. }