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