InteractiveTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. // -----------------------------------------------------------------------
  2. // <copyright file="InteractiveTests.cs" company="Steven Kirk">
  3. // Copyright 2014 MIT Licence. See licence.md for more information.
  4. // </copyright>
  5. // -----------------------------------------------------------------------
  6. namespace Perspex.Interactivity.UnitTests
  7. {
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using Perspex.Interactivity;
  12. using Perspex.VisualTree;
  13. using Xunit;
  14. public class InteractiveTests
  15. {
  16. [Fact]
  17. public void Direct_Event_Should_Go_Straight_To_Source()
  18. {
  19. var ev = new RoutedEvent("test", RoutingStrategies.Direct, typeof(RoutedEventArgs), typeof(TestInteractive));
  20. var invoked = new List<string>();
  21. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  22. var target = this.CreateTree(ev, handler, RoutingStrategies.Direct);
  23. var args = new RoutedEventArgs(ev, target);
  24. target.RaiseEvent(args);
  25. Assert.Equal(new[] { "2b" }, invoked);
  26. }
  27. [Fact]
  28. public void Direct_Event_Should_Have_Route_Set_To_Direct()
  29. {
  30. var ev = new RoutedEvent("test", RoutingStrategies.Direct, typeof(RoutedEventArgs), typeof(TestInteractive));
  31. bool called = false;
  32. EventHandler<RoutedEventArgs> handler = (s, e) =>
  33. {
  34. Assert.Equal(RoutingStrategies.Direct, e.Route);
  35. called = true;
  36. };
  37. var target = this.CreateTree(ev, handler, RoutingStrategies.Direct);
  38. var args = new RoutedEventArgs(ev, target);
  39. target.RaiseEvent(args);
  40. Assert.True(called);
  41. }
  42. [Fact]
  43. public void Bubbling_Event_Should_Bubble_Up()
  44. {
  45. var ev = new RoutedEvent("test", RoutingStrategies.Bubble, typeof(RoutedEventArgs), typeof(TestInteractive));
  46. var invoked = new List<string>();
  47. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  48. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
  49. var args = new RoutedEventArgs(ev, target);
  50. target.RaiseEvent(args);
  51. Assert.Equal(new[] { "2b", "1" }, invoked);
  52. }
  53. [Fact]
  54. public void Tunneling_Event_Should_Tunnel()
  55. {
  56. var ev = new RoutedEvent("test", RoutingStrategies.Tunnel, typeof(RoutedEventArgs), typeof(TestInteractive));
  57. var invoked = new List<string>();
  58. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  59. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
  60. var args = new RoutedEventArgs(ev, target);
  61. target.RaiseEvent(args);
  62. Assert.Equal(new[] { "1", "2b" }, invoked);
  63. }
  64. [Fact]
  65. public void Tunneling_Bubbling_Event_Should_Tunnel_Then_Bubble_Up()
  66. {
  67. var ev = new RoutedEvent(
  68. "test",
  69. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  70. typeof(RoutedEventArgs),
  71. typeof(TestInteractive));
  72. var invoked = new List<string>();
  73. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  74. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
  75. var args = new RoutedEventArgs(ev, target);
  76. target.RaiseEvent(args);
  77. Assert.Equal(new[] { "1", "2b", "2b", "1" }, invoked);
  78. }
  79. [Fact]
  80. public void Events_Should_Have_Route_Set()
  81. {
  82. var ev = new RoutedEvent(
  83. "test",
  84. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  85. typeof(RoutedEventArgs),
  86. typeof(TestInteractive));
  87. var invoked = new List<RoutingStrategies>();
  88. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(e.Route);
  89. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
  90. var args = new RoutedEventArgs(ev, target);
  91. target.RaiseEvent(args);
  92. Assert.Equal(new[]
  93. {
  94. RoutingStrategies.Tunnel,
  95. RoutingStrategies.Tunnel,
  96. RoutingStrategies.Bubble,
  97. RoutingStrategies.Bubble,
  98. },
  99. invoked);
  100. }
  101. [Fact]
  102. public void Direct_Subscription_Should_Not_Catch_Tunneling_Or_Bubbling()
  103. {
  104. var ev = new RoutedEvent(
  105. "test",
  106. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  107. typeof(RoutedEventArgs),
  108. typeof(TestInteractive));
  109. var count = 0;
  110. EventHandler<RoutedEventArgs> handler = (s, e) =>
  111. {
  112. ++count;
  113. };
  114. var target = this.CreateTree(ev, handler, RoutingStrategies.Direct);
  115. var args = new RoutedEventArgs(ev, target);
  116. target.RaiseEvent(args);
  117. Assert.Equal(0, count);
  118. }
  119. [Fact]
  120. public void Bubbling_Subscription_Should_Not_Catch_Tunneling()
  121. {
  122. var ev = new RoutedEvent(
  123. "test",
  124. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  125. typeof(RoutedEventArgs),
  126. typeof(TestInteractive));
  127. var count = 0;
  128. EventHandler<RoutedEventArgs> handler = (s, e) =>
  129. {
  130. Assert.Equal(RoutingStrategies.Bubble, e.Route);
  131. ++count;
  132. };
  133. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble);
  134. var args = new RoutedEventArgs(ev, target);
  135. target.RaiseEvent(args);
  136. Assert.Equal(2, count);
  137. }
  138. [Fact]
  139. public void Tunneling_Subscription_Should_Not_Catch_Bubbling()
  140. {
  141. var ev = new RoutedEvent(
  142. "test",
  143. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  144. typeof(RoutedEventArgs),
  145. typeof(TestInteractive));
  146. var count = 0;
  147. EventHandler<RoutedEventArgs> handler = (s, e) =>
  148. {
  149. Assert.Equal(RoutingStrategies.Tunnel, e.Route);
  150. ++count;
  151. };
  152. var target = this.CreateTree(ev, handler, RoutingStrategies.Tunnel);
  153. var args = new RoutedEventArgs(ev, target);
  154. target.RaiseEvent(args);
  155. Assert.Equal(2, count);
  156. }
  157. [Fact]
  158. public void Event_Should_Should_Keep_Propogating_To_HandedEventsToo_Handlers()
  159. {
  160. var ev = new RoutedEvent(
  161. "test",
  162. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  163. typeof(RoutedEventArgs),
  164. typeof(TestInteractive));
  165. var invoked = new List<string>();
  166. EventHandler<RoutedEventArgs> handler = (s, e) =>
  167. {
  168. invoked.Add(((TestInteractive)s).Name);
  169. e.Handled = true;
  170. };
  171. var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel, true);
  172. var args = new RoutedEventArgs(ev, target);
  173. target.RaiseEvent(args);
  174. Assert.Equal(new[] { "1", "2b", "2b", "1" }, invoked);
  175. }
  176. [Fact]
  177. public void Direct_Class_Handlers_Should_Be_Called()
  178. {
  179. var ev = new RoutedEvent(
  180. "test",
  181. RoutingStrategies.Direct,
  182. typeof(RoutedEventArgs),
  183. typeof(TestInteractive));
  184. var invoked = new List<string>();
  185. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  186. var target = this.CreateTree(ev, null, 0);
  187. ev.AddClassHandler(typeof(TestInteractive), handler, RoutingStrategies.Direct);
  188. var args = new RoutedEventArgs(ev, target);
  189. target.RaiseEvent(args);
  190. Assert.Equal(new[] { "2b" }, invoked);
  191. }
  192. [Fact]
  193. public void Tunneling_Class_Handlers_Should_Be_Called()
  194. {
  195. var ev = new RoutedEvent(
  196. "test",
  197. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  198. typeof(RoutedEventArgs),
  199. typeof(TestInteractive));
  200. var invoked = new List<string>();
  201. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  202. var target = this.CreateTree(ev, null, 0);
  203. ev.AddClassHandler(typeof(TestInteractive), handler, RoutingStrategies.Tunnel);
  204. var args = new RoutedEventArgs(ev, target);
  205. target.RaiseEvent(args);
  206. Assert.Equal(new[] { "1", "2b" }, invoked);
  207. }
  208. [Fact]
  209. public void Bubbling_Class_Handlers_Should_Be_Called()
  210. {
  211. var ev = new RoutedEvent(
  212. "test",
  213. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  214. typeof(RoutedEventArgs),
  215. typeof(TestInteractive));
  216. var invoked = new List<string>();
  217. EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Name);
  218. var target = this.CreateTree(ev, null, 0);
  219. ev.AddClassHandler(typeof(TestInteractive), handler, RoutingStrategies.Bubble);
  220. var args = new RoutedEventArgs(ev, target);
  221. target.RaiseEvent(args);
  222. Assert.Equal(new[] { "2b", "1" }, invoked);
  223. }
  224. [Fact]
  225. public void Typed_Class_Handlers_Should_Be_Called()
  226. {
  227. var ev = new RoutedEvent<RoutedEventArgs>(
  228. "test",
  229. RoutingStrategies.Bubble | RoutingStrategies.Tunnel,
  230. typeof(TestInteractive));
  231. var target = this.CreateTree(ev, null, 0);
  232. ev.AddClassHandler<TestInteractive>(x => x.ClassHandler, RoutingStrategies.Bubble);
  233. var args = new RoutedEventArgs(ev, target);
  234. target.RaiseEvent(args);
  235. Assert.True(target.ClassHandlerInvoked);
  236. Assert.True(target.GetVisualParent<TestInteractive>().ClassHandlerInvoked);
  237. }
  238. private TestInteractive CreateTree(
  239. RoutedEvent ev,
  240. EventHandler<RoutedEventArgs> handler,
  241. RoutingStrategies handlerRoutes,
  242. bool handledEventsToo = false)
  243. {
  244. TestInteractive target;
  245. var tree = new TestInteractive
  246. {
  247. Name = "1",
  248. Children = new[]
  249. {
  250. new TestInteractive
  251. {
  252. Name = "2a",
  253. },
  254. (target = new TestInteractive
  255. {
  256. Name = "2b",
  257. Children = new[]
  258. {
  259. new TestInteractive
  260. {
  261. Name = "3",
  262. },
  263. },
  264. }),
  265. }
  266. };
  267. if (handler != null)
  268. {
  269. foreach (var i in tree.GetSelfAndVisualDescendents().Cast<Interactive>())
  270. {
  271. i.AddHandler(ev, handler, handlerRoutes, handledEventsToo);
  272. }
  273. }
  274. return target;
  275. }
  276. private class TestInteractive : Interactive
  277. {
  278. public string Name { get; set; }
  279. public bool ClassHandlerInvoked { get; private set; }
  280. public IEnumerable<IVisual> Children
  281. {
  282. get
  283. {
  284. return ((IVisual)this).VisualChildren.AsEnumerable();
  285. }
  286. set
  287. {
  288. this.AddVisualChildren(value.Cast<Visual>());
  289. }
  290. }
  291. public void ClassHandler(RoutedEventArgs e)
  292. {
  293. this.ClassHandlerInvoked = true;
  294. }
  295. }
  296. }
  297. }