ThemeScopeTests.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #nullable enable
  2. using System.Collections.Concurrent;
  3. using System.Collections.Frozen;
  4. using System.Collections.Immutable;
  5. using System.Text.Json;
  6. using static Terminal.Gui.Configuration.ConfigurationManager;
  7. namespace Terminal.Gui.ConfigurationTests;
  8. public class ThemeScopeTests
  9. {
  10. [Fact]
  11. public void Load_AllThemesPresent ()
  12. {
  13. Enable (ConfigLocations.HardCoded);
  14. Load (ConfigLocations.All);
  15. Assert.True (ThemeManager.Themes!.ContainsKey ("Default"));
  16. Assert.True (ThemeManager.Themes.ContainsKey ("Dark"));
  17. Assert.True (ThemeManager.Themes.ContainsKey ("Light"));
  18. Disable (true);
  19. }
  20. [Fact]
  21. public void Apply_ShouldApplyUpdatedProperties ()
  22. {
  23. Enable (ConfigLocations.HardCoded);
  24. Assert.NotEmpty (ThemeManager.Themes!);
  25. Alignment savedButtonAlignment = Dialog.DefaultButtonAlignment;
  26. Alignment newButtonAlignment = Alignment.Center != savedButtonAlignment ? Alignment.Center : Alignment.Start;
  27. ThemeManager.GetCurrentTheme () ["Dialog.DefaultButtonAlignment"].PropertyValue = newButtonAlignment;
  28. LineStyle savedBorderStyle = Dialog.DefaultBorderStyle;
  29. var newBorderStyle = LineStyle.HeavyDotted;
  30. ThemeManager.GetCurrentTheme () ["Dialog.DefaultBorderStyle"].PropertyValue = newBorderStyle;
  31. ThemeManager.Themes! [ThemeManager.Theme]!.Apply ();
  32. Assert.Equal (newButtonAlignment, Dialog.DefaultButtonAlignment);
  33. Assert.Equal (newBorderStyle, Dialog.DefaultBorderStyle);
  34. // Replace with the savedValue to avoid failures on other unit tests that rely on the default value
  35. ThemeManager.GetCurrentTheme () ["Dialog.DefaultButtonAlignment"].PropertyValue = savedButtonAlignment;
  36. ThemeManager.GetCurrentTheme () ["Dialog.DefaultBorderStyle"].PropertyValue = savedBorderStyle;
  37. ThemeManager.GetCurrentTheme ().Apply ();
  38. Assert.Equal (savedButtonAlignment, Dialog.DefaultButtonAlignment);
  39. Assert.Equal (savedBorderStyle, Dialog.DefaultBorderStyle);
  40. Disable (true);
  41. }
  42. [Fact]
  43. public void UpdateToHardCodedDefaults_Resets_Config_Does_Not_Apply ()
  44. {
  45. Enable (ConfigLocations.HardCoded);
  46. Load (ConfigLocations.LibraryResources);
  47. Assert.Equal ("Default", ThemeManager.Theme);
  48. ThemeManager.Theme = "Dark";
  49. Assert.Equal ("Dark", ThemeManager.Theme);
  50. Apply ();
  51. Assert.Equal ("Dark", ThemeManager.Theme);
  52. // Act
  53. ThemeManager.LoadHardCodedDefaults ();
  54. Assert.Equal ("Default", ThemeManager.Theme);
  55. Disable (true);
  56. }
  57. [Fact]
  58. public void Serialize_Themes_RoundTrip ()
  59. {
  60. Enable (ConfigLocations.HardCoded);
  61. IDictionary<string, ThemeScope> initial = ThemeManager.Themes!;
  62. string serialized = JsonSerializer.Serialize (ThemeManager.Themes, SerializerContext.Options);
  63. ConcurrentDictionary<string, ThemeScope>? deserialized =
  64. JsonSerializer.Deserialize<ConcurrentDictionary<string, ThemeScope>> (serialized, SerializerContext.Options);
  65. Assert.NotEqual (initial, deserialized);
  66. Assert.Equal (deserialized!.Count, initial!.Count);
  67. Disable (true);
  68. }
  69. [Fact]
  70. public void Serialize_New_RoundTrip ()
  71. {
  72. Enable (ConfigLocations.HardCoded);
  73. var theme = new ThemeScope ();
  74. theme.LoadHardCodedDefaults ();
  75. theme ["Dialog.DefaultButtonAlignment"].PropertyValue = Alignment.End;
  76. string json = JsonSerializer.Serialize (theme, SerializerContext.Options);
  77. var deserialized = JsonSerializer.Deserialize<ThemeScope> (json, SerializerContext.Options);
  78. Assert.Equal (
  79. Alignment.End,
  80. (Alignment)deserialized! ["Dialog.DefaultButtonAlignment"].PropertyValue!
  81. );
  82. Disable (true);
  83. }
  84. [Fact (Skip = "Temp work arounds for #4288 prevent corruption.")]
  85. public void UpdateFrom_Corrupts_Schemes_HardCodeDefaults ()
  86. {
  87. // BUGBUG: ThemeScope is broken and needs to be fixed to not have the hard coded schemes get overwritten.
  88. // BUGBUG: This test demonstrates the problem.
  89. // BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/4288
  90. // Create a test theme
  91. var json = """
  92. {
  93. "Schemes": [
  94. {
  95. "Base": {
  96. "Normal": {
  97. "Foreground": "White",
  98. "Background": "Blue"
  99. }
  100. }
  101. }
  102. ]
  103. }
  104. """;
  105. //var json = """
  106. // {
  107. // "Themes": [
  108. // {
  109. // "Default": {
  110. // "Schemes": [
  111. // {
  112. // "Base": {
  113. // "Normal": {
  114. // "Foreground": "White",
  115. // "Background": "Blue"
  116. // }
  117. // }
  118. // }
  119. // ]
  120. // }
  121. // }
  122. // ]
  123. // }
  124. // """;
  125. try
  126. {
  127. Assert.False (IsEnabled);
  128. ThrowOnJsonErrors = true;
  129. // Enable (ConfigLocations.HardCoded);
  130. //ResetToCurrentValues ();
  131. // Capture dynamically created hardCoded hard-coded scheme colors
  132. ImmutableSortedDictionary<string, Scheme> hardCodedSchemes = SchemeManager.GetHardCodedSchemes ()!;
  133. Color hardCodedBaseNormalFg = hardCodedSchemes ["Base"].Normal.Foreground;
  134. Assert.Equal (new Color (StandardColor.LightBlue).ToString (), hardCodedBaseNormalFg.ToString ());
  135. // Capture hard-coded scheme colors via cache
  136. Dictionary<string, Scheme>? hardCodedSchemesViaCache =
  137. GetHardCodedConfigPropertiesByScope ("ThemeScope")!.ToFrozenDictionary () ["Schemes"].PropertyValue as Dictionary<string, Scheme>;
  138. Assert.Equal (hardCodedBaseNormalFg.ToString (), hardCodedSchemesViaCache! ["Base"].Normal.Foreground.ToString ());
  139. // (ConfigLocations.HardCoded);
  140. // Capture current scheme
  141. Dictionary<string, Scheme> currentSchemes = SchemeManager.GetSchemes ()!;
  142. Color currentBaseNormalFg = currentSchemes ["Base"].Normal.Foreground;
  143. Assert.Equal (hardCodedBaseNormalFg.ToString (), currentBaseNormalFg.ToString ());
  144. //ConfigurationManager.SourcesManager?.Load (Settings, json, "UpdateFromJson", ConfigLocations.Runtime);
  145. ThemeScope scope = (JsonSerializer.Deserialize (json, typeof (ThemeScope), SerializerContext.Options) as ThemeScope)!;
  146. ThemeScope defaultTheme = ThemeManager.Themes! ["Default"]!;
  147. Dictionary<string, Scheme?> schemesScope = (defaultTheme ["Schemes"].PropertyValue as Dictionary<string, Scheme?>)!;
  148. defaultTheme ["Schemes"].UpdateFrom (scope ["Schemes"].PropertyValue!);
  149. defaultTheme.UpdateFrom (scope);
  150. Assert.Equal (Color.White.ToString (), hardCodedSchemesViaCache! ["Base"].Normal.Foreground.ToString ());
  151. }
  152. finally
  153. {
  154. ResetToHardCodedDefaults ();
  155. }
  156. }
  157. }