ConfigurationMangerTests.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. using System.Diagnostics;
  2. using System.Reflection;
  3. using System.Text.Json;
  4. using UnitTests;
  5. using Xunit.Abstractions;
  6. using static Terminal.Gui.ConfigurationManager;
  7. #pragma warning disable IDE1006
  8. namespace Terminal.Gui.ConfigurationTests;
  9. public class ConfigurationManagerTests
  10. {
  11. private readonly ITestOutputHelper _output;
  12. public ConfigurationManagerTests (ITestOutputHelper output)
  13. {
  14. _output = output;
  15. }
  16. public static readonly JsonSerializerOptions _jsonOptions = new ()
  17. {
  18. Converters = { new AttributeJsonConverter (), new ColorJsonConverter () }
  19. };
  20. [Fact]
  21. public void Apply_Raises_Applied ()
  22. {
  23. Reset ();
  24. Applied += ConfigurationManager_Applied;
  25. var fired = false;
  26. void ConfigurationManager_Applied (object sender, ConfigurationManagerEventArgs obj)
  27. {
  28. fired = true;
  29. // assert
  30. Assert.Equal (KeyCode.Q, Application.QuitKey.KeyCode);
  31. Assert.Equal (KeyCode.F, Application.NextTabGroupKey.KeyCode);
  32. Assert.Equal (KeyCode.B, Application.PrevTabGroupKey.KeyCode);
  33. }
  34. // act
  35. Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
  36. Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
  37. Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
  38. Apply ();
  39. // assert
  40. Assert.True (fired);
  41. Applied -= ConfigurationManager_Applied;
  42. Reset ();
  43. }
  44. [Fact]
  45. public void DeepMemberWiseCopyTest ()
  46. {
  47. // Value types
  48. var stringDest = "Destination";
  49. var stringSrc = "Source";
  50. object stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
  51. Assert.Equal (stringSrc, stringCopy);
  52. stringDest = "Destination";
  53. stringSrc = "Destination";
  54. stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
  55. Assert.Equal (stringSrc, stringCopy);
  56. stringDest = "Destination";
  57. stringSrc = null;
  58. stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
  59. Assert.Equal (stringSrc, stringCopy);
  60. stringDest = "Destination";
  61. stringSrc = string.Empty;
  62. stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
  63. Assert.Equal (stringSrc, stringCopy);
  64. var boolDest = true;
  65. var boolSrc = false;
  66. object boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
  67. Assert.Equal (boolSrc, boolCopy);
  68. boolDest = false;
  69. boolSrc = true;
  70. boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
  71. Assert.Equal (boolSrc, boolCopy);
  72. boolDest = true;
  73. boolSrc = true;
  74. boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
  75. Assert.Equal (boolSrc, boolCopy);
  76. boolDest = false;
  77. boolSrc = false;
  78. boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
  79. Assert.Equal (boolSrc, boolCopy);
  80. // Structs
  81. var attrDest = new Attribute (Color.Black);
  82. var attrSrc = new Attribute (Color.White);
  83. object attrCopy = DeepMemberWiseCopy (attrSrc, attrDest);
  84. Assert.Equal (attrSrc, attrCopy);
  85. // Classes
  86. var colorschemeDest = new ColorScheme { Disabled = new Attribute (Color.Black) };
  87. var colorschemeSrc = new ColorScheme { Disabled = new Attribute (Color.White) };
  88. object colorschemeCopy = DeepMemberWiseCopy (colorschemeSrc, colorschemeDest);
  89. Assert.Equal (colorschemeSrc, colorschemeCopy);
  90. // Dictionaries
  91. Dictionary<string, Attribute> dictDest = new () { { "Disabled", new Attribute (Color.Black) } };
  92. Dictionary<string, Attribute> dictSrc = new () { { "Disabled", new Attribute (Color.White) } };
  93. Dictionary<string, Attribute> dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
  94. Assert.Equal (dictSrc, dictCopy);
  95. dictDest = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.Black) } };
  96. dictSrc = new Dictionary<string, Attribute>
  97. {
  98. { "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) }
  99. };
  100. dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
  101. Assert.Equal (dictSrc, dictCopy);
  102. // src adds an item
  103. dictDest = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.Black) } };
  104. dictSrc = new Dictionary<string, Attribute>
  105. {
  106. { "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) }
  107. };
  108. dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
  109. Assert.Equal (2, dictCopy!.Count);
  110. Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]);
  111. Assert.Equal (dictSrc ["Normal"], dictCopy ["Normal"]);
  112. // src updates only one item
  113. dictDest = new Dictionary<string, Attribute>
  114. {
  115. { "Disabled", new Attribute (Color.Black) }, { "Normal", new Attribute (Color.White) }
  116. };
  117. dictSrc = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.White) } };
  118. dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
  119. Assert.Equal (2, dictCopy!.Count);
  120. Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]);
  121. Assert.Equal (dictDest ["Normal"], dictCopy ["Normal"]);
  122. }
  123. public class DeepCopyTest ()
  124. {
  125. public static Key key = Key.Esc;
  126. }
  127. [Fact]
  128. public void Illustrate_DeepMemberWiseCopy_Breaks_Dictionary ()
  129. {
  130. Assert.Equal (Key.Esc, DeepCopyTest.key);
  131. Dictionary<Key, string> dict = new Dictionary<Key, string> (new KeyEqualityComparer ());
  132. dict.Add (new (DeepCopyTest.key), "Esc");
  133. Assert.Contains (Key.Esc, dict);
  134. DeepCopyTest.key = (Key)DeepMemberWiseCopy (Key.Q.WithCtrl, DeepCopyTest.key);
  135. Assert.Equal (Key.Q.WithCtrl, DeepCopyTest.key);
  136. Assert.Equal (Key.Esc, dict.Keys.ToArray () [0]);
  137. var eq = new KeyEqualityComparer ();
  138. Assert.True (eq.Equals (Key.Q.WithCtrl, DeepCopyTest.key));
  139. Assert.Equal (Key.Q.WithCtrl.GetHashCode (), DeepCopyTest.key.GetHashCode ());
  140. Assert.Equal (eq.GetHashCode (Key.Q.WithCtrl), eq.GetHashCode (DeepCopyTest.key));
  141. Assert.Equal (Key.Q.WithCtrl.GetHashCode (), eq.GetHashCode (DeepCopyTest.key));
  142. Assert.True (dict.ContainsKey (Key.Esc));
  143. dict.Remove (Key.Esc);
  144. dict.Add (new (DeepCopyTest.key), "Ctrl+Q");
  145. Assert.True (dict.ContainsKey (Key.Q.WithCtrl));
  146. }
  147. [Fact]
  148. public void Load_Raises_Updated ()
  149. {
  150. ThrowOnJsonErrors = true;
  151. Locations = ConfigLocations.All;
  152. Reset ();
  153. Assert.Equal (Key.Esc, (((Key)Settings! ["Application.QuitKey"].PropertyValue)!).KeyCode);
  154. Updated += ConfigurationManager_Updated;
  155. var fired = false;
  156. void ConfigurationManager_Updated (object sender, ConfigurationManagerEventArgs obj)
  157. {
  158. fired = true;
  159. }
  160. // Act
  161. // Reset to cause load to raise event
  162. Load (true);
  163. // assert
  164. Assert.True (fired);
  165. Updated -= ConfigurationManager_Updated;
  166. // clean up
  167. Locations = ConfigLocations.Default;
  168. Reset ();
  169. }
  170. [Fact]
  171. public void Load_Performance_Check ()
  172. {
  173. Locations = ConfigLocations.All;
  174. Reset ();
  175. // Start stopwatch
  176. Stopwatch stopwatch = new Stopwatch ();
  177. stopwatch.Start ();
  178. // Act
  179. Load (true);
  180. Apply();
  181. // Stop stopwatch
  182. stopwatch.Stop ();
  183. // Assert
  184. _output.WriteLine ($"Load took {stopwatch.ElapsedMilliseconds} ms");
  185. }
  186. [Fact]
  187. public void Load_Loads_Custom_Json ()
  188. {
  189. // arrange
  190. Locations = ConfigLocations.All;
  191. Reset ();
  192. ThrowOnJsonErrors = true;
  193. Assert.Equal (Key.Esc, (Key)Settings! ["Application.QuitKey"].PropertyValue);
  194. // act
  195. RuntimeConfig = """
  196. {
  197. "Application.QuitKey": "Ctrl-Q"
  198. }
  199. """;
  200. Load (false);
  201. // assert
  202. Assert.Equal (Key.Q.WithCtrl, (Key)Settings ["Application.QuitKey"].PropertyValue);
  203. // clean up
  204. Locations = ConfigLocations.Default;
  205. Reset ();
  206. }
  207. //[Fact]
  208. //[AutoInitShutdown]
  209. //public void LoadConfigurationFromAllSources_ShouldLoadSettingsFromAllSources ()
  210. //{
  211. // //var _configFilename = "config.json";
  212. // //// Arrange
  213. // //// Create a mock of the configuration files in all sources
  214. // //// Home directory
  215. // //string homeDir = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".tui");
  216. // //if (!Directory.Exists (homeDir)) {
  217. // // Directory.CreateDirectory (homeDir);
  218. // //}
  219. // //string globalConfigFile = Path.Combine (homeDir, _configFilename);
  220. // //string appSpecificConfigFile = Path.Combine (homeDir, "appname.config.json");
  221. // //File.WriteAllText (globalConfigFile, "{\"Settings\": {\"TestSetting\":\"Global\"}}");
  222. // //File.WriteAllText (appSpecificConfigFile, "{\"Settings\": {\"TestSetting\":\"AppSpecific\"}}");
  223. // //// App directory
  224. // //string appDir = Directory.GetCurrentDirectory ();
  225. // //string appDirGlobalConfigFile = Path.Combine (appDir, _configFilename);
  226. // //string appDirAppSpecificConfigFile = Path.Combine (appDir, "appname.config.json");
  227. // //File.WriteAllText (appDirGlobalConfigFile, "{\"Settings\": {\"TestSetting\":\"GlobalAppDir\"}}");
  228. // //File.WriteAllText (appDirAppSpecificConfigFile, "{\"Settings\": {\"TestSetting\":\"AppSpecificAppDir\"}}");
  229. // //// App resources
  230. // //// ...
  231. // //// Act
  232. // //ConfigurationManager.Locations = ConfigurationManager.ConfigLocation.All;
  233. // //ConfigurationManager.Load ();
  234. // //// Assert
  235. // //// Check that the settings from the highest precedence source are loaded
  236. // //Assert.Equal ("AppSpecific", ConfigurationManager.Config.Settings.TestSetting);
  237. //}
  238. [Fact]
  239. public void Reset_Raises_Updated ()
  240. {
  241. ConfigLocations savedLocations = Locations;
  242. Locations = ConfigLocations.All;
  243. Reset ();
  244. Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
  245. Updated += ConfigurationManager_Updated;
  246. var fired = false;
  247. void ConfigurationManager_Updated (object sender, ConfigurationManagerEventArgs obj)
  248. {
  249. fired = true;
  250. }
  251. // Act
  252. Reset ();
  253. // assert
  254. Assert.True (fired);
  255. Updated -= ConfigurationManager_Updated;
  256. Reset ();
  257. Locations = savedLocations;
  258. }
  259. [Fact]
  260. public void Reset_and_ResetLoadWithLibraryResourcesOnly_are_same ()
  261. {
  262. Locations = ConfigLocations.Default;
  263. // arrange
  264. Reset ();
  265. Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
  266. Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
  267. Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
  268. Settings.Apply ();
  269. // assert apply worked
  270. Assert.Equal (KeyCode.Q, Application.QuitKey.KeyCode);
  271. Assert.Equal (KeyCode.F, Application.NextTabGroupKey.KeyCode);
  272. Assert.Equal (KeyCode.B, Application.PrevTabGroupKey.KeyCode);
  273. //act
  274. Reset ();
  275. // assert
  276. Assert.NotEmpty (Themes!);
  277. Assert.Equal ("Default", Themes.Theme);
  278. Assert.Equal (Key.Esc, Application.QuitKey);
  279. Assert.Equal (Key.F6, Application.NextTabGroupKey);
  280. Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey);
  281. // arrange
  282. Settings ["Application.QuitKey"].PropertyValue = Key.Q;
  283. Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
  284. Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
  285. Settings.Apply ();
  286. Locations = ConfigLocations.Default;
  287. // act
  288. Reset ();
  289. Load ();
  290. // assert
  291. Assert.NotEmpty (Themes);
  292. Assert.Equal ("Default", Themes.Theme);
  293. Assert.Equal (KeyCode.Esc, Application.QuitKey.KeyCode);
  294. Assert.Equal (Key.F6, Application.NextTabGroupKey);
  295. Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey);
  296. Reset ();
  297. }
  298. [Fact]
  299. public void Reset_Resets ()
  300. {
  301. Locations = ConfigLocations.Default;
  302. Reset ();
  303. Assert.NotEmpty (Themes!);
  304. Assert.Equal ("Default", Themes.Theme);
  305. }
  306. //[Fact ()]
  307. //public void LoadFromJsonTest ()
  308. //{
  309. // Assert.True (false, "This test needs an implementation");
  310. //}
  311. //[Fact ()]
  312. //public void ToJsonTest ()
  313. //{
  314. // Assert.True (false, "This test needs an implementation");
  315. //}
  316. //[Fact ()]
  317. //public void UpdateConfigurationTest ()
  318. //{
  319. // Assert.True (false, "This test needs an implementation");
  320. //}
  321. //[Fact ()]
  322. //public void UpdateConfigurationFromFileTest ()
  323. //{
  324. // Assert.True (false, "This test needs an implementation");
  325. //}
  326. //[Fact ()]
  327. //public void SaveHardCodedDefaultsTest ()
  328. //{
  329. // Assert.True (false, "This test needs an implementation");
  330. //}
  331. //[Fact ()]
  332. //public void LoadGlobalFromLibraryResourceTest ()
  333. //{
  334. // Assert.True (false, "This test needs an implementation");
  335. //}
  336. //[Fact ()]
  337. //public void LoadGlobalFromAppDirectoryTest ()
  338. //{
  339. // Assert.True (false, "This test needs an implementation");
  340. //}
  341. //[Fact ()]
  342. //public void LoadGlobalFromHomeDirectoryTest ()
  343. //{
  344. // Assert.True (false, "This test needs an implementation");
  345. //}
  346. //[Fact ()]
  347. //public void LoadAppFromAppResourcesTest ()
  348. //{
  349. // Assert.True (false, "This test needs an implementation");
  350. //}
  351. //[Fact ()]
  352. //public void LoadAppFromAppDirectoryTest ()
  353. //{
  354. // Assert.True (false, "This test needs an implementation");
  355. //}
  356. //[Fact ()]
  357. //public void LoadAppFromHomeDirectoryTest ()
  358. //{
  359. // Assert.True (false, "This test needs an implementation");
  360. //}
  361. //[Fact ()]
  362. //public void LoadTest ()
  363. //{
  364. // Assert.True (false, "This test needs an implementation");
  365. //}
  366. /// <summary>Save the `config.json` file; this can be used to update the file in `Terminal.Gui.Resources.config.json'.</summary>
  367. /// <remarks>
  368. /// IMPORTANT: For the file generated to be valid, this must be the ONLY test run. Config Properties are all
  369. /// static and thus can be overwritten by other tests.
  370. /// </remarks>
  371. [Fact]
  372. public void SaveDefaults ()
  373. {
  374. Initialize ();
  375. Reset ();
  376. // Get the hard coded settings
  377. GetHardCodedDefaults ();
  378. // Serialize to a JSON string
  379. string json = ToJson ();
  380. // Write the JSON string to the file
  381. File.WriteAllText ("config.json", json);
  382. }
  383. [Fact]
  384. public void TestConfigProperties ()
  385. {
  386. Locations = ConfigLocations.All;
  387. Reset ();
  388. Assert.NotEmpty (Settings!);
  389. // test that all ConfigProperties have our attribute
  390. Assert.All (
  391. Settings,
  392. item => Assert.NotEmpty (
  393. item.Value.PropertyInfo!.CustomAttributes.Where (
  394. a => a.AttributeType == typeof (SerializableConfigurationProperty)
  395. )
  396. )
  397. );
  398. #pragma warning disable xUnit2029
  399. Assert.Empty (
  400. Settings.Where (
  401. cp => cp.Value.PropertyInfo!.GetCustomAttribute (
  402. typeof (SerializableConfigurationProperty)
  403. )
  404. == null
  405. )
  406. );
  407. #pragma warning restore xUnit2029
  408. // Application is a static class
  409. PropertyInfo pi = typeof (Application).GetProperty ("QuitKey");
  410. Assert.Equal (pi, Settings ["Application.QuitKey"].PropertyInfo);
  411. // FrameView is not a static class and DefaultBorderStyle is Scope.Scheme
  412. pi = typeof (FrameView).GetProperty ("DefaultBorderStyle");
  413. Assert.False (Settings.ContainsKey ("FrameView.DefaultBorderStyle"));
  414. Assert.True (Themes! ["Default"].ContainsKey ("FrameView.DefaultBorderStyle"));
  415. Assert.Equal (pi, Themes! ["Default"] ["FrameView.DefaultBorderStyle"].PropertyInfo);
  416. }
  417. [Fact]
  418. public void TestConfigPropertyOmitClassName ()
  419. {
  420. ConfigLocations savedLocations = Locations;
  421. Locations = ConfigLocations.All;
  422. // Color.ColorSchemes is serialized as "ColorSchemes", not "Colors.ColorSchemes"
  423. PropertyInfo pi = typeof (Colors).GetProperty ("ColorSchemes");
  424. var scp = (SerializableConfigurationProperty)pi!.GetCustomAttribute (typeof (SerializableConfigurationProperty));
  425. Assert.True (scp!.Scope == typeof (ThemeScope));
  426. Assert.True (scp.OmitClassName);
  427. Reset ();
  428. Assert.Equal (pi, Themes! ["Default"] ["ColorSchemes"].PropertyInfo);
  429. Locations = savedLocations;
  430. }
  431. [Fact]
  432. [AutoInitShutdown (configLocation: ConfigLocations.Default)]
  433. public void TestConfigurationManagerInitDriver ()
  434. {
  435. Assert.Equal ("Default", Themes!.Theme);
  436. Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"]!.Normal.Foreground);
  437. Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
  438. // Change Base
  439. Stream json = ToStream ();
  440. Settings!.Update (json, "TestConfigurationManagerInitDriver", ConfigLocations.Runtime);
  441. Dictionary<string, ColorScheme> colorSchemes =
  442. (Dictionary<string, ColorScheme>)Themes [Themes.Theme] ["ColorSchemes"].PropertyValue;
  443. Assert.Equal (Colors.ColorSchemes ["Base"], colorSchemes! ["Base"]);
  444. Assert.Equal (Colors.ColorSchemes ["TopLevel"], colorSchemes ["TopLevel"]);
  445. Assert.Equal (Colors.ColorSchemes ["Error"], colorSchemes ["Error"]);
  446. Assert.Equal (Colors.ColorSchemes ["Dialog"], colorSchemes ["Dialog"]);
  447. Assert.Equal (Colors.ColorSchemes ["Menu"], colorSchemes ["Menu"]);
  448. Colors.ColorSchemes ["Base"] = colorSchemes ["Base"];
  449. Colors.ColorSchemes ["TopLevel"] = colorSchemes ["TopLevel"];
  450. Colors.ColorSchemes ["Error"] = colorSchemes ["Error"];
  451. Colors.ColorSchemes ["Dialog"] = colorSchemes ["Dialog"];
  452. Colors.ColorSchemes ["Menu"] = colorSchemes ["Menu"];
  453. Assert.Equal (colorSchemes ["Base"], Colors.ColorSchemes ["Base"]);
  454. Assert.Equal (colorSchemes ["TopLevel"], Colors.ColorSchemes ["TopLevel"]);
  455. Assert.Equal (colorSchemes ["Error"], Colors.ColorSchemes ["Error"]);
  456. Assert.Equal (colorSchemes ["Dialog"], Colors.ColorSchemes ["Dialog"]);
  457. Assert.Equal (colorSchemes ["Menu"], Colors.ColorSchemes ["Menu"]);
  458. }
  459. [Fact]
  460. [AutoInitShutdown (configLocation: ConfigLocations.None)]
  461. public void TestConfigurationManagerInitDriver_NoLocations ()
  462. {
  463. // TODO: Write this test
  464. }
  465. [Fact]
  466. public void TestConfigurationManagerInvalidJsonLogs ()
  467. {
  468. Application.Init (new FakeDriver ());
  469. ThrowOnJsonErrors = false;
  470. // "brown" is not a color
  471. var json = @"
  472. {
  473. ""Themes"" : [
  474. {
  475. ""Default"" : {
  476. ""ColorSchemes"": [
  477. {
  478. ""UserDefined"": {
  479. ""hotNormal"": {
  480. ""foreground"": ""brown"",
  481. ""background"": ""1234""
  482. }
  483. }
  484. }
  485. ]
  486. }
  487. }
  488. }
  489. }";
  490. Settings!.Update (json, "test", ConfigLocations.Runtime);
  491. // AbNormal is not a ColorScheme attribute
  492. json = @"
  493. {
  494. ""Themes"" : [
  495. {
  496. ""Default"" : {
  497. ""ColorSchemes"": [
  498. {
  499. ""UserDefined"": {
  500. ""AbNormal"": {
  501. ""foreground"": ""green"",
  502. ""background"": ""black""
  503. }
  504. }
  505. }
  506. ]
  507. }
  508. }
  509. }
  510. }";
  511. Settings.Update (json, "test", ConfigLocations.Runtime);
  512. // Modify hotNormal background only
  513. json = @"
  514. {
  515. ""Themes"" : [
  516. {
  517. ""Default"" : {
  518. ""ColorSchemes"": [
  519. {
  520. ""UserDefined"": {
  521. ""hotNormal"": {
  522. ""background"": ""cyan""
  523. }
  524. }
  525. }
  526. ]
  527. }
  528. }
  529. }
  530. }";
  531. Settings.Update (json, "test", ConfigLocations.Runtime);
  532. Settings.Update ("{}}", "test", ConfigLocations.Runtime);
  533. Assert.NotEqual (0, _jsonErrors.Length);
  534. Application.Shutdown ();
  535. ThrowOnJsonErrors = false;
  536. }
  537. [Fact]
  538. [AutoInitShutdown]
  539. public void TestConfigurationManagerInvalidJsonThrows ()
  540. {
  541. ThrowOnJsonErrors = true;
  542. // "yellow" is not a color
  543. var json = @"
  544. {
  545. ""Themes"" : [
  546. {
  547. ""Default"" : {
  548. ""ColorSchemes"": [
  549. {
  550. ""UserDefined"": {
  551. ""hotNormal"": {
  552. ""foreground"": ""brownish"",
  553. ""background"": ""1234""
  554. }
  555. }
  556. }
  557. ]
  558. }
  559. }
  560. ]
  561. }";
  562. var jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
  563. Assert.Equal ("Unexpected color name: brownish.", jsonException.Message);
  564. // AbNormal is not a ColorScheme attribute
  565. json = @"
  566. {
  567. ""Themes"" : [
  568. {
  569. ""Default"" : {
  570. ""ColorSchemes"": [
  571. {
  572. ""UserDefined"": {
  573. ""AbNormal"": {
  574. ""foreground"": ""green"",
  575. ""background"": ""black""
  576. }
  577. }
  578. }
  579. ]
  580. }
  581. }
  582. ]
  583. }";
  584. jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
  585. Assert.Equal ("Unrecognized ColorScheme Attribute name: AbNormal.", jsonException.Message);
  586. // Modify hotNormal background only
  587. json = @"
  588. {
  589. ""Themes"" : [
  590. {
  591. ""Default"" : {
  592. ""ColorSchemes"": [
  593. {
  594. ""UserDefined"": {
  595. ""hotNormal"": {
  596. ""background"": ""cyan""
  597. }
  598. }
  599. }
  600. ]
  601. }
  602. }
  603. ]
  604. }";
  605. jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
  606. Assert.Equal ("Both Foreground and Background colors must be provided.", jsonException.Message);
  607. // Unknown property
  608. json = @"
  609. {
  610. ""Unknown"" : ""Not known""
  611. }";
  612. jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
  613. Assert.StartsWith ("Unknown property", jsonException.Message);
  614. Assert.Equal (0, _jsonErrors.Length);
  615. ThrowOnJsonErrors = false;
  616. }
  617. [Fact]
  618. [AutoInitShutdown]
  619. public void TestConfigurationManagerToJson ()
  620. {
  621. Reset ();
  622. GetHardCodedDefaults ();
  623. Stream stream = ToStream ();
  624. Settings!.Update (stream, "TestConfigurationManagerToJson", ConfigLocations.Runtime);
  625. }
  626. [Fact]
  627. public void TestConfigurationManagerUpdateFromJson ()
  628. {
  629. ConfigLocations savedLocations = Locations;
  630. Locations = ConfigLocations.All;
  631. // Arrange
  632. var json = @"
  633. {
  634. ""$schema"": ""https://gui-cs.github.io/Terminal.GuiV2Docs/schemas/tui-config-schema.json"",
  635. ""Application.QuitKey"": ""Alt-Z"",
  636. ""Theme"": ""Default"",
  637. ""Themes"": [
  638. {
  639. ""Default"": {
  640. ""ColorSchemes"": [
  641. {
  642. ""TopLevel"": {
  643. ""Normal"": {
  644. ""Foreground"": ""BrightGreen"",
  645. ""Background"": ""Black""
  646. },
  647. ""Focus"": {
  648. ""Foreground"": ""White"",
  649. ""Background"": ""Cyan""
  650. },
  651. ""HotNormal"": {
  652. ""Foreground"": ""Yellow"",
  653. ""Background"": ""Black""
  654. },
  655. ""HotFocus"": {
  656. ""Foreground"": ""Blue"",
  657. ""Background"": ""Cyan""
  658. },
  659. ""Disabled"": {
  660. ""Foreground"": ""DarkGray"",
  661. ""Background"": ""Black""
  662. }
  663. }
  664. },
  665. {
  666. ""Base"": {
  667. ""Normal"": {
  668. ""Foreground"": ""White"",
  669. ""Background"": ""Blue""
  670. },
  671. ""Focus"": {
  672. ""Foreground"": ""Black"",
  673. ""Background"": ""Gray""
  674. },
  675. ""HotNormal"": {
  676. ""Foreground"": ""BrightCyan"",
  677. ""Background"": ""Blue""
  678. },
  679. ""HotFocus"": {
  680. ""Foreground"": ""BrightBlue"",
  681. ""Background"": ""Gray""
  682. },
  683. ""Disabled"": {
  684. ""Foreground"": ""DarkGray"",
  685. ""Background"": ""Blue""
  686. }
  687. }
  688. },
  689. {
  690. ""Dialog"": {
  691. ""Normal"": {
  692. ""Foreground"": ""Black"",
  693. ""Background"": ""Gray""
  694. },
  695. ""Focus"": {
  696. ""Foreground"": ""White"",
  697. ""Background"": ""DarkGray""
  698. },
  699. ""HotNormal"": {
  700. ""Foreground"": ""Blue"",
  701. ""Background"": ""Gray""
  702. },
  703. ""HotFocus"": {
  704. ""Foreground"": ""BrightYellow"",
  705. ""Background"": ""DarkGray""
  706. },
  707. ""Disabled"": {
  708. ""Foreground"": ""Gray"",
  709. ""Background"": ""DarkGray""
  710. }
  711. }
  712. },
  713. {
  714. ""Menu"": {
  715. ""Normal"": {
  716. ""Foreground"": ""White"",
  717. ""Background"": ""DarkGray""
  718. },
  719. ""Focus"": {
  720. ""Foreground"": ""White"",
  721. ""Background"": ""Black""
  722. },
  723. ""HotNormal"": {
  724. ""Foreground"": ""BrightYellow"",
  725. ""Background"": ""DarkGray""
  726. },
  727. ""HotFocus"": {
  728. ""Foreground"": ""BrightYellow"",
  729. ""Background"": ""Black""
  730. },
  731. ""Disabled"": {
  732. ""Foreground"": ""Gray"",
  733. ""Background"": ""DarkGray""
  734. }
  735. }
  736. },
  737. {
  738. ""Error"": {
  739. ""Normal"": {
  740. ""Foreground"": ""Red"",
  741. ""Background"": ""White""
  742. },
  743. ""Focus"": {
  744. ""Foreground"": ""Black"",
  745. ""Background"": ""BrightRed""
  746. },
  747. ""HotNormal"": {
  748. ""Foreground"": ""Black"",
  749. ""Background"": ""White""
  750. },
  751. ""HotFocus"": {
  752. ""Foreground"": ""White"",
  753. ""Background"": ""BrightRed""
  754. },
  755. ""Disabled"": {
  756. ""Foreground"": ""DarkGray"",
  757. ""Background"": ""White""
  758. }
  759. }
  760. }
  761. ]
  762. }
  763. }
  764. ]
  765. }
  766. ";
  767. Reset ();
  768. ThrowOnJsonErrors = true;
  769. Settings!.Update (json, "TestConfigurationManagerUpdateFromJson", ConfigLocations.Runtime);
  770. Assert.Equal (KeyCode.Esc, Application.QuitKey.KeyCode);
  771. Assert.Equal (KeyCode.Z | KeyCode.AltMask, ((Key)Settings ["Application.QuitKey"].PropertyValue)!.KeyCode);
  772. Assert.Equal ("Default", Themes!.Theme);
  773. Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"]!.Normal.Foreground);
  774. Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
  775. Dictionary<string, ColorScheme> colorSchemes =
  776. (Dictionary<string, ColorScheme>)Themes.First ().Value ["ColorSchemes"].PropertyValue;
  777. Assert.Equal (new Color (Color.White), colorSchemes! ["Base"].Normal.Foreground);
  778. Assert.Equal (new Color (Color.Blue), colorSchemes ["Base"].Normal.Background);
  779. // Now re-apply
  780. Apply ();
  781. Assert.Equal (KeyCode.Z | KeyCode.AltMask, Application.QuitKey.KeyCode);
  782. Assert.Equal ("Default", Themes.Theme);
  783. Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"].Normal.Foreground);
  784. Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
  785. Reset ();
  786. Locations = savedLocations;
  787. }
  788. [Fact]
  789. public void UseWithoutResetDoesNotThrow ()
  790. {
  791. Initialize ();
  792. _ = Settings;
  793. }
  794. }