diff --git a/src/Elzik.FmSync.Infrastructure/FrontMatterOptions.cs b/src/Elzik.FmSync.Infrastructure/FrontMatterOptions.cs index ff2dbdb..5949e6a 100644 --- a/src/Elzik.FmSync.Infrastructure/FrontMatterOptions.cs +++ b/src/Elzik.FmSync.Infrastructure/FrontMatterOptions.cs @@ -1,7 +1,6 @@ -namespace Elzik.FmSync.Infrastructure +namespace Elzik.FmSync.Infrastructure; + +public class FrontMatterOptions { - public class FrontMatterOptions - { - public string? TimeZoneId { get; set; } - } -} + public string? TimeZoneId { get; set; } +} \ No newline at end of file diff --git a/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFileSynchroniserTests.cs b/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFileSynchroniserTests.cs index e8f5a2a..9625792 100644 --- a/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFileSynchroniserTests.cs +++ b/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFileSynchroniserTests.cs @@ -6,134 +6,133 @@ using Thinktecture.IO; using Xunit; -namespace Elzik.FmSync.Application.Tests.Unit +namespace Elzik.FmSync.Application.Tests.Unit; + +public class FrontMatterFileSynchroniserTests { - public class FrontMatterFileSynchroniserTests + private readonly Fixture _fixture; + private readonly MockLogger _mockLogger; + private readonly IMarkdownFrontMatter _mockMarkDownFrontMatter; + private readonly IFile _mockFile; + private readonly FrontMatterFileSynchroniser _frontMatterFileSynchroniser; + + public FrontMatterFileSynchroniserTests() + { + _mockMarkDownFrontMatter = Substitute.For(); + _mockFile = Substitute.For(); + _mockLogger = Substitute.For>(); + + _fixture = new Fixture(); + _fixture.Register>(() => _mockLogger); + _fixture.Register(() => _mockMarkDownFrontMatter); + _fixture.Register(() => _mockFile); + _frontMatterFileSynchroniser = _fixture.Create(); + } + + [Fact] + public void SyncCreationDates_NoMarkDownCreationDate_OnlyLogs() { - private readonly Fixture _fixture; - private readonly MockLogger _mockLogger; - private readonly IMarkdownFrontMatter _mockMarkDownFrontMatter; - private readonly IFile _mockFile; - private readonly FrontMatterFileSynchroniser _frontMatterFileSynchroniser; - - public FrontMatterFileSynchroniserTests() - { - _mockMarkDownFrontMatter = Substitute.For(); - _mockFile = Substitute.For(); - _mockLogger = Substitute.For>(); - - _fixture = new Fixture(); - _fixture.Register>(() => _mockLogger); - _fixture.Register(() => _mockMarkDownFrontMatter); - _fixture.Register(() => _mockFile); - _frontMatterFileSynchroniser = _fixture.Create(); - } - - [Fact] - public void SyncCreationDates_NoMarkDownCreationDate_OnlyLogs() - { - // Arrange - var testFilePath = _fixture.Create(); - _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).ReturnsNull(); - - // Act - _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); - - // Assert - _mockLogger.Received(1).Log(LogLevel.Information, - $"{testFilePath} has no Front Matter created date."); - _mockFile.DidNotReceiveWithAnyArgs().SetCreationTimeUtc(default!, default); - } - - [Fact] - public void SyncCreationDates_MarkDownAndFileDateEqual_OnlyLogs() - { - // Arrange - var testFilePath = _fixture.Create(); - var testDate = _fixture.Create(); - _mockFile.GetCreationTimeUtc(testFilePath).Returns(testDate); - _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testDate); - - // Act - _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); - - // Assert - _mockLogger.Received(1).Log( - LogLevel.Information, - Arg.Is>( - dict => - dict.Any(kv => kv.Key == "{OriginalFormat}" - && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) " + - "the same as the created date specified in its Front Matter.") && - dict.Any(kv => kv.Key == "FilePath" - && (string)kv.Value == testFilePath) && - dict.Any(kv => kv.Key == "FileCreatedDate" - && (DateTime)kv.Value == testDate))); - _mockFile.DidNotReceiveWithAnyArgs().SetCreationTimeUtc(default!, default); - } - - [Fact] - public void SyncCreationDates_FileDateLaterThanMarkdownDate_LogsAndUpdates() - { - // Arrange - var testFilePath = _fixture.Create(); - var testMarkDownDate = _fixture.Create(); - var testFileDate = testMarkDownDate.AddTicks(_fixture.Create()); - _mockFile.GetCreationTimeUtc(testFilePath).Returns(testFileDate); - _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testMarkDownDate); - - // Act - _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); - - // Assert - _mockLogger.Received(1).Log( - LogLevel.Information, - Arg.Is>( - dict => - dict.Any(kv => kv.Key == "{OriginalFormat}" - && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) {RelativeDescription} " + - "than the created date specified in its Front Matter ({FrontMatterCreatedDate})") && - dict.Any(kv => kv.Key == "FilePath" - && (string)kv.Value == testFilePath) && - dict.Any(kv => kv.Key == "FileCreatedDate" - && (DateTime)kv.Value == testFileDate) && - dict.Any(kv => kv.Key == "RelativeDescription" - && (string)kv.Value == "later") && - dict.Any(kv => kv.Key == "FrontMatterCreatedDate" - && (DateTime)kv.Value == testMarkDownDate))); - _mockFile.Received(1).SetCreationTimeUtc(testFilePath, testMarkDownDate); - } - - [Fact] - public void SyncCreationDates_FileDateEarlierThanMarkdownDate_LogsAndUpdates() - { - // Arrange - var testFilePath = _fixture.Create(); - var testMarkDownDate = _fixture.Create(); - var testFileDate = testMarkDownDate.Subtract(_fixture.Create()); - _mockFile.GetCreationTimeUtc(testFilePath).Returns(testFileDate); - _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testMarkDownDate); - - // Act - _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); - - // Assert - _mockLogger.Received(1).Log( - LogLevel.Information, - Arg.Is>( - dict => - dict.Any(kv => kv.Key == "{OriginalFormat}" - && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) {RelativeDescription} " + - "than the created date specified in its Front Matter ({FrontMatterCreatedDate})") && - dict.Any(kv => kv.Key == "FilePath" - && (string)kv.Value == testFilePath) && - dict.Any(kv => kv.Key == "FileCreatedDate" - && (DateTime)kv.Value == testFileDate) && - dict.Any(kv => kv.Key == "RelativeDescription" - && (string)kv.Value == "earlier") && - dict.Any(kv => kv.Key == "FrontMatterCreatedDate" - && (DateTime)kv.Value == testMarkDownDate))); - _mockFile.Received(1).SetCreationTimeUtc(testFilePath, testMarkDownDate); - } + // Arrange + var testFilePath = _fixture.Create(); + _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).ReturnsNull(); + + // Act + _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); + + // Assert + _mockLogger.Received(1).Log(LogLevel.Information, + $"{testFilePath} has no Front Matter created date."); + _mockFile.DidNotReceiveWithAnyArgs().SetCreationTimeUtc(default!, default); + } + + [Fact] + public void SyncCreationDates_MarkDownAndFileDateEqual_OnlyLogs() + { + // Arrange + var testFilePath = _fixture.Create(); + var testDate = _fixture.Create(); + _mockFile.GetCreationTimeUtc(testFilePath).Returns(testDate); + _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testDate); + + // Act + _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); + + // Assert + _mockLogger.Received(1).Log( + LogLevel.Information, + Arg.Is>( + dict => + dict.Any(kv => kv.Key == "{OriginalFormat}" + && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) " + + "the same as the created date specified in its Front Matter.") && + dict.Any(kv => kv.Key == "FilePath" + && (string)kv.Value == testFilePath) && + dict.Any(kv => kv.Key == "FileCreatedDate" + && (DateTime)kv.Value == testDate))); + _mockFile.DidNotReceiveWithAnyArgs().SetCreationTimeUtc(default!, default); + } + + [Fact] + public void SyncCreationDates_FileDateLaterThanMarkdownDate_LogsAndUpdates() + { + // Arrange + var testFilePath = _fixture.Create(); + var testMarkDownDate = _fixture.Create(); + var testFileDate = testMarkDownDate.AddTicks(_fixture.Create()); + _mockFile.GetCreationTimeUtc(testFilePath).Returns(testFileDate); + _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testMarkDownDate); + + // Act + _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); + + // Assert + _mockLogger.Received(1).Log( + LogLevel.Information, + Arg.Is>( + dict => + dict.Any(kv => kv.Key == "{OriginalFormat}" + && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) {RelativeDescription} " + + "than the created date specified in its Front Matter ({FrontMatterCreatedDate})") && + dict.Any(kv => kv.Key == "FilePath" + && (string)kv.Value == testFilePath) && + dict.Any(kv => kv.Key == "FileCreatedDate" + && (DateTime)kv.Value == testFileDate) && + dict.Any(kv => kv.Key == "RelativeDescription" + && (string)kv.Value == "later") && + dict.Any(kv => kv.Key == "FrontMatterCreatedDate" + && (DateTime)kv.Value == testMarkDownDate))); + _mockFile.Received(1).SetCreationTimeUtc(testFilePath, testMarkDownDate); + } + + [Fact] + public void SyncCreationDates_FileDateEarlierThanMarkdownDate_LogsAndUpdates() + { + // Arrange + var testFilePath = _fixture.Create(); + var testMarkDownDate = _fixture.Create(); + var testFileDate = testMarkDownDate.Subtract(_fixture.Create()); + _mockFile.GetCreationTimeUtc(testFilePath).Returns(testFileDate); + _mockMarkDownFrontMatter.GetCreatedDateUtc(testFilePath).Returns(testMarkDownDate); + + // Act + _frontMatterFileSynchroniser.SyncCreationDate(testFilePath); + + // Assert + _mockLogger.Received(1).Log( + LogLevel.Information, + Arg.Is>( + dict => + dict.Any(kv => kv.Key == "{OriginalFormat}" + && (string)kv.Value == "{FilePath} has a file created date ({FileCreatedDate}) {RelativeDescription} " + + "than the created date specified in its Front Matter ({FrontMatterCreatedDate})") && + dict.Any(kv => kv.Key == "FilePath" + && (string)kv.Value == testFilePath) && + dict.Any(kv => kv.Key == "FileCreatedDate" + && (DateTime)kv.Value == testFileDate) && + dict.Any(kv => kv.Key == "RelativeDescription" + && (string)kv.Value == "earlier") && + dict.Any(kv => kv.Key == "FrontMatterCreatedDate" + && (DateTime)kv.Value == testMarkDownDate))); + _mockFile.Received(1).SetCreationTimeUtc(testFilePath, testMarkDownDate); } } \ No newline at end of file diff --git a/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFolderSynchroniserTests.cs b/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFolderSynchroniserTests.cs index efd1bae..c5a76ef 100644 --- a/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFolderSynchroniserTests.cs +++ b/tests/Elzik.FmSync.Application.Tests.Unit/FrontMatterFolderSynchroniserTests.cs @@ -6,173 +6,172 @@ using Thinktecture.IO; using Xunit; -namespace Elzik.FmSync.Application.Tests.Unit +namespace Elzik.FmSync.Application.Tests.Unit; + +public class FrontMatterFolderSynchroniserTests { - public class FrontMatterFolderSynchroniserTests - { - private readonly Fixture _fixture; - private readonly MockLogger _mockLogger; - private readonly IDirectory _mockDirectory; - private readonly IFrontMatterFileSynchroniser _mockFileSynchroniser; - private readonly FrontMatterFolderSynchroniser _frontMatterFolderSynchroniser; + private readonly Fixture _fixture; + private readonly MockLogger _mockLogger; + private readonly IDirectory _mockDirectory; + private readonly IFrontMatterFileSynchroniser _mockFileSynchroniser; + private readonly FrontMatterFolderSynchroniser _frontMatterFolderSynchroniser; - public FrontMatterFolderSynchroniserTests() - { - _mockLogger = Substitute.For>(); - _mockDirectory = Substitute.For(); - _mockFileSynchroniser = Substitute.For(); - - _fixture = new Fixture(); - _fixture.Register>(() => _mockLogger); - _fixture.Register(() => _mockDirectory); - _fixture.Register(() => _mockFileSynchroniser); - _frontMatterFolderSynchroniser = _fixture.Create(); - } + public FrontMatterFolderSynchroniserTests() + { + _mockLogger = Substitute.For>(); + _mockDirectory = Substitute.For(); + _mockFileSynchroniser = Substitute.For(); + + _fixture = new Fixture(); + _fixture.Register>(() => _mockLogger); + _fixture.Register(() => _mockDirectory); + _fixture.Register(() => _mockFileSynchroniser); + _frontMatterFolderSynchroniser = _fixture.Create(); + } - [Fact] - public void SyncCreationDates_DirectoryPathSupplied_OnlyLogs() - { - // Arrange - var testDirectoryPath = _fixture.Create(); + [Fact] + public void SyncCreationDates_DirectoryPathSupplied_OnlyLogs() + { + // Arrange + var testDirectoryPath = _fixture.Create(); - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - // Assert - _mockLogger.Received(1).Log(LogLevel.Information, $"Synchronising files in {testDirectoryPath}"); + // Assert + _mockLogger.Received(1).Log(LogLevel.Information, $"Synchronising files in {testDirectoryPath}"); - _mockFileSynchroniser.DidNotReceiveWithAnyArgs().SyncCreationDate(default!); - } + _mockFileSynchroniser.DidNotReceiveWithAnyArgs().SyncCreationDate(default!); + } - [Fact] - public void SyncCreationDates_NoMarkDownFiles_OnlyLogs() - { - // Arrange - var testDirectoryPath = _fixture.Create(); + [Fact] + public void SyncCreationDates_NoMarkDownFiles_OnlyLogs() + { + // Arrange + var testDirectoryPath = _fixture.Create(); - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - // Assert - _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => - s.StartsWith("Synchronised 0 files out of a total 0 in"))); - _mockFileSynchroniser.DidNotReceiveWithAnyArgs().SyncCreationDate(default!); - } + // Assert + _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => + s.StartsWith("Synchronised 0 files out of a total 0 in"))); + _mockFileSynchroniser.DidNotReceiveWithAnyArgs().SyncCreationDate(default!); + } - [Fact] - public void SyncCreationDates_WithMarkDownFiles_SyncsThoseFiles() - { - // Arrange - var testDirectoryPath = _fixture.Create(); - var testFiles = _fixture.CreateMany>().ToList(); - SetMockDirectoryFilePaths(testDirectoryPath, testFiles); + [Fact] + public void SyncCreationDates_WithMarkDownFiles_SyncsThoseFiles() + { + // Arrange + var testDirectoryPath = _fixture.Create(); + var testFiles = _fixture.CreateMany>().ToList(); + SetMockDirectoryFilePaths(testDirectoryPath, testFiles); - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - // Assert - _mockFileSynchroniser.ReceivedWithAnyArgs(testFiles.Count).SyncCreationDate(default!); - foreach (var testFilesPath in testFiles) - { - _mockFileSynchroniser.Received(1).SyncCreationDate(testFilesPath.Key); - } + // Assert + _mockFileSynchroniser.ReceivedWithAnyArgs(testFiles.Count).SyncCreationDate(default!); + foreach (var testFilesPath in testFiles) + { + _mockFileSynchroniser.Received(1).SyncCreationDate(testFilesPath.Key); } + } - [Fact] - public void SyncCreationDates_WithMarkDownFiles_LogsSummary() - { - // Arrange - var testDirectoryPath = _fixture.Create(); - var testFiles = _fixture.CreateMany>().ToList(); - SetMockDirectoryFilePaths(testDirectoryPath, testFiles); + [Fact] + public void SyncCreationDates_WithMarkDownFiles_LogsSummary() + { + // Arrange + var testDirectoryPath = _fixture.Create(); + var testFiles = _fixture.CreateMany>().ToList(); + SetMockDirectoryFilePaths(testDirectoryPath, testFiles); - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - // Assert - _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => - s.StartsWith($"Synchronised {testFiles.Count(pair => pair.Value)} files out of a total {testFiles.Count} in"))); - } + // Assert + _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => + s.StartsWith($"Synchronised {testFiles.Count(pair => pair.Value)} files out of a total {testFiles.Count} in"))); + } - [Fact] - public void SyncCreationDates_SyncFailsWithInnerException_LogsError() - { - // Arrange - var testDirectoryPath = _fixture.Create(); - var testFile = _fixture.Create>(); - var testFiles = new List> { testFile }; - SetMockDirectoryFilePaths(testDirectoryPath, testFiles); - var testException = new Exception(_fixture.Create(), _fixture.Create()); - _mockFileSynchroniser.SyncCreationDate(testFile.Key).Throws(testException); - - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - - // Assert - _mockLogger.Received(1).Log( LogLevel.Error, - testFile.Key + " - " + testException.Message + " " + testException.InnerException?.Message); - } + [Fact] + public void SyncCreationDates_SyncFailsWithInnerException_LogsError() + { + // Arrange + var testDirectoryPath = _fixture.Create(); + var testFile = _fixture.Create>(); + var testFiles = new List> { testFile }; + SetMockDirectoryFilePaths(testDirectoryPath, testFiles); + var testException = new Exception(_fixture.Create(), _fixture.Create()); + _mockFileSynchroniser.SyncCreationDate(testFile.Key).Throws(testException); + + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + + // Assert + _mockLogger.Received(1).Log( LogLevel.Error, + testFile.Key + " - " + testException.Message + " " + testException.InnerException?.Message); + } - [Fact] - public void SyncCreationDates_SyncFailsWithoutInnerException_LogsError() - { - // Arrange - var testDirectoryPath = _fixture.Create(); - var testFile = _fixture.Create>(); - var testFiles = new List> { testFile }; - SetMockDirectoryFilePaths(testDirectoryPath, testFiles); - var testException = new Exception(_fixture.Create()); - _mockFileSynchroniser.SyncCreationDate(testFile.Key).Throws(testException); - - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - - // Assert - _mockLogger.Received(1).Log(LogLevel.Error, - testFile.Key + " - " + testException.Message); - } + [Fact] + public void SyncCreationDates_SyncFailsWithoutInnerException_LogsError() + { + // Arrange + var testDirectoryPath = _fixture.Create(); + var testFile = _fixture.Create>(); + var testFiles = new List> { testFile }; + SetMockDirectoryFilePaths(testDirectoryPath, testFiles); + var testException = new Exception(_fixture.Create()); + _mockFileSynchroniser.SyncCreationDate(testFile.Key).Throws(testException); + + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + + // Assert + _mockLogger.Received(1).Log(LogLevel.Error, + testFile.Key + " - " + testException.Message); + } - [Fact] - public void SyncCreationDates_SyncFails_LogsSummary() + [Fact] + public void SyncCreationDates_SyncFails_LogsSummary() + { + // Arrange + var testDirectoryPath = _fixture.Create(); + var testFailingFile = new KeyValuePair(_fixture.Create(), false); + var testFiles = new [] { - // Arrange - var testDirectoryPath = _fixture.Create(); - var testFailingFile = new KeyValuePair(_fixture.Create(), false); - var testFiles = new [] - { - testFailingFile, - new (_fixture.Create(), false), - new (_fixture.Create(), true) - }; - SetMockDirectoryFilePaths(testDirectoryPath, testFiles); - var testException = new Exception(_fixture.Create(), _fixture.Create()); - _mockFileSynchroniser.SyncCreationDate(testFailingFile.Key).Throws(testException); - - // Act - _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); - - // Assert - _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => - s.StartsWith("Synchronised 1 and failed 1 files out of a total 3 in"))); - } + testFailingFile, + new (_fixture.Create(), false), + new (_fixture.Create(), true) + }; + SetMockDirectoryFilePaths(testDirectoryPath, testFiles); + var testException = new Exception(_fixture.Create(), _fixture.Create()); + _mockFileSynchroniser.SyncCreationDate(testFailingFile.Key).Throws(testException); + + // Act + _frontMatterFolderSynchroniser.SyncCreationDates(testDirectoryPath); + + // Assert + _mockLogger.Received(1).Log(LogLevel.Information, Arg.Is(s => + s.StartsWith("Synchronised 1 and failed 1 files out of a total 3 in"))); + } - private void SetMockDirectoryFilePaths(string testDirectoryPath, IEnumerable> testFiles) - { - var testFileList = testFiles.ToList(); + private void SetMockDirectoryFilePaths(string testDirectoryPath, IEnumerable> testFiles) + { + var testFileList = testFiles.ToList(); - _mockDirectory.EnumerateFiles(testDirectoryPath, "*.md", - Arg.Is(options => - options.MatchCasing == MatchCasing.CaseInsensitive && options.RecurseSubdirectories)) - .Returns(testFileList.Select(pair => pair.Key)); + _mockDirectory.EnumerateFiles(testDirectoryPath, "*.md", + Arg.Is(options => + options.MatchCasing == MatchCasing.CaseInsensitive && options.RecurseSubdirectories)) + .Returns(testFileList.Select(pair => pair.Key)); - foreach (var testFilePath in testFileList) + foreach (var testFilePath in testFileList) + { + _mockFileSynchroniser.SyncCreationDate(testFilePath.Key).Returns(new SyncResult { - _mockFileSynchroniser.SyncCreationDate(testFilePath.Key).Returns(new SyncResult - { - FileCreatedDateUpdated = testFilePath.Value - }); - } + FileCreatedDateUpdated = testFilePath.Value + }); } } } \ No newline at end of file diff --git a/tests/Elzik.FmSync.Application.Tests.Unit/MockLogger.cs b/tests/Elzik.FmSync.Application.Tests.Unit/MockLogger.cs index 6e363ad..701e713 100644 --- a/tests/Elzik.FmSync.Application.Tests.Unit/MockLogger.cs +++ b/tests/Elzik.FmSync.Application.Tests.Unit/MockLogger.cs @@ -1,39 +1,38 @@ -namespace Elzik.FmSync.Application.Tests.Unit -{ - using Microsoft.Extensions.Logging; +namespace Elzik.FmSync.Application.Tests.Unit; - // This class is necessary because mocking an ILogger will not work; further explanation here: - // https://github.com/nsubstitute/NSubstitute/issues/597#issuecomment-1081422618 +using Microsoft.Extensions.Logging; - public abstract class MockLogger : ILogger - { - public void Log(LogLevel logLevel, EventId eventId, TState state, - Exception? exception, Func formatter) - { - var unboxed = (IReadOnlyList>)state!; - var message = formatter(state, exception); +// This class is necessary because mocking an ILogger will not work; further explanation here: +// https://github.com/nsubstitute/NSubstitute/issues/597#issuecomment-1081422618 - Log(); - Log(logLevel, message); - Log(logLevel, message, exception); - Log(logLevel, unboxed.ToDictionary(k => - k.Key, v => v.Value)); - Log(logLevel, unboxed.ToDictionary(k => - k.Key, v => v.Value), exception); - } +public abstract class MockLogger : ILogger +{ + public void Log(LogLevel logLevel, EventId eventId, TState state, + Exception? exception, Func formatter) + { + var unboxed = (IReadOnlyList>)state!; + var message = formatter(state, exception); + + Log(); + Log(logLevel, message); + Log(logLevel, message, exception); + Log(logLevel, unboxed.ToDictionary(k => + k.Key, v => v.Value)); + Log(logLevel, unboxed.ToDictionary(k => + k.Key, v => v.Value), exception); + } - public abstract void Log(); + public abstract void Log(); - public abstract void Log(LogLevel logLevel, string message); + public abstract void Log(LogLevel logLevel, string message); - public abstract void Log(LogLevel logLevel, string message, Exception? exception); + public abstract void Log(LogLevel logLevel, string message, Exception? exception); - public abstract void Log(LogLevel logLevel, IDictionary state); + public abstract void Log(LogLevel logLevel, IDictionary state); - public abstract void Log(LogLevel logLevel, IDictionary state, Exception? exception); + public abstract void Log(LogLevel logLevel, IDictionary state, Exception? exception); - public virtual bool IsEnabled(LogLevel logLevel) => true; + public virtual bool IsEnabled(LogLevel logLevel) => true; - public abstract IDisposable? BeginScope(TState state) where TState : notnull; - } -} + public abstract IDisposable? BeginScope(TState state) where TState : notnull; +} \ No newline at end of file diff --git a/tests/Elzik.FmSync.Infrastructure.Tests.Integration/MarkdownFrontMatterTests.cs b/tests/Elzik.FmSync.Infrastructure.Tests.Integration/MarkdownFrontMatterTests.cs index 4ce1c3f..3cf26be 100644 --- a/tests/Elzik.FmSync.Infrastructure.Tests.Integration/MarkdownFrontMatterTests.cs +++ b/tests/Elzik.FmSync.Infrastructure.Tests.Integration/MarkdownFrontMatterTests.cs @@ -5,129 +5,128 @@ using Microsoft.Extensions.Options; using Xunit; -namespace Elzik.FmSync.Infrastructure.Tests.Integration +namespace Elzik.FmSync.Infrastructure.Tests.Integration; + +public sealed class MarkdownFrontMatterTests : IDisposable { - public sealed class MarkdownFrontMatterTests : IDisposable + [Theory] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "GMT Standard Time", null, "2023-01-07 14:28:22", + "because the current timezone is GMT")] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "GMT Standard Time", null, "2023-01-07 14:28:22", + "because the current timezone is GMT")] + [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "GMT Standard Time", null, "2022-03-31 13:52:15", + "because the current timezone is GMT at BST")] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "AUS Eastern Standard Time", null, "2023-01-07 03:28:22", + "because the current timezone is AUS")] + [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "AUS Eastern Standard Time", null, "2022-03-31 03:52:15", + "because the current timezone is AUS")] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "AUS Eastern Standard Time", null, "2023-01-07 03:28:22", + "because the current timezone is AUS")] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-01-07 03:28:22", + "because even though the current timezone is GMT the YAML is configured for AUS")] + [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "GMT Standard Time", "AUS Eastern Standard Time", "2022-03-31 03:52:15", + "because even though the current timezone is GMT the YAML is configured for AUS")] + [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-01-07 03:28:22", + "because even though the current timezone is GMT the YAML is configured for AUS")] + [InlineData("./TestFiles/YamlContainsOnlyDateWithOffset.md", "GMT Standard Time", null, "2023-02-14 13:20:32", + "because even though our current timezone is GMT it is ignored because a time offset was supplied in the Front Matter data")] + [InlineData("./TestFiles/YamlContainsOnlyDateWithOffset.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-02-14 13:20:32", + "because even though our current timezone is GMT and the Front Matter is configured for AUS they are both ignored because a time offset was supplied in the Front Matter data")] + public void GetCreatedDate_YamlContainsCreatedDate_ReturnsCreatedDate(string testFilePath, string localTimeZone, + string configuredTimeZone, string expectedUtcDateString, string because) { - [Theory] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "GMT Standard Time", null, "2023-01-07 14:28:22", - "because the current timezone is GMT")] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "GMT Standard Time", null, "2023-01-07 14:28:22", - "because the current timezone is GMT")] - [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "GMT Standard Time", null, "2022-03-31 13:52:15", - "because the current timezone is GMT at BST")] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "AUS Eastern Standard Time", null, "2023-01-07 03:28:22", - "because the current timezone is AUS")] - [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "AUS Eastern Standard Time", null, "2022-03-31 03:52:15", - "because the current timezone is AUS")] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "AUS Eastern Standard Time", null, "2023-01-07 03:28:22", - "because the current timezone is AUS")] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDate.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-01-07 03:28:22", - "because even though the current timezone is GMT the YAML is configured for AUS")] - [InlineData("./TestFiles/YamlContainsCreatedDateAndOtherValue.md", "GMT Standard Time", "AUS Eastern Standard Time", "2022-03-31 03:52:15", - "because even though the current timezone is GMT the YAML is configured for AUS")] - [InlineData("./TestFiles/YamlContainsOnlyCreatedDateWithPrecedingNewLines.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-01-07 03:28:22", - "because even though the current timezone is GMT the YAML is configured for AUS")] - [InlineData("./TestFiles/YamlContainsOnlyDateWithOffset.md", "GMT Standard Time", null, "2023-02-14 13:20:32", - "because even though our current timezone is GMT it is ignored because a time offset was supplied in the Front Matter data")] - [InlineData("./TestFiles/YamlContainsOnlyDateWithOffset.md", "GMT Standard Time", "AUS Eastern Standard Time", "2023-02-14 13:20:32", - "because even though our current timezone is GMT and the Front Matter is configured for AUS they are both ignored because a time offset was supplied in the Front Matter data")] - public void GetCreatedDate_YamlContainsCreatedDate_ReturnsCreatedDate(string testFilePath, string localTimeZone, - string configuredTimeZone, string expectedUtcDateString, string because) - { - // Arrange - SetTimeZone(localTimeZone); - var testOptions = Options.Create(new FrontMatterOptions - { - TimeZoneId = configuredTimeZone - }); - var expectedDateUtc = DateTime.ParseExact(expectedUtcDateString, "yyyy-MM-dd HH:mm:ss", - CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); - - // Act - var markdownFrontMatter = new MarkdownFrontMatter(testOptions); - var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); - - // Assert - createdDate.Should().Be(expectedDateUtc, because); - createdDate!.Value.Kind.Should().Be(DateTimeKind.Utc); - } - - [Theory] - [InlineData("./TestFiles/YamlIsEmpty.md")] - [InlineData("./TestFiles/YamlContainsOnlyWhitespace.md")] - [InlineData("./TestFiles/YamlContainsOnlyNonCreatedDate.md")] - [InlineData("./TestFiles/YamlIsMissingBodyIsPresent.md")] - [InlineData("./TestFiles/YamlSectionNeverClosed.md")] - [InlineData("./TestFiles/YamlSectionNeverOpened.md")] - [InlineData("./TestFiles/TextPrecedesYamlSection.md")] - [InlineData("./TestFiles/WhitespacePrecedesYamlSection.md")] - [InlineData("./TestFiles/YamlSectionOpenedWithExtraCharacters.md")] - [InlineData("./TestFiles/YamlSectionClosedWithExtraCharacters.md")] - public void GetCreatedDate_YamlContainsNoCreatedDateOrNoValidYaml_ReturnsNullDate(string testFilePath) + // Arrange + SetTimeZone(localTimeZone); + var testOptions = Options.Create(new FrontMatterOptions { - // Arrange - var testOptions = Options.Create(new FrontMatterOptions()); + TimeZoneId = configuredTimeZone + }); + var expectedDateUtc = DateTime.ParseExact(expectedUtcDateString, "yyyy-MM-dd HH:mm:ss", + CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + + // Act + var markdownFrontMatter = new MarkdownFrontMatter(testOptions); + var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); + + // Assert + createdDate.Should().Be(expectedDateUtc, because); + createdDate!.Value.Kind.Should().Be(DateTimeKind.Utc); + } - // Act - var markdownFrontMatter = new MarkdownFrontMatter(testOptions); - var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); + [Theory] + [InlineData("./TestFiles/YamlIsEmpty.md")] + [InlineData("./TestFiles/YamlContainsOnlyWhitespace.md")] + [InlineData("./TestFiles/YamlContainsOnlyNonCreatedDate.md")] + [InlineData("./TestFiles/YamlIsMissingBodyIsPresent.md")] + [InlineData("./TestFiles/YamlSectionNeverClosed.md")] + [InlineData("./TestFiles/YamlSectionNeverOpened.md")] + [InlineData("./TestFiles/TextPrecedesYamlSection.md")] + [InlineData("./TestFiles/WhitespacePrecedesYamlSection.md")] + [InlineData("./TestFiles/YamlSectionOpenedWithExtraCharacters.md")] + [InlineData("./TestFiles/YamlSectionClosedWithExtraCharacters.md")] + public void GetCreatedDate_YamlContainsNoCreatedDateOrNoValidYaml_ReturnsNullDate(string testFilePath) + { + // Arrange + var testOptions = Options.Create(new FrontMatterOptions()); - // Assert - createdDate.Should().BeNull(); - } + // Act + var markdownFrontMatter = new MarkdownFrontMatter(testOptions); + var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); - [Theory] - [InlineData("./TestFiles/YamlContainsOnlyMinCreatedDate.md")] - public void GetCreatedDate_YamlContainsMinDate_ReturnsCreatedDate(string testFilePath) - { - // Arrange - var testOptions = Options.Create(new FrontMatterOptions()); - var expectedDateUtc = DateTime.MinValue; + // Assert + createdDate.Should().BeNull(); + } - // Act - var markdownFrontMatter = new MarkdownFrontMatter(testOptions); - var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); + [Theory] + [InlineData("./TestFiles/YamlContainsOnlyMinCreatedDate.md")] + public void GetCreatedDate_YamlContainsMinDate_ReturnsCreatedDate(string testFilePath) + { + // Arrange + var testOptions = Options.Create(new FrontMatterOptions()); + var expectedDateUtc = DateTime.MinValue; - // Assert - createdDate.Should().Be(expectedDateUtc); - } + // Act + var markdownFrontMatter = new MarkdownFrontMatter(testOptions); + var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); - [Theory] - [InlineData("./TestFiles/YamlContainsOnlyMaxCreatedDate.md")] - public void GetCreatedDate_YamlContainsMaxDate_ReturnsCreatedDate(string testFilePath) - { - // Arrange - var testOptions = Options.Create(new FrontMatterOptions()); - var expectedDateUtc = DateTime.MaxValue; + // Assert + createdDate.Should().Be(expectedDateUtc); + } - // Act - var markdownFrontMatter = new MarkdownFrontMatter(testOptions); - var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); + [Theory] + [InlineData("./TestFiles/YamlContainsOnlyMaxCreatedDate.md")] + public void GetCreatedDate_YamlContainsMaxDate_ReturnsCreatedDate(string testFilePath) + { + // Arrange + var testOptions = Options.Create(new FrontMatterOptions()); + var expectedDateUtc = DateTime.MaxValue; - // Assert - createdDate.Should().Be(expectedDateUtc); - } + // Act + var markdownFrontMatter = new MarkdownFrontMatter(testOptions); + var createdDate = markdownFrontMatter.GetCreatedDateUtc(testFilePath); - private void SetTimeZone(string mockTimeZoneId) - { - var timeZone = TimeZoneInfo.FindSystemTimeZoneById(mockTimeZoneId); - var info = typeof(TimeZoneInfo).GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static); - Debug.Assert(info != null, nameof(info) + " != null"); + // Assert + createdDate.Should().Be(expectedDateUtc); + } + + private void SetTimeZone(string mockTimeZoneId) + { + var timeZone = TimeZoneInfo.FindSystemTimeZoneById(mockTimeZoneId); + var info = typeof(TimeZoneInfo).GetField("s_cachedData", BindingFlags.NonPublic | BindingFlags.Static); + Debug.Assert(info != null, nameof(info) + " != null"); - var cachedData = info.GetValue(null); - Debug.Assert(cachedData != null, nameof(cachedData) + " != null"); + var cachedData = info.GetValue(null); + Debug.Assert(cachedData != null, nameof(cachedData) + " != null"); - var field = cachedData.GetType().GetField("_localTimeZone", - BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Instance); - Debug.Assert(field != null, nameof(field) + " != null"); + var field = cachedData.GetType().GetField("_localTimeZone", + BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Instance); + Debug.Assert(field != null, nameof(field) + " != null"); - field.SetValue(cachedData, timeZone); - } + field.SetValue(cachedData, timeZone); + } - public void Dispose() - { - TimeZoneInfo.ClearCachedData(); - } + public void Dispose() + { + TimeZoneInfo.ClearCachedData(); } -} +} \ No newline at end of file