From 7f7599be5af657835f39224678646c26b5c1121d Mon Sep 17 00:00:00 2001 From: IhateTrains Date: Sat, 22 Aug 2026 06:04:33 +0200 Subject: [PATCH] More unit tests --- .../Models/ConfigurationTests.cs | 50 ++++++++++++++++++- .../Services/MessageSlicerTests.cs | 36 +++++++++++++ .../Services/TargetDbManagerTests.cs | 45 +++++++++++++++++ .../ValueConverters/ValueConverterTests.cs | 36 +++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 Fronter.NET.Tests/Services/TargetDbManagerTests.cs create mode 100644 Fronter.NET.Tests/ValueConverters/ValueConverterTests.cs diff --git a/Fronter.NET.Tests/Models/ConfigurationTests.cs b/Fronter.NET.Tests/Models/ConfigurationTests.cs index 4930e2d8..b6cfb413 100644 --- a/Fronter.NET.Tests/Models/ConfigurationTests.cs +++ b/Fronter.NET.Tests/Models/ConfigurationTests.cs @@ -1,6 +1,10 @@ -using Fronter.Models.Configuration; +using Avalonia.Data; +using commonItems; +using Fronter.Models.Configuration; +using Fronter.Models.Configuration.Options; using Microsoft.Data.Sqlite; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; @@ -87,6 +91,50 @@ public void EmptyStringCanBeUsedAsDateOptionValue() { Assert.Equal(string.Empty, bookmarkDateOption.GetValue()); } + [Fact] + public void CheckBoxSelector_TracksSelectedValuesAndIds() { + var selector = new CheckBoxSelector(new BufferedReader(string.Empty)); + selector.CheckBoxOptions.Add(new ToggleableOption(new BufferedReader("name = alpha default = true"), 1)); + selector.CheckBoxOptions.Add(new ToggleableOption(new BufferedReader("name = beta default = false"), 2)); + + selector.SetSelectedValues(new HashSet(new[] { "beta" })); + + Assert.Equal(new HashSet { "beta" }, selector.GetSelectedValues()); + Assert.Equal(new HashSet { 2 }, selector.GetSelectedIds()); + } + + [Fact] + public void TextSelector_ParsesEditableValueAndTooltip() { + var selector = new TextSelector(new BufferedReader("editable = false\nvalue = \"chosen-name\"\ntooltip = \"example tooltip\"")); + + Assert.False(selector.Editable); + Assert.Equal("chosen-name", selector.Value); + Assert.Equal("example tooltip", selector.Tooltip); + } + + [Fact] + public void DateSelector_TextValue_AllowsValidDatesAndClearsEmptyValues() { + var selector = new DateSelector(new BufferedReader("editable = true\nvalue = \"2025.05.04\"\ntooltip = \"example date\"")); + + Assert.Equal("2025.5.4", selector.TextValue); + + selector.TextValue = "2026.06.15"; + Assert.Equal("2026.6.15", selector.TextValue); + + selector.TextValue = string.Empty; + Assert.Null(selector.Value); + } + + [Theory] + [InlineData("2025.13.01")] + [InlineData("2025.00.01")] + [InlineData("2025.12.32")] + public void DateSelector_TextValue_RejectsInvalidDates(string invalidDate) { + var selector = new DateSelector(new BufferedReader(string.Empty)); + + Assert.Throws(() => selector.TextValue = invalidDate); + } + [Fact] public void AutoLocatePlaysets_DoesNotThrowWhenLauncherDbIsInvalid() { var config = new Config(); diff --git a/Fronter.NET.Tests/Services/MessageSlicerTests.cs b/Fronter.NET.Tests/Services/MessageSlicerTests.cs index c394d6b8..f265969f 100644 --- a/Fronter.NET.Tests/Services/MessageSlicerTests.cs +++ b/Fronter.NET.Tests/Services/MessageSlicerTests.cs @@ -1,5 +1,6 @@ using Fronter.Services; using log4net.Core; +using System; using Xunit; namespace Fronter.Tests.Services; @@ -14,4 +15,39 @@ public void MessageIsCorrectlySliced() { Assert.Equal(Level.Alert, logLine.Level); Assert.Equal("test message", logLine.Message); } + + [Theory] + [InlineData("2000-06-06 15:23:33 [DEBUG] debug message", "DEBUG", "debug message")] + [InlineData("2000-06-06 15:23:33 [INFO] info message", "INFO", "info message")] + [InlineData("2000-06-06 15:23:33 [WARN] warning message", "WARN", "warning message")] + [InlineData("2000-06-06 15:23:33 [NOTICE] notice message", "NOTICE", "notice message")] + [InlineData("2000-06-06 15:23:33 [ERROR] error message", "ERROR", "error message")] + [InlineData("2000-06-06 15:23:33 [FATAL] fatal message", "FATAL", "fatal message")] + [InlineData("2000-06-06 15:23:33 [PROGRESS] 25%", "PROGRESS", "25%")] + public void SliceMessage_ParsesKnownLevels(string message, string expectedLevelName, string expectedText) { + var logLine = MessageSlicer.SliceMessage(message); + + Assert.NotNull(logLine.Level); + Assert.Equal(expectedLevelName, logLine.Level.Name); + Assert.Equal(expectedText, logLine.Message); + Assert.Equal("2000-06-06 15:23:33", logLine.Timestamp.ToString("yyyy-MM-dd HH:mm:ss")); + } + + [Fact] + public void SliceMessage_WithoutTimestamp_StillParsesLevelAndMessage() { + var logLine = MessageSlicer.SliceMessage("[WARNING] keep going"); + + Assert.Equal(Level.Warn, logLine.Level); + Assert.Equal("keep going", logLine.Message); + Assert.True(logLine.Timestamp <= DateTime.Now); + } + + [Fact] + public void SliceMessage_WithoutBracketedLevel_ReturnsOriginalText() { + var message = "plain log line without a level prefix"; + var logLine = MessageSlicer.SliceMessage(message); + + Assert.Null(logLine.Level); + Assert.Equal(message, logLine.Message); + } } \ No newline at end of file diff --git a/Fronter.NET.Tests/Services/TargetDbManagerTests.cs b/Fronter.NET.Tests/Services/TargetDbManagerTests.cs new file mode 100644 index 00000000..ccd9476f --- /dev/null +++ b/Fronter.NET.Tests/Services/TargetDbManagerTests.cs @@ -0,0 +1,45 @@ +using Fronter.Services; +using System; +using System.IO; +using Xunit; + +namespace Fronter.Tests.Services; + +public class TargetDbManagerTests { + [Fact] + public void GetLastUpdatedLauncherDbPath_ReturnsNewestExistingLauncherDatabase() { + var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(tempDir); + + try { + var olderPath = Path.Combine(tempDir, "launcher-v2.sqlite"); + var newerPath = Path.Combine(tempDir, "launcher-v2_openbeta.sqlite"); + + File.WriteAllText(olderPath, "older"); + File.WriteAllText(newerPath, "newer"); + + File.SetLastWriteTimeUtc(olderPath, new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)); + File.SetLastWriteTimeUtc(newerPath, new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Utc)); + + Assert.Equal(newerPath, TargetDbManager.GetLastUpdatedLauncherDbPath(tempDir)); + } finally { + if (Directory.Exists(tempDir)) { + Directory.Delete(tempDir, recursive: true); + } + } + } + + [Fact] + public void GetLastUpdatedLauncherDbPath_ReturnsNullWhenNoDatabaseExists() { + var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(tempDir); + + try { + Assert.Null(TargetDbManager.GetLastUpdatedLauncherDbPath(tempDir)); + } finally { + if (Directory.Exists(tempDir)) { + Directory.Delete(tempDir, recursive: true); + } + } + } +} diff --git a/Fronter.NET.Tests/ValueConverters/ValueConverterTests.cs b/Fronter.NET.Tests/ValueConverters/ValueConverterTests.cs new file mode 100644 index 00000000..05c922c7 --- /dev/null +++ b/Fronter.NET.Tests/ValueConverters/ValueConverterTests.cs @@ -0,0 +1,36 @@ +using Avalonia; +using Fronter.ValueConverters; +using System.Globalization; +using Xunit; + +namespace Fronter.Tests.ValueConverters; + +public class ValueConverterTests { + [Fact] + public void BooleanNegationConverter_InvertsBooleanValues() { + var converter = BooleanNegationConverter.Instance; + + Assert.Equal(false, converter.Convert(true, typeof(bool), null, CultureInfo.InvariantCulture)); + Assert.Equal(true, converter.Convert(false, typeof(bool), null, CultureInfo.InvariantCulture)); + Assert.Same(AvaloniaProperty.UnsetValue, converter.Convert("not a bool", typeof(bool), null, CultureInfo.InvariantCulture)); + Assert.Equal(false, converter.ConvertBack(true, typeof(bool), null, CultureInfo.InvariantCulture)); + Assert.Equal(true, converter.ConvertBack(false, typeof(bool), null, CultureInfo.InvariantCulture)); + Assert.Same(AvaloniaProperty.UnsetValue, converter.ConvertBack("not a bool", typeof(bool), null, CultureInfo.InvariantCulture)); + } + + [Fact] + public void EnumToBooleanConverter_UsesParameterForEqualityChecks() { + var converter = EnumToBooleanConverter.Instance; + + Assert.Equal(true, converter.Convert(TestEnum.Second, typeof(bool), TestEnum.Second, CultureInfo.InvariantCulture)); + Assert.Equal(false, converter.Convert(TestEnum.First, typeof(bool), TestEnum.Second, CultureInfo.InvariantCulture)); + Assert.Same(AvaloniaProperty.UnsetValue, converter.Convert(null, typeof(bool), TestEnum.Second, CultureInfo.InvariantCulture)); + Assert.Equal(TestEnum.Second, converter.ConvertBack(true, typeof(TestEnum), TestEnum.Second, CultureInfo.InvariantCulture)); + Assert.Same(AvaloniaProperty.UnsetValue, converter.ConvertBack(false, typeof(TestEnum), TestEnum.Second, CultureInfo.InvariantCulture)); + } + + private enum TestEnum { + First, + Second, + } +}