ApplicationTests.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. using Xunit.Abstractions;
  2. // Alias Console to MockConsole so we don't accidentally use Console
  3. namespace Terminal.Gui.ApplicationTests;
  4. public class ApplicationTests
  5. {
  6. private readonly ITestOutputHelper _output;
  7. public ApplicationTests (ITestOutputHelper output)
  8. {
  9. _output = output;
  10. ConsoleDriver.RunningUnitTests = true;
  11. #if DEBUG_IDISPOSABLE
  12. Responder.Instances.Clear ();
  13. RunState.Instances.Clear ();
  14. #endif
  15. }
  16. [Fact]
  17. public void Begin_Null_Toplevel_Throws ()
  18. {
  19. // Setup Mock driver
  20. Init ();
  21. // Test null Toplevel
  22. Assert.Throws<ArgumentNullException> (() => Application.Begin (null));
  23. Shutdown ();
  24. Assert.Null (Application.Top);
  25. Assert.Null (Application.MainLoop);
  26. Assert.Null (Application.Driver);
  27. }
  28. [Fact]
  29. [AutoInitShutdown]
  30. public void Begin_Sets_Application_Top_To_Console_Size ()
  31. {
  32. Assert.Equal (new Rectangle (0, 0, 80, 25), Application.Top.Frame);
  33. Application.Begin (Application.Top);
  34. Assert.Equal (new Rectangle (0, 0, 80, 25), Application.Top.Frame);
  35. ((FakeDriver)Application.Driver).SetBufferSize (5, 5);
  36. Assert.Equal (new Rectangle (0, 0, 5, 5), Application.Top.Frame);
  37. }
  38. [Fact]
  39. public void Init_Begin_End_Cleans_Up ()
  40. {
  41. Init ();
  42. // Begin will cause Run() to be called, which will call Begin(). Thus will block the tests
  43. // if we don't stop
  44. Application.Iteration += (s, a) => { Application.RequestStop (); };
  45. RunState runstate = null;
  46. EventHandler<RunStateEventArgs> NewRunStateFn = (s, e) =>
  47. {
  48. Assert.NotNull (e.State);
  49. runstate = e.State;
  50. };
  51. Application.NotifyNewRunState += NewRunStateFn;
  52. var topLevel = new Toplevel ();
  53. RunState rs = Application.Begin (topLevel);
  54. Assert.NotNull (rs);
  55. Assert.NotNull (runstate);
  56. Assert.Equal (rs, runstate);
  57. Assert.Equal (topLevel, Application.Top);
  58. Assert.Equal (topLevel, Application.Current);
  59. Application.NotifyNewRunState -= NewRunStateFn;
  60. Application.End (runstate);
  61. Assert.Null (Application.Current);
  62. Assert.NotNull (Application.Top);
  63. Assert.NotNull (Application.MainLoop);
  64. Assert.NotNull (Application.Driver);
  65. Shutdown ();
  66. Assert.Null (Application.Top);
  67. Assert.Null (Application.MainLoop);
  68. Assert.Null (Application.Driver);
  69. }
  70. [Theory]
  71. [InlineData (typeof (FakeDriver))]
  72. [InlineData (typeof (NetDriver))]
  73. //[InlineData (typeof (ANSIDriver))]
  74. [InlineData (typeof (WindowsDriver))]
  75. [InlineData (typeof (CursesDriver))]
  76. public void Init_DriverName_Should_Pick_Correct_Driver (Type driverType)
  77. {
  78. var driver = (ConsoleDriver)Activator.CreateInstance (driverType);
  79. Application.Init (driverName: driverType.Name);
  80. Assert.NotNull (Application.Driver);
  81. Assert.Equal (driverType, Application.Driver.GetType ());
  82. Shutdown ();
  83. }
  84. [Fact]
  85. public void Init_Null_Driver_Should_Pick_A_Driver ()
  86. {
  87. Application.Init ();
  88. Assert.NotNull (Application.Driver);
  89. Shutdown ();
  90. }
  91. [Fact]
  92. public void Init_ResetState_Resets_Properties ()
  93. {
  94. ConfigurationManager.ThrowOnJsonErrors = true;
  95. // For all the fields/properties of Application, check that they are reset to their default values
  96. // Set some values
  97. Application.Init ();
  98. Application._initialized = true;
  99. // Reset
  100. Application.ResetState ();
  101. void CheckReset ()
  102. {
  103. // Check that all fields and properties are set to their default values
  104. // Public Properties
  105. Assert.Null (Application.Top);
  106. Assert.Null (Application.Current);
  107. Assert.Null (Application.MouseGrabView);
  108. Assert.Null (Application.WantContinuousButtonPressedView);
  109. // Don't check Application.ForceDriver
  110. // Assert.Empty (Application.ForceDriver);
  111. Assert.False (Application.Force16Colors);
  112. Assert.Null (Application.Driver);
  113. Assert.Null (Application.MainLoop);
  114. Assert.False (Application.EndAfterFirstIteration);
  115. Assert.Equal (Key.Empty, Application.AlternateBackwardKey);
  116. Assert.Equal (Key.Empty, Application.AlternateForwardKey);
  117. Assert.Equal (Key.Empty, Application.QuitKey);
  118. Assert.Null (Application.OverlappedChildren);
  119. Assert.Null (Application.OverlappedTop);
  120. // Internal properties
  121. Assert.False (Application._initialized);
  122. Assert.Equal (Application.GetSupportedCultures (), Application.SupportedCultures);
  123. Assert.False (Application._forceFakeConsole);
  124. Assert.Equal (-1, Application._mainThreadId);
  125. Assert.Empty (Application._topLevels);
  126. Assert.Null (Application._mouseEnteredView);
  127. // Events - Can't check
  128. //Assert.Null (Application.NotifyNewRunState);
  129. //Assert.Null (Application.NotifyNewRunState);
  130. //Assert.Null (Application.Iteration);
  131. //Assert.Null (Application.SizeChanging);
  132. //Assert.Null (Application.GrabbedMouse);
  133. //Assert.Null (Application.UnGrabbingMouse);
  134. //Assert.Null (Application.GrabbedMouse);
  135. //Assert.Null (Application.UnGrabbedMouse);
  136. //Assert.Null (Application.MouseEvent);
  137. //Assert.Null (Application.KeyDown);
  138. //Assert.Null (Application.KeyUp);
  139. }
  140. CheckReset ();
  141. // Set the values that can be set
  142. Application._initialized = true;
  143. Application._forceFakeConsole = true;
  144. Application._mainThreadId = 1;
  145. //Application._topLevels = new List<Toplevel> ();
  146. Application._mouseEnteredView = new View ();
  147. //Application.SupportedCultures = new List<CultureInfo> ();
  148. Application.Force16Colors = true;
  149. //Application.ForceDriver = "driver";
  150. Application.EndAfterFirstIteration = true;
  151. Application.AlternateBackwardKey = Key.A;
  152. Application.AlternateForwardKey = Key.B;
  153. Application.QuitKey = Key.C;
  154. //Application.OverlappedChildren = new List<View> ();
  155. //Application.OverlappedTop =
  156. Application._mouseEnteredView = new View ();
  157. //Application.WantContinuousButtonPressedView = new View ();
  158. Application.ResetState ();
  159. CheckReset ();
  160. ConfigurationManager.ThrowOnJsonErrors = false;
  161. }
  162. [Fact]
  163. public void Init_Shutdown_Cleans_Up ()
  164. {
  165. // Verify initial state is per spec
  166. //Pre_Init_State ();
  167. Application.Init (new FakeDriver ());
  168. // Verify post-Init state is correct
  169. //Post_Init_State ();
  170. Application.Shutdown ();
  171. // Verify state is back to initial
  172. //Pre_Init_State ();
  173. #if DEBUG_IDISPOSABLE
  174. // Validate there are no outstanding Responder-based instances
  175. // after a scenario was selected to run. This proves the main UI Catalog
  176. // 'app' closed cleanly.
  177. Assert.Empty (Responder.Instances);
  178. #endif
  179. }
  180. [Fact]
  181. public void Init_Unbalanced_Throws ()
  182. {
  183. Application.Init (new FakeDriver ());
  184. Toplevel topLevel = null;
  185. Assert.Throws<InvalidOperationException> (
  186. () =>
  187. Application.InternalInit (
  188. () => topLevel = new TestToplevel (),
  189. new FakeDriver ()
  190. )
  191. );
  192. Shutdown ();
  193. Assert.Null (Application.Top);
  194. Assert.Null (Application.MainLoop);
  195. Assert.Null (Application.Driver);
  196. // Now try the other way
  197. topLevel = null;
  198. Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver ());
  199. Assert.Throws<InvalidOperationException> (() => Application.Init (new FakeDriver ()));
  200. Shutdown ();
  201. Assert.Null (Application.Top);
  202. Assert.Null (Application.MainLoop);
  203. Assert.Null (Application.Driver);
  204. }
  205. [Fact]
  206. public void InitWithTopLevelFactory_Begin_End_Cleans_Up ()
  207. {
  208. // Begin will cause Run() to be called, which will call Begin(). Thus will block the tests
  209. // if we don't stop
  210. Application.Iteration += (s, a) => { Application.RequestStop (); };
  211. // NOTE: Run<T>, when called after Init has been called behaves differently than
  212. // when called if Init has not been called.
  213. Toplevel topLevel = null;
  214. Application.InternalInit (() => topLevel = new TestToplevel (), new FakeDriver ());
  215. RunState runstate = null;
  216. EventHandler<RunStateEventArgs> NewRunStateFn = (s, e) =>
  217. {
  218. Assert.NotNull (e.State);
  219. runstate = e.State;
  220. };
  221. Application.NotifyNewRunState += NewRunStateFn;
  222. RunState rs = Application.Begin (topLevel);
  223. Assert.NotNull (rs);
  224. Assert.NotNull (runstate);
  225. Assert.Equal (rs, runstate);
  226. Assert.Equal (topLevel, Application.Top);
  227. Assert.Equal (topLevel, Application.Current);
  228. Application.NotifyNewRunState -= NewRunStateFn;
  229. Application.End (runstate);
  230. Assert.Null (Application.Current);
  231. Assert.NotNull (Application.Top);
  232. Assert.NotNull (Application.MainLoop);
  233. Assert.NotNull (Application.Driver);
  234. Shutdown ();
  235. Assert.Null (Application.Top);
  236. Assert.Null (Application.MainLoop);
  237. Assert.Null (Application.Driver);
  238. }
  239. [Fact]
  240. [AutoInitShutdown]
  241. public void Internal_Properties_Correct ()
  242. {
  243. Assert.True (Application._initialized);
  244. Assert.NotNull (Application.Top);
  245. RunState rs = Application.Begin (Application.Top);
  246. Assert.Equal (Application.Top, rs.Toplevel);
  247. Assert.Null (Application.MouseGrabView); // public
  248. Assert.Null (Application.WantContinuousButtonPressedView); // public
  249. Assert.False (Application.MoveToOverlappedChild (Application.Top));
  250. }
  251. // Invoke Tests
  252. // TODO: Test with threading scenarios
  253. [Fact]
  254. public void Invoke_Adds_Idle ()
  255. {
  256. Application.Init (new FakeDriver ());
  257. var top = new Toplevel ();
  258. RunState rs = Application.Begin (top);
  259. var firstIteration = false;
  260. var actionCalled = 0;
  261. Application.Invoke (() => { actionCalled++; });
  262. Application.MainLoop.Running = true;
  263. Application.RunIteration (ref rs, ref firstIteration);
  264. Assert.Equal (1, actionCalled);
  265. Application.Shutdown ();
  266. }
  267. [Fact]
  268. [AutoInitShutdown]
  269. public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Application_Top ()
  270. {
  271. var t1 = new Toplevel ();
  272. var t2 = new Toplevel ();
  273. var t3 = new Toplevel ();
  274. // Don't use Dialog here as it has more layout logic. Use Window instead.
  275. var d = new Dialog ();
  276. var t4 = new Toplevel ();
  277. // t1, t2, t3, d, t4
  278. var iterations = 5;
  279. t1.Ready += (s, e) =>
  280. {
  281. Assert.Equal (t1, Application.Top);
  282. Application.Run (t2);
  283. };
  284. t2.Ready += (s, e) =>
  285. {
  286. Assert.Equal (t2, Application.Top);
  287. Application.Run (t3);
  288. };
  289. t3.Ready += (s, e) =>
  290. {
  291. Assert.Equal (t3, Application.Top);
  292. Application.Run (d);
  293. };
  294. d.Ready += (s, e) =>
  295. {
  296. Assert.Equal (t3, Application.Top);
  297. Application.Run (t4);
  298. };
  299. t4.Ready += (s, e) =>
  300. {
  301. Assert.Equal (t4, Application.Top);
  302. t4.RequestStop ();
  303. d.RequestStop ();
  304. t3.RequestStop ();
  305. t2.RequestStop ();
  306. };
  307. // Now this will close the OverlappedContainer when all OverlappedChildren was closed
  308. t2.Closed += (s, _) => { t1.RequestStop (); };
  309. Application.Iteration += (s, a) =>
  310. {
  311. if (iterations == 5)
  312. {
  313. // The Current still is t4 because Current.Running is false.
  314. Assert.Equal (t4, Application.Current);
  315. Assert.False (Application.Current.Running);
  316. Assert.Equal (t4, Application.Top);
  317. }
  318. else if (iterations == 4)
  319. {
  320. // The Current is d and Current.Running is false.
  321. Assert.Equal (d, Application.Current);
  322. Assert.False (Application.Current.Running);
  323. Assert.Equal (t4, Application.Top);
  324. }
  325. else if (iterations == 3)
  326. {
  327. // The Current is t3 and Current.Running is false.
  328. Assert.Equal (t3, Application.Current);
  329. Assert.False (Application.Current.Running);
  330. Assert.Equal (t3, Application.Top);
  331. }
  332. else if (iterations == 2)
  333. {
  334. // The Current is t2 and Current.Running is false.
  335. Assert.Equal (t2, Application.Current);
  336. Assert.False (Application.Current.Running);
  337. Assert.Equal (t2, Application.Top);
  338. }
  339. else
  340. {
  341. // The Current is t1.
  342. Assert.Equal (t1, Application.Current);
  343. Assert.False (Application.Current.Running);
  344. Assert.Equal (t1, Application.Top);
  345. }
  346. iterations--;
  347. };
  348. Application.Run (t1);
  349. Assert.Equal (t1, Application.Top);
  350. }
  351. private void Init ()
  352. {
  353. Application.Init (new FakeDriver ());
  354. Assert.NotNull (Application.Driver);
  355. Assert.NotNull (Application.MainLoop);
  356. Assert.NotNull (SynchronizationContext.Current);
  357. }
  358. private void Post_Init_State ()
  359. {
  360. Assert.NotNull (Application.Driver);
  361. Assert.NotNull (Application.Top);
  362. Assert.NotNull (Application.Current);
  363. Assert.NotNull (Application.MainLoop);
  364. // FakeDriver is always 80x25
  365. Assert.Equal (80, Application.Driver.Cols);
  366. Assert.Equal (25, Application.Driver.Rows);
  367. }
  368. private void Pre_Init_State ()
  369. {
  370. Assert.Null (Application.Driver);
  371. Assert.Null (Application.Top);
  372. Assert.Null (Application.Current);
  373. Assert.Null (Application.MainLoop);
  374. }
  375. private void Shutdown () { Application.Shutdown (); }
  376. private class TestToplevel : Toplevel
  377. {
  378. public TestToplevel () { IsOverlappedContainer = false; }
  379. }
  380. #region RunTests
  381. [Fact]
  382. public void Run_T_After_InitWithDriver_with_TopLevel_Throws ()
  383. {
  384. // Setup Mock driver
  385. Init ();
  386. // Run<Toplevel> when already initialized with a Driver will throw (because Toplevel is not dervied from TopLevel)
  387. Assert.Throws<ArgumentException> (() => Application.Run<Toplevel> ());
  388. Shutdown ();
  389. Assert.Null (Application.Top);
  390. Assert.Null (Application.MainLoop);
  391. Assert.Null (Application.Driver);
  392. }
  393. [Fact]
  394. public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Throws ()
  395. {
  396. // Setup Mock driver
  397. Init ();
  398. // Run<Toplevel> when already initialized with a Driver will throw (because Toplevel is not dervied from TopLevel)
  399. Assert.Throws<ArgumentException> (() => Application.Run<Toplevel> (null, new FakeDriver ()));
  400. Shutdown ();
  401. Assert.Null (Application.Top);
  402. Assert.Null (Application.MainLoop);
  403. Assert.Null (Application.Driver);
  404. }
  405. [Fact]
  406. public void Run_T_After_InitWithDriver_with_TestTopLevel_DoesNotThrow ()
  407. {
  408. // Setup Mock driver
  409. Init ();
  410. Application.Iteration += (s, a) => { Application.RequestStop (); };
  411. // Init has been called and we're passing no driver to Run<TestTopLevel>. This is ok.
  412. Application.Run<TestToplevel> ();
  413. Shutdown ();
  414. Assert.Null (Application.Top);
  415. Assert.Null (Application.MainLoop);
  416. Assert.Null (Application.Driver);
  417. }
  418. [Fact]
  419. public void Run_T_After_InitNullDriver_with_TestTopLevel_Throws ()
  420. {
  421. Application.ForceDriver = "FakeDriver";
  422. Application.Init ();
  423. Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
  424. Application.Iteration += (s, a) => { Application.RequestStop (); };
  425. // Init has been called without selecting a driver and we're passing no driver to Run<TestTopLevel>. Bad
  426. Application.Run<TestToplevel> ();
  427. Shutdown ();
  428. Assert.Null (Application.Top);
  429. Assert.Null (Application.MainLoop);
  430. Assert.Null (Application.Driver);
  431. }
  432. [Fact]
  433. public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws ()
  434. {
  435. Init ();
  436. Application.Driver = null;
  437. Application.Iteration += (s, a) => { Application.RequestStop (); };
  438. // Init has been called, but Driver has been set to null. Bad.
  439. Assert.Throws<InvalidOperationException> (() => Application.Run<TestToplevel> ());
  440. Shutdown ();
  441. Assert.Null (Application.Top);
  442. Assert.Null (Application.MainLoop);
  443. Assert.Null (Application.Driver);
  444. }
  445. [Fact]
  446. public void Run_T_NoInit_DoesNotThrow ()
  447. {
  448. Application.ForceDriver = "FakeDriver";
  449. Application.Iteration += (s, a) => { Application.RequestStop (); };
  450. Application.Run<TestToplevel> ();
  451. Assert.Equal (typeof (FakeDriver), Application.Driver.GetType ());
  452. Shutdown ();
  453. Assert.Null (Application.Top);
  454. Assert.Null (Application.MainLoop);
  455. Assert.Null (Application.Driver);
  456. }
  457. [Fact]
  458. public void Run_T_NoInit_WithDriver_DoesNotThrow ()
  459. {
  460. Application.Iteration += (s, a) => { Application.RequestStop (); };
  461. // Init has NOT been called and we're passing a valid driver to Run<TestTopLevel>. This is ok.
  462. Application.Run<TestToplevel> (null, new FakeDriver ());
  463. Shutdown ();
  464. Assert.Null (Application.Top);
  465. Assert.Null (Application.MainLoop);
  466. Assert.Null (Application.Driver);
  467. }
  468. [Fact]
  469. public void Run_RequestStop_Stops ()
  470. {
  471. // Setup Mock driver
  472. Init ();
  473. var top = new Toplevel ();
  474. RunState rs = Application.Begin (top);
  475. Assert.NotNull (rs);
  476. Assert.Equal (top, Application.Current);
  477. Application.Iteration += (s, a) => { Application.RequestStop (); };
  478. Application.Run (top);
  479. Application.Shutdown ();
  480. Assert.Null (Application.Current);
  481. Assert.Null (Application.Top);
  482. Assert.Null (Application.MainLoop);
  483. Assert.Null (Application.Driver);
  484. }
  485. [Fact]
  486. public void Run_RunningFalse_Stops ()
  487. {
  488. // Setup Mock driver
  489. Init ();
  490. var top = new Toplevel ();
  491. RunState rs = Application.Begin (top);
  492. Assert.NotNull (rs);
  493. Assert.Equal (top, Application.Current);
  494. Application.Iteration += (s, a) => { top.Running = false; };
  495. Application.Run (top);
  496. Application.Shutdown ();
  497. Assert.Null (Application.Current);
  498. Assert.Null (Application.Top);
  499. Assert.Null (Application.MainLoop);
  500. Assert.Null (Application.Driver);
  501. }
  502. [Fact]
  503. public void Run_Loaded_Ready_Unlodaded_Events ()
  504. {
  505. Init ();
  506. Toplevel top = Application.Top;
  507. var count = 0;
  508. top.Loaded += (s, e) => count++;
  509. top.Ready += (s, e) => count++;
  510. top.Unloaded += (s, e) => count++;
  511. Application.Iteration += (s, a) => Application.RequestStop ();
  512. Application.Run ();
  513. Application.Shutdown ();
  514. Assert.Equal (3, count);
  515. }
  516. // TODO: All Toplevel layout tests should be moved to ToplevelTests.cs
  517. [Fact]
  518. public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty ()
  519. {
  520. Init ();
  521. var count = 0;
  522. // Don't use Dialog here as it has more layout logic. Use Window instead.
  523. Dialog d = null;
  524. Toplevel top = Application.Top;
  525. top.DrawContent += (s, a) => count++;
  526. int iteration = -1;
  527. Application.Iteration += (s, a) =>
  528. {
  529. iteration++;
  530. if (iteration == 0)
  531. {
  532. // TODO: Don't use Dialog here as it has more layout logic. Use Window instead.
  533. d = new Dialog ();
  534. d.DrawContent += (s, a) => count++;
  535. Application.Run (d);
  536. }
  537. else if (iteration < 3)
  538. {
  539. Application.OnMouseEvent (
  540. new MouseEventEventArgs (
  541. new MouseEvent
  542. { X = 0, Y = 0, Flags = MouseFlags.ReportMousePosition }
  543. )
  544. );
  545. Assert.False (top.NeedsDisplay);
  546. Assert.False (top.SubViewNeedsDisplay);
  547. Assert.False (top.LayoutNeeded);
  548. Assert.False (d.NeedsDisplay);
  549. Assert.False (d.SubViewNeedsDisplay);
  550. Assert.False (d.LayoutNeeded);
  551. }
  552. else
  553. {
  554. Application.RequestStop ();
  555. }
  556. };
  557. Application.Run ();
  558. Application.Shutdown ();
  559. // 1 - First top load, 1 - Dialog load, 1 - Dialog unload, Total - 3.
  560. Assert.Equal (3, count);
  561. }
  562. // TODO: All Toplevel layout tests should be moved to ToplevelTests.cs
  563. [Fact]
  564. public void Run_A_Modal_Toplevel_Refresh_Background_On_Moving ()
  565. {
  566. Init ();
  567. // Don't use Dialog here as it has more layout logic. Use Window instead.
  568. var w = new Window { Width = 5, Height = 5 };
  569. ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
  570. RunState rs = Application.Begin (w);
  571. TestHelpers.AssertDriverContentsWithFrameAre (
  572. @"
  573. ┌───┐
  574. │ │
  575. │ │
  576. │ │
  577. └───┘",
  578. _output
  579. );
  580. Attribute [] attributes =
  581. {
  582. // 0
  583. new (ColorName.White, ColorName.Black),
  584. // 1
  585. Colors.ColorSchemes ["Base"].Normal
  586. };
  587. TestHelpers.AssertDriverAttributesAre (
  588. @"
  589. 1111100000
  590. 1111100000
  591. 1111100000
  592. 1111100000
  593. 1111100000
  594. ",
  595. null,
  596. attributes
  597. );
  598. // TODO: In PR #2920 this breaks because the mouse is not grabbed anymore.
  599. // TODO: Move the mouse grap/drag mode from Toplevel to Border.
  600. Application.OnMouseEvent (
  601. new MouseEventEventArgs (
  602. new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }
  603. )
  604. );
  605. Assert.Equal (w.Border, Application.MouseGrabView);
  606. // Move down and to the right.
  607. Application.OnMouseEvent (
  608. new MouseEventEventArgs (
  609. new MouseEvent
  610. {
  611. X = 1,
  612. Y = 1,
  613. Flags = MouseFlags.Button1Pressed
  614. | MouseFlags.ReportMousePosition
  615. }
  616. )
  617. );
  618. Application.Refresh ();
  619. TestHelpers.AssertDriverContentsWithFrameAre (
  620. @"
  621. ┌───┐
  622. │ │
  623. │ │
  624. │ │
  625. └───┘",
  626. _output
  627. );
  628. attributes = new []
  629. {
  630. // 0
  631. new (ColorName.White, ColorName.Black),
  632. // 1
  633. Colors.ColorSchemes ["Base"].Normal
  634. };
  635. TestHelpers.AssertDriverAttributesAre (
  636. @"
  637. 0000000000
  638. 0111110000
  639. 0111110000
  640. 0111110000
  641. 0111110000
  642. 0111110000
  643. ",
  644. null,
  645. attributes
  646. );
  647. Application.End (rs);
  648. Application.Shutdown ();
  649. }
  650. // TODO: Add tests for Run that test errorHandler
  651. #endregion
  652. #region ShutdownTests
  653. [Fact]
  654. public async void Shutdown_Allows_Async ()
  655. {
  656. var isCompletedSuccessfully = false;
  657. async Task TaskWithAsyncContinuation ()
  658. {
  659. await Task.Yield ();
  660. await Task.Yield ();
  661. isCompletedSuccessfully = true;
  662. }
  663. Init ();
  664. Application.Shutdown ();
  665. Assert.False (isCompletedSuccessfully);
  666. await TaskWithAsyncContinuation ();
  667. Thread.Sleep (100);
  668. Assert.True (isCompletedSuccessfully);
  669. }
  670. [Fact]
  671. public void Shutdown_Resets_SyncContext ()
  672. {
  673. Init ();
  674. Application.Shutdown ();
  675. Assert.Null (SynchronizationContext.Current);
  676. }
  677. #endregion
  678. }