DialogTests.cs 58 KB

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