MessageBoxTests.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. using System.Text;
  2. using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.DialogTests;
  5. public class MessageBoxTests
  6. {
  7. private readonly ITestOutputHelper _output;
  8. public MessageBoxTests (ITestOutputHelper output) { _output = output; }
  9. [Fact]
  10. [AutoInitShutdown]
  11. public void KeyBindings_Enter_Causes_Focused_Button_Click ()
  12. {
  13. int result = -1;
  14. var iteration = 0;
  15. Application.Iteration += (s, a) =>
  16. {
  17. iteration++;
  18. switch (iteration)
  19. {
  20. case 1:
  21. result = MessageBox.Query (string.Empty, string.Empty, 0, false, "btn0", "btn1");
  22. Application.RequestStop ();
  23. break;
  24. case 2:
  25. // Tab to btn2
  26. Application.OnKeyDown (Key.Tab);
  27. Application.OnKeyDown (Key.Enter);
  28. break;
  29. default:
  30. Assert.Fail ();
  31. break;
  32. }
  33. };
  34. Application.Run ().Dispose ();
  35. Assert.Equal (1, result);
  36. }
  37. [Fact]
  38. [AutoInitShutdown]
  39. public void KeyBindings_Esc_Closes ()
  40. {
  41. var result = 999;
  42. var iteration = 0;
  43. Application.Iteration += (s, a) =>
  44. {
  45. iteration++;
  46. switch (iteration)
  47. {
  48. case 1:
  49. result = MessageBox.Query (string.Empty, string.Empty, 0, false, "btn0", "btn1");
  50. Application.RequestStop ();
  51. break;
  52. case 2:
  53. Application.OnKeyDown (Key.Esc);
  54. break;
  55. default:
  56. Assert.Fail ();
  57. break;
  58. }
  59. };
  60. Application.Run ().Dispose ();
  61. Assert.Equal (-1, result);
  62. }
  63. [Fact]
  64. [AutoInitShutdown]
  65. public void KeyBindings_Space_Causes_Focused_Button_Click ()
  66. {
  67. int result = -1;
  68. var iteration = 0;
  69. Application.Iteration += (s, a) =>
  70. {
  71. iteration++;
  72. switch (iteration)
  73. {
  74. case 1:
  75. result = MessageBox.Query (string.Empty, string.Empty, 0, false, "btn0", "btn1");
  76. Application.RequestStop ();
  77. break;
  78. case 2:
  79. // Tab to btn2
  80. Application.OnKeyDown (Key.Tab);
  81. Application.OnKeyDown (Key.Space);
  82. break;
  83. default:
  84. Assert.Fail ();
  85. break;
  86. }
  87. };
  88. Application.Run ().Dispose ();
  89. Assert.Equal (1, result);
  90. }
  91. [Theory]
  92. [InlineData (@"", false, false, 6, 6, 2, 2)]
  93. [InlineData (@"", false, true, 3, 6, 9, 3)]
  94. [InlineData (@"01234\n-----\n01234", false, false, 1, 6, 13, 3)]
  95. [InlineData (@"01234\n-----\n01234", true, false, 1, 5, 13, 4)]
  96. [InlineData (@"0123456789", false, false, 1, 6, 12, 3)]
  97. [InlineData (@"0123456789", false, true, 1, 5, 12, 4)]
  98. [InlineData (@"01234567890123456789", false, true, 1, 5, 13, 4)]
  99. [InlineData (@"01234567890123456789", true, true, 1, 5, 13, 5)]
  100. [InlineData (@"01234567890123456789\n01234567890123456789", false, true, 1, 5, 13, 4)]
  101. [InlineData (@"01234567890123456789\n01234567890123456789", true, true, 1, 4, 13, 7)]
  102. [AutoInitShutdown]
  103. public void Location_And_Size_Correct (string message, bool wrapMessage, bool hasButton, int expectedX, int expectedY, int expectedW, int expectedH)
  104. {
  105. int iterations = -1;
  106. ((FakeDriver)Application.Driver!).SetBufferSize (15, 15); // 15 x 15 gives us enough room for a button with one char (9x1)
  107. Dialog.DefaultShadow = ShadowStyle.None;
  108. Button.DefaultShadow = ShadowStyle.None;
  109. Rectangle mbFrame = Rectangle.Empty;
  110. Application.Iteration += (s, a) =>
  111. {
  112. iterations++;
  113. if (iterations == 0)
  114. {
  115. MessageBox.Query (string.Empty, message, 0, wrapMessage, hasButton ? ["0"] : []);
  116. Application.RequestStop ();
  117. }
  118. else if (iterations == 1)
  119. {
  120. mbFrame = Application.Current.Frame;
  121. Application.RequestStop ();
  122. }
  123. };
  124. Application.Run ().Dispose ();
  125. Assert.Equal (new (expectedX, expectedY, expectedW, expectedH), mbFrame);
  126. }
  127. [Fact]
  128. [AutoInitShutdown]
  129. public void Message_With_Spaces_WrapMessage_False ()
  130. {
  131. int iterations = -1;
  132. var top = new Toplevel ();
  133. top.BorderStyle = LineStyle.None;
  134. ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
  135. var btn =
  136. $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} btn {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}";
  137. // Override CM
  138. MessageBox.DefaultButtonAlignment = Alignment.End;
  139. MessageBox.DefaultBorderStyle = LineStyle.Double;
  140. Dialog.DefaultShadow = ShadowStyle.None;
  141. Button.DefaultShadow = ShadowStyle.None;
  142. Application.Iteration += (s, a) =>
  143. {
  144. iterations++;
  145. if (iterations == 0)
  146. {
  147. var sb = new StringBuilder ();
  148. for (var i = 0; i < 17; i++)
  149. {
  150. sb.Append ("ff ");
  151. }
  152. MessageBox.Query (string.Empty, sb.ToString (), 0, false, "btn");
  153. Application.RequestStop ();
  154. }
  155. else if (iterations == 1)
  156. {
  157. Application.Refresh ();
  158. TestHelpers.AssertDriverContentsWithFrameAre (
  159. @"
  160. ╔════════════════╗
  161. ║ ff ff ff ff ff ║
  162. ║ ⟦► btn ◄⟧║
  163. ╚════════════════╝",
  164. _output
  165. );
  166. Application.RequestStop ();
  167. // Really long text
  168. MessageBox.Query (string.Empty, new string ('f', 500), 0, false, "btn");
  169. }
  170. else if (iterations == 2)
  171. {
  172. Application.Refresh ();
  173. TestHelpers.AssertDriverContentsWithFrameAre (
  174. @"
  175. ╔════════════════╗
  176. ║ffffffffffffffff║
  177. ║ ⟦► btn ◄⟧║
  178. ╚════════════════╝",
  179. _output
  180. );
  181. Application.RequestStop ();
  182. }
  183. };
  184. Application.Run (top);
  185. top.Dispose ();
  186. }
  187. [Fact]
  188. [AutoInitShutdown]
  189. public void Message_With_Spaces_WrapMessage_True ()
  190. {
  191. int iterations = -1;
  192. var top = new Toplevel ();
  193. top.BorderStyle = LineStyle.None;
  194. ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
  195. var btn =
  196. $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} btn {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}";
  197. // Override CM
  198. MessageBox.DefaultButtonAlignment = Alignment.End;
  199. MessageBox.DefaultBorderStyle = LineStyle.Double;
  200. Dialog.DefaultShadow = ShadowStyle.None;
  201. Button.DefaultShadow = ShadowStyle.None;
  202. Application.Iteration += (s, a) =>
  203. {
  204. iterations++;
  205. if (iterations == 0)
  206. {
  207. var sb = new StringBuilder ();
  208. for (var i = 0; i < 17; i++)
  209. {
  210. sb.Append ("ff ");
  211. }
  212. MessageBox.Query (string.Empty, sb.ToString (), 0, true, "btn");
  213. Application.RequestStop ();
  214. }
  215. else if (iterations == 1)
  216. {
  217. Application.Refresh ();
  218. TestHelpers.AssertDriverContentsWithFrameAre (
  219. @"
  220. ╔══════════════╗
  221. ║ff ff ff ff ff║
  222. ║ff ff ff ff ff║
  223. ║ff ff ff ff ff║
  224. ║ ff ff ║
  225. ║ ⟦► btn ◄⟧║
  226. ╚══════════════╝",
  227. _output
  228. );
  229. Application.RequestStop ();
  230. // Really long text
  231. MessageBox.Query (string.Empty, new string ('f', 500), 0, true, "btn");
  232. }
  233. else if (iterations == 2)
  234. {
  235. Application.Refresh ();
  236. TestHelpers.AssertDriverContentsWithFrameAre (
  237. @$"
  238. ╔════════════════╗
  239. ║ffffffffffffffff║
  240. ║ffffffffffffffff║
  241. ║ffffffffffffffff║
  242. ║ffffffffffffffff║
  243. ║ffffffffffffffff║
  244. ║ffffffffffffffff║
  245. ║fffffff⟦► btn ◄⟧║
  246. ╚════════════════╝",
  247. _output
  248. );
  249. Application.RequestStop ();
  250. }
  251. };
  252. Application.Run (top);
  253. top.Dispose ();
  254. }
  255. [Theory]
  256. [InlineData (0, 0, "1")]
  257. [InlineData (1, 1, "1")]
  258. [InlineData (7, 5, "1")]
  259. [InlineData (50, 50, "1")]
  260. [InlineData (0, 0, "message")]
  261. [InlineData (1, 1, "message")]
  262. [InlineData (7, 5, "message")]
  263. [InlineData (50, 50, "message")]
  264. [AutoInitShutdown]
  265. public void Size_Not_Default_Message (int height, int width, string message)
  266. {
  267. int iterations = -1;
  268. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  269. Application.Iteration += (s, a) =>
  270. {
  271. iterations++;
  272. if (iterations == 0)
  273. {
  274. MessageBox.Query (height, width, string.Empty, message, null);
  275. Application.RequestStop ();
  276. }
  277. else if (iterations == 1)
  278. {
  279. Application.Refresh ();
  280. Assert.IsType<Dialog> (Application.Current);
  281. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  282. Application.RequestStop ();
  283. }
  284. };
  285. }
  286. [Theory]
  287. [InlineData (0, 0, "1")]
  288. [InlineData (1, 1, "1")]
  289. [InlineData (7, 5, "1")]
  290. [InlineData (50, 50, "1")]
  291. [InlineData (0, 0, "message")]
  292. [InlineData (1, 1, "message")]
  293. [InlineData (7, 5, "message")]
  294. [InlineData (50, 50, "message")]
  295. [AutoInitShutdown]
  296. public void Size_Not_Default_Message_Button (int height, int width, string message)
  297. {
  298. int iterations = -1;
  299. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  300. Application.Iteration += (s, a) =>
  301. {
  302. iterations++;
  303. if (iterations == 0)
  304. {
  305. MessageBox.Query (height, width, string.Empty, message, "_Ok");
  306. Application.RequestStop ();
  307. }
  308. else if (iterations == 1)
  309. {
  310. Application.Refresh ();
  311. Assert.IsType<Dialog> (Application.Current);
  312. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  313. Application.RequestStop ();
  314. }
  315. };
  316. }
  317. [Theory]
  318. [InlineData (0, 0)]
  319. [InlineData (1, 1)]
  320. [InlineData (7, 5)]
  321. [InlineData (50, 50)]
  322. [AutoInitShutdown]
  323. public void Size_Not_Default_No_Message (int height, int width)
  324. {
  325. int iterations = -1;
  326. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  327. Application.Iteration += (s, a) =>
  328. {
  329. iterations++;
  330. if (iterations == 0)
  331. {
  332. MessageBox.Query (height, width, string.Empty, string.Empty, null);
  333. Application.RequestStop ();
  334. }
  335. else if (iterations == 1)
  336. {
  337. Application.Refresh ();
  338. Assert.IsType<Dialog> (Application.Current);
  339. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  340. Application.RequestStop ();
  341. }
  342. };
  343. }
  344. [Fact]
  345. [AutoInitShutdown]
  346. public void UICatalog_AboutBox ()
  347. {
  348. int iterations = -1;
  349. ((FakeDriver)Application.Driver).SetBufferSize (70, 15);
  350. // Override CM
  351. MessageBox.DefaultButtonAlignment = Alignment.End;
  352. MessageBox.DefaultBorderStyle = LineStyle.Double;
  353. Dialog.DefaultShadow = ShadowStyle.None;
  354. Button.DefaultShadow = ShadowStyle.None;
  355. Application.Iteration += (s, a) =>
  356. {
  357. iterations++;
  358. if (iterations == 0)
  359. {
  360. MessageBox.Query (
  361. title: "",
  362. message: UICatalog.UICatalogApp.GetAboutBoxMessage (),
  363. wrapMessage: false,
  364. buttons: "_Ok"
  365. );
  366. Application.RequestStop ();
  367. }
  368. else if (iterations == 1)
  369. {
  370. Application.Refresh ();
  371. string expectedText = """
  372. ┌────────────────────────────────────────────────────────────────────┐
  373. │ ╔══════════════════════════════════════════════════════════╗ │
  374. │ ║ UI Catalog: A comprehensive sample library for ║ │
  375. │ ║ ║ │
  376. │ ║ _______ _ _ _____ _ ║ │
  377. │ ║|__ __| (_) | | / ____| (_)║ │
  378. │ ║ | | ___ _ __ _ __ ___ _ _ __ __ _| || | __ _ _ _ ║ │
  379. │ ║ | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | || | |_ | | | | |║ │
  380. │ ║ | | __/ | | | | | | | | | | | (_| | || |__| | |_| | |║ │
  381. │ ║ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_(_)_____|\__,_|_|║ │
  382. │ ║ ║ │
  383. │ ║ v2 - Pre-Alpha ║ │
  384. │ ║ ⟦► Ok ◄⟧║ │
  385. │ ╚══════════════════════════════════════════════════════════╝ │
  386. └────────────────────────────────────────────────────────────────────┘
  387. """;
  388. TestHelpers.AssertDriverContentsAre (expectedText, _output);
  389. Application.RequestStop ();
  390. }
  391. };
  392. var top = new Toplevel ();
  393. top.BorderStyle = LineStyle.Single;
  394. Application.Run (top);
  395. top.Dispose ();
  396. }
  397. }