MessageBoxTests.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. }
  186. [Fact]
  187. [AutoInitShutdown]
  188. public void Message_With_Spaces_WrapMessage_True ()
  189. {
  190. int iterations = -1;
  191. var top = new Toplevel ();
  192. top.BorderStyle = LineStyle.None;
  193. ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
  194. var btn =
  195. $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} btn {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}";
  196. // Override CM
  197. MessageBox.DefaultButtonAlignment = Alignment.End;
  198. MessageBox.DefaultBorderStyle = LineStyle.Double;
  199. Dialog.DefaultShadow = ShadowStyle.None;
  200. Button.DefaultShadow = ShadowStyle.None;
  201. Application.Iteration += (s, a) =>
  202. {
  203. iterations++;
  204. if (iterations == 0)
  205. {
  206. var sb = new StringBuilder ();
  207. for (var i = 0; i < 17; i++)
  208. {
  209. sb.Append ("ff ");
  210. }
  211. MessageBox.Query (string.Empty, sb.ToString (), 0, true, "btn");
  212. Application.RequestStop ();
  213. }
  214. else if (iterations == 1)
  215. {
  216. Application.Refresh ();
  217. TestHelpers.AssertDriverContentsWithFrameAre (
  218. @"
  219. ╔══════════════╗
  220. ║ff ff ff ff ff║
  221. ║ff ff ff ff ff║
  222. ║ff ff ff ff ff║
  223. ║ ff ff ║
  224. ║ ⟦► btn ◄⟧║
  225. ╚══════════════╝",
  226. _output
  227. );
  228. Application.RequestStop ();
  229. // Really long text
  230. MessageBox.Query (string.Empty, new string ('f', 500), 0, true, "btn");
  231. }
  232. else if (iterations == 2)
  233. {
  234. Application.Refresh ();
  235. TestHelpers.AssertDriverContentsWithFrameAre (
  236. @$"
  237. ╔════════════════╗
  238. ║ffffffffffffffff║
  239. ║ffffffffffffffff║
  240. ║ffffffffffffffff║
  241. ║ffffffffffffffff║
  242. ║ffffffffffffffff║
  243. ║ffffffffffffffff║
  244. ║fffffff⟦► btn ◄⟧║
  245. ╚════════════════╝",
  246. _output
  247. );
  248. Application.RequestStop ();
  249. }
  250. };
  251. Application.Run (top);
  252. top.Dispose ();
  253. }
  254. [Theory]
  255. [InlineData (0, 0, "1")]
  256. [InlineData (1, 1, "1")]
  257. [InlineData (7, 5, "1")]
  258. [InlineData (50, 50, "1")]
  259. [InlineData (0, 0, "message")]
  260. [InlineData (1, 1, "message")]
  261. [InlineData (7, 5, "message")]
  262. [InlineData (50, 50, "message")]
  263. [AutoInitShutdown]
  264. public void Size_Not_Default_Message (int height, int width, string message)
  265. {
  266. int iterations = -1;
  267. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  268. Application.Iteration += (s, a) =>
  269. {
  270. iterations++;
  271. if (iterations == 0)
  272. {
  273. MessageBox.Query (height, width, string.Empty, message, null);
  274. Application.RequestStop ();
  275. }
  276. else if (iterations == 1)
  277. {
  278. Application.Refresh ();
  279. Assert.IsType<Dialog> (Application.Current);
  280. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  281. Application.RequestStop ();
  282. }
  283. };
  284. }
  285. [Theory]
  286. [InlineData (0, 0, "1")]
  287. [InlineData (1, 1, "1")]
  288. [InlineData (7, 5, "1")]
  289. [InlineData (50, 50, "1")]
  290. [InlineData (0, 0, "message")]
  291. [InlineData (1, 1, "message")]
  292. [InlineData (7, 5, "message")]
  293. [InlineData (50, 50, "message")]
  294. [AutoInitShutdown]
  295. public void Size_Not_Default_Message_Button (int height, int width, string message)
  296. {
  297. int iterations = -1;
  298. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  299. Application.Iteration += (s, a) =>
  300. {
  301. iterations++;
  302. if (iterations == 0)
  303. {
  304. MessageBox.Query (height, width, string.Empty, message, "_Ok");
  305. Application.RequestStop ();
  306. }
  307. else if (iterations == 1)
  308. {
  309. Application.Refresh ();
  310. Assert.IsType<Dialog> (Application.Current);
  311. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  312. Application.RequestStop ();
  313. }
  314. };
  315. }
  316. [Theory]
  317. [InlineData (0, 0)]
  318. [InlineData (1, 1)]
  319. [InlineData (7, 5)]
  320. [InlineData (50, 50)]
  321. [AutoInitShutdown]
  322. public void Size_Not_Default_No_Message (int height, int width)
  323. {
  324. int iterations = -1;
  325. ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
  326. Application.Iteration += (s, a) =>
  327. {
  328. iterations++;
  329. if (iterations == 0)
  330. {
  331. MessageBox.Query (height, width, string.Empty, string.Empty, null);
  332. Application.RequestStop ();
  333. }
  334. else if (iterations == 1)
  335. {
  336. Application.Refresh ();
  337. Assert.IsType<Dialog> (Application.Current);
  338. Assert.Equal (new (height, width), Application.Current.Frame.Size);
  339. Application.RequestStop ();
  340. }
  341. };
  342. }
  343. [Fact]
  344. [AutoInitShutdown]
  345. public void UICatalog_AboutBox ()
  346. {
  347. int iterations = -1;
  348. ((FakeDriver)Application.Driver).SetBufferSize (70, 15);
  349. // Override CM
  350. MessageBox.DefaultButtonAlignment = Alignment.End;
  351. MessageBox.DefaultBorderStyle = LineStyle.Double;
  352. Dialog.DefaultShadow = ShadowStyle.None;
  353. Button.DefaultShadow = ShadowStyle.None;
  354. Application.Iteration += (s, a) =>
  355. {
  356. iterations++;
  357. if (iterations == 0)
  358. {
  359. MessageBox.Query (
  360. title: "",
  361. message: UICatalog.UICatalogApp.GetAboutBoxMessage (),
  362. wrapMessage: false,
  363. buttons: "_Ok"
  364. );
  365. Application.RequestStop ();
  366. }
  367. else if (iterations == 1)
  368. {
  369. Application.Refresh ();
  370. string expectedText = """
  371. ┌────────────────────────────────────────────────────────────────────┐
  372. │ ╔══════════════════════════════════════════════════════════╗ │
  373. │ ║ UI Catalog: A comprehensive sample library for ║ │
  374. │ ║ ║ │
  375. │ ║ _______ _ _ _____ _ ║ │
  376. │ ║|__ __| (_) | | / ____| (_)║ │
  377. │ ║ | | ___ _ __ _ __ ___ _ _ __ __ _| || | __ _ _ _ ║ │
  378. │ ║ | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | || | |_ | | | | |║ │
  379. │ ║ | | __/ | | | | | | | | | | | (_| | || |__| | |_| | |║ │
  380. │ ║ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_(_)_____|\__,_|_|║ │
  381. │ ║ ║ │
  382. │ ║ v2 - Pre-Alpha ║ │
  383. │ ║ ⟦► Ok ◄⟧║ │
  384. │ ╚══════════════════════════════════════════════════════════╝ │
  385. └────────────────────────────────────────────────────────────────────┘
  386. """;
  387. TestHelpers.AssertDriverContentsAre (expectedText, _output);
  388. Application.RequestStop ();
  389. }
  390. };
  391. var top = new Toplevel ();
  392. top.BorderStyle = LineStyle.Single;
  393. Application.Run (top);
  394. }
  395. }