Ver código fonte

Basic tokenizer tests

Daniel Chalmers 2 anos atrás
pai
commit
228ffcb7e1

+ 3 - 0
.github/workflows/build.yml

@@ -14,3 +14,6 @@ jobs:
 
       - name: Build
         run: dotnet build
+
+      - name: Test
+        run: dotnet test

+ 19 - 0
DesktopClock.Tests/DesktopClock.Tests.csproj

@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net48</TargetFramework>
+    <LangVersion>latest</LangVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
+    <PackageReference Include="xunit" Version="2.5.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.1" PrivateAssets="All">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <ProjectReference Include="..\DesktopClock\DesktopClock.csproj" />
+
+    <Using Include="Xunit" />
+  </ItemGroup>
+
+</Project>

+ 27 - 0
DesktopClock.Tests/TokenizerTests.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+
+namespace DesktopClock.Tests;
+
+public class TokenizerTests
+{
+    [Fact]
+    public void FormatWithTokenizer()
+    {
+        var dateTime = new DateTime(2023, 09, 24, 12, 13, 14);
+        var format = "{dddd}, {MMM dd}, {HH:mm:ss}";
+        var result = Tokenizer.FormatWithTokenizerOrFallBack(dateTime, format, CultureInfo.InvariantCulture);
+
+        Assert.Equal("Sunday, Sep 24, 12:13:14", result);
+    }
+
+    [Fact]
+    public void FormatWithFallback()
+    {
+        var dateTime = new DateTime(2023, 09, 24, 12, 13, 14);
+        var format = "dddd, MMM dd, HH:mm:ss";
+        var result = Tokenizer.FormatWithTokenizerOrFallBack(dateTime, format, CultureInfo.InvariantCulture);
+
+        Assert.Equal("Sunday, Sep 24, 12:13:14", result);
+    }
+}

+ 8 - 2
DesktopClock.sln

@@ -1,9 +1,11 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30907.101
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34112.27
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DesktopClock", "DesktopClock\DesktopClock.csproj", "{6BD5BA59-2419-4A0E-89F8-C6F8A4EA08F7}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClock.Tests", "DesktopClock.Tests\DesktopClock.Tests.csproj", "{1180264E-9996-41AA-96F8-8885AAF52ED6}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -14,6 +16,10 @@ Global
 		{6BD5BA59-2419-4A0E-89F8-C6F8A4EA08F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{6BD5BA59-2419-4A0E-89F8-C6F8A4EA08F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6BD5BA59-2419-4A0E-89F8-C6F8A4EA08F7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1180264E-9996-41AA-96F8-8885AAF52ED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1180264E-9996-41AA-96F8-8885AAF52ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1180264E-9996-41AA-96F8-8885AAF52ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1180264E-9996-41AA-96F8-8885AAF52ED6}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 2 - 27
DesktopClock/MainWindow.xaml.cs

@@ -3,7 +3,6 @@ using System.ComponentModel;
 using System.Diagnostics;
 using System.Globalization;
 using System.IO;
-using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
@@ -22,7 +21,6 @@ namespace DesktopClock;
 [ObservableObject]
 public partial class MainWindow : Window
 {
-    private readonly Regex _tokenizerRegex = new("{([^{}]+)}", RegexOptions.Compiled);
     private readonly SystemClockTimer _systemClockTimer;
     private TaskbarIcon _trayIcon;
     private TimeZoneInfo _timeZone;
@@ -213,29 +211,6 @@ public partial class MainWindow : Window
 
     private void UpdateTimeString()
     {
-        string FormatWithTokenizerOrFallBack(IFormattable formattable, string format)
-        {
-            try
-            {
-                if (format.Contains("}"))
-                {
-                    return _tokenizerRegex.Replace(format, (m) =>
-                    {
-                        var formatString = m.Value.Replace("{", "").Replace("}", "");
-                        return formattable.ToString(formatString, CultureInfo.DefaultThreadCurrentCulture);
-                    });
-                }
-
-                // Use basic formatter if no special formatting tokens are present.
-                return formattable.ToString(format, CultureInfo.DefaultThreadCurrentCulture);
-            }
-            catch
-            {
-                // Fallback to the default format.
-                return formattable.ToString();
-            }
-        }
-
         string GetTimeString()
         {
             var timeInSelectedZone = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, _timeZone);
@@ -245,11 +220,11 @@ public partial class MainWindow : Window
                 if (string.IsNullOrWhiteSpace(Settings.Default.CountdownFormat))
                     return Settings.Default.CountdownTo.Humanize(timeInSelectedZone);
 
-                return FormatWithTokenizerOrFallBack(Settings.Default.CountdownTo - timeInSelectedZone, Settings.Default.CountdownFormat);
+                return Tokenizer.FormatWithTokenizerOrFallBack(Settings.Default.CountdownTo - timeInSelectedZone, Settings.Default.CountdownFormat, CultureInfo.DefaultThreadCurrentCulture);
             }
             else
             {
-                return FormatWithTokenizerOrFallBack(timeInSelectedZone, Settings.Default.Format);
+                return Tokenizer.FormatWithTokenizerOrFallBack(timeInSelectedZone, Settings.Default.Format, CultureInfo.DefaultThreadCurrentCulture);
             }
         }
 

+ 40 - 0
DesktopClock/Tokenizer.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace DesktopClock;
+
+public static class Tokenizer
+{
+    private static readonly Regex _tokenizerRegex = new("{([^{}]+)}", RegexOptions.Compiled);
+
+    /// <summary>
+    /// Formats with a tokenized format in mind, or treats it as a regular formatting string.
+    /// Falls back to the default format on any exception.
+    /// </summary>
+    /// <param name="formattable">The object to format.</param>
+    /// <param name="format">The format to use.</param>
+    /// <param name="formatProvider">The format provider.</param>
+    /// <returns></returns>
+    public static string FormatWithTokenizerOrFallBack(IFormattable formattable, string format, IFormatProvider formatProvider)
+    {
+        try
+        {
+            if (format.Contains("}"))
+            {
+                return _tokenizerRegex.Replace(format, (m) =>
+                {
+                    var formatString = m.Value.Replace("{", "").Replace("}", "");
+                    return formattable.ToString(formatString, formatProvider);
+                });
+            }
+
+            // Use basic formatter if no special formatting tokens are present.
+            return formattable.ToString(format, formatProvider);
+        }
+        catch
+        {
+            // Fallback to the default format.
+            return formattable.ToString();
+        }
+    }
+}