mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Tons of API doc updates * Removed stale test * Removed stale tests * Fixed Skipped Shadow test 1 * Fixed Skipped Shadow test 2 * Fixed Skipped Shadow test 3 * Removed stale test * Removed stale test2 * Explicit unregister of event handler on Application.Driver!.ClearedContents * Added Toplevels to dict * code cleanup * spelling error * Removed stale test3 * Removed stale test4 * Removed stale test5 * added script * tweaked script * tweaked script * Created StressTests project; moved some tests * Created IntegrationTests project; moved some tests * New yml * made old yml just unit tests * Tweaked Button_IsDefault_Raises_Accepted_Correctly * tweaked script * cleaned up ymls * tweakled up ymls * stress tests... * stress tests on ubuntu only * Fixed WindowsDriver in InvokeLeakTest * Fixed WindowsDriver in InvokeLeakTest2 * Added Directory.Packages.props. Added Directory.Build.props * Shortened StressTest time * Removed dupe file. * DemoFiles * Moved all tests to ./Tests dir. * Fixed release build issue * Fixed .sln file * Fixed .sl* files * Fixing ymls * Fixing interation tests * Create link to the file TestHelpers. * Created Tests/UnitTestsParallelizable. Moved all obviously parallelizable tests. Updated yml. * fixing logs * fixing logs2 * fixing logs3 * don't require stress to pass for PRs * Fix a failure? * tweaked script * Coudl this be it? * Moved tons of tests to parallelizable * Fixed some stuff * Script to find duplicate tests * Testing workflows * Updated to v4 * Fix RelativeBasePath issue * Replace powershell to pwsh * Add ignore projects. * Removed dupe unit tests * Code cleanup of tests * Cleaned up test warnings * yml tweak * Moved setter * tweak ymls * just randomly throwing spaghetti at a wall * Enable runing 5 test runners in par * Turned off DEBUG_DISPOSABLE for par tests * RunningUnitTests=true * code cleanup (forcing more Action runs) * DISABLE_DEBUG_IDISPOSABLE * Added View.DebugIDisposable. False by default. * Remobed bogus tareet * Remobed bogus tareet2 * fixed warning * added api doc * fixed warning * fixed warning * fixed warning2 * fixed warning3 * fixed warning4 --------- Co-authored-by: BDisp <bd.bdisp@gmail.com>
This commit is contained in:
87
Tests/UnitTests/Configuration/AppScopeTests.cs
Normal file
87
Tests/UnitTests/Configuration/AppScopeTests.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class AppScopeTests
|
||||
{
|
||||
public static readonly JsonSerializerOptions _jsonOptions = new ()
|
||||
{
|
||||
Converters =
|
||||
{
|
||||
//new AttributeJsonConverter (),
|
||||
//new ColorJsonConverter ()
|
||||
}
|
||||
};
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void Apply_ShouldApplyUpdatedProperties ()
|
||||
{
|
||||
Reset ();
|
||||
Assert.Null (AppSettingsTestClass.TestProperty);
|
||||
Assert.NotEmpty (AppSettings);
|
||||
Assert.Null (AppSettings ["AppSettingsTestClass.TestProperty"].PropertyValue);
|
||||
|
||||
AppSettingsTestClass.TestProperty = true;
|
||||
Reset ();
|
||||
Assert.True (AppSettingsTestClass.TestProperty);
|
||||
Assert.NotEmpty (AppSettings);
|
||||
Assert.Null (AppSettings ["AppSettingsTestClass.TestProperty"].PropertyValue as bool?);
|
||||
|
||||
AppSettings ["AppSettingsTestClass.TestProperty"].PropertyValue = false;
|
||||
Assert.False (AppSettings ["AppSettingsTestClass.TestProperty"].PropertyValue as bool?);
|
||||
|
||||
// ConfigurationManager.Settings should NOT apply theme settings
|
||||
Settings.Apply ();
|
||||
Assert.True (AppSettingsTestClass.TestProperty);
|
||||
|
||||
// ConfigurationManager.Themes should NOT apply theme settings
|
||||
ThemeManager.Themes! [ThemeManager.SelectedTheme]!.Apply ();
|
||||
Assert.True (AppSettingsTestClass.TestProperty);
|
||||
|
||||
// ConfigurationManager.AppSettings should NOT apply theme settings
|
||||
AppSettings.Apply ();
|
||||
Assert.False (AppSettingsTestClass.TestProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestNullable ()
|
||||
{
|
||||
AppSettingsTestClass.TestProperty = null;
|
||||
Assert.Null (AppSettingsTestClass.TestProperty);
|
||||
|
||||
Initialize ();
|
||||
GetHardCodedDefaults ();
|
||||
Apply ();
|
||||
Assert.Null (AppSettingsTestClass.TestProperty);
|
||||
|
||||
AppSettingsTestClass.TestProperty = true;
|
||||
Initialize ();
|
||||
GetHardCodedDefaults ();
|
||||
Assert.NotNull (AppSettingsTestClass.TestProperty);
|
||||
Apply ();
|
||||
Assert.NotNull (AppSettingsTestClass.TestProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSerialize_RoundTrip ()
|
||||
{
|
||||
Reset ();
|
||||
|
||||
AppScope initial = AppSettings;
|
||||
|
||||
string serialized = JsonSerializer.Serialize (AppSettings, _jsonOptions);
|
||||
var deserialized = JsonSerializer.Deserialize<AppScope> (serialized, _jsonOptions);
|
||||
|
||||
Assert.NotEqual (initial, deserialized);
|
||||
Assert.Equal (deserialized.Count, initial.Count);
|
||||
}
|
||||
|
||||
public class AppSettingsTestClass
|
||||
{
|
||||
[SerializableConfigurationProperty (Scope = typeof (AppScope))]
|
||||
public static bool? TestProperty { get; set; }
|
||||
}
|
||||
}
|
||||
33
Tests/UnitTests/Configuration/AttributeJsonConverterTests.cs
Normal file
33
Tests/UnitTests/Configuration/AttributeJsonConverterTests.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class AttributeJsonConverterTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestDeserialize ()
|
||||
{
|
||||
// Test deserializing from human-readable color names
|
||||
var json = "{\"Foreground\":\"Blue\",\"Background\":\"Green\"}";
|
||||
var attribute = JsonSerializer.Deserialize<Attribute> (json, ConfigurationManagerTests._jsonOptions);
|
||||
Assert.Equal (Color.Blue, attribute.Foreground.GetClosestNamedColor16 ());
|
||||
Assert.Equal (Color.Green, attribute.Background.GetClosestNamedColor16 ());
|
||||
|
||||
// Test deserializing from RGB values
|
||||
json = "{\"Foreground\":\"rgb(255,0,0)\",\"Background\":\"rgb(0,255,0)\"}";
|
||||
attribute = JsonSerializer.Deserialize<Attribute> (json, ConfigurationManagerTests._jsonOptions);
|
||||
Assert.Equal (Color.Red, attribute.Foreground.GetClosestNamedColor16 ());
|
||||
Assert.Equal (Color.BrightGreen, attribute.Background.GetClosestNamedColor16 ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void TestSerialize ()
|
||||
{
|
||||
// Test serializing to human-readable color names
|
||||
var attribute = new Attribute (Color.Blue, Color.Green);
|
||||
string json = JsonSerializer.Serialize (attribute, ConfigurationManagerTests._jsonOptions);
|
||||
Assert.Equal ("{\"Foreground\":\"Blue\",\"Background\":\"Green\"}", json);
|
||||
}
|
||||
}
|
||||
180
Tests/UnitTests/Configuration/ColorJsonConverterTests.cs
Normal file
180
Tests/UnitTests/Configuration/ColorJsonConverterTests.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ColorJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData ("\"#000000\"", 0, 0, 0)]
|
||||
public void DeserializesFromHexCode (string hexCode, int r, int g, int b)
|
||||
{
|
||||
// Arrange
|
||||
var expected = new Color (r, g, b);
|
||||
|
||||
// Act
|
||||
var actual = JsonSerializer.Deserialize<Color> (
|
||||
hexCode,
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
//Assert
|
||||
Assert.Equal (expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData ("\"rgb(0,0,0)\"", 0, 0, 0)]
|
||||
public void DeserializesFromRgb (string rgb, int r, int g, int b)
|
||||
{
|
||||
// Arrange
|
||||
var expected = new Color (r, g, b);
|
||||
|
||||
// Act
|
||||
var actual = JsonSerializer.Deserialize<Color> (
|
||||
rgb,
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
//Assert
|
||||
Assert.Equal (expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (ColorName16.Black, "Black")]
|
||||
[InlineData (ColorName16.Blue, "Blue")]
|
||||
[InlineData (ColorName16.Green, "Green")]
|
||||
[InlineData (ColorName16.Cyan, "Cyan")]
|
||||
[InlineData (ColorName16.Gray, "Gray")]
|
||||
[InlineData (ColorName16.Red, "Red")]
|
||||
[InlineData (ColorName16.Magenta, "Magenta")]
|
||||
[InlineData (ColorName16.Yellow, "Yellow")]
|
||||
[InlineData (ColorName16.DarkGray, "DarkGray")]
|
||||
[InlineData (ColorName16.BrightBlue, "BrightBlue")]
|
||||
[InlineData (ColorName16.BrightGreen, "BrightGreen")]
|
||||
[InlineData (ColorName16.BrightCyan, "BrightCyan")]
|
||||
[InlineData (ColorName16.BrightRed, "BrightRed")]
|
||||
[InlineData (ColorName16.BrightMagenta, "BrightMagenta")]
|
||||
[InlineData (ColorName16.BrightYellow, "BrightYellow")]
|
||||
[InlineData (ColorName16.White, "White")]
|
||||
public void SerializesColorName16ValuesAsStrings (ColorName16 colorName, string expectedJson)
|
||||
{
|
||||
var converter = new ColorJsonConverter ();
|
||||
var options = new JsonSerializerOptions { Converters = { converter } };
|
||||
|
||||
string serialized = JsonSerializer.Serialize (new Color (colorName), options);
|
||||
|
||||
Assert.Equal ($"\"{expectedJson}\"", serialized);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (1, 0, 0, "\"#010000\"")]
|
||||
[InlineData (0, 0, 1, "\"#000001\"")]
|
||||
public void SerializesToHexCode (int r, int g, int b, string expected)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
string actual = JsonSerializer.Serialize (
|
||||
new Color (r, g, b),
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
//Assert
|
||||
Assert.Equal (expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData ("Black", Color.Black)]
|
||||
[InlineData ("Blue", Color.Blue)]
|
||||
[InlineData ("BrightBlue", Color.BrightBlue)]
|
||||
[InlineData ("BrightCyan", Color.BrightCyan)]
|
||||
[InlineData ("BrightGreen", Color.BrightGreen)]
|
||||
[InlineData ("BrightMagenta", Color.BrightMagenta)]
|
||||
[InlineData ("BrightRed", Color.BrightRed)]
|
||||
[InlineData ("BrightYellow", Color.BrightYellow)]
|
||||
[InlineData ("Yellow", Color.Yellow)]
|
||||
[InlineData ("Cyan", Color.Cyan)]
|
||||
[InlineData ("DarkGray", Color.DarkGray)]
|
||||
[InlineData ("Gray", Color.Gray)]
|
||||
[InlineData ("Green", Color.Green)]
|
||||
[InlineData ("Magenta", Color.Magenta)]
|
||||
[InlineData ("Red", Color.Red)]
|
||||
[InlineData ("White", Color.White)]
|
||||
public void TestColorDeserializationFromHumanReadableColorName16 (string colorName, ColorName16 expectedColor)
|
||||
{
|
||||
// Arrange
|
||||
var json = $"\"{colorName}\"";
|
||||
|
||||
// Act
|
||||
var actualColor = JsonSerializer.Deserialize<Color> (json, ConfigurationManagerTests._jsonOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (new Color (expectedColor), actualColor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestDeserializeColor_Black ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "\"Black\"";
|
||||
var expectedColor = new Color ("Black");
|
||||
|
||||
// Act
|
||||
var color = JsonSerializer.Deserialize<Color> (
|
||||
json,
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedColor, color);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestDeserializeColor_BrightRed ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "\"BrightRed\"";
|
||||
var expectedColor = Color.BrightRed;
|
||||
|
||||
// Act
|
||||
var color = JsonSerializer.Deserialize<Color> (
|
||||
json,
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedColor, color);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSerializeColor_Black ()
|
||||
{
|
||||
// Arrange
|
||||
var expectedJson = "\"Black\"";
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (
|
||||
new Color (Color.Black),
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedJson, json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSerializeColor_BrightRed ()
|
||||
{
|
||||
// Arrange
|
||||
var expectedJson = "\"BrightRed\"";
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (
|
||||
new Color (Color.BrightRed),
|
||||
new JsonSerializerOptions { Converters = { new ColorJsonConverter () } }
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedJson, json);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ColorSchemeJsonConverterTests
|
||||
{
|
||||
//string json = @"
|
||||
// {
|
||||
// ""ColorSchemes"": {
|
||||
// ""Base"": {
|
||||
// ""normal"": {
|
||||
// ""foreground"": ""White"",
|
||||
// ""background"": ""Blue""
|
||||
// },
|
||||
// ""focus"": {
|
||||
// ""foreground"": ""Black"",
|
||||
// ""background"": ""Gray""
|
||||
// },
|
||||
// ""hotNormal"": {
|
||||
// ""foreground"": ""BrightCyan"",
|
||||
// ""background"": ""Blue""
|
||||
// },
|
||||
// ""hotFocus"": {
|
||||
// ""foreground"": ""BrightBlue"",
|
||||
// ""background"": ""Gray""
|
||||
// },
|
||||
// ""disabled"": {
|
||||
// ""foreground"": ""DarkGray"",
|
||||
// ""background"": ""Blue""
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }";
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void TestColorSchemesSerialization ()
|
||||
{
|
||||
// Arrange
|
||||
var expectedColorScheme = new ColorScheme
|
||||
{
|
||||
Normal = new Attribute (Color.White, Color.Blue),
|
||||
Focus = new Attribute (Color.Black, Color.Gray),
|
||||
HotNormal = new Attribute (Color.BrightCyan, Color.Blue),
|
||||
HotFocus = new Attribute (Color.BrightBlue, Color.Gray),
|
||||
Disabled = new Attribute (Color.DarkGray, Color.Blue)
|
||||
};
|
||||
|
||||
string serializedColorScheme =
|
||||
JsonSerializer.Serialize (expectedColorScheme, ConfigurationManagerTests._jsonOptions);
|
||||
|
||||
// Act
|
||||
var actualColorScheme =
|
||||
JsonSerializer.Deserialize<ColorScheme> (serializedColorScheme, ConfigurationManagerTests._jsonOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedColorScheme, actualColorScheme);
|
||||
}
|
||||
}
|
||||
176
Tests/UnitTests/Configuration/ConfigPropertyTests.cs
Normal file
176
Tests/UnitTests/Configuration/ConfigPropertyTests.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Terminal.Gui;
|
||||
using Xunit;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ConfigPropertyTests
|
||||
{
|
||||
[Fact]
|
||||
public void Apply_PropertyValueIsAppliedToStatic_String_Property()
|
||||
{
|
||||
// Arrange
|
||||
TestConfiguration.Reset ();
|
||||
var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
var configProperty = new ConfigProperty
|
||||
{
|
||||
PropertyInfo = propertyInfo,
|
||||
PropertyValue = "UpdatedValue"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = configProperty.Apply();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (1, TestConfiguration.TestStringPropertySetCount);
|
||||
Assert.True(result);
|
||||
Assert.Equal("UpdatedValue", TestConfiguration.TestStringProperty);
|
||||
TestConfiguration.Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Apply_PropertyValueIsAppliedToStatic_Key_Property ()
|
||||
{
|
||||
// Arrange
|
||||
TestConfiguration.Reset ();
|
||||
var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestKeyProperty));
|
||||
var configProperty = new ConfigProperty
|
||||
{
|
||||
PropertyInfo = propertyInfo,
|
||||
PropertyValue = Key.Q.WithCtrl
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = configProperty.Apply ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, TestConfiguration.TestKeyPropertySetCount);
|
||||
Assert.True (result);
|
||||
Assert.Equal (Key.Q.WithCtrl, TestConfiguration.TestKeyProperty);
|
||||
TestConfiguration.Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RetrieveValue_GetsCurrentValueOfStaticProperty()
|
||||
{
|
||||
// Arrange
|
||||
TestConfiguration.TestStringProperty = "CurrentValue";
|
||||
var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
var configProperty = new ConfigProperty
|
||||
{
|
||||
PropertyInfo = propertyInfo
|
||||
};
|
||||
|
||||
// Act
|
||||
var value = configProperty.RetrieveValue();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("CurrentValue", value);
|
||||
Assert.Equal("CurrentValue", configProperty.PropertyValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdateValueFrom_Updates_String_Property_Value ()
|
||||
{
|
||||
// Arrange
|
||||
TestConfiguration.Reset ();
|
||||
var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
var configProperty = new ConfigProperty
|
||||
{
|
||||
PropertyInfo = propertyInfo,
|
||||
PropertyValue = "InitialValue"
|
||||
};
|
||||
|
||||
// Act
|
||||
var updatedValue = configProperty.UpdateValueFrom("NewValue");
|
||||
|
||||
// Assert
|
||||
Assert.Equal (0, TestConfiguration.TestStringPropertySetCount);
|
||||
Assert.Equal("NewValue", updatedValue);
|
||||
Assert.Equal("NewValue", configProperty.PropertyValue);
|
||||
TestConfiguration.Reset ();
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
//public void UpdateValueFrom_InvalidType_ThrowsArgumentException()
|
||||
//{
|
||||
// // Arrange
|
||||
// var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
// var configProperty = new ConfigProperty
|
||||
// {
|
||||
// PropertyInfo = propertyInfo
|
||||
// };
|
||||
|
||||
// // Act & Assert
|
||||
// Assert.Throws<ArgumentException>(() => configProperty.UpdateValueFrom(123));
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public void Apply_TargetInvocationException_ThrowsJsonException()
|
||||
{
|
||||
// Arrange
|
||||
var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
var configProperty = new ConfigProperty
|
||||
{
|
||||
PropertyInfo = propertyInfo,
|
||||
PropertyValue = null // This will cause ArgumentNullException in the set accessor
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<JsonException> (() => configProperty.Apply());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetJsonPropertyName_ReturnsJsonPropertyNameAttributeValue()
|
||||
{
|
||||
// Arrange
|
||||
var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
|
||||
|
||||
// Act
|
||||
var jsonPropertyName = ConfigProperty.GetJsonPropertyName(propertyInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("TestStringProperty", jsonPropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestConfiguration
|
||||
{
|
||||
private static string _testStringProperty = "Default";
|
||||
public static int TestStringPropertySetCount { get; set; }
|
||||
|
||||
[SerializableConfigurationProperty]
|
||||
public static string TestStringProperty
|
||||
{
|
||||
get => _testStringProperty;
|
||||
set
|
||||
{
|
||||
TestStringPropertySetCount++;
|
||||
_testStringProperty = value ?? throw new ArgumentNullException (nameof (value));
|
||||
}
|
||||
}
|
||||
|
||||
private static Key _testKeyProperty = Key.Esc;
|
||||
|
||||
public static int TestKeyPropertySetCount { get; set; }
|
||||
|
||||
[SerializableConfigurationProperty]
|
||||
public static Key TestKeyProperty
|
||||
{
|
||||
get => _testKeyProperty;
|
||||
set
|
||||
{
|
||||
TestKeyPropertySetCount++;
|
||||
_testKeyProperty = value ?? throw new ArgumentNullException (nameof (value));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset ()
|
||||
{
|
||||
TestStringPropertySetCount = 0;
|
||||
TestKeyPropertySetCount = 0;
|
||||
}
|
||||
}
|
||||
943
Tests/UnitTests/Configuration/ConfigurationMangerTests.cs
Normal file
943
Tests/UnitTests/Configuration/ConfigurationMangerTests.cs
Normal file
@@ -0,0 +1,943 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
using Xunit.Abstractions;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
#pragma warning disable IDE1006
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ConfigurationManagerTests
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
public ConfigurationManagerTests (ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public static readonly JsonSerializerOptions _jsonOptions = new ()
|
||||
{
|
||||
Converters = { new AttributeJsonConverter (), new ColorJsonConverter () }
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void Apply_Raises_Applied ()
|
||||
{
|
||||
Reset ();
|
||||
Applied += ConfigurationManager_Applied;
|
||||
var fired = false;
|
||||
|
||||
void ConfigurationManager_Applied (object sender, ConfigurationManagerEventArgs obj)
|
||||
{
|
||||
fired = true;
|
||||
|
||||
// assert
|
||||
Assert.Equal (KeyCode.Q, Application.QuitKey.KeyCode);
|
||||
Assert.Equal (KeyCode.F, Application.NextTabGroupKey.KeyCode);
|
||||
Assert.Equal (KeyCode.B, Application.PrevTabGroupKey.KeyCode);
|
||||
}
|
||||
|
||||
// act
|
||||
Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
|
||||
Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
|
||||
Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
|
||||
|
||||
Apply ();
|
||||
|
||||
// assert
|
||||
Assert.True (fired);
|
||||
|
||||
Applied -= ConfigurationManager_Applied;
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeepMemberWiseCopyTest ()
|
||||
{
|
||||
// Value types
|
||||
var stringDest = "Destination";
|
||||
var stringSrc = "Source";
|
||||
object stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
|
||||
Assert.Equal (stringSrc, stringCopy);
|
||||
|
||||
stringDest = "Destination";
|
||||
stringSrc = "Destination";
|
||||
stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
|
||||
Assert.Equal (stringSrc, stringCopy);
|
||||
|
||||
stringDest = "Destination";
|
||||
stringSrc = null;
|
||||
stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
|
||||
Assert.Equal (stringSrc, stringCopy);
|
||||
|
||||
stringDest = "Destination";
|
||||
stringSrc = string.Empty;
|
||||
stringCopy = DeepMemberWiseCopy (stringSrc, stringDest);
|
||||
Assert.Equal (stringSrc, stringCopy);
|
||||
|
||||
var boolDest = true;
|
||||
var boolSrc = false;
|
||||
object boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
|
||||
Assert.Equal (boolSrc, boolCopy);
|
||||
|
||||
boolDest = false;
|
||||
boolSrc = true;
|
||||
boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
|
||||
Assert.Equal (boolSrc, boolCopy);
|
||||
|
||||
boolDest = true;
|
||||
boolSrc = true;
|
||||
boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
|
||||
Assert.Equal (boolSrc, boolCopy);
|
||||
|
||||
boolDest = false;
|
||||
boolSrc = false;
|
||||
boolCopy = DeepMemberWiseCopy (boolSrc, boolDest);
|
||||
Assert.Equal (boolSrc, boolCopy);
|
||||
|
||||
// Structs
|
||||
var attrDest = new Attribute (Color.Black);
|
||||
var attrSrc = new Attribute (Color.White);
|
||||
object attrCopy = DeepMemberWiseCopy (attrSrc, attrDest);
|
||||
Assert.Equal (attrSrc, attrCopy);
|
||||
|
||||
// Classes
|
||||
var colorschemeDest = new ColorScheme { Disabled = new Attribute (Color.Black) };
|
||||
var colorschemeSrc = new ColorScheme { Disabled = new Attribute (Color.White) };
|
||||
object colorschemeCopy = DeepMemberWiseCopy (colorschemeSrc, colorschemeDest);
|
||||
Assert.Equal (colorschemeSrc, colorschemeCopy);
|
||||
|
||||
// Dictionaries
|
||||
Dictionary<string, Attribute> dictDest = new () { { "Disabled", new Attribute (Color.Black) } };
|
||||
Dictionary<string, Attribute> dictSrc = new () { { "Disabled", new Attribute (Color.White) } };
|
||||
Dictionary<string, Attribute> dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
|
||||
Assert.Equal (dictSrc, dictCopy);
|
||||
|
||||
dictDest = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.Black) } };
|
||||
|
||||
dictSrc = new Dictionary<string, Attribute>
|
||||
{
|
||||
{ "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) }
|
||||
};
|
||||
dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
|
||||
Assert.Equal (dictSrc, dictCopy);
|
||||
|
||||
// src adds an item
|
||||
dictDest = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.Black) } };
|
||||
|
||||
dictSrc = new Dictionary<string, Attribute>
|
||||
{
|
||||
{ "Disabled", new Attribute (Color.White) }, { "Normal", new Attribute (Color.Blue) }
|
||||
};
|
||||
dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
|
||||
Assert.Equal (2, dictCopy!.Count);
|
||||
Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]);
|
||||
Assert.Equal (dictSrc ["Normal"], dictCopy ["Normal"]);
|
||||
|
||||
// src updates only one item
|
||||
dictDest = new Dictionary<string, Attribute>
|
||||
{
|
||||
{ "Disabled", new Attribute (Color.Black) }, { "Normal", new Attribute (Color.White) }
|
||||
};
|
||||
dictSrc = new Dictionary<string, Attribute> { { "Disabled", new Attribute (Color.White) } };
|
||||
dictCopy = (Dictionary<string, Attribute>)DeepMemberWiseCopy (dictSrc, dictDest);
|
||||
Assert.Equal (2, dictCopy!.Count);
|
||||
Assert.Equal (dictSrc ["Disabled"], dictCopy ["Disabled"]);
|
||||
Assert.Equal (dictDest ["Normal"], dictCopy ["Normal"]);
|
||||
}
|
||||
|
||||
public class DeepCopyTest ()
|
||||
{
|
||||
public static Key key = Key.Esc;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Illustrate_DeepMemberWiseCopy_Breaks_Dictionary ()
|
||||
{
|
||||
Assert.Equal (Key.Esc, DeepCopyTest.key);
|
||||
|
||||
Dictionary<Key, string> dict = new Dictionary<Key, string> (new KeyEqualityComparer ());
|
||||
dict.Add (new (DeepCopyTest.key), "Esc");
|
||||
Assert.Contains (Key.Esc, dict);
|
||||
|
||||
DeepCopyTest.key = (Key)DeepMemberWiseCopy (Key.Q.WithCtrl, DeepCopyTest.key);
|
||||
|
||||
Assert.Equal (Key.Q.WithCtrl, DeepCopyTest.key);
|
||||
Assert.Equal (Key.Esc, dict.Keys.ToArray () [0]);
|
||||
|
||||
var eq = new KeyEqualityComparer ();
|
||||
Assert.True (eq.Equals (Key.Q.WithCtrl, DeepCopyTest.key));
|
||||
Assert.Equal (Key.Q.WithCtrl.GetHashCode (), DeepCopyTest.key.GetHashCode ());
|
||||
Assert.Equal (eq.GetHashCode (Key.Q.WithCtrl), eq.GetHashCode (DeepCopyTest.key));
|
||||
Assert.Equal (Key.Q.WithCtrl.GetHashCode (), eq.GetHashCode (DeepCopyTest.key));
|
||||
Assert.True (dict.ContainsKey (Key.Esc));
|
||||
|
||||
dict.Remove (Key.Esc);
|
||||
dict.Add (new (DeepCopyTest.key), "Ctrl+Q");
|
||||
Assert.True (dict.ContainsKey (Key.Q.WithCtrl));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Load_Raises_Updated ()
|
||||
{
|
||||
ThrowOnJsonErrors = true;
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
Assert.Equal (Key.Esc, (((Key)Settings! ["Application.QuitKey"].PropertyValue)!).KeyCode);
|
||||
|
||||
Updated += ConfigurationManager_Updated;
|
||||
var fired = false;
|
||||
|
||||
void ConfigurationManager_Updated (object sender, ConfigurationManagerEventArgs obj)
|
||||
{
|
||||
fired = true;
|
||||
}
|
||||
|
||||
// Act
|
||||
// Reset to cause load to raise event
|
||||
Load (true);
|
||||
|
||||
// assert
|
||||
Assert.True (fired);
|
||||
|
||||
Updated -= ConfigurationManager_Updated;
|
||||
|
||||
// clean up
|
||||
Locations = ConfigLocations.Default;
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Load_Performance_Check ()
|
||||
{
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
|
||||
// Start stopwatch
|
||||
Stopwatch stopwatch = new Stopwatch ();
|
||||
stopwatch.Start ();
|
||||
|
||||
// Act
|
||||
Load (true);
|
||||
Apply();
|
||||
|
||||
// Stop stopwatch
|
||||
stopwatch.Stop ();
|
||||
|
||||
// Assert
|
||||
_output.WriteLine ($"Load took {stopwatch.ElapsedMilliseconds} ms");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Load_Loads_Custom_Json ()
|
||||
{
|
||||
// arrange
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
ThrowOnJsonErrors = true;
|
||||
|
||||
Assert.Equal (Key.Esc, (Key)Settings! ["Application.QuitKey"].PropertyValue);
|
||||
|
||||
// act
|
||||
RuntimeConfig = """
|
||||
|
||||
{
|
||||
"Application.QuitKey": "Ctrl-Q"
|
||||
}
|
||||
""";
|
||||
Load (false);
|
||||
|
||||
// assert
|
||||
Assert.Equal (Key.Q.WithCtrl, (Key)Settings ["Application.QuitKey"].PropertyValue);
|
||||
|
||||
// clean up
|
||||
Locations = ConfigLocations.Default;
|
||||
Reset ();
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
//[AutoInitShutdown]
|
||||
//public void LoadConfigurationFromAllSources_ShouldLoadSettingsFromAllSources ()
|
||||
//{
|
||||
// //var _configFilename = "config.json";
|
||||
// //// Arrange
|
||||
// //// Create a mock of the configuration files in all sources
|
||||
// //// Home directory
|
||||
// //string homeDir = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".tui");
|
||||
// //if (!Directory.Exists (homeDir)) {
|
||||
// // Directory.CreateDirectory (homeDir);
|
||||
// //}
|
||||
// //string globalConfigFile = Path.Combine (homeDir, _configFilename);
|
||||
// //string appSpecificConfigFile = Path.Combine (homeDir, "appname.config.json");
|
||||
// //File.WriteAllText (globalConfigFile, "{\"Settings\": {\"TestSetting\":\"Global\"}}");
|
||||
// //File.WriteAllText (appSpecificConfigFile, "{\"Settings\": {\"TestSetting\":\"AppSpecific\"}}");
|
||||
|
||||
// //// App directory
|
||||
// //string appDir = Directory.GetCurrentDirectory ();
|
||||
// //string appDirGlobalConfigFile = Path.Combine (appDir, _configFilename);
|
||||
// //string appDirAppSpecificConfigFile = Path.Combine (appDir, "appname.config.json");
|
||||
// //File.WriteAllText (appDirGlobalConfigFile, "{\"Settings\": {\"TestSetting\":\"GlobalAppDir\"}}");
|
||||
// //File.WriteAllText (appDirAppSpecificConfigFile, "{\"Settings\": {\"TestSetting\":\"AppSpecificAppDir\"}}");
|
||||
|
||||
// //// App resources
|
||||
// //// ...
|
||||
|
||||
// //// Act
|
||||
// //ConfigurationManager.Locations = ConfigurationManager.ConfigLocation.All;
|
||||
// //ConfigurationManager.Load ();
|
||||
|
||||
// //// Assert
|
||||
// //// Check that the settings from the highest precedence source are loaded
|
||||
// //Assert.Equal ("AppSpecific", ConfigurationManager.Config.Settings.TestSetting);
|
||||
//}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Reset_Raises_Updated ()
|
||||
{
|
||||
ConfigLocations savedLocations = Locations;
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
|
||||
Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
|
||||
|
||||
Updated += ConfigurationManager_Updated;
|
||||
var fired = false;
|
||||
|
||||
void ConfigurationManager_Updated (object sender, ConfigurationManagerEventArgs obj)
|
||||
{
|
||||
fired = true;
|
||||
}
|
||||
|
||||
// Act
|
||||
Reset ();
|
||||
|
||||
// assert
|
||||
Assert.True (fired);
|
||||
|
||||
Updated -= ConfigurationManager_Updated;
|
||||
Reset ();
|
||||
Locations = savedLocations;
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Reset_and_ResetLoadWithLibraryResourcesOnly_are_same ()
|
||||
{
|
||||
Locations = ConfigLocations.Default;
|
||||
|
||||
// arrange
|
||||
Reset ();
|
||||
Settings! ["Application.QuitKey"].PropertyValue = Key.Q;
|
||||
Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
|
||||
Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
|
||||
Settings.Apply ();
|
||||
|
||||
// assert apply worked
|
||||
Assert.Equal (KeyCode.Q, Application.QuitKey.KeyCode);
|
||||
Assert.Equal (KeyCode.F, Application.NextTabGroupKey.KeyCode);
|
||||
Assert.Equal (KeyCode.B, Application.PrevTabGroupKey.KeyCode);
|
||||
|
||||
//act
|
||||
Reset ();
|
||||
|
||||
// assert
|
||||
Assert.NotEmpty (Themes!);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
Assert.Equal (Key.Esc, Application.QuitKey);
|
||||
Assert.Equal (Key.F6, Application.NextTabGroupKey);
|
||||
Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey);
|
||||
|
||||
// arrange
|
||||
Settings ["Application.QuitKey"].PropertyValue = Key.Q;
|
||||
Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
|
||||
Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
|
||||
Settings.Apply ();
|
||||
|
||||
Locations = ConfigLocations.Default;
|
||||
|
||||
// act
|
||||
Reset ();
|
||||
Load ();
|
||||
|
||||
// assert
|
||||
Assert.NotEmpty (Themes);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
Assert.Equal (KeyCode.Esc, Application.QuitKey.KeyCode);
|
||||
Assert.Equal (Key.F6, Application.NextTabGroupKey);
|
||||
Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey);
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reset_Resets ()
|
||||
{
|
||||
Locations = ConfigLocations.Default;
|
||||
Reset ();
|
||||
Assert.NotEmpty (Themes!);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadFromJsonTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void ToJsonTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void UpdateConfigurationTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void UpdateConfigurationFromFileTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void SaveHardCodedDefaultsTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadGlobalFromLibraryResourceTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadGlobalFromAppDirectoryTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadGlobalFromHomeDirectoryTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadAppFromAppResourcesTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadAppFromAppDirectoryTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadAppFromHomeDirectoryTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
//[Fact ()]
|
||||
//public void LoadTest ()
|
||||
//{
|
||||
// Assert.True (false, "This test needs an implementation");
|
||||
//}
|
||||
|
||||
/// <summary>Save the `config.json` file; this can be used to update the file in `Terminal.Gui.Resources.config.json'.</summary>
|
||||
/// <remarks>
|
||||
/// IMPORTANT: For the file generated to be valid, this must be the ONLY test run. Config Properties are all
|
||||
/// static and thus can be overwritten by other tests.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public void SaveDefaults ()
|
||||
{
|
||||
Initialize ();
|
||||
Reset ();
|
||||
|
||||
// Get the hard coded settings
|
||||
GetHardCodedDefaults ();
|
||||
|
||||
// Serialize to a JSON string
|
||||
string json = ToJson ();
|
||||
|
||||
// Write the JSON string to the file
|
||||
File.WriteAllText ("config.json", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestConfigProperties ()
|
||||
{
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
|
||||
Assert.NotEmpty (Settings!);
|
||||
|
||||
// test that all ConfigProperties have our attribute
|
||||
Assert.All (
|
||||
Settings,
|
||||
item => Assert.NotEmpty (
|
||||
item.Value.PropertyInfo!.CustomAttributes.Where (
|
||||
a => a.AttributeType == typeof (SerializableConfigurationProperty)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
#pragma warning disable xUnit2029
|
||||
Assert.Empty (
|
||||
Settings.Where (
|
||||
cp => cp.Value.PropertyInfo!.GetCustomAttribute (
|
||||
typeof (SerializableConfigurationProperty)
|
||||
)
|
||||
== null
|
||||
)
|
||||
);
|
||||
#pragma warning restore xUnit2029
|
||||
|
||||
// Application is a static class
|
||||
PropertyInfo pi = typeof (Application).GetProperty ("QuitKey");
|
||||
Assert.Equal (pi, Settings ["Application.QuitKey"].PropertyInfo);
|
||||
|
||||
// FrameView is not a static class and DefaultBorderStyle is Scope.Scheme
|
||||
pi = typeof (FrameView).GetProperty ("DefaultBorderStyle");
|
||||
Assert.False (Settings.ContainsKey ("FrameView.DefaultBorderStyle"));
|
||||
Assert.True (Themes! ["Default"].ContainsKey ("FrameView.DefaultBorderStyle"));
|
||||
Assert.Equal (pi, Themes! ["Default"] ["FrameView.DefaultBorderStyle"].PropertyInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestConfigPropertyOmitClassName ()
|
||||
{
|
||||
ConfigLocations savedLocations = Locations;
|
||||
Locations = ConfigLocations.All;
|
||||
|
||||
// Color.ColorSchemes is serialized as "ColorSchemes", not "Colors.ColorSchemes"
|
||||
PropertyInfo pi = typeof (Colors).GetProperty ("ColorSchemes");
|
||||
var scp = (SerializableConfigurationProperty)pi!.GetCustomAttribute (typeof (SerializableConfigurationProperty));
|
||||
Assert.True (scp!.Scope == typeof (ThemeScope));
|
||||
Assert.True (scp.OmitClassName);
|
||||
|
||||
Reset ();
|
||||
Assert.Equal (pi, Themes! ["Default"] ["ColorSchemes"].PropertyInfo);
|
||||
|
||||
Locations = savedLocations;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void TestConfigurationManagerInitDriver ()
|
||||
{
|
||||
Assert.Equal ("Default", Themes!.Theme);
|
||||
|
||||
Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"]!.Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
|
||||
|
||||
// Change Base
|
||||
Stream json = ToStream ();
|
||||
|
||||
Settings!.Update (json, "TestConfigurationManagerInitDriver", ConfigLocations.Runtime);
|
||||
|
||||
Dictionary<string, ColorScheme> colorSchemes =
|
||||
(Dictionary<string, ColorScheme>)Themes [Themes.Theme] ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (Colors.ColorSchemes ["Base"], colorSchemes! ["Base"]);
|
||||
Assert.Equal (Colors.ColorSchemes ["TopLevel"], colorSchemes ["TopLevel"]);
|
||||
Assert.Equal (Colors.ColorSchemes ["Error"], colorSchemes ["Error"]);
|
||||
Assert.Equal (Colors.ColorSchemes ["Dialog"], colorSchemes ["Dialog"]);
|
||||
Assert.Equal (Colors.ColorSchemes ["Menu"], colorSchemes ["Menu"]);
|
||||
|
||||
Colors.ColorSchemes ["Base"] = colorSchemes ["Base"];
|
||||
Colors.ColorSchemes ["TopLevel"] = colorSchemes ["TopLevel"];
|
||||
Colors.ColorSchemes ["Error"] = colorSchemes ["Error"];
|
||||
Colors.ColorSchemes ["Dialog"] = colorSchemes ["Dialog"];
|
||||
Colors.ColorSchemes ["Menu"] = colorSchemes ["Menu"];
|
||||
|
||||
Assert.Equal (colorSchemes ["Base"], Colors.ColorSchemes ["Base"]);
|
||||
Assert.Equal (colorSchemes ["TopLevel"], Colors.ColorSchemes ["TopLevel"]);
|
||||
Assert.Equal (colorSchemes ["Error"], Colors.ColorSchemes ["Error"]);
|
||||
Assert.Equal (colorSchemes ["Dialog"], Colors.ColorSchemes ["Dialog"]);
|
||||
Assert.Equal (colorSchemes ["Menu"], Colors.ColorSchemes ["Menu"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.None)]
|
||||
public void TestConfigurationManagerInitDriver_NoLocations ()
|
||||
{
|
||||
// TODO: Write this test
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestConfigurationManagerInvalidJsonLogs ()
|
||||
{
|
||||
Application.Init (new FakeDriver ());
|
||||
|
||||
ThrowOnJsonErrors = false;
|
||||
|
||||
// "brown" is not a color
|
||||
var json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""hotNormal"": {
|
||||
""foreground"": ""brown"",
|
||||
""background"": ""1234""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
Settings!.Update (json, "test", ConfigLocations.Runtime);
|
||||
|
||||
// AbNormal is not a ColorScheme attribute
|
||||
json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""AbNormal"": {
|
||||
""foreground"": ""green"",
|
||||
""background"": ""black""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
Settings.Update (json, "test", ConfigLocations.Runtime);
|
||||
|
||||
// Modify hotNormal background only
|
||||
json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""hotNormal"": {
|
||||
""background"": ""cyan""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
Settings.Update (json, "test", ConfigLocations.Runtime);
|
||||
|
||||
Settings.Update ("{}}", "test", ConfigLocations.Runtime);
|
||||
|
||||
Assert.NotEqual (0, _jsonErrors.Length);
|
||||
|
||||
Application.Shutdown ();
|
||||
|
||||
ThrowOnJsonErrors = false;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void TestConfigurationManagerInvalidJsonThrows ()
|
||||
{
|
||||
ThrowOnJsonErrors = true;
|
||||
|
||||
// "yellow" is not a color
|
||||
var json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""hotNormal"": {
|
||||
""foreground"": ""brownish"",
|
||||
""background"": ""1234""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
var jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
|
||||
Assert.Equal ("Unexpected color name: brownish.", jsonException.Message);
|
||||
|
||||
// AbNormal is not a ColorScheme attribute
|
||||
json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""AbNormal"": {
|
||||
""foreground"": ""green"",
|
||||
""background"": ""black""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
|
||||
Assert.Equal ("Unrecognized ColorScheme Attribute name: AbNormal.", jsonException.Message);
|
||||
|
||||
// Modify hotNormal background only
|
||||
json = @"
|
||||
{
|
||||
""Themes"" : [
|
||||
{
|
||||
""Default"" : {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""UserDefined"": {
|
||||
""hotNormal"": {
|
||||
""background"": ""cyan""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
|
||||
Assert.Equal ("Both Foreground and Background colors must be provided.", jsonException.Message);
|
||||
|
||||
// Unknown property
|
||||
json = @"
|
||||
{
|
||||
""Unknown"" : ""Not known""
|
||||
}";
|
||||
|
||||
jsonException = Assert.Throws<JsonException> (() => Settings!.Update (json, "test", ConfigLocations.Runtime));
|
||||
Assert.StartsWith ("Unknown property", jsonException.Message);
|
||||
|
||||
Assert.Equal (0, _jsonErrors.Length);
|
||||
|
||||
ThrowOnJsonErrors = false;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void TestConfigurationManagerToJson ()
|
||||
{
|
||||
Reset ();
|
||||
GetHardCodedDefaults ();
|
||||
Stream stream = ToStream ();
|
||||
|
||||
Settings!.Update (stream, "TestConfigurationManagerToJson", ConfigLocations.Runtime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestConfigurationManagerUpdateFromJson ()
|
||||
{
|
||||
ConfigLocations savedLocations = Locations;
|
||||
Locations = ConfigLocations.All;
|
||||
|
||||
// Arrange
|
||||
var json = @"
|
||||
{
|
||||
""$schema"": ""https://gui-cs.github.io/Terminal.GuiV2Docs/schemas/tui-config-schema.json"",
|
||||
""Application.QuitKey"": ""Alt-Z"",
|
||||
""Theme"": ""Default"",
|
||||
""Themes"": [
|
||||
{
|
||||
""Default"": {
|
||||
""ColorSchemes"": [
|
||||
{
|
||||
""TopLevel"": {
|
||||
""Normal"": {
|
||||
""Foreground"": ""BrightGreen"",
|
||||
""Background"": ""Black""
|
||||
},
|
||||
""Focus"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""Cyan""
|
||||
},
|
||||
""HotNormal"": {
|
||||
""Foreground"": ""Yellow"",
|
||||
""Background"": ""Black""
|
||||
},
|
||||
""HotFocus"": {
|
||||
""Foreground"": ""Blue"",
|
||||
""Background"": ""Cyan""
|
||||
},
|
||||
""Disabled"": {
|
||||
""Foreground"": ""DarkGray"",
|
||||
""Background"": ""Black""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
""Base"": {
|
||||
""Normal"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""Blue""
|
||||
},
|
||||
""Focus"": {
|
||||
""Foreground"": ""Black"",
|
||||
""Background"": ""Gray""
|
||||
},
|
||||
""HotNormal"": {
|
||||
""Foreground"": ""BrightCyan"",
|
||||
""Background"": ""Blue""
|
||||
},
|
||||
""HotFocus"": {
|
||||
""Foreground"": ""BrightBlue"",
|
||||
""Background"": ""Gray""
|
||||
},
|
||||
""Disabled"": {
|
||||
""Foreground"": ""DarkGray"",
|
||||
""Background"": ""Blue""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
""Dialog"": {
|
||||
""Normal"": {
|
||||
""Foreground"": ""Black"",
|
||||
""Background"": ""Gray""
|
||||
},
|
||||
""Focus"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""DarkGray""
|
||||
},
|
||||
""HotNormal"": {
|
||||
""Foreground"": ""Blue"",
|
||||
""Background"": ""Gray""
|
||||
},
|
||||
""HotFocus"": {
|
||||
""Foreground"": ""BrightYellow"",
|
||||
""Background"": ""DarkGray""
|
||||
},
|
||||
""Disabled"": {
|
||||
""Foreground"": ""Gray"",
|
||||
""Background"": ""DarkGray""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
""Menu"": {
|
||||
""Normal"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""DarkGray""
|
||||
},
|
||||
""Focus"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""Black""
|
||||
},
|
||||
""HotNormal"": {
|
||||
""Foreground"": ""BrightYellow"",
|
||||
""Background"": ""DarkGray""
|
||||
},
|
||||
""HotFocus"": {
|
||||
""Foreground"": ""BrightYellow"",
|
||||
""Background"": ""Black""
|
||||
},
|
||||
""Disabled"": {
|
||||
""Foreground"": ""Gray"",
|
||||
""Background"": ""DarkGray""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
""Error"": {
|
||||
""Normal"": {
|
||||
""Foreground"": ""Red"",
|
||||
""Background"": ""White""
|
||||
},
|
||||
""Focus"": {
|
||||
""Foreground"": ""Black"",
|
||||
""Background"": ""BrightRed""
|
||||
},
|
||||
""HotNormal"": {
|
||||
""Foreground"": ""Black"",
|
||||
""Background"": ""White""
|
||||
},
|
||||
""HotFocus"": {
|
||||
""Foreground"": ""White"",
|
||||
""Background"": ""BrightRed""
|
||||
},
|
||||
""Disabled"": {
|
||||
""Foreground"": ""DarkGray"",
|
||||
""Background"": ""White""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
";
|
||||
|
||||
Reset ();
|
||||
ThrowOnJsonErrors = true;
|
||||
|
||||
Settings!.Update (json, "TestConfigurationManagerUpdateFromJson", ConfigLocations.Runtime);
|
||||
|
||||
Assert.Equal (KeyCode.Esc, Application.QuitKey.KeyCode);
|
||||
Assert.Equal (KeyCode.Z | KeyCode.AltMask, ((Key)Settings ["Application.QuitKey"].PropertyValue)!.KeyCode);
|
||||
|
||||
Assert.Equal ("Default", Themes!.Theme);
|
||||
|
||||
Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"]!.Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
|
||||
|
||||
Dictionary<string, ColorScheme> colorSchemes =
|
||||
(Dictionary<string, ColorScheme>)Themes.First ().Value ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (new Color (Color.White), colorSchemes! ["Base"].Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.Blue), colorSchemes ["Base"].Normal.Background);
|
||||
|
||||
// Now re-apply
|
||||
Apply ();
|
||||
|
||||
Assert.Equal (KeyCode.Z | KeyCode.AltMask, Application.QuitKey.KeyCode);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
|
||||
Assert.Equal (new Color (Color.White), Colors.ColorSchemes ["Base"].Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.Blue), Colors.ColorSchemes ["Base"].Normal.Background);
|
||||
Reset ();
|
||||
|
||||
Locations = savedLocations;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UseWithoutResetDoesNotThrow ()
|
||||
{
|
||||
Initialize ();
|
||||
_ = Settings;
|
||||
}
|
||||
}
|
||||
49
Tests/UnitTests/Configuration/GlyphTests.cs
Normal file
49
Tests/UnitTests/Configuration/GlyphTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class GlyphTests
|
||||
{
|
||||
[Fact]
|
||||
public void Overrides_Defaults ()
|
||||
{
|
||||
// arrange
|
||||
Locations = ConfigLocations.Default;
|
||||
Load (true);
|
||||
|
||||
Assert.Equal ((Rune)'⟦', Glyphs.LeftBracket);
|
||||
|
||||
var glyph = (Rune)Themes ["Default"] ["Glyphs.LeftBracket"].PropertyValue;
|
||||
Assert.Equal ((Rune)'⟦', glyph);
|
||||
|
||||
ThrowOnJsonErrors = true;
|
||||
|
||||
// act
|
||||
var json = """
|
||||
{
|
||||
"Themes": [
|
||||
{
|
||||
"Default":
|
||||
{
|
||||
"Glyphs.LeftBracket": "["
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
Settings!.Update (json, "Overrides_Defaults", ConfigLocations.Runtime);
|
||||
Apply();
|
||||
|
||||
// assert
|
||||
glyph = glyph = (Rune)Themes ["Default"] ["Glyphs.LeftBracket"].PropertyValue;
|
||||
Assert.Equal ((Rune)'[', glyph);
|
||||
Assert.Equal((Rune)'[', Glyphs.LeftBracket);
|
||||
|
||||
// clean up
|
||||
Reset ();
|
||||
}
|
||||
}
|
||||
30
Tests/UnitTests/Configuration/KeyCodeJsonConverterTests.cs
Normal file
30
Tests/UnitTests/Configuration/KeyCodeJsonConverterTests.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class KeyCodeJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData (KeyCode.A, "A")]
|
||||
[InlineData (KeyCode.A | KeyCode.ShiftMask, "A, ShiftMask")]
|
||||
[InlineData (KeyCode.A | KeyCode.CtrlMask, "A, CtrlMask")]
|
||||
[InlineData (KeyCode.A | KeyCode.AltMask | KeyCode.CtrlMask, "A, CtrlMask, AltMask")]
|
||||
[InlineData ((KeyCode)'a' | KeyCode.AltMask | KeyCode.CtrlMask, "Space, A, CtrlMask, AltMask")]
|
||||
[InlineData ((KeyCode)'a' | KeyCode.ShiftMask, "Space, A, ShiftMask")]
|
||||
[InlineData (KeyCode.Delete | KeyCode.AltMask | KeyCode.CtrlMask, "Delete, CtrlMask, AltMask")]
|
||||
[InlineData (KeyCode.D4, "D4")]
|
||||
[InlineData (KeyCode.Esc, "Esc")]
|
||||
public void TestKeyRoundTripConversion (KeyCode key, string expectedStringTo)
|
||||
{
|
||||
// Arrange
|
||||
var options = new JsonSerializerOptions ();
|
||||
options.Converters.Add (new KeyCodeJsonConverter ());
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (key, options);
|
||||
var deserializedKey = JsonSerializer.Deserialize<KeyCode> (json, options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedStringTo, deserializedKey.ToString ());
|
||||
}
|
||||
}
|
||||
140
Tests/UnitTests/Configuration/KeyJsonConverterTests.cs
Normal file
140
Tests/UnitTests/Configuration/KeyJsonConverterTests.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Unicode;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class KeyJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData (KeyCode.A, "\"a\"")]
|
||||
[InlineData ((KeyCode)'â', "\"â\"")]
|
||||
[InlineData (KeyCode.A | KeyCode.ShiftMask, "\"A\"")]
|
||||
[InlineData (KeyCode.A | KeyCode.CtrlMask, "\"Ctrl+A\"")]
|
||||
[InlineData (KeyCode.A | KeyCode.AltMask | KeyCode.CtrlMask, "\"Ctrl+Alt+A\"")]
|
||||
[InlineData (KeyCode.Delete | KeyCode.AltMask | KeyCode.CtrlMask, "\"Ctrl+Alt+Delete\"")]
|
||||
[InlineData (KeyCode.D4, "\"4\"")]
|
||||
[InlineData (KeyCode.Esc, "\"Esc\"")]
|
||||
[InlineData ((KeyCode)'+' | KeyCode.AltMask | KeyCode.CtrlMask, "\"Ctrl+Alt++\"")]
|
||||
public void TestKey_Serialize (KeyCode key, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var options = new JsonSerializerOptions ();
|
||||
options.Converters.Add (new KeyJsonConverter ());
|
||||
options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize ((Key)key, options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expected, json);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (KeyCode.A, "a")]
|
||||
[InlineData (KeyCode.A | KeyCode.ShiftMask, "A")]
|
||||
[InlineData (KeyCode.A | KeyCode.CtrlMask, "Ctrl+A")]
|
||||
[InlineData (KeyCode.A | KeyCode.AltMask | KeyCode.CtrlMask, "Ctrl+Alt+A")]
|
||||
[InlineData (KeyCode.Delete | KeyCode.AltMask | KeyCode.CtrlMask, "Ctrl+Alt+Delete")]
|
||||
[InlineData (KeyCode.D4, "4")]
|
||||
[InlineData (KeyCode.Esc, "Esc")]
|
||||
[InlineData ((KeyCode)'+' | KeyCode.AltMask | KeyCode.CtrlMask, "Ctrl+Alt++")]
|
||||
public void TestKeyRoundTripConversion (KeyCode key, string expectedStringTo)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize ((Key)key, ConfigurationManager.SerializerOptions);
|
||||
var deserializedKey = JsonSerializer.Deserialize<Key> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedStringTo, deserializedKey.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialized_Key_Equals ()
|
||||
{
|
||||
// Arrange
|
||||
Key key = Key.Q.WithCtrl;
|
||||
|
||||
// Act
|
||||
string json = "\"Ctrl+Q\"";
|
||||
Key deserializedKey = JsonSerializer.Deserialize<Key> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (key, deserializedKey);
|
||||
|
||||
}
|
||||
[Fact]
|
||||
public void Separator_Property_Serializes_As_Glyph ()
|
||||
{
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (Key.Separator, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ($"\"{Key.Separator}\"", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Separator_Property_Set_Changes_Serialization_Format ()
|
||||
{
|
||||
Rune savedSeparator = Key.Separator;
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
Key.Separator = (Rune)'*';
|
||||
string json = JsonSerializer.Serialize (Key.Separator, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("\"*\"", json);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Key.Separator = savedSeparator;
|
||||
}
|
||||
|
||||
Key.Separator = savedSeparator;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData ('A', '+', "\"Ctrl+Alt+A\"")]
|
||||
[InlineData ('A', '-', "\"Ctrl+Alt+A\"")]
|
||||
[InlineData ('A', '*', "\"Ctrl+Alt+A\"")]
|
||||
[InlineData ('A', '@', "\"Ctrl+Alt+A\"")]
|
||||
[InlineData ('A', '+', "\"Ctrl@Alt@A\"")]
|
||||
[InlineData ('A', '-', "\"Ctrl@Alt@A\"")]
|
||||
[InlineData ('A', '*', "\"Ctrl@Alt@A\"")]
|
||||
[InlineData ('A', '@', "\"Ctrl@Alt@A\"")]
|
||||
[InlineData ('+', '+', "\"Ctrl+Alt++\"")]
|
||||
[InlineData ('+', '-', "\"Ctrl+Alt++\"")]
|
||||
[InlineData ('+', '*', "\"Ctrl+Alt++\"")]
|
||||
[InlineData ('+', '@', "\"Ctrl+Alt++\"")]
|
||||
[InlineData ('+', '+', "\"Ctrl@Alt@+\"")]
|
||||
[InlineData ('+', '-', "\"Ctrl@Alt@+\"")]
|
||||
[InlineData ('+', '*', "\"Ctrl@Alt@+\"")]
|
||||
[InlineData ('+', '@', "\"Ctrl@Alt@+\"")]
|
||||
public void Separator_Property_Set_Deserialization_Works_With_Any (char keyChar, char separator, string json)
|
||||
{
|
||||
Rune savedSeparator = Key.Separator;
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
Key.Separator = (Rune)separator;
|
||||
|
||||
Key deserializedKey = JsonSerializer.Deserialize<Key> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
Key expectedKey = new Key ((KeyCode)keyChar).WithCtrl.WithAlt;
|
||||
// Assert
|
||||
Assert.Equal (expectedKey, deserializedKey);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Key.Separator = savedSeparator;
|
||||
}
|
||||
|
||||
Key.Separator = savedSeparator;
|
||||
}
|
||||
}
|
||||
146
Tests/UnitTests/Configuration/RuneJsonConverterTests.cs
Normal file
146
Tests/UnitTests/Configuration/RuneJsonConverterTests.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class RuneJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData ("aa")]
|
||||
[InlineData ("☑☑")]
|
||||
[InlineData ("\\x2611")]
|
||||
[InlineData ("Z+2611")]
|
||||
[InlineData ("🍎🍎")]
|
||||
[InlineData ("U+FFF1F34E")]
|
||||
[InlineData ("\\UFFF1F34E")]
|
||||
[InlineData ("\\ud83d")] // not printable "high surrogate"
|
||||
[InlineData ("\\udc3d")] // not printable "low surrogate"
|
||||
[InlineData ("\\ud83d \\u1c69")] // bad surrogate pair
|
||||
[InlineData ("\\ud83ddc69")]
|
||||
|
||||
// Emoji - Family Unit:
|
||||
// Woman (U+1F469, 👩)
|
||||
// Zero Width Joiner (U+200D)
|
||||
// Woman (U+1F469, 👩)
|
||||
// Zero Width Joiner (U+200D)
|
||||
// Girl (U+1F467, 👧)
|
||||
// Zero Width Joiner (U+200D)
|
||||
// Girl (U+1F467, 👧)
|
||||
[InlineData ("U+1F469 U+200D U+1F469 U+200D U+1F467 U+200D U+1F467")]
|
||||
[InlineData ("\\U0001F469\\u200D\\U0001F469\\u200D\\U0001F467\\u200D\\U0001F467")]
|
||||
public void RoundTripConversion_Negative (string rune)
|
||||
{
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (rune, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Throws<JsonException> (
|
||||
() => JsonSerializer.Deserialize<Rune> (
|
||||
json,
|
||||
ConfigurationManager.SerializerOptions
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData ("a", "a")]
|
||||
[InlineData ("☑", "☑")]
|
||||
[InlineData ("\\u2611", "☑")]
|
||||
[InlineData ("U+2611", "☑")]
|
||||
[InlineData ("🍎", "🍎")]
|
||||
[InlineData ("U+1F34E", "🍎")]
|
||||
[InlineData ("\\U0001F34E", "🍎")]
|
||||
[InlineData ("\\ud83d \\udc69", "👩")]
|
||||
[InlineData ("\\ud83d\\udc69", "👩")]
|
||||
[InlineData ("U+d83d U+dc69", "👩")]
|
||||
[InlineData ("U+1F469", "👩")]
|
||||
[InlineData ("\\U0001F469", "👩")]
|
||||
[InlineData ("\\u0065\\u0301", "é")]
|
||||
public void RoundTripConversion_Positive (string rune, string expected)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize (rune, ConfigurationManager.SerializerOptions);
|
||||
var deserialized = JsonSerializer.Deserialize<Rune> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expected, deserialized.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Printable_Rune_Is_Serialized_As_Glyph ()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize ((Rune)'a', ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("\"a\"", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Non_Printable_Rune_Is_Serialized_As_u_Encoded_Value ()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
string json = JsonSerializer.Serialize ((Rune)0x01, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("\"\\u0001\"", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Json_With_Glyph_Works ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "\"a\"";
|
||||
|
||||
// Act
|
||||
var deserialized = JsonSerializer.Deserialize<Rune> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("a", deserialized.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Json_With_u_Encoded_Works ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "\"\\u0061\"";
|
||||
|
||||
// Act
|
||||
var deserialized = JsonSerializer.Deserialize<Rune> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("a", deserialized.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Json_With_U_Encoded_Works ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "\"U+0061\"";
|
||||
|
||||
// Act
|
||||
var deserialized = JsonSerializer.Deserialize<Rune> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("a", deserialized.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Json_With_Decimal_Works ()
|
||||
{
|
||||
// Arrange
|
||||
var json = "97";
|
||||
|
||||
// Act
|
||||
var deserialized = JsonSerializer.Deserialize<Rune> (json, ConfigurationManager.SerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal ("a", deserialized.ToString ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#nullable enable
|
||||
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class SerializableConfigurationPropertyTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// If this test fails, you need to add a new property to <see cref="SourceGenerationContext"/> to support serialization of the new property type.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Test_SerializableConfigurationProperty_Types_Added_To_JsonSerializerContext ()
|
||||
{
|
||||
// The assembly containing the types to inspect
|
||||
var assembly = Assembly.GetAssembly (typeof (SourceGenerationContext));
|
||||
|
||||
// Get all types from the assembly
|
||||
var types = assembly!.GetTypes ();
|
||||
|
||||
// Find all properties with the SerializableConfigurationProperty attribute
|
||||
var properties = new List<PropertyInfo> ();
|
||||
foreach (var type in types)
|
||||
{
|
||||
properties.AddRange (type.GetProperties ().Where (p =>
|
||||
p.GetCustomAttributes (typeof (SerializableConfigurationProperty), false).Any ()));
|
||||
}
|
||||
|
||||
// Get the types of the properties
|
||||
var propertyTypes = properties.Select (p => p.PropertyType).Distinct ();
|
||||
|
||||
// Get the types registered in the JsonSerializerContext derived class
|
||||
var contextType = typeof (SourceGenerationContext);
|
||||
var contextTypes = GetRegisteredTypes (contextType);
|
||||
|
||||
// Ensure all property types are included in the JsonSerializerContext derived class
|
||||
IEnumerable<Type> collection = contextTypes as Type [] ?? contextTypes.ToArray ();
|
||||
|
||||
foreach (var type in propertyTypes)
|
||||
{
|
||||
Assert.Contains (type, collection);
|
||||
}
|
||||
|
||||
// Ensure no property has the generic JsonStringEnumConverter<>
|
||||
EnsureNoSpecifiedConverters (properties, new [] { typeof (JsonStringEnumConverter<>) });
|
||||
// Ensure no property has the type RuneJsonConverter
|
||||
EnsureNoSpecifiedConverters (properties, new [] { typeof (RuneJsonConverter) });
|
||||
// Ensure no property has the type KeyJsonConverter
|
||||
EnsureNoSpecifiedConverters (properties, new [] { typeof (KeyJsonConverter) });
|
||||
|
||||
// Find all classes with the JsonConverter attribute of type ScopeJsonConverter<>
|
||||
var classesWithScopeJsonConverter = types.Where (t =>
|
||||
t.GetCustomAttributes (typeof (JsonConverterAttribute), false)
|
||||
.Any (attr => ((JsonConverterAttribute)attr).ConverterType!.IsGenericType &&
|
||||
((JsonConverterAttribute)attr).ConverterType!.GetGenericTypeDefinition () == typeof (ScopeJsonConverter<>)));
|
||||
|
||||
// Ensure all these classes are included in the JsonSerializerContext derived class
|
||||
foreach (var type in classesWithScopeJsonConverter)
|
||||
{
|
||||
Assert.Contains (type, collection);
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetRegisteredTypes (Type contextType)
|
||||
{
|
||||
// Use reflection to find which types are registered in the JsonSerializerContext
|
||||
var registeredTypes = new List<Type> ();
|
||||
|
||||
var properties = contextType.GetProperties (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (property.PropertyType.IsGenericType &&
|
||||
property.PropertyType.GetGenericTypeDefinition () == typeof (JsonTypeInfo<>))
|
||||
{
|
||||
registeredTypes.Add (property.PropertyType.GetGenericArguments () [0]);
|
||||
}
|
||||
}
|
||||
|
||||
return registeredTypes.Distinct ();
|
||||
}
|
||||
|
||||
private static void EnsureNoSpecifiedConverters (List<PropertyInfo> properties, IEnumerable<Type> converterTypes)
|
||||
{
|
||||
// Ensure no property has any of the specified converter types
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var jsonConverterAttributes = property.GetCustomAttributes (typeof (JsonConverterAttribute), false)
|
||||
.Cast<JsonConverterAttribute> ();
|
||||
|
||||
foreach (var attribute in jsonConverterAttributes)
|
||||
{
|
||||
foreach (var converterType in converterTypes)
|
||||
{
|
||||
if (attribute.ConverterType!.IsGenericType &&
|
||||
attribute.ConverterType.GetGenericTypeDefinition () == converterType)
|
||||
{
|
||||
Assert.Fail ($"Property '{property.Name}' should not use the converter '{converterType.Name}'.");
|
||||
}
|
||||
|
||||
if (!attribute.ConverterType!.IsGenericType &&
|
||||
attribute.ConverterType == converterType)
|
||||
{
|
||||
Assert.Fail ($"Property '{property.Name}' should not use the converter '{converterType.Name}'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Tests/UnitTests/Configuration/SettingsScopeTests.cs
Normal file
117
Tests/UnitTests/Configuration/SettingsScopeTests.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using UnitTests;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class SettingsScopeTests
|
||||
{
|
||||
[Fact]
|
||||
public void Update_Overrides_Defaults ()
|
||||
{
|
||||
// arrange
|
||||
Locations = ConfigLocations.Default;
|
||||
Load (true);
|
||||
|
||||
Assert.Equal (Key.Esc, (Key)Settings ["Application.QuitKey"].PropertyValue);
|
||||
|
||||
ThrowOnJsonErrors = true;
|
||||
|
||||
// act
|
||||
var json = """
|
||||
|
||||
{
|
||||
"Application.QuitKey": "Ctrl-Q"
|
||||
}
|
||||
""";
|
||||
|
||||
Settings!.Update (json, "test", ConfigLocations.Runtime);
|
||||
|
||||
// assert
|
||||
Assert.Equal (Key.Q.WithCtrl, (Key)Settings ["Application.QuitKey"].PropertyValue);
|
||||
|
||||
// clean up
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Apply_ShouldApplyProperties ()
|
||||
{
|
||||
Locations = ConfigLocations.Default;
|
||||
Reset();
|
||||
|
||||
// arrange
|
||||
Assert.Equal (Key.Esc, (Key)Settings ["Application.QuitKey"].PropertyValue);
|
||||
|
||||
Assert.Equal (
|
||||
Key.F6,
|
||||
(Key)Settings ["Application.NextTabGroupKey"].PropertyValue
|
||||
);
|
||||
|
||||
Assert.Equal (
|
||||
Key.F6.WithShift,
|
||||
(Key)Settings ["Application.PrevTabGroupKey"].PropertyValue
|
||||
);
|
||||
|
||||
// act
|
||||
Settings ["Application.QuitKey"].PropertyValue = Key.Q;
|
||||
Settings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
|
||||
Settings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
|
||||
|
||||
Settings.Apply ();
|
||||
|
||||
// assert
|
||||
Assert.Equal (Key.Q, Application.QuitKey);
|
||||
Assert.Equal (Key.F, Application.NextTabGroupKey);
|
||||
Assert.Equal (Key.B, Application.PrevTabGroupKey);
|
||||
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void CopyUpdatedPropertiesFrom_ShouldCopyChangedPropertiesOnly ()
|
||||
{
|
||||
Settings ["Application.QuitKey"].PropertyValue = Key.End;
|
||||
|
||||
var updatedSettings = new SettingsScope ();
|
||||
|
||||
///Don't set Quitkey
|
||||
updatedSettings ["Application.NextTabGroupKey"].PropertyValue = Key.F;
|
||||
updatedSettings ["Application.PrevTabGroupKey"].PropertyValue = Key.B;
|
||||
|
||||
Settings.Update (updatedSettings);
|
||||
Assert.Equal (KeyCode.End, ((Key)Settings ["Application.QuitKey"].PropertyValue).KeyCode);
|
||||
Assert.Equal (KeyCode.F, ((Key)updatedSettings ["Application.NextTabGroupKey"].PropertyValue).KeyCode);
|
||||
Assert.Equal (KeyCode.B, ((Key)updatedSettings ["Application.PrevTabGroupKey"].PropertyValue).KeyCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetHardCodedDefaults_ShouldSetProperties ()
|
||||
{
|
||||
ConfigLocations savedLocations = Locations;
|
||||
Locations = ConfigLocations.Default;
|
||||
Reset ();
|
||||
|
||||
Assert.Equal (5, ((Dictionary<string, ThemeScope>)Settings ["Themes"].PropertyValue).Count);
|
||||
|
||||
GetHardCodedDefaults ();
|
||||
Assert.NotEmpty (Themes);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
|
||||
Assert.True (Settings ["Application.QuitKey"].PropertyValue is Key);
|
||||
Assert.True (Settings ["Application.NextTabGroupKey"].PropertyValue is Key);
|
||||
Assert.True (Settings ["Application.PrevTabGroupKey"].PropertyValue is Key);
|
||||
|
||||
Assert.True (Settings ["Theme"].PropertyValue is string);
|
||||
Assert.Equal ("Default", Settings ["Theme"].PropertyValue as string);
|
||||
|
||||
Assert.True (Settings ["Themes"].PropertyValue is Dictionary<string, ThemeScope>);
|
||||
Assert.Single ((Dictionary<string, ThemeScope>)Settings ["Themes"].PropertyValue);
|
||||
|
||||
Locations = ConfigLocations.All;
|
||||
Reset ();
|
||||
}
|
||||
}
|
||||
89
Tests/UnitTests/Configuration/ThemeScopeTests.cs
Normal file
89
Tests/UnitTests/Configuration/ThemeScopeTests.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ThemeScopeTests
|
||||
{
|
||||
public static readonly JsonSerializerOptions _jsonOptions = new ()
|
||||
{
|
||||
Converters =
|
||||
{
|
||||
//new AttributeJsonConverter (),
|
||||
//new ColorJsonConverter ()
|
||||
}
|
||||
};
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void AllThemesPresent ()
|
||||
{
|
||||
Reset ();
|
||||
Assert.True (Themes.ContainsKey ("Default"));
|
||||
Assert.True (Themes.ContainsKey ("Dark"));
|
||||
Assert.True (Themes.ContainsKey ("Light"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void Apply_ShouldApplyUpdatedProperties ()
|
||||
{
|
||||
Reset ();
|
||||
Assert.NotEmpty (Themes);
|
||||
Alignment savedValue = Dialog.DefaultButtonAlignment;
|
||||
Alignment newValue = Alignment.Center != savedValue ? Alignment.Center : Alignment.Start;
|
||||
|
||||
Themes ["Default"] ["Dialog.DefaultButtonAlignment"].PropertyValue = newValue;
|
||||
|
||||
ThemeManager.Themes! [ThemeManager.SelectedTheme]!.Apply ();
|
||||
Assert.Equal (newValue, Dialog.DefaultButtonAlignment);
|
||||
|
||||
// Replace with the savedValue to avoid failures on other unit tests that rely on the default value
|
||||
Themes ["Default"] ["Dialog.DefaultButtonAlignment"].PropertyValue = savedValue;
|
||||
ThemeManager.Themes! [ThemeManager.SelectedTheme]!.Apply ();
|
||||
Assert.Equal (savedValue, Dialog.DefaultButtonAlignment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetHardCodedDefaults_ShouldSetProperties ()
|
||||
{
|
||||
Reset ();
|
||||
GetHardCodedDefaults ();
|
||||
Assert.NotEmpty (Themes);
|
||||
Assert.Equal ("Default", Themes.Theme);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void TestSerialize_RoundTrip ()
|
||||
{
|
||||
Reset ();
|
||||
|
||||
Dictionary<string, ThemeScope> initial = ThemeManager.Themes;
|
||||
|
||||
string serialized = JsonSerializer.Serialize<IDictionary<string, ThemeScope>> (Themes, _jsonOptions);
|
||||
|
||||
IDictionary<string, ThemeScope> deserialized =
|
||||
JsonSerializer.Deserialize<IDictionary<string, ThemeScope>> (serialized, _jsonOptions);
|
||||
|
||||
Assert.NotEqual (initial, deserialized);
|
||||
Assert.Equal (deserialized.Count, initial.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void ThemeManager_ClassMethodsWork ()
|
||||
{
|
||||
Reset ();
|
||||
Assert.Equal (ThemeManager.Instance, Themes);
|
||||
Assert.NotEmpty (ThemeManager.Themes);
|
||||
|
||||
ThemeManager.SelectedTheme = "foo";
|
||||
Assert.Equal ("foo", ThemeManager.SelectedTheme);
|
||||
ThemeManager.Reset ();
|
||||
Assert.Equal (string.Empty, ThemeManager.SelectedTheme);
|
||||
|
||||
Assert.Empty (ThemeManager.Themes);
|
||||
}
|
||||
}
|
||||
202
Tests/UnitTests/Configuration/ThemeTests.cs
Normal file
202
Tests/UnitTests/Configuration/ThemeTests.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System.Text.Json;
|
||||
using UnitTests;
|
||||
using static Terminal.Gui.ConfigurationManager;
|
||||
|
||||
namespace Terminal.Gui.ConfigurationTests;
|
||||
|
||||
public class ThemeTests
|
||||
{
|
||||
public static readonly JsonSerializerOptions _jsonOptions = new ()
|
||||
{
|
||||
Converters = { new AttributeJsonConverter (), new ColorJsonConverter () }
|
||||
};
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void TestApply ()
|
||||
{
|
||||
Reset ();
|
||||
|
||||
var theme = new ThemeScope ();
|
||||
Assert.NotEmpty (theme);
|
||||
|
||||
Themes.Add ("testTheme", theme);
|
||||
|
||||
Assert.Equal (LineStyle.Single, FrameView.DefaultBorderStyle);
|
||||
theme ["FrameView.DefaultBorderStyle"].PropertyValue = LineStyle.Double; // default is Single
|
||||
|
||||
Themes.Theme = "testTheme";
|
||||
Themes! [ThemeManager.SelectedTheme]!.Apply ();
|
||||
|
||||
Assert.Equal (LineStyle.Double, FrameView.DefaultBorderStyle);
|
||||
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown (configLocation: ConfigLocations.Default)]
|
||||
public void TestApply_UpdatesColors ()
|
||||
{
|
||||
// Arrange
|
||||
Reset ();
|
||||
|
||||
Assert.False (Colors.ColorSchemes.ContainsKey ("test"));
|
||||
|
||||
var theme = new ThemeScope ();
|
||||
Assert.NotEmpty (theme);
|
||||
|
||||
Themes.Add ("testTheme", theme);
|
||||
|
||||
var colorScheme = new ColorScheme { Normal = new Attribute (Color.Red, Color.Green) };
|
||||
|
||||
theme ["ColorSchemes"].PropertyValue = new Dictionary<string, ColorScheme> { { "test", colorScheme } };
|
||||
|
||||
Assert.Equal (
|
||||
new Color (Color.Red),
|
||||
((Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue) ["test"].Normal.Foreground
|
||||
);
|
||||
|
||||
Assert.Equal (
|
||||
new Color (Color.Green),
|
||||
((Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue) ["test"].Normal.Background
|
||||
);
|
||||
|
||||
// Act
|
||||
Themes.Theme = "testTheme";
|
||||
Themes! [ThemeManager.SelectedTheme]!.Apply ();
|
||||
|
||||
// Assert
|
||||
ColorScheme updatedScheme = Colors.ColorSchemes ["test"];
|
||||
Assert.Equal (new Color (Color.Red), updatedScheme.Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.Green), updatedScheme.Normal.Background);
|
||||
|
||||
// remove test ColorScheme from Colors to avoid failures on others unit tests with ColorScheme
|
||||
Colors.ColorSchemes.Remove ("test");
|
||||
Assert.Equal (5, Colors.ColorSchemes.Count);
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSerialize_RoundTrip ()
|
||||
{
|
||||
// This is needed to test only this alone
|
||||
Reset ();
|
||||
|
||||
var theme = new ThemeScope ();
|
||||
theme ["Dialog.DefaultButtonAlignment"].PropertyValue = Alignment.End;
|
||||
|
||||
string json = JsonSerializer.Serialize (theme, _jsonOptions);
|
||||
|
||||
var deserialized = JsonSerializer.Deserialize<ThemeScope> (json, _jsonOptions);
|
||||
|
||||
Assert.Equal (
|
||||
Alignment.End,
|
||||
(Alignment)deserialized ["Dialog.DefaultButtonAlignment"].PropertyValue
|
||||
);
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestUpdatFrom_Add ()
|
||||
{
|
||||
// arrange
|
||||
Reset ();
|
||||
|
||||
var theme = new ThemeScope ();
|
||||
Assert.NotEmpty (theme);
|
||||
|
||||
Assert.Equal (5, Colors.ColorSchemes.Count);
|
||||
|
||||
theme ["ColorSchemes"].PropertyValue = Colors.ColorSchemes;
|
||||
|
||||
Dictionary<string, ColorScheme> colorSchemes =
|
||||
(Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (Colors.ColorSchemes.Count, colorSchemes.Count);
|
||||
|
||||
var newTheme = new ThemeScope ();
|
||||
|
||||
var colorScheme = new ColorScheme
|
||||
{
|
||||
// note: ColorScheme's can't be partial; default for each attribute
|
||||
// is always White/Black
|
||||
Normal = new Attribute (Color.Red, Color.Green),
|
||||
Focus = new Attribute (Color.Cyan, Color.BrightCyan),
|
||||
HotNormal = new Attribute (Color.Yellow, Color.BrightYellow),
|
||||
HotFocus = new Attribute (Color.Green, Color.BrightGreen),
|
||||
Disabled = new Attribute (Color.Gray, Color.DarkGray)
|
||||
};
|
||||
|
||||
newTheme ["ColorSchemes"].PropertyValue = Colors.Reset ();
|
||||
Assert.Equal (5, Colors.ColorSchemes.Count);
|
||||
|
||||
// add a new ColorScheme to the newTheme
|
||||
((Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue) ["test"] = colorScheme;
|
||||
|
||||
colorSchemes = (Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (Colors.ColorSchemes.Count, colorSchemes.Count);
|
||||
|
||||
// Act
|
||||
theme.Update (newTheme);
|
||||
|
||||
// Assert
|
||||
colorSchemes = (Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (colorSchemes ["Test"].Normal, colorScheme.Normal);
|
||||
Assert.Equal (colorSchemes ["Test"].Focus, colorScheme.Focus);
|
||||
Reset ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestUpdatFrom_Change ()
|
||||
{
|
||||
// arrange
|
||||
Reset ();
|
||||
|
||||
var theme = new ThemeScope ();
|
||||
Assert.NotEmpty (theme);
|
||||
|
||||
var colorScheme = new ColorScheme
|
||||
{
|
||||
// note: ColorScheme's can't be partial; default for each attribute
|
||||
// is always White/Black
|
||||
Normal = new Attribute (Color.Red, Color.Green),
|
||||
Focus = new Attribute (Color.Cyan, Color.BrightCyan),
|
||||
HotNormal = new Attribute (Color.Yellow, Color.BrightYellow),
|
||||
HotFocus = new Attribute (Color.Green, Color.BrightGreen),
|
||||
Disabled = new Attribute (Color.Gray, Color.DarkGray)
|
||||
};
|
||||
theme ["ColorSchemes"].PropertyValue = Colors.Reset ();
|
||||
((Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue) ["test"] = colorScheme;
|
||||
|
||||
Dictionary<string, ColorScheme> colorSchemes =
|
||||
(Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue;
|
||||
Assert.Equal (colorScheme.Normal, colorSchemes ["Test"].Normal);
|
||||
Assert.Equal (colorScheme.Focus, colorSchemes ["Test"].Focus);
|
||||
|
||||
// Change just Normal
|
||||
var newTheme = new ThemeScope ();
|
||||
|
||||
var newColorScheme = new ColorScheme
|
||||
{
|
||||
Normal = new Attribute (Color.Blue, Color.BrightBlue),
|
||||
Focus = colorScheme.Focus,
|
||||
HotNormal = colorScheme.HotNormal,
|
||||
HotFocus = colorScheme.HotFocus,
|
||||
Disabled = colorScheme.Disabled
|
||||
};
|
||||
newTheme ["ColorSchemes"].PropertyValue = Colors.Reset ();
|
||||
((Dictionary<string, ColorScheme>)newTheme ["ColorSchemes"].PropertyValue) ["test"] = newColorScheme;
|
||||
|
||||
// Act
|
||||
theme.Update (newTheme);
|
||||
|
||||
// Assert
|
||||
colorSchemes = (Dictionary<string, ColorScheme>)theme ["ColorSchemes"].PropertyValue;
|
||||
|
||||
// Normal should have changed
|
||||
Assert.Equal (new Color (Color.Blue), colorSchemes ["Test"].Normal.Foreground);
|
||||
Assert.Equal (new Color (Color.BrightBlue), colorSchemes ["Test"].Normal.Background);
|
||||
Assert.Equal (new Color (Color.Cyan), colorSchemes ["Test"].Focus.Foreground);
|
||||
Assert.Equal (new Color (Color.BrightCyan), colorSchemes ["Test"].Focus.Background);
|
||||
Reset ();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user