DialogTests.cs 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530
  1. #nullable enable
  2. using Xunit.Abstractions;
  3. namespace UnitTests.DialogTests;
  4. public class DialogTests (ITestOutputHelper output)
  5. {
  6. [Fact]
  7. [AutoInitShutdown]
  8. public void Add_Button_Works ()
  9. {
  10. SessionToken? sessionToken = null;
  11. var title = "1234";
  12. var btn1Text = "yes";
  13. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  14. var btn2Text = "no";
  15. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  16. // We test with one button first, but do this to get the width right for 2
  17. int width = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}".Length;
  18. Application.Driver?.SetScreenSize (width, 1);
  19. // Override CM
  20. Dialog.DefaultButtonAlignment = Alignment.Center;
  21. Dialog.DefaultBorderStyle = LineStyle.Single;
  22. Dialog.DefaultShadow = ShadowStyle.None;
  23. Button.DefaultShadow = ShadowStyle.None;
  24. // Default (center)
  25. var dlg = new Dialog
  26. {
  27. Title = title,
  28. Width = width,
  29. Height = 1,
  30. ButtonAlignment = Alignment.Center,
  31. Buttons = [new () { Text = btn1Text }]
  32. };
  33. // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
  34. dlg.Border!.Thickness = new (1, 0, 1, 0);
  35. sessionToken = Application.Begin (dlg);
  36. var buttonRow = $"{Glyphs.VLine} {btn1} {Glyphs.VLine}";
  37. AutoInitShutdownAttribute.RunIteration ();
  38. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  39. // Now add a second button
  40. buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
  41. dlg.AddButton (new () { Text = btn2Text });
  42. AutoInitShutdownAttribute.RunIteration ();
  43. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  44. Application.End (sessionToken);
  45. dlg.Dispose ();
  46. // Justify
  47. dlg = new ()
  48. {
  49. Title = title,
  50. Width = width,
  51. Height = 1,
  52. ButtonAlignment = Alignment.Fill,
  53. Buttons = [new () { Text = btn1Text }]
  54. };
  55. // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
  56. dlg.Border!.Thickness = new (1, 0, 1, 0);
  57. sessionToken = Application.Begin (dlg);
  58. AutoInitShutdownAttribute.RunIteration ();
  59. buttonRow = $"{Glyphs.VLine}{btn1} {Glyphs.VLine}";
  60. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  61. // Now add a second button
  62. buttonRow = $"{Glyphs.VLine}{btn1} {btn2}{Glyphs.VLine}";
  63. dlg.AddButton (new () { Text = btn2Text });
  64. AutoInitShutdownAttribute.RunIteration ();
  65. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  66. Application.End (sessionToken);
  67. dlg.Dispose ();
  68. // Right
  69. dlg = new ()
  70. {
  71. Title = title,
  72. Width = width,
  73. Height = 1,
  74. ButtonAlignment = Alignment.End,
  75. Buttons = [new () { Text = btn1Text }]
  76. };
  77. // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
  78. dlg.Border!.Thickness = new (1, 0, 1, 0);
  79. sessionToken = Application.Begin (dlg);
  80. AutoInitShutdownAttribute.RunIteration ();
  81. buttonRow = $"{Glyphs.VLine}{new (' ', width - btn1.Length - 2)}{btn1}{Glyphs.VLine}";
  82. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  83. // Now add a second button
  84. buttonRow = $"{Glyphs.VLine} {btn1} {btn2}{Glyphs.VLine}";
  85. dlg.AddButton (new () { Text = btn2Text });
  86. AutoInitShutdownAttribute.RunIteration ();
  87. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  88. Application.End (sessionToken);
  89. dlg.Dispose ();
  90. // Left
  91. dlg = new ()
  92. {
  93. Title = title,
  94. Width = width,
  95. Height = 1,
  96. ButtonAlignment = Alignment.Start,
  97. Buttons = [new () { Text = btn1Text }]
  98. };
  99. // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
  100. dlg.Border!.Thickness = new (1, 0, 1, 0);
  101. sessionToken = Application.Begin (dlg);
  102. AutoInitShutdownAttribute.RunIteration ();
  103. buttonRow = $"{Glyphs.VLine}{btn1}{new (' ', width - btn1.Length - 2)}{Glyphs.VLine}";
  104. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  105. // Now add a second button
  106. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {Glyphs.VLine}";
  107. dlg.AddButton (new () { Text = btn2Text });
  108. AutoInitShutdownAttribute.RunIteration ();
  109. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  110. Application.End (sessionToken);
  111. dlg.Dispose ();
  112. }
  113. [Fact]
  114. [AutoInitShutdown]
  115. public void ButtonAlignment_Four ()
  116. {
  117. SessionToken? sessionToken = null;
  118. Dialog.DefaultShadow = ShadowStyle.None;
  119. Button.DefaultShadow = ShadowStyle.None;
  120. var title = "1234";
  121. // E.g "|[ yes ][ no ][ maybe ]|"
  122. var btn1Text = "yes";
  123. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  124. var btn2Text = "no";
  125. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  126. var btn3Text = "maybe";
  127. var btn3 = $"{Glyphs.LeftBracket} {btn3Text} {Glyphs.RightBracket}";
  128. var btn4Text = "never";
  129. var btn4 = $"{Glyphs.LeftBracket} {btn4Text} {Glyphs.RightBracket}";
  130. var buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  131. int width = buttonRow.Length;
  132. Application.Driver?.SetScreenSize (buttonRow.Length, 3);
  133. // Default - Center
  134. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  135. title,
  136. width,
  137. Alignment.Center,
  138. new Button { Text = btn1Text },
  139. new Button { Text = btn2Text },
  140. new Button { Text = btn3Text },
  141. new Button { Text = btn4Text }
  142. );
  143. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  144. Application.End (sessionToken);
  145. dlg.Dispose ();
  146. // Justify
  147. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  148. Assert.Equal (width, buttonRow.Length);
  149. (sessionToken, dlg) = BeginButtonTestDialog (
  150. title,
  151. width,
  152. Alignment.Fill,
  153. new Button { Text = btn1Text },
  154. new Button { Text = btn2Text },
  155. new Button { Text = btn3Text },
  156. new Button { Text = btn4Text }
  157. );
  158. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  159. Application.End (sessionToken);
  160. dlg.Dispose ();
  161. // Right
  162. buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  163. Assert.Equal (width, buttonRow.Length);
  164. (sessionToken, dlg) = BeginButtonTestDialog (
  165. title,
  166. width,
  167. Alignment.End,
  168. new Button { Text = btn1Text },
  169. new Button { Text = btn2Text },
  170. new Button { Text = btn3Text },
  171. new Button { Text = btn4Text }
  172. );
  173. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  174. Application.End (sessionToken);
  175. dlg.Dispose ();
  176. // Left
  177. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  178. Assert.Equal (width, buttonRow.Length);
  179. (sessionToken, dlg) = BeginButtonTestDialog (
  180. title,
  181. width,
  182. Alignment.Start,
  183. new Button { Text = btn1Text },
  184. new Button { Text = btn2Text },
  185. new Button { Text = btn3Text },
  186. new Button { Text = btn4Text }
  187. );
  188. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  189. Application.End (sessionToken);
  190. dlg.Dispose ();
  191. }
  192. [Fact]
  193. [AutoInitShutdown]
  194. public void ButtonAlignment_Four_On_Too_Small_Width ()
  195. {
  196. SessionToken? sessionToken = null;
  197. Dialog.DefaultShadow = ShadowStyle.None;
  198. Button.DefaultShadow = ShadowStyle.None;
  199. var title = "1234";
  200. // E.g "|[ yes ][ no ][ maybe ][ never ]|"
  201. var btn1Text = "yes";
  202. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  203. var btn2Text = "no";
  204. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  205. var btn3Text = "maybe";
  206. var btn3 = $"{Glyphs.LeftBracket} {btn3Text} {Glyphs.RightBracket}";
  207. var btn4Text = "never";
  208. var btn4 = $"{Glyphs.LeftBracket} {btn4Text} {Glyphs.RightBracket}";
  209. var buttonRow = string.Empty;
  210. var width = 30;
  211. Application.Driver?.SetScreenSize (width, 1);
  212. // Default - Center
  213. buttonRow =
  214. $"{Glyphs.VLine} yes {Glyphs.RightBracket}{btn2}{btn3}{Glyphs.LeftBracket} never{Glyphs.VLine}";
  215. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  216. title,
  217. width,
  218. Alignment.Center,
  219. new Button { Text = btn1Text },
  220. new Button { Text = btn2Text },
  221. new Button { Text = btn3Text },
  222. new Button { Text = btn4Text }
  223. );
  224. Assert.Equal (new (width, 1), dlg.Frame.Size);
  225. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  226. Application.End (sessionToken);
  227. dlg.Dispose ();
  228. // Justify
  229. buttonRow =
  230. $"{Glyphs.VLine}{Glyphs.LeftBracket} yes {Glyphs.LeftBracket} no {Glyphs.LeftBracket} maybe {Glyphs.LeftBracket} never {Glyphs.RightBracket}{Glyphs.VLine}";
  231. (sessionToken, dlg) = BeginButtonTestDialog (
  232. title,
  233. width,
  234. Alignment.Fill,
  235. new Button { Text = btn1Text },
  236. new Button { Text = btn2Text },
  237. new Button { Text = btn3Text },
  238. new Button { Text = btn4Text }
  239. );
  240. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  241. Application.End (sessionToken);
  242. dlg.Dispose ();
  243. // Right
  244. buttonRow = $"{Glyphs.VLine}es {Glyphs.RightBracket}{btn2}{btn3}{btn4}{Glyphs.VLine}";
  245. Assert.Equal (width, buttonRow.Length);
  246. (sessionToken, dlg) = BeginButtonTestDialog (
  247. title,
  248. width,
  249. Alignment.End,
  250. new Button { Text = btn1Text },
  251. new Button { Text = btn2Text },
  252. new Button { Text = btn3Text },
  253. new Button { Text = btn4Text }
  254. );
  255. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  256. Application.End (sessionToken);
  257. dlg.Dispose ();
  258. // Left
  259. buttonRow = $"{Glyphs.VLine}{btn1}{btn2}{btn3}{Glyphs.LeftBracket} neve{Glyphs.VLine}";
  260. (sessionToken, dlg) = BeginButtonTestDialog (
  261. title,
  262. width,
  263. Alignment.Start,
  264. new Button { Text = btn1Text },
  265. new Button { Text = btn2Text },
  266. new Button { Text = btn3Text },
  267. new Button { Text = btn4Text }
  268. );
  269. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  270. Application.End (sessionToken);
  271. dlg.Dispose ();
  272. }
  273. [Fact]
  274. [AutoInitShutdown]
  275. public void ButtonAlignment_Four_WideOdd ()
  276. {
  277. SessionToken? sessionToken = null;
  278. Dialog.DefaultShadow = ShadowStyle.None;
  279. Button.DefaultShadow = ShadowStyle.None;
  280. var title = "1234";
  281. // E.g "|[ yes ][ no ][ maybe ]|"
  282. var btn1Text = "really long button 1";
  283. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  284. var btn2Text = "really long button 2";
  285. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  286. var btn3Text = "really long button 3";
  287. var btn3 = $"{Glyphs.LeftBracket} {btn3Text} {Glyphs.RightBracket}";
  288. var btn4Text = "really long button 44"; // 44 is intentional to make length different than rest
  289. var btn4 = $"{Glyphs.LeftBracket} {btn4Text} {Glyphs.RightBracket}";
  290. // Note extra spaces to make dialog even wider
  291. // 123456 1234567
  292. var buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  293. int width = buttonRow.Length;
  294. Application.Driver?.SetScreenSize (buttonRow.Length, 1);
  295. // Default - Center
  296. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  297. title,
  298. width,
  299. Alignment.Center,
  300. new Button { Text = btn1Text },
  301. new Button { Text = btn2Text },
  302. new Button { Text = btn3Text },
  303. new Button { Text = btn4Text }
  304. );
  305. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  306. Application.End (sessionToken);
  307. dlg.Dispose ();
  308. // Justify
  309. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  310. Assert.Equal (width, buttonRow.Length);
  311. (sessionToken, dlg) = BeginButtonTestDialog (
  312. title,
  313. width,
  314. Alignment.Fill,
  315. new Button { Text = btn1Text },
  316. new Button { Text = btn2Text },
  317. new Button { Text = btn3Text },
  318. new Button { Text = btn4Text }
  319. );
  320. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  321. Application.End (sessionToken);
  322. dlg.Dispose ();
  323. // Right
  324. buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  325. Assert.Equal (width, buttonRow.Length);
  326. (sessionToken, dlg) = BeginButtonTestDialog (
  327. title,
  328. width,
  329. Alignment.End,
  330. new Button { Text = btn1Text },
  331. new Button { Text = btn2Text },
  332. new Button { Text = btn3Text },
  333. new Button { Text = btn4Text }
  334. );
  335. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  336. Application.End (sessionToken);
  337. dlg.Dispose ();
  338. // Left
  339. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  340. Assert.Equal (width, buttonRow.Length);
  341. (sessionToken, dlg) = BeginButtonTestDialog (
  342. title,
  343. width,
  344. Alignment.Start,
  345. new Button { Text = btn1Text },
  346. new Button { Text = btn2Text },
  347. new Button { Text = btn3Text },
  348. new Button { Text = btn4Text }
  349. );
  350. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  351. Application.End (sessionToken);
  352. dlg.Dispose ();
  353. }
  354. [Fact]
  355. [AutoInitShutdown]
  356. public void ButtonAlignment_Four_Wider ()
  357. {
  358. SessionToken? sessionToken = null;
  359. Dialog.DefaultShadow = ShadowStyle.None;
  360. Button.DefaultShadow = ShadowStyle.None;
  361. var title = "1234";
  362. // E.g "|[ yes ][ no ][ maybe ]|"
  363. var btn1Text = "yes";
  364. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  365. var btn2Text = "no";
  366. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  367. var btn3Text = "你你你你你"; // This is a wide char
  368. var btn3 = $"{Glyphs.LeftBracket} {btn3Text} {Glyphs.RightBracket}";
  369. // Requires a Nerd Font
  370. var btn4Text = "\uE36E\uE36F\uE370\uE371\uE372\uE373";
  371. var btn4 = $"{Glyphs.LeftBracket} {btn4Text} {Glyphs.RightBracket}";
  372. // Note extra spaces to make dialog even wider
  373. // 123456 123456
  374. var buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  375. int width = buttonRow.GetColumns ();
  376. Application.Driver?.SetScreenSize (width, 3);
  377. // Default - Center
  378. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  379. title,
  380. width,
  381. Alignment.Center,
  382. new Button { Text = btn1Text },
  383. new Button { Text = btn2Text },
  384. new Button { Text = btn3Text },
  385. new Button { Text = btn4Text }
  386. );
  387. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  388. Application.End (sessionToken);
  389. dlg.Dispose ();
  390. // Justify
  391. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  392. Assert.Equal (width, buttonRow.GetColumns ());
  393. (sessionToken, dlg) = BeginButtonTestDialog (
  394. title,
  395. width,
  396. Alignment.Fill,
  397. new Button { Text = btn1Text },
  398. new Button { Text = btn2Text },
  399. new Button { Text = btn3Text },
  400. new Button { Text = btn4Text }
  401. );
  402. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  403. Application.End (sessionToken);
  404. dlg.Dispose ();
  405. // Right
  406. buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4}{Glyphs.VLine}";
  407. Assert.Equal (width, buttonRow.GetColumns ());
  408. (sessionToken, dlg) = BeginButtonTestDialog (
  409. title,
  410. width,
  411. Alignment.End,
  412. new Button { Text = btn1Text },
  413. new Button { Text = btn2Text },
  414. new Button { Text = btn3Text },
  415. new Button { Text = btn4Text }
  416. );
  417. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  418. Application.End (sessionToken);
  419. dlg.Dispose ();
  420. // Left
  421. buttonRow = $"{Glyphs.VLine}{btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
  422. Assert.Equal (width, buttonRow.GetColumns ());
  423. (sessionToken, dlg) = BeginButtonTestDialog (
  424. title,
  425. width,
  426. Alignment.Start,
  427. new Button { Text = btn1Text },
  428. new Button { Text = btn2Text },
  429. new Button { Text = btn3Text },
  430. new Button { Text = btn4Text }
  431. );
  432. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  433. Application.End (sessionToken);
  434. dlg.Dispose ();
  435. }
  436. [Fact]
  437. [AutoInitShutdown]
  438. public void ButtonAlignment_One ()
  439. {
  440. SessionToken? sessionToken = null;
  441. Dialog.DefaultShadow = ShadowStyle.None;
  442. Button.DefaultShadow = ShadowStyle.None;
  443. var title = "1234";
  444. // E.g "|[ ok ]|"
  445. var btnText = "ok";
  446. var buttonRow =
  447. $"{Glyphs.VLine} {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  448. int width = buttonRow.Length;
  449. Application.Driver?.SetScreenSize (width, 1);
  450. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  451. title,
  452. width,
  453. Alignment.Center,
  454. new Button { Text = btnText }
  455. );
  456. // Center
  457. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  458. Application.End (sessionToken);
  459. dlg.Dispose ();
  460. // Justify
  461. buttonRow =
  462. $"{Glyphs.VLine}{Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  463. Assert.Equal (width, buttonRow.Length);
  464. (sessionToken, dlg) = BeginButtonTestDialog (
  465. title,
  466. width,
  467. Alignment.Fill,
  468. new Button { Text = btnText }
  469. );
  470. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  471. Application.End (sessionToken);
  472. dlg.Dispose ();
  473. // Right
  474. buttonRow =
  475. $"{Glyphs.VLine} {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket}{Glyphs.VLine}";
  476. Assert.Equal (width, buttonRow.Length);
  477. (sessionToken, dlg) = BeginButtonTestDialog (
  478. title,
  479. width,
  480. Alignment.End,
  481. new Button { Text = btnText }
  482. );
  483. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  484. Application.End (sessionToken);
  485. dlg.Dispose ();
  486. // Left
  487. buttonRow =
  488. $"{Glyphs.VLine}{Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  489. Assert.Equal (width, buttonRow.Length);
  490. (sessionToken, dlg) = BeginButtonTestDialog (
  491. title,
  492. width,
  493. Alignment.Start,
  494. new Button { Text = btnText }
  495. );
  496. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  497. Application.End (sessionToken);
  498. dlg.Dispose ();
  499. // Wider
  500. buttonRow =
  501. $"{Glyphs.VLine} {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  502. width = buttonRow.Length;
  503. Application.Driver?.SetScreenSize (width, 1);
  504. (sessionToken, dlg) = BeginButtonTestDialog (
  505. title,
  506. width,
  507. Alignment.Center,
  508. new Button { Text = btnText }
  509. );
  510. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  511. Application.End (sessionToken);
  512. dlg.Dispose ();
  513. // Justify
  514. buttonRow =
  515. $"{Glyphs.VLine}{Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  516. Assert.Equal (width, buttonRow.Length);
  517. (sessionToken, dlg) = BeginButtonTestDialog (
  518. title,
  519. width,
  520. Alignment.Fill,
  521. new Button { Text = btnText }
  522. );
  523. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  524. Application.End (sessionToken);
  525. dlg.Dispose ();
  526. // Right
  527. buttonRow =
  528. $"{Glyphs.VLine} {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket}{Glyphs.VLine}";
  529. Assert.Equal (width, buttonRow.Length);
  530. (sessionToken, dlg) = BeginButtonTestDialog (
  531. title,
  532. width,
  533. Alignment.End,
  534. new Button { Text = btnText }
  535. );
  536. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  537. Application.End (sessionToken);
  538. dlg.Dispose ();
  539. // Left
  540. buttonRow =
  541. $"{Glyphs.VLine}{Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  542. Assert.Equal (width, buttonRow.Length);
  543. (sessionToken, dlg) = BeginButtonTestDialog (
  544. title,
  545. width,
  546. Alignment.Start,
  547. new Button { Text = btnText }
  548. );
  549. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  550. Application.End (sessionToken);
  551. dlg.Dispose ();
  552. }
  553. [Fact]
  554. [AutoInitShutdown]
  555. public void ButtonAlignment_Three ()
  556. {
  557. SessionToken? sessionToken = null;
  558. Dialog.DefaultShadow = ShadowStyle.None;
  559. Button.DefaultShadow = ShadowStyle.None;
  560. var title = "1234";
  561. // E.g "|[ yes ][ no ][ maybe ]|"
  562. var btn1Text = "yes";
  563. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  564. var btn2Text = "no";
  565. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  566. var btn3Text = "maybe";
  567. var btn3 = $"{Glyphs.LeftBracket} {btn3Text} {Glyphs.RightBracket}";
  568. var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {btn3} {Glyphs.VLine}";
  569. int width = buttonRow.Length;
  570. Application.Driver?.SetScreenSize (buttonRow.Length, 3);
  571. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  572. title,
  573. width,
  574. Alignment.Center,
  575. new Button { Text = btn1Text },
  576. new Button { Text = btn2Text },
  577. new Button { Text = btn3Text }
  578. );
  579. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  580. Application.End (sessionToken);
  581. dlg.Dispose ();
  582. // Justify
  583. buttonRow = $@"{Glyphs.VLine}{btn1} {btn2} {btn3}{Glyphs.VLine}";
  584. Assert.Equal (width, buttonRow.Length);
  585. (sessionToken, dlg) = BeginButtonTestDialog (
  586. title,
  587. width,
  588. Alignment.Fill,
  589. new Button { Text = btn1Text },
  590. new Button { Text = btn2Text },
  591. new Button { Text = btn3Text }
  592. );
  593. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  594. Application.End (sessionToken);
  595. dlg.Dispose ();
  596. // Right
  597. buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {btn3}{Glyphs.VLine}";
  598. Assert.Equal (width, buttonRow.Length);
  599. (sessionToken, dlg) = BeginButtonTestDialog (
  600. title,
  601. width,
  602. Alignment.End,
  603. new Button { Text = btn1Text },
  604. new Button { Text = btn2Text },
  605. new Button { Text = btn3Text }
  606. );
  607. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  608. Application.End (sessionToken);
  609. dlg.Dispose ();
  610. // Left
  611. buttonRow = $@"{Glyphs.VLine}{btn1} {btn2} {btn3} {Glyphs.VLine}";
  612. Assert.Equal (width, buttonRow.Length);
  613. (sessionToken, dlg) = BeginButtonTestDialog (
  614. title,
  615. width,
  616. Alignment.Start,
  617. new Button { Text = btn1Text },
  618. new Button { Text = btn2Text },
  619. new Button { Text = btn3Text }
  620. );
  621. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  622. Application.End (sessionToken);
  623. dlg.Dispose ();
  624. }
  625. [Fact]
  626. [AutoInitShutdown]
  627. public void ButtonAlignment_Two ()
  628. {
  629. SessionToken? sessionToken = null;
  630. Dialog.DefaultShadow = ShadowStyle.None;
  631. Button.DefaultShadow = ShadowStyle.None;
  632. var title = "1234";
  633. // E.g "|[ yes ][ no ]|"
  634. var btn1Text = "yes";
  635. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  636. var btn2Text = "no";
  637. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  638. var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
  639. int width = buttonRow.Length;
  640. Application.Driver?.SetScreenSize (buttonRow.Length, 3);
  641. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  642. title,
  643. width,
  644. Alignment.Center,
  645. new Button { Text = btn1Text },
  646. new Button { Text = btn2Text }
  647. );
  648. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  649. Application.End (sessionToken);
  650. dlg.Dispose ();
  651. // Justify
  652. buttonRow = $@"{Glyphs.VLine}{btn1} {btn2}{Glyphs.VLine}";
  653. Assert.Equal (width, buttonRow.Length);
  654. (sessionToken, dlg) = BeginButtonTestDialog (
  655. title,
  656. width,
  657. Alignment.Fill,
  658. new Button { Text = btn1Text },
  659. new Button { Text = btn2Text }
  660. );
  661. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  662. Application.End (sessionToken);
  663. dlg.Dispose ();
  664. // Right
  665. buttonRow = $@"{Glyphs.VLine} {btn1} {btn2}{Glyphs.VLine}";
  666. Assert.Equal (width, buttonRow.Length);
  667. (sessionToken, dlg) = BeginButtonTestDialog (
  668. title,
  669. width,
  670. Alignment.End,
  671. new Button { Text = btn1Text },
  672. new Button { Text = btn2Text }
  673. );
  674. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  675. Application.End (sessionToken);
  676. dlg.Dispose ();
  677. // Left
  678. buttonRow = $@"{Glyphs.VLine}{btn1} {btn2} {Glyphs.VLine}";
  679. Assert.Equal (width, buttonRow.Length);
  680. (sessionToken, dlg) = BeginButtonTestDialog (
  681. title,
  682. width,
  683. Alignment.Start,
  684. new Button { Text = btn1Text },
  685. new Button { Text = btn2Text }
  686. );
  687. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  688. Application.End (sessionToken);
  689. dlg.Dispose ();
  690. }
  691. [Fact]
  692. [AutoInitShutdown]
  693. public void ButtonAlignment_Two_Hidden ()
  694. {
  695. SessionToken? sessionToken = null;
  696. Dialog.DefaultShadow = ShadowStyle.None;
  697. Button.DefaultShadow = ShadowStyle.None;
  698. var title = "1234";
  699. // E.g "|[ yes ][ no ]|"
  700. var btn1Text = "yes";
  701. var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
  702. var btn2Text = "no";
  703. var btn2 = $"{Glyphs.LeftBracket} {btn2Text} {Glyphs.RightBracket}";
  704. var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
  705. int width = buttonRow.Length;
  706. Application.Driver?.SetScreenSize (buttonRow.Length, 3);
  707. // Default (Center)
  708. Button button1 = new () { Text = btn1Text };
  709. Button button2 = new () { Text = btn2Text };
  710. (sessionToken, Dialog dlg) = BeginButtonTestDialog (title, width, Alignment.Center, button1, button2);
  711. button1.Visible = false;
  712. AutoInitShutdownAttribute.RunIteration ();
  713. buttonRow = $@"{Glyphs.VLine} {btn2} {Glyphs.VLine}";
  714. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  715. Application.End (sessionToken);
  716. dlg.Dispose ();
  717. // Justify
  718. Assert.Equal (width, buttonRow.Length);
  719. button1 = new () { Text = btn1Text };
  720. button2 = new () { Text = btn2Text };
  721. (sessionToken, dlg) = BeginButtonTestDialog (title, width, Alignment.Fill, button1, button2);
  722. button1.Visible = false;
  723. AutoInitShutdownAttribute.RunIteration ();
  724. buttonRow = $@"{Glyphs.VLine} {btn2}{Glyphs.VLine}";
  725. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  726. Application.End (sessionToken);
  727. dlg.Dispose ();
  728. // Right
  729. Assert.Equal (width, buttonRow.Length);
  730. button1 = new () { Text = btn1Text };
  731. button2 = new () { Text = btn2Text };
  732. (sessionToken, dlg) = BeginButtonTestDialog (title, width, Alignment.End, button1, button2);
  733. button1.Visible = false;
  734. AutoInitShutdownAttribute.RunIteration ();
  735. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  736. Application.End (sessionToken);
  737. dlg.Dispose ();
  738. // Left
  739. Assert.Equal (width, buttonRow.Length);
  740. button1 = new () { Text = btn1Text };
  741. button2 = new () { Text = btn2Text };
  742. (sessionToken, dlg) = BeginButtonTestDialog (title, width, Alignment.Start, button1, button2);
  743. button1.Visible = false;
  744. AutoInitShutdownAttribute.RunIteration ();
  745. buttonRow = $@"{Glyphs.VLine} {btn2} {Glyphs.VLine}";
  746. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  747. Application.End (sessionToken);
  748. dlg.Dispose ();
  749. }
  750. [Fact]
  751. [AutoInitShutdown]
  752. public void Can_Access_Cancel_Property_After_Run ()
  753. {
  754. Dialog dlg = new ();
  755. dlg.Ready += Dlg_Ready;
  756. Application.Run (dlg);
  757. #if DEBUG_IDISPOSABLE
  758. Assert.False (dlg.WasDisposed);
  759. Assert.False (Application.Current!.WasDisposed);
  760. Assert.Equal (dlg, Application.Current);
  761. #endif
  762. Assert.True (dlg.Canceled);
  763. // Run it again is possible because it isn't disposed yet
  764. Application.Run (dlg);
  765. // Run another view without dispose the prior will throw an assertion
  766. #if DEBUG_IDISPOSABLE
  767. Dialog dlg2 = new ();
  768. dlg2.Ready += Dlg_Ready;
  769. // Exception exception = Record.Exception (() => Application.Run (dlg2));
  770. // Assert.NotNull (exception);
  771. dlg.Dispose ();
  772. // Now it's possible to tun dlg2 without throw
  773. Application.Run (dlg2);
  774. Assert.True (dlg.WasDisposed);
  775. Assert.False (Application.Current.WasDisposed);
  776. Assert.Equal (dlg2, Application.Current);
  777. Assert.False (dlg2.WasDisposed);
  778. dlg2.Dispose ();
  779. // tznind REMOVED: Why wouldn't you be able to read cancelled after dispose - that makes no sense
  780. // Now an assertion will throw accessing the Canceled property
  781. //var exception = Record.Exception (() => Assert.True (dlg.Canceled))!;
  782. //Assert.NotNull (exception);
  783. //Assert.StartsWith ("Cannot access a disposed object.", exception.Message);
  784. Assert.True (Application.Current.WasDisposed);
  785. Application.Shutdown ();
  786. Assert.True (dlg2.WasDisposed);
  787. Assert.Null (Application.Current);
  788. #endif
  789. return;
  790. void Dlg_Ready (object? sender, EventArgs e)
  791. {
  792. ((Dialog)sender!).Canceled = true;
  793. Application.RequestStop ();
  794. }
  795. }
  796. [Fact]
  797. [AutoInitShutdown]
  798. public void Dialog_In_Window_With_Size_One_Button_Aligns ()
  799. {
  800. Application.Driver?.SetScreenSize (20, 5);
  801. // Override CM
  802. Window.DefaultBorderStyle = LineStyle.Single;
  803. Dialog.DefaultButtonAlignment = Alignment.Center;
  804. Dialog.DefaultBorderStyle = LineStyle.Single;
  805. Dialog.DefaultShadow = ShadowStyle.None;
  806. Button.DefaultShadow = ShadowStyle.None;
  807. var win = new Window ();
  808. var iterations = 0;
  809. Application.Iteration += OnApplicationOnIteration;
  810. var btn = $"{Glyphs.LeftBracket} Ok {Glyphs.RightBracket}";
  811. win.Loaded += (s, a) =>
  812. {
  813. var dlg = new Dialog { Width = 18, Height = 3, Buttons = [new () { Text = "Ok" }] };
  814. dlg.Loaded += (s, a) =>
  815. {
  816. AutoInitShutdownAttribute.RunIteration ();
  817. var expected = @$"
  818. ┌──────────────────┐
  819. │┌────────────────┐│
  820. ││ {btn} ││
  821. │└────────────────┘│
  822. └──────────────────┘";
  823. _ = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  824. };
  825. Application.Run (dlg);
  826. dlg.Dispose ();
  827. };
  828. Application.Run (win);
  829. Application.Iteration -= OnApplicationOnIteration;
  830. win.Dispose ();
  831. return;
  832. void OnApplicationOnIteration (object? s, IterationEventArgs a)
  833. {
  834. if (++iterations > 2)
  835. {
  836. Application.RequestStop ();
  837. }
  838. }
  839. }
  840. [Theory]
  841. [AutoInitShutdown]
  842. [InlineData (
  843. 5,
  844. @"
  845. ┌┌───────────────┐─┐
  846. ││ │ │
  847. ││ ⟦ Ok ⟧ │ │
  848. │└───────────────┘ │
  849. └──────────────────┘"
  850. )]
  851. [InlineData (
  852. 6,
  853. @"
  854. ┌┌───────────────┐─┐
  855. ││ │ │
  856. ││ │ │
  857. ││ ⟦ Ok ⟧ │ │
  858. │└───────────────┘ │
  859. └──────────────────┘"
  860. )]
  861. [InlineData (
  862. 7,
  863. @"
  864. ┌──────────────────┐
  865. │┌───────────────┐ │
  866. ││ │ │
  867. ││ │ │
  868. ││ ⟦ Ok ⟧ │ │
  869. │└───────────────┘ │
  870. └──────────────────┘"
  871. )]
  872. [InlineData (
  873. 8,
  874. @"
  875. ┌──────────────────┐
  876. │┌───────────────┐ │
  877. ││ │ │
  878. ││ │ │
  879. ││ │ │
  880. ││ ⟦ Ok ⟧ │ │
  881. │└───────────────┘ │
  882. └──────────────────┘"
  883. )]
  884. [InlineData (
  885. 9,
  886. @"
  887. ┌──────────────────┐
  888. │┌───────────────┐ │
  889. ││ │ │
  890. ││ │ │
  891. ││ │ │
  892. ││ │ │
  893. ││ ⟦ Ok ⟧ │ │
  894. │└───────────────┘ │
  895. └──────────────────┘"
  896. )]
  897. public void Dialog_In_Window_Without_Size_One_Button_Aligns (int height, string expected)
  898. {
  899. Application.Driver?.SetScreenSize (20, height);
  900. var win = new Window ();
  901. int iterations = -1;
  902. // Override CM
  903. Dialog.DefaultButtonAlignment = Alignment.Center;
  904. Dialog.DefaultBorderStyle = LineStyle.Single;
  905. Dialog.DefaultShadow = ShadowStyle.None;
  906. Button.DefaultShadow = ShadowStyle.None;
  907. Application.Iteration += OnApplicationOnIteration;
  908. Application.Run (win);
  909. Application.Iteration -= OnApplicationOnIteration;
  910. win.Dispose ();
  911. return;
  912. void OnApplicationOnIteration (object? s, IterationEventArgs a)
  913. {
  914. iterations++;
  915. if (iterations == 0)
  916. {
  917. var dlg = new Dialog { Buttons = [new () { Text = "Ok" }], Width = Dim.Percent (85), Height = Dim.Percent (85) };
  918. Application.Run (dlg);
  919. dlg.Dispose ();
  920. }
  921. else if (iterations == 1)
  922. {
  923. AutoInitShutdownAttribute.RunIteration ();
  924. // BUGBUG: This seems wrong; is it a bug in Dim.Percent(85)?? No
  925. _ = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  926. }
  927. else
  928. {
  929. Application.RequestStop ();
  930. }
  931. }
  932. }
  933. [Fact]
  934. [AutoInitShutdown]
  935. public void Dialog_Opened_From_Another_Dialog ()
  936. {
  937. Application.Driver?.SetScreenSize (30, 10);
  938. // Override CM
  939. Dialog.DefaultButtonAlignment = Alignment.Center;
  940. Dialog.DefaultBorderStyle = LineStyle.Single;
  941. Dialog.DefaultShadow = ShadowStyle.None;
  942. Button.DefaultShadow = ShadowStyle.None;
  943. var btn1 = new Button { Text = "press me 1" };
  944. Button? btn2 = null;
  945. Button? btn3 = null;
  946. string? expected = null;
  947. btn1.Accepting += (s, e) =>
  948. {
  949. btn2 = new () { Text = "Show Sub" };
  950. btn3 = new () { Text = "Close" };
  951. btn3.Accepting += (s, e) => Application.RequestStop ();
  952. btn2.Accepting += (s, e) =>
  953. {
  954. // Don't test MessageBox in Dialog unit tests!
  955. var subBtn = new Button { Text = "Ok", IsDefault = true };
  956. var subDlg = new Dialog { Text = "ya", Width = 20, Height = 5, Buttons = [subBtn] };
  957. subBtn.Accepting += (s, e) => Application.RequestStop (subDlg);
  958. Application.Run (subDlg);
  959. };
  960. var dlg = new Dialog
  961. {
  962. Buttons = [btn2, btn3],
  963. Width = Dim.Percent (85),
  964. Height = Dim.Percent (85)
  965. };
  966. Application.Run (dlg);
  967. dlg.Dispose ();
  968. };
  969. var btn =
  970. $"{Glyphs.LeftBracket}{Glyphs.LeftDefaultIndicator} Ok {Glyphs.RightDefaultIndicator}{Glyphs.RightBracket}";
  971. int iterations = -1;
  972. Application.Iteration += OnApplicationOnIteration;
  973. Application.Run ().Dispose ();
  974. Application.Iteration -= OnApplicationOnIteration;
  975. Application.Shutdown ();
  976. Assert.Equal (9, iterations);
  977. return;
  978. void OnApplicationOnIteration (object? s, IterationEventArgs a)
  979. {
  980. iterations++;
  981. switch (iterations)
  982. {
  983. case 0:
  984. Application.Current!.SetNeedsLayout ();
  985. Application.Current.SetNeedsDraw ();
  986. break;
  987. case 1:
  988. Assert.False (btn1.NewKeyDownEvent (Key.Space));
  989. break;
  990. // Now this happens on iteration 3 because Space triggers Run on the new dialog which itself causes another iteration
  991. // as it starts. Meaning we haven't exited case 1 when we enter case 2 from next Run stack frame.
  992. case 3:
  993. expected = @$"
  994. ┌───────────────────────┐
  995. │ │
  996. │ │
  997. │ │
  998. │ │
  999. │ │
  1000. │{Glyphs.LeftBracket} Show Sub {Glyphs.RightBracket} {Glyphs.LeftBracket} Close {Glyphs.RightBracket} │
  1001. └───────────────────────┘";
  1002. DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  1003. Assert.False (btn2!.NewKeyDownEvent (Key.Space));
  1004. break;
  1005. case 5:
  1006. DriverAssert.AssertDriverContentsWithFrameAre (
  1007. @$"
  1008. ┌───────────────────────┐
  1009. │ ┌──────────────────┐ │
  1010. │ │ya │ │
  1011. │ │ │ │
  1012. │ │ {btn} │ │
  1013. │ └──────────────────┘ │
  1014. │{Glyphs.LeftBracket} Show Sub {Glyphs.RightBracket} {Glyphs.LeftBracket} Close {Glyphs.RightBracket} │
  1015. └───────────────────────┘",
  1016. output);
  1017. Assert.False (Application.Current!.NewKeyDownEvent (Key.Enter));
  1018. break;
  1019. case 7:
  1020. DriverAssert.AssertDriverContentsWithFrameAre (expected!, output);
  1021. Assert.False (btn3!.NewKeyDownEvent (Key.Space));
  1022. break;
  1023. case 9:
  1024. DriverAssert.AssertDriverContentsWithFrameAre ("", output);
  1025. Application.RequestStop ();
  1026. break;
  1027. }
  1028. }
  1029. }
  1030. [Fact]
  1031. [AutoInitShutdown]
  1032. public void FileDialog_FileSystemWatcher ()
  1033. {
  1034. for (var i = 0; i < 8; i++)
  1035. {
  1036. var fd = new FileDialog ();
  1037. fd.Ready += (s, e) => Application.RequestStop ();
  1038. Application.Run (fd);
  1039. fd.Dispose ();
  1040. }
  1041. }
  1042. [Fact]
  1043. [AutoInitShutdown]
  1044. public void Location_Default ()
  1045. {
  1046. var d = new Dialog
  1047. {
  1048. Width = Dim.Percent (85),
  1049. Height = Dim.Percent (85)
  1050. };
  1051. Application.Begin (d);
  1052. Application.Driver?.SetScreenSize (100, 100);
  1053. // Default location is centered, so 100 / 2 - 85 / 2 = 7
  1054. var expected = 7;
  1055. Assert.Equal (new (expected, expected), d.Frame.Location);
  1056. d.Dispose ();
  1057. }
  1058. [Fact]
  1059. [AutoInitShutdown]
  1060. public void Location_Not_Default ()
  1061. {
  1062. var d = new Dialog { X = 1, Y = 1 };
  1063. Application.Begin (d);
  1064. Application.Driver?.SetScreenSize (100, 100);
  1065. // Default location is centered, so 100 / 2 - 85 / 2 = 7
  1066. var expected = 1;
  1067. Assert.Equal (new (expected, expected), d.Frame.Location);
  1068. d.Dispose ();
  1069. }
  1070. [Fact]
  1071. [AutoInitShutdown]
  1072. public void Location_When_Application_Top_Not_Default ()
  1073. {
  1074. // Override CM
  1075. Window.DefaultBorderStyle = LineStyle.Single;
  1076. Dialog.DefaultButtonAlignment = Alignment.Center;
  1077. Dialog.DefaultBorderStyle = LineStyle.Single;
  1078. Dialog.DefaultShadow = ShadowStyle.None;
  1079. Button.DefaultShadow = ShadowStyle.None;
  1080. var expected = 5;
  1081. var d = new Dialog { X = expected, Y = expected, Height = 5, Width = 5 };
  1082. Application.Begin (d);
  1083. Application.Driver?.SetScreenSize (20, 10);
  1084. // Default location is centered, so 100 / 2 - 85 / 2 = 7
  1085. Assert.Equal (new (expected, expected), d.Frame.Location);
  1086. DriverAssert.AssertDriverContentsWithFrameAre (
  1087. @"
  1088. ┌───┐
  1089. │ │
  1090. │ │
  1091. │ │
  1092. └───┘",
  1093. output
  1094. );
  1095. d.Dispose ();
  1096. }
  1097. [Fact]
  1098. [AutoInitShutdown]
  1099. public void Modal_Captures_All_Mouse ()
  1100. {
  1101. var top = new Toplevel
  1102. {
  1103. Id = "top"
  1104. };
  1105. var d = new Dialog
  1106. {
  1107. Width = 10,
  1108. Height = 10,
  1109. X = 1,
  1110. Y = 1
  1111. };
  1112. Application.Driver?.SetScreenSize (20, 20);
  1113. var iterations = 0;
  1114. Application.Iteration += OnApplicationOnIteration;
  1115. top.MouseEvent += (s, e) =>
  1116. {
  1117. // This should not be called because the dialog is modal
  1118. Assert.Fail ("Mouse event should not be captured by the top level when a dialog is modal.");
  1119. };
  1120. Application.Run (top);
  1121. top.Dispose ();
  1122. Application.Iteration -= OnApplicationOnIteration;
  1123. Application.Shutdown ();
  1124. return;
  1125. void OnApplicationOnIteration (object? s, IterationEventArgs a)
  1126. {
  1127. if (++iterations > 2)
  1128. {
  1129. Application.RequestStop ();
  1130. }
  1131. if (iterations == 1)
  1132. {
  1133. Application.Run (d);
  1134. d.Dispose ();
  1135. }
  1136. else if (iterations == 2)
  1137. {
  1138. // Mouse click outside of dialog
  1139. Application.Mouse.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Clicked, ScreenPosition = new (0, 0) });
  1140. }
  1141. }
  1142. }
  1143. [Fact]
  1144. [AutoInitShutdown]
  1145. public void One_Button_Works ()
  1146. {
  1147. SessionToken? sessionToken = null;
  1148. Button.DefaultShadow = ShadowStyle.None;
  1149. var title = "";
  1150. var btnText = "ok";
  1151. var buttonRow =
  1152. $"{Glyphs.VLine} {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket} {Glyphs.VLine}";
  1153. int width = buttonRow.Length;
  1154. Application.Driver?.SetScreenSize (buttonRow.Length, 10);
  1155. (sessionToken, Dialog dlg) = BeginButtonTestDialog (
  1156. title,
  1157. width,
  1158. Alignment.Center,
  1159. new Button { Text = btnText }
  1160. );
  1161. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  1162. Application.End (sessionToken);
  1163. dlg.Dispose ();
  1164. }
  1165. [Fact]
  1166. [AutoInitShutdown]
  1167. public void Run_Does_Not_Dispose_Dialog ()
  1168. {
  1169. var top = new Toplevel ();
  1170. Dialog dlg = new ();
  1171. dlg.Ready += Dlg_Ready;
  1172. Application.Run (dlg);
  1173. #if DEBUG_IDISPOSABLE
  1174. Assert.False (dlg.WasDisposed);
  1175. Assert.False (Application.Current!.WasDisposed);
  1176. Assert.NotEqual (top, Application.Current);
  1177. Assert.Equal (dlg, Application.Current);
  1178. #endif
  1179. // dlg wasn't disposed yet and it's possible to access to his properties
  1180. Assert.False (dlg.Canceled);
  1181. Assert.NotNull (dlg);
  1182. dlg.Canceled = true;
  1183. Assert.True (dlg.Canceled);
  1184. dlg.Dispose ();
  1185. top.Dispose ();
  1186. #if DEBUG_IDISPOSABLE
  1187. Assert.True (dlg.WasDisposed);
  1188. Assert.True (Application.Current.WasDisposed);
  1189. Assert.NotNull (Application.Current);
  1190. #endif
  1191. Application.Shutdown ();
  1192. Assert.Null (Application.Current);
  1193. return;
  1194. void Dlg_Ready (object? sender, EventArgs e) { Application.RequestStop (); }
  1195. }
  1196. [Fact]
  1197. [AutoInitShutdown]
  1198. public void Size_Default ()
  1199. {
  1200. var d = new Dialog
  1201. {
  1202. Width = Dim.Percent (85),
  1203. Height = Dim.Percent (85)
  1204. };
  1205. Application.Begin (d);
  1206. Application.Driver?.SetScreenSize (100, 100);
  1207. // Default size is Percent(85)
  1208. Assert.Equal (new ((int)(100 * .85), (int)(100 * .85)), d.Frame.Size);
  1209. d.Dispose ();
  1210. }
  1211. [Fact]
  1212. [AutoInitShutdown]
  1213. public void Size_Not_Default ()
  1214. {
  1215. Dialog.DefaultShadow = ShadowStyle.None;
  1216. Button.DefaultShadow = ShadowStyle.None;
  1217. var d = new Dialog { Width = 50, Height = 50 };
  1218. Application.Begin (d);
  1219. Application.Driver?.SetScreenSize (100, 100);
  1220. // Default size is Percent(85)
  1221. Assert.Equal (new (50, 50), d.Frame.Size);
  1222. d.Dispose ();
  1223. }
  1224. [Fact]
  1225. [AutoInitShutdown]
  1226. public void Zero_Buttons_Works ()
  1227. {
  1228. SessionToken? sessionToken = null;
  1229. var title = "1234";
  1230. var buttonRow = $"{Glyphs.VLine} {Glyphs.VLine}";
  1231. int width = buttonRow.Length;
  1232. Application.Driver?.SetScreenSize (buttonRow.Length, 3);
  1233. (sessionToken, Dialog dlg) = BeginButtonTestDialog (title, width, Alignment.Center);
  1234. DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
  1235. Application.End (sessionToken);
  1236. dlg.Dispose ();
  1237. }
  1238. private (SessionToken, Dialog) BeginButtonTestDialog (
  1239. string title,
  1240. int width,
  1241. Alignment align,
  1242. params Button [] btns
  1243. )
  1244. {
  1245. // Override CM
  1246. Dialog.DefaultButtonAlignment = Alignment.Center;
  1247. Dialog.DefaultBorderStyle = LineStyle.Single;
  1248. Dialog.DefaultShadow = ShadowStyle.None;
  1249. Button.DefaultShadow = ShadowStyle.None;
  1250. var dlg = new Dialog
  1251. {
  1252. Title = title,
  1253. X = 0,
  1254. Y = 0,
  1255. Width = width,
  1256. Height = 1,
  1257. ButtonAlignment = align,
  1258. Buttons = btns
  1259. };
  1260. // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
  1261. dlg.Border!.Thickness = new (1, 0, 1, 0);
  1262. SessionToken sessionToken = Application.Begin (dlg);
  1263. dlg.SetNeedsDraw ();
  1264. dlg.SetNeedsLayout ();
  1265. AutoInitShutdownAttribute.RunIteration ();
  1266. return (sessionToken, dlg);
  1267. }
  1268. }