Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions RepoM.sln
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Clipboard.Test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.EverythingFileSearch.Tests", "tests\RepoM.Plugin.EverythingFileSearch.Tests\RepoM.Plugin.EverythingFileSearch.Tests.csproj", "{89D96078-2951-44C2-B5B1-1DA0D5E94C0C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.WindowsExplorerGitInfo.Tests", "tests\RepoM.Plugin.WindowsExplorerGitInfo.Tests\RepoM.Plugin.WindowsExplorerGitInfo.Tests.csproj", "{99DFA130-C0F4-4D1F-8428-5CACA481B688}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -481,6 +483,26 @@ Global
{89D96078-2951-44C2-B5B1-1DA0D5E94C0C}.Release|x64.Build.0 = Release|Any CPU
{89D96078-2951-44C2-B5B1-1DA0D5E94C0C}.Release|x86.ActiveCfg = Release|Any CPU
{89D96078-2951-44C2-B5B1-1DA0D5E94C0C}.Release|x86.Build.0 = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|ARM.ActiveCfg = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|ARM.Build.0 = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|ARM64.Build.0 = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|x64.ActiveCfg = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|x64.Build.0 = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|x86.ActiveCfg = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Debug|x86.Build.0 = Debug|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|Any CPU.Build.0 = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|ARM.ActiveCfg = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|ARM.Build.0 = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|ARM64.ActiveCfg = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|ARM64.Build.0 = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|x64.ActiveCfg = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|x64.Build.0 = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|x86.ActiveCfg = Release|Any CPU
{99DFA130-C0F4-4D1F-8428-5CACA481B688}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -501,6 +523,7 @@ Global
{8F87B73D-8A5D-4335-96E9-97EE0495B671} = {D6E372DC-10D3-4997-9DFC-568B4666635A}
{A26EF3E9-C267-499C-B5AB-E4FB3C7AB6E1} = {D6E372DC-10D3-4997-9DFC-568B4666635A}
{89D96078-2951-44C2-B5B1-1DA0D5E94C0C} = {D6E372DC-10D3-4997-9DFC-568B4666635A}
{99DFA130-C0F4-4D1F-8428-5CACA481B688} = {D6E372DC-10D3-4997-9DFC-568B4666635A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1765ABAA-0652-4DA5-ABBF-05396F2957D7}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RepoM.Plugin.WindowsExplorerGitInfo.PInvoke.Explorer;

internal interface IWindowsExplorerHandler
{
void UpdateTitles();

void CleanTitles();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
namespace RepoM.Plugin.WindowsExplorerGitInfo.PInvoke.Explorer;

using JetBrains.Annotations;
using RepoM.Api.Git;

internal class WindowsExplorerHandler
internal class WindowsExplorerHandler : IWindowsExplorerHandler
{
private readonly IRepositoryInformationAggregator _repositoryInfoAggregator;

Expand All @@ -18,7 +17,6 @@ public void UpdateTitles()
actor.Pulse();
}

[PublicAPI]
public void CleanTitles()
{
var actor = new CleanWindowTitleActor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace RepoM.Plugin.WindowsExplorerGitInfo.PInvoke;

using System;

public class WindowPath
internal class WindowPath
{
public WindowPath(IntPtr handle, string path)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ namespace RepoM.Plugin.WindowsExplorerGitInfo;
internal class WindowExplorerBarGitInfoModule : IModule
{
private readonly Timer _explorerUpdateTimer;
private readonly WindowsExplorerHandler _explorerHandler;
private readonly IWindowsExplorerHandler _explorerHandler;

public WindowExplorerBarGitInfoModule(WindowsExplorerHandler explorerHandler)
public WindowExplorerBarGitInfoModule(IWindowsExplorerHandler explorerHandler)
{
_explorerHandler = explorerHandler ?? throw new ArgumentNullException(nameof(explorerHandler));
_explorerUpdateTimer = new Timer(RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ namespace RepoM.Plugin.WindowsExplorerGitInfo;
using SimpleInjector.Packaging;

[UsedImplicitly]
public class WindowsExplorerGitInfoModule : IPackage
public class WindowsExplorerGitInfoPackage : IPackage
{
public void RegisterServices(Container container)
{
container.Register<WindowsExplorerHandler>(Lifestyle.Singleton);
container.Register<IWindowsExplorerHandler, WindowsExplorerHandler>(Lifestyle.Singleton);
container.Collection.Append<IModule, WindowExplorerBarGitInfoModule>(Lifestyle.Singleton);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="EasyTestFile.XUnit" Version="2.0.6" />
<PackageReference Include="FakeItEasy" Version="7.3.1" />
<PackageReference Include="FakeItEasy.Analyzer.CSharp" Version="6.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.8.0" />
<PackageReference Include="Meziantou.Xunit.ParallelTestFramework" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="System.IO.Abstractions" Version="19.0.1" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="19.0.1" />
<PackageReference Include="Verify.Xunit" Version="19.3.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="Xunit.EnumMemberData" Version="1.0.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\RepoM.Plugin.WindowsExplorerGitInfo\RepoM.Plugin.WindowsExplorerGitInfo.csproj" />
<ProjectReference Include="..\RepoM.Api.Tests\RepoM.Api.Tests.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace RepoM.Plugin.WindowsExplorerGitInfo.Tests.TestFramework;

using System.Runtime.CompilerServices;
using Argon;
using VerifyTests;

public static class VerifierInitializer
{
[ModuleInitializer]
public static void Initialize()
{
VerifierSettings.DisableRequireUniquePrefix();
VerifierSettings.AddExtraSettings(serializerSettings => serializerSettings.TypeNameHandling = TypeNameHandling.Auto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
namespace RepoM.Plugin.WindowsExplorerGitInfo.Tests;

using System;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using FluentAssertions;
using RepoM.Plugin.WindowsExplorerGitInfo.PInvoke.Explorer;
using Xunit;

public class WindowExplorerBarGitInfoModuleTest
{
private readonly IWindowsExplorerHandler _explorerHandler;
private readonly WindowExplorerBarGitInfoModule _sut;

public WindowExplorerBarGitInfoModuleTest()
{
_explorerHandler = A.Fake<IWindowsExplorerHandler>();
_sut = new WindowExplorerBarGitInfoModule(_explorerHandler);
}

[Fact]
public void Ctor_ShouldThrow_WhenArgumentIsNull()
{
// arrange

// act
Action act = () => _ = new WindowExplorerBarGitInfoModule(null!);

// assert
act.Should().ThrowExactly<ArgumentNullException>();
}

[Fact]
public async Task StopAsync_ShouldCleanTitles()
{
// arrange

// act
await _sut.StopAsync();

// assert
A.CallTo(() => _explorerHandler.CleanTitles()).MustHaveHappenedOnceExactly();
}

[Fact]
public async Task StartAsync_ShouldCallUpdateTitlesUntilStopped()
{
// arrange
var count = 0;
var mre = new ManualResetEvent(false);
A.CallTo(() => _explorerHandler.UpdateTitles()).
Invokes(_ =>
{
var currentCount = Interlocked.Increment(ref count);
if (currentCount == 3)
{
mre.Set();
}
});

// act
await _sut.StartAsync();
_ = mre.WaitOne(TimeSpan.FromSeconds(5));

// assert
A.CallTo(() => _explorerHandler.UpdateTitles()).MustHaveHappened(3, Times.Exactly);
A.CallTo(() => _explorerHandler.CleanTitles()).MustNotHaveHappened();
}

[Fact]
public async Task StopAsync_ShouldCancelTimerExecution_WhenStarted()
{
// arrange
var count = 0;
var mreAfterStart = new ManualResetEvent(false);
var mreAfterStop = new ManualResetEvent(false);
A.CallTo(() => _explorerHandler.UpdateTitles()).
Invokes(_ =>
{
var currentCount = Interlocked.Increment(ref count);
if (currentCount == 2)
{
mreAfterStart.Set();
return;
}

if (currentCount > 2)
{
mreAfterStop.Set();
}
});

await _sut.StartAsync();
_ = mreAfterStart.WaitOne(TimeSpan.FromSeconds(2));

// act
await _sut.StopAsync();
_ = mreAfterStop.WaitOne(TimeSpan.FromSeconds(2));

// assert
A.CallTo(() => _explorerHandler.UpdateTitles()).MustHaveHappened(2, Times.Exactly);
A.CallTo(() => _explorerHandler.CleanTitles()).MustHaveHappenedOnceExactly();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
namespace RepoM.Plugin.WindowsExplorerGitInfo.Tests;

using System;
using System.IO.Abstractions;
using FakeItEasy;
using Microsoft.Extensions.Logging;
using RepoM.Api.Git;
using RepoM.Core.Plugin.Common;
using SimpleInjector;
using Xunit;

public class WindowsExplorerGitInfoPackageTests
{
[Fact]
public void RegisterServices_ShouldBeSuccessful_WhenExternalDependenciesAreRegistered()
{
// arrange
var container = new Container();
RegisterExternals(container);
var sut = new WindowsExplorerGitInfoPackage();

// act
sut.RegisterServices(container);

// assert
// implicit, Verify throws when container is not valid.
container.Verify(VerificationOption.VerifyAndDiagnose);
}

[Fact]
public void RegisterServices_ShouldFail_WhenExternalDependenciesAreNotRegistered()
{
// arrange
var container = new Container();
var sut = new WindowsExplorerGitInfoPackage();

// act
sut.RegisterServices(container);

// assert
Assert.Throws<InvalidOperationException>(() => container.Verify(VerificationOption.VerifyAndDiagnose));
}

private static void RegisterExternals(Container container)
{
container.RegisterSingleton(A.Dummy<IRepositoryInformationAggregator>);
}
}