DefaultMenuInteractionHandlerTests.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. using System;
  2. using Avalonia.Controls.Platform;
  3. using Avalonia.Input;
  4. using Avalonia.Interactivity;
  5. using Avalonia.VisualTree;
  6. using Moq;
  7. using Xunit;
  8. namespace Avalonia.Controls.UnitTests.Platform
  9. {
  10. public class DefaultMenuInteractionHandlerTests
  11. {
  12. static PointerEventArgs CreateArgs(RoutedEvent ev, IInteractive source)
  13. => new PointerEventArgs(ev, source, new FakePointer(), (IVisual)source, default, new PointerPointProperties(), default);
  14. static PointerPressedEventArgs CreatePressed(IInteractive source) => new PointerPressedEventArgs(source,
  15. new FakePointer(), (IVisual)source, default, new PointerPointProperties {IsLeftButtonPressed = true},
  16. default);
  17. static PointerReleasedEventArgs CreateReleased(IInteractive source) => new PointerReleasedEventArgs(source,
  18. new FakePointer(), (IVisual)source, default, new PointerPointProperties(), default, MouseButton.Left);
  19. public class TopLevel
  20. {
  21. [Fact]
  22. public void Up_Opens_MenuItem_With_SubMenu()
  23. {
  24. var target = new DefaultMenuInteractionHandler(false);
  25. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  26. var e = new KeyEventArgs { Key = Key.Up, Source = item };
  27. target.KeyDown(item, e);
  28. Mock.Get(item).Verify(x => x.Open());
  29. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  30. Assert.True(e.Handled);
  31. }
  32. [Fact]
  33. public void Down_Opens_MenuItem_With_SubMenu()
  34. {
  35. var target = new DefaultMenuInteractionHandler(false);
  36. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  37. var e = new KeyEventArgs { Key = Key.Down, Source = item };
  38. target.KeyDown(item, e);
  39. Mock.Get(item).Verify(x => x.Open());
  40. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  41. Assert.True(e.Handled);
  42. }
  43. [Fact]
  44. public void Right_Selects_Next_MenuItem()
  45. {
  46. var target = new DefaultMenuInteractionHandler(false);
  47. var menu = Mock.Of<IMenu>(x => x.MoveSelection(NavigationDirection.Right, true) == true);
  48. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu);
  49. var e = new KeyEventArgs { Key = Key.Right, Source = item };
  50. target.KeyDown(item, e);
  51. Mock.Get(menu).Verify(x => x.MoveSelection(NavigationDirection.Right, true));
  52. Assert.True(e.Handled);
  53. }
  54. [Fact]
  55. public void Left_Selects_Previous_MenuItem()
  56. {
  57. var target = new DefaultMenuInteractionHandler(false);
  58. var menu = Mock.Of<IMenu>(x => x.MoveSelection(NavigationDirection.Left, true) == true);
  59. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu);
  60. var e = new KeyEventArgs { Key = Key.Left, Source = item };
  61. target.KeyDown(item, e);
  62. Mock.Get(menu).Verify(x => x.MoveSelection(NavigationDirection.Left, true));
  63. Assert.True(e.Handled);
  64. }
  65. [Fact]
  66. public void Enter_On_Item_With_No_SubMenu_Causes_Click()
  67. {
  68. var target = new DefaultMenuInteractionHandler(false);
  69. var menu = Mock.Of<IMenu>();
  70. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu);
  71. var e = new KeyEventArgs { Key = Key.Enter, Source = item };
  72. target.KeyDown(item, e);
  73. Mock.Get(item).Verify(x => x.RaiseClick());
  74. Mock.Get(menu).Verify(x => x.Close());
  75. Assert.True(e.Handled);
  76. }
  77. [Fact]
  78. public void Enter_On_Item_With_SubMenu_Opens_SubMenu()
  79. {
  80. var target = new DefaultMenuInteractionHandler(false);
  81. var menu = Mock.Of<IMenu>();
  82. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  83. var e = new KeyEventArgs { Key = Key.Enter, Source = item };
  84. target.KeyDown(item, e);
  85. Mock.Get(item).Verify(x => x.Open());
  86. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  87. Assert.True(e.Handled);
  88. }
  89. [Fact]
  90. public void Escape_Closes_Parent_Menu()
  91. {
  92. var target = new DefaultMenuInteractionHandler(false);
  93. var menu = Mock.Of<IMenu>();
  94. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu);
  95. var e = new KeyEventArgs { Key = Key.Escape, Source = item };
  96. target.KeyDown(item, e);
  97. Mock.Get(menu).Verify(x => x.Close());
  98. Assert.True(e.Handled);
  99. }
  100. [Fact]
  101. public void Click_On_Open_TopLevel_Menu_Closes_Menu()
  102. {
  103. var target = new DefaultMenuInteractionHandler(false);
  104. var menu = Mock.Of<IMenu>();
  105. var item = Mock.Of<IMenuItem>(x =>
  106. x.IsSubMenuOpen == true &&
  107. x.IsTopLevel == true &&
  108. x.HasSubMenu == true &&
  109. x.Parent == menu);
  110. var e = CreatePressed(item);
  111. target.PointerPressed(item, e);
  112. Mock.Get(menu).Verify(x => x.Close());
  113. }
  114. [Fact]
  115. public void PointerEnter_Opens_Item_When_Old_Item_Is_Open()
  116. {
  117. var target = new DefaultMenuInteractionHandler(false);
  118. var menu = new Mock<IMenu>();
  119. var item = Mock.Of<IMenuItem>(x =>
  120. x.IsSubMenuOpen == true &&
  121. x.IsTopLevel == true &&
  122. x.HasSubMenu == true &&
  123. x.Parent == menu.Object);
  124. var nextItem = Mock.Of<IMenuItem>(x =>
  125. x.IsTopLevel == true &&
  126. x.HasSubMenu == true &&
  127. x.Parent == menu.Object);
  128. var e = CreateArgs(MenuItem.PointerEnterItemEvent, nextItem);
  129. menu.SetupGet(x => x.SelectedItem).Returns(item);
  130. target.PointerEnter(nextItem, e);
  131. Mock.Get(item).Verify(x => x.Close());
  132. menu.VerifySet(x => x.SelectedItem = nextItem);
  133. Mock.Get(nextItem).Verify(x => x.Open());
  134. Mock.Get(nextItem).Verify(x => x.MoveSelection(NavigationDirection.First, true), Times.Never);
  135. Assert.False(e.Handled);
  136. }
  137. [Fact]
  138. public void PointerLeave_Deselects_Item_When_Menu_Not_Open()
  139. {
  140. var target = new DefaultMenuInteractionHandler(false);
  141. var menu = new Mock<IMenu>();
  142. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu.Object);
  143. var e = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  144. menu.SetupGet(x => x.SelectedItem).Returns(item);
  145. target.PointerLeave(item, e);
  146. menu.VerifySet(x => x.SelectedItem = null);
  147. Assert.False(e.Handled);
  148. }
  149. [Fact]
  150. public void PointerLeave_Doesnt_Deselect_Item_When_Menu_Open()
  151. {
  152. var target = new DefaultMenuInteractionHandler(false);
  153. var menu = new Mock<IMenu>();
  154. var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.Parent == menu.Object);
  155. var e = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  156. menu.SetupGet(x => x.IsOpen).Returns(true);
  157. menu.SetupGet(x => x.SelectedItem).Returns(item);
  158. target.PointerLeave(item, e);
  159. menu.VerifySet(x => x.SelectedItem = null, Times.Never);
  160. Assert.False(e.Handled);
  161. }
  162. }
  163. public class NonTopLevel
  164. {
  165. [Fact]
  166. public void Up_Selects_Previous_MenuItem()
  167. {
  168. var target = new DefaultMenuInteractionHandler(false);
  169. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  170. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  171. var e = new KeyEventArgs { Key = Key.Up, Source = item };
  172. target.KeyDown(item, e);
  173. Mock.Get(parentItem).Verify(x => x.MoveSelection(NavigationDirection.Up, true));
  174. Assert.True(e.Handled);
  175. }
  176. [Fact]
  177. public void Down_Selects_Next_MenuItem()
  178. {
  179. var target = new DefaultMenuInteractionHandler(false);
  180. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  181. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  182. var e = new KeyEventArgs { Key = Key.Down, Source = item };
  183. target.KeyDown(item, e);
  184. Mock.Get(parentItem).Verify(x => x.MoveSelection(NavigationDirection.Down, true));
  185. Assert.True(e.Handled);
  186. }
  187. [Fact]
  188. public void Left_Closes_Parent_SubMenu()
  189. {
  190. var target = new DefaultMenuInteractionHandler(false);
  191. var parentItem = Mock.Of<IMenuItem>(x => x.HasSubMenu == true && x.IsSubMenuOpen == true);
  192. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  193. var e = new KeyEventArgs { Key = Key.Left, Source = item };
  194. target.KeyDown(item, e);
  195. Mock.Get(parentItem).Verify(x => x.Close());
  196. Mock.Get(parentItem).Verify(x => x.Focus());
  197. Assert.True(e.Handled);
  198. }
  199. [Fact]
  200. public void Right_With_SubMenu_Items_Opens_SubMenu()
  201. {
  202. var target = new DefaultMenuInteractionHandler(false);
  203. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  204. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true);
  205. var e = new KeyEventArgs { Key = Key.Right, Source = item };
  206. target.KeyDown(item, e);
  207. Mock.Get(item).Verify(x => x.Open());
  208. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  209. Assert.True(e.Handled);
  210. }
  211. [Fact]
  212. public void Right_On_TopLevel_Child_Navigates_TopLevel_Selection()
  213. {
  214. var target = new DefaultMenuInteractionHandler(false);
  215. var menu = new Mock<IMenu>();
  216. var parentItem = Mock.Of<IMenuItem>(x =>
  217. x.IsSubMenuOpen == true &&
  218. x.IsTopLevel == true &&
  219. x.HasSubMenu == true &&
  220. x.Parent == menu.Object);
  221. var nextItem = Mock.Of<IMenuItem>(x =>
  222. x.IsTopLevel == true &&
  223. x.HasSubMenu == true &&
  224. x.Parent == menu.Object);
  225. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  226. var e = new KeyEventArgs { Key = Key.Right, Source = item };
  227. menu.Setup(x => x.MoveSelection(NavigationDirection.Right, true))
  228. .Callback(() => menu.SetupGet(x => x.SelectedItem).Returns(nextItem))
  229. .Returns(true);
  230. target.KeyDown(item, e);
  231. menu.Verify(x => x.MoveSelection(NavigationDirection.Right, true));
  232. Mock.Get(parentItem).Verify(x => x.Close());
  233. Mock.Get(nextItem).Verify(x => x.Open());
  234. Mock.Get(nextItem).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  235. Assert.True(e.Handled);
  236. }
  237. [Fact]
  238. public void Enter_On_Item_With_No_SubMenu_Causes_Click()
  239. {
  240. var target = new DefaultMenuInteractionHandler(false);
  241. var menu = Mock.Of<IMenu>();
  242. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  243. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  244. var e = new KeyEventArgs { Key = Key.Enter, Source = item };
  245. target.KeyDown(item, e);
  246. Mock.Get(item).Verify(x => x.RaiseClick());
  247. Mock.Get(menu).Verify(x => x.Close());
  248. Assert.True(e.Handled);
  249. }
  250. [Fact]
  251. public void Enter_On_Item_With_SubMenu_Opens_SubMenu()
  252. {
  253. var target = new DefaultMenuInteractionHandler(false);
  254. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  255. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true);
  256. var e = new KeyEventArgs { Key = Key.Enter, Source = item };
  257. target.KeyDown(item, e);
  258. Mock.Get(item).Verify(x => x.Open());
  259. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
  260. Assert.True(e.Handled);
  261. }
  262. [Fact]
  263. public void Escape_Closes_Parent_MenuItem()
  264. {
  265. var target = new DefaultMenuInteractionHandler(false);
  266. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true);
  267. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  268. var e = new KeyEventArgs { Key = Key.Escape, Source = item };
  269. target.KeyDown(item, e);
  270. Mock.Get(parentItem).Verify(x => x.Close());
  271. Mock.Get(parentItem).Verify(x => x.Focus());
  272. Assert.True(e.Handled);
  273. }
  274. [Fact]
  275. public void PointerEnter_Selects_Item()
  276. {
  277. var target = new DefaultMenuInteractionHandler(false);
  278. var menu = Mock.Of<IMenu>();
  279. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  280. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  281. var e = CreateArgs(MenuItem.PointerEnterItemEvent, item);
  282. target.PointerEnter(item, e);
  283. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = item);
  284. Assert.False(e.Handled);
  285. }
  286. [Fact]
  287. public void PointerEnter_Opens_Submenu_After_Delay()
  288. {
  289. var timer = new TestTimer();
  290. var target = new DefaultMenuInteractionHandler(false, null, timer.RunOnce);
  291. var menu = Mock.Of<IMenu>();
  292. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  293. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true);
  294. var e = CreateArgs(MenuItem.PointerEnterItemEvent, item);
  295. target.PointerEnter(item, e);
  296. Mock.Get(item).Verify(x => x.Open(), Times.Never);
  297. timer.Pulse();
  298. Mock.Get(item).Verify(x => x.Open());
  299. Assert.False(e.Handled);
  300. }
  301. [Fact]
  302. public void PointerEnter_Closes_Sibling_Submenu_After_Delay()
  303. {
  304. var timer = new TestTimer();
  305. var target = new DefaultMenuInteractionHandler(false, null, timer.RunOnce);
  306. var menu = Mock.Of<IMenu>();
  307. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  308. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  309. var sibling = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true && x.IsSubMenuOpen == true);
  310. var e = CreateArgs(MenuItem.PointerEnterItemEvent, item);
  311. Mock.Get(parentItem).SetupGet(x => x.SubItems).Returns(new[] { item, sibling });
  312. target.PointerEnter(item, e);
  313. Mock.Get(sibling).Verify(x => x.Close(), Times.Never);
  314. timer.Pulse();
  315. Mock.Get(sibling).Verify(x => x.Close());
  316. Assert.False(e.Handled);
  317. }
  318. [Fact]
  319. public void PointerLeave_Deselects_Item()
  320. {
  321. var target = new DefaultMenuInteractionHandler(false);
  322. var menu = Mock.Of<IMenu>();
  323. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  324. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  325. var e = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  326. Mock.Get(parentItem).SetupGet(x => x.SelectedItem).Returns(item);
  327. target.PointerLeave(item, e);
  328. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = null);
  329. Assert.False(e.Handled);
  330. }
  331. [Fact]
  332. public void PointerLeave_Doesnt_Deselect_Sibling()
  333. {
  334. var target = new DefaultMenuInteractionHandler(false);
  335. var menu = Mock.Of<IMenu>();
  336. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  337. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  338. var sibling = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  339. var e = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  340. Mock.Get(parentItem).SetupGet(x => x.SelectedItem).Returns(sibling);
  341. target.PointerLeave(item, e);
  342. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = null, Times.Never);
  343. Assert.False(e.Handled);
  344. }
  345. [Fact]
  346. public void PointerLeave_Doesnt_Deselect_Item_If_Pointer_Over_Submenu()
  347. {
  348. var target = new DefaultMenuInteractionHandler(false);
  349. var menu = Mock.Of<IMenu>();
  350. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  351. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true && x.IsPointerOverSubMenu == true);
  352. var e = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  353. target.PointerLeave(item, e);
  354. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = null, Times.Never);
  355. Assert.False(e.Handled);
  356. }
  357. [Fact]
  358. public void PointerReleased_On_Item_With_No_SubMenu_Causes_Click()
  359. {
  360. var target = new DefaultMenuInteractionHandler(false);
  361. var menu = Mock.Of<IMenu>();
  362. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  363. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem);
  364. var e = CreateReleased(item);
  365. target.PointerReleased(item, e);
  366. Mock.Get(item).Verify(x => x.RaiseClick());
  367. Mock.Get(menu).Verify(x => x.Close());
  368. Assert.True(e.Handled);
  369. }
  370. [Fact]
  371. public void Selection_Is_Correct_When_Pointer_Temporarily_Exits_Item_To_Select_SubItem()
  372. {
  373. var timer = new TestTimer();
  374. var target = new DefaultMenuInteractionHandler(false, null, timer.RunOnce);
  375. var menu = Mock.Of<IMenu>();
  376. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  377. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true);
  378. var childItem = Mock.Of<IMenuItem>(x => x.Parent == item);
  379. var enter = CreateArgs(MenuItem.PointerEnterItemEvent, item);
  380. var leave = CreateArgs(MenuItem.PointerLeaveItemEvent, item);
  381. // Pointer enters item; item is selected.
  382. target.PointerEnter(item, enter);
  383. Assert.True(timer.ActionIsQueued);
  384. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = item);
  385. Mock.Get(parentItem).ResetCalls();
  386. // SubMenu shown after a delay.
  387. timer.Pulse();
  388. Mock.Get(item).Verify(x => x.Open());
  389. Mock.Get(item).SetupGet(x => x.IsSubMenuOpen).Returns(true);
  390. Mock.Get(item).ResetCalls();
  391. // Pointer briefly exits item, but submenu remains open.
  392. target.PointerLeave(item, leave);
  393. Mock.Get(item).Verify(x => x.Close(), Times.Never);
  394. Mock.Get(item).ResetCalls();
  395. // Pointer enters child item; is selected.
  396. enter.Source = childItem;
  397. target.PointerEnter(childItem, enter);
  398. Mock.Get(item).VerifySet(x => x.SelectedItem = childItem);
  399. Mock.Get(parentItem).VerifySet(x => x.SelectedItem = item);
  400. Mock.Get(item).ResetCalls();
  401. Mock.Get(parentItem).ResetCalls();
  402. }
  403. [Fact]
  404. public void PointerPressed_On_Item_With_SubMenu_Causes_Opens_Submenu()
  405. {
  406. var target = new DefaultMenuInteractionHandler(false);
  407. var menu = Mock.Of<IMenu>();
  408. var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.Parent == menu);
  409. var item = Mock.Of<IMenuItem>(x => x.Parent == parentItem && x.HasSubMenu == true);
  410. var e = CreatePressed(item);
  411. target.PointerPressed(item, e);
  412. Mock.Get(item).Verify(x => x.Open());
  413. Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true), Times.Never);
  414. Assert.True(e.Handled);
  415. }
  416. }
  417. public class ContextMenu
  418. {
  419. [Fact]
  420. public void Down_Selects_Selects_First_MenuItem_When_No_Selection()
  421. {
  422. var target = new DefaultMenuInteractionHandler(true);
  423. var contextMenu = Mock.Of<IMenu>(x => x.MoveSelection(NavigationDirection.Down, true) == true);
  424. var e = new KeyEventArgs { Key = Key.Down, Source = contextMenu };
  425. target.Attach(contextMenu);
  426. target.KeyDown(contextMenu, e);
  427. Mock.Get(contextMenu).Verify(x => x.MoveSelection(NavigationDirection.Down, true));
  428. Assert.True(e.Handled);
  429. }
  430. }
  431. private class TestTimer
  432. {
  433. private Action _action;
  434. public bool ActionIsQueued => _action != null;
  435. public void Pulse()
  436. {
  437. _action();
  438. _action = null;
  439. }
  440. public void RunOnce(Action action, TimeSpan timeSpan)
  441. {
  442. if (_action != null)
  443. {
  444. throw new NotSupportedException("Action already set.");
  445. }
  446. _action = action;
  447. }
  448. }
  449. class FakePointer : IPointer
  450. {
  451. public int Id { get; } = Pointer.GetNextFreeId();
  452. public void Capture(IInputElement control)
  453. {
  454. Captured = control;
  455. }
  456. public IInputElement Captured { get; set; }
  457. public PointerType Type { get; }
  458. public bool IsPrimary { get; } = true;
  459. }
  460. }
  461. }