Skip to content

Commit

Permalink
Fix init config (#32)
Browse files Browse the repository at this point in the history
* fix(config): error if user doesn't want to init config

* ensure same config after init

* test: ensure ioc is reset before all tests
  • Loading branch information
MrLuje authored May 11, 2020
1 parent cc9f222 commit ab0da85
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 33 deletions.
136 changes: 136 additions & 0 deletions vs-commitizen.Tests/OpenGenerateLocalConfigViewModelTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using AutoFixture;
using AutoFixture.AutoNSubstitute;
using AutoFixture.Xunit2;
using NSubstitute;
using NSubstitute.Extensions;
using Shouldly;
using System.Threading.Tasks;
using vs_commitizen.Infrastructure;
using vs_commitizen.Settings;
using vs_commitizen.Tests.TestAttributes;
using vs_commitizen.ViewModels;
using Xunit;

namespace vs_commitizen.Tests
{
public class OpenGenerateLocalConfigViewModelTests
{
OpenGenerateLocalConfigViewModel getSut(Fixture fixture, ConfigFileProvider configFileProvider, IFileAccessor fileAccessor, string configPath, bool fileExists)
{
configFileProvider.Configure().TryGetLocalConfigAsync().Returns(configPath);
fileAccessor.Exists(Arg.Any<string>()).ReturnsForAnyArgs(fileExists);

IoC.Container.EjectAllInstancesOf<IConfigFileProvider>();
IoC.Container.Inject<IConfigFileProvider>(configFileProvider);

IoC.Container.EjectAllInstancesOf<IFileAccessor>();
IoC.Container.Inject<IFileAccessor>(fileAccessor);

return fixture.Create<OpenGenerateLocalConfigViewModel>();
}

[Theory]
[InlineTestConventions(true, "path to config")]
[InlineTestConventions(false, null)]
public async Task Command_Is_Enabled_Based_On_Solution_Loaded(
bool solutionLoaded,
string configPath,
[Frozen]IFileAccessor fileAccessor,
[Frozen][Substitute] ConfigFileProvider configFileProvider,
Fixture fixture
)
{
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);

var expectedEnabledState = solutionLoaded;
(await sut.IsCommandEnabledAsync()).ShouldBe(expectedEnabledState);
}

[Theory]
[InlineTestConventions(true, "path to config")]
public async Task Execute_With_Existing_Config_Opens_The_File(
bool solutionLoaded,
string configPath,
[Frozen]IFileAccessor fileAccessor,
[Frozen][Substitute] IPopupManager popupManager,
[Frozen][Substitute] ConfigFileProvider configFileProvider,
Fixture fixture
)
{
// Arrange
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
var called = false;

// Act
await sut.ExecuteAsync(s =>
{
called = true;
return Task.CompletedTask;
});

// Assert
called.ShouldBeTrue();
popupManager.DidNotReceiveWithAnyArgs().Confirm(Arg.Any<string>(), Arg.Any<string>());
}

[Theory]
[InlineTestConventions(false, "path to config")]
public async Task Execute_With_NonExisting_Config_Asks_To_Create_It(
bool solutionLoaded,
string configPath,
[Frozen]IFileAccessor fileAccessor,
[Frozen][Substitute] IPopupManager popupManager,
[Frozen][Substitute] ConfigFileProvider configFileProvider,
Fixture fixture
)
{
// Arrange
IoC.Container.Inject(popupManager);
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
var called = false;

// Act
await sut.ExecuteAsync(s =>
{
called = true;
return Task.CompletedTask;
});

// Assert
called.ShouldBeFalse();
popupManager.Received().Confirm(Arg.Any<string>(), Arg.Any<string>());
}

[Theory]
[InlineTestConventions(false, "path to config", true)]
[InlineTestConventions(false, "path to config", false)]
public async Task Response_To_Popup_Should_Open_File(
bool solutionLoaded,
string configPath,
bool userWantsToCreateFile,
[Frozen]IFileAccessor fileAccessor,
[Frozen][Substitute] IPopupManager popupManager,
[Frozen][Substitute] ConfigFileProvider configFileProvider,
Fixture fixture
)
{
// Arrange
popupManager.Configure().Confirm(Arg.Any<string>(), Arg.Any<string>()).Returns(userWantsToCreateFile);
IoC.Container.Inject(popupManager);
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
var called = false;

// Act
await sut.ExecuteAsync(s =>
{
called = true;
return Task.CompletedTask;
});

// Assert
var expectedResult = userWantsToCreateFile;
called.ShouldBe(expectedResult);
popupManager.Received().Confirm(Arg.Any<string>(), Arg.Any<string>());
}
}
}
4 changes: 4 additions & 0 deletions vs-commitizen.Tests/vs-commitizen.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
<Reference Include="Microsoft.TeamFoundation.Controls">
<HintPath>..\lib\vs2019\Microsoft.TeamFoundation.Controls.dll</HintPath>
</Reference>
<Reference Include="Microsoft.TeamFoundation.Git.Provider">
<HintPath>..\lib\vs2019\Microsoft.TeamFoundation.Git.Provider.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
Expand All @@ -73,6 +76,7 @@
<Compile Include="TestAttributes\TestConventionsAttribute.cs" />
<Compile Include="CommitizenViewModelTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="OpenGenerateLocalConfigViewModelTests.cs" />
<Compile Include="ViewTests.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
36 changes: 6 additions & 30 deletions vs-commitizen/Commands/OpenGenerateLocalConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.VisualStudio.Shell.Interop;
using vs_commitizen.Infrastructure;
using vs_commitizen.Settings;
using vs_commitizen.ViewModels;
using Task = System.Threading.Tasks.Task;

namespace vs_commitizen.Commands
Expand All @@ -30,6 +31,7 @@ internal sealed class OpenGenerateLocalConfig
/// VS Package that provides this command, not null.
/// </summary>
private readonly AsyncPackage package;
private OpenGenerateLocalConfigViewModel viewModel;

/// <summary>
/// Initializes a new instance of the <see cref="OpenGenerateLocalConfig"/> class.
Expand All @@ -41,6 +43,7 @@ private OpenGenerateLocalConfig(AsyncPackage package, OleMenuCommandService comm
{
this.package = package ?? throw new ArgumentNullException(nameof(package));
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
viewModel = new OpenGenerateLocalConfigViewModel();

var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new OleMenuCommand(Execute, menuCommandID);
Expand All @@ -54,7 +57,7 @@ private void MenuItem_BeforeQueryStatus(object sender, EventArgs e)

}

private static async Task HandleIsCommandVisibleAsync(object sender)
private async Task HandleIsCommandVisibleAsync(object sender)
{
try
{
Expand All @@ -63,11 +66,7 @@ private static async Task HandleIsCommandVisibleAsync(object sender)
switch (menuCommand.CommandID.ID)
{
case (int)PackageIds.OpenGenerateLocalConfigCmd:
var configFileProvider = IoC.GetInstance<IConfigFileProvider>();
var fileAccessor = IoC.GetInstance<IFileAccessor>();

var localConfigPath = await configFileProvider.TryGetLocalConfigAsync();
menuCommand.Enabled = !string.IsNullOrWhiteSpace(localConfigPath);
menuCommand.Enabled = await this.viewModel.IsCommandEnabledAsync();
break;
}
}
Expand Down Expand Up @@ -124,30 +123,7 @@ private void Execute(object sender, EventArgs e)

private async Task ProcessAsync()
{
var popupManager = IoC.GetInstance<IPopupManager>();

try
{
var configFileProvider = IoC.GetInstance<IConfigFileProvider>();
var fileAccessor = IoC.GetInstance<IFileAccessor>();

var localConfigPath = await configFileProvider.TryGetLocalConfigAsync();
if (string.IsNullOrWhiteSpace(localConfigPath)) return;

if (!fileAccessor.Exists(localConfigPath))
{
if (popupManager.Confirm("There is no local configuration file yet, do you want to create it for this repository ?", "Init local config file"))
{
fileAccessor.CopyFile(ConfigFileProvider.ConfigPathUserProfile, localConfigPath);
}
}

await OpenFileInEditorAsync(localConfigPath);
}
catch (Exception ex)
{
popupManager.Show(ex.ToString(), "An error occured");
}
await this.viewModel.ExecuteAsync(OpenFileInEditorAsync);
}

private async Task OpenFileInEditorAsync(string localConfigPath)
Expand Down
4 changes: 2 additions & 2 deletions vs-commitizen/Infrastructure/ConfigFileProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private async Task<string> GetCacheKeyAsync()
return (repository != null, repository?.RepositoryPath);
}

public async Task<string> TryGetLocalConfigAsync()
public virtual async Task<string> TryGetLocalConfigAsync()
{
var (isRepositoryLoaded, repositoryPath) = await GetLocalPathAsync(); // await GetCurrentSolutionAsync();
if (isRepositoryLoaded)
Expand Down Expand Up @@ -181,7 +181,7 @@ private async Task<string> GenerateDefaultConfigFileAsync(string configFileInUse
var defaultConfigFileContent = await reader.ReadToEndAsync();
await fileStream.WriteAsync(defaultConfigFileContent);

return defaultConfigFileContent;
return JObject.Parse(defaultConfigFileContent).SelectToken("types").ToString();
}
}
}
Expand Down
58 changes: 58 additions & 0 deletions vs-commitizen/ViewModels/OpenGenerateLocalConfigViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using vs_commitizen.Infrastructure;
using vs_commitizen.Settings;

namespace vs_commitizen.ViewModels
{
public class OpenGenerateLocalConfigViewModel
{
private readonly IConfigFileProvider configFileProvider;
private readonly IFileAccessor fileAccessor;
private readonly IPopupManager popupManager;

public OpenGenerateLocalConfigViewModel()
{
configFileProvider = IoC.GetInstance<IConfigFileProvider>();
fileAccessor = IoC.GetInstance<IFileAccessor>();
popupManager = IoC.GetInstance<IPopupManager>();

}

public async Task<bool> IsCommandEnabledAsync()
{
var localConfigPath = await this.configFileProvider.TryGetLocalConfigAsync();

return !string.IsNullOrWhiteSpace(localConfigPath);
}

public async Task ExecuteAsync(Func<string, Task> openFunc)
{
try
{
var localConfigPath = await this.configFileProvider.TryGetLocalConfigAsync();
if (string.IsNullOrWhiteSpace(localConfigPath)) return;

if (fileAccessor.Exists(localConfigPath))
{
await openFunc(localConfigPath);
}
else
{
if (popupManager.Confirm("There is no local configuration file yet, do you want to create it for this repository ?", "Init local config file"))
{
fileAccessor.CopyFile(ConfigFileProvider.ConfigPathUserProfile, localConfigPath);
await openFunc(localConfigPath);
}
}
}
catch (Exception ex)
{
popupManager.Show(ex.ToString(), "An error occured");
}
}
}
}
2 changes: 1 addition & 1 deletion vs-commitizen/defaultConfigFile.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://github.com/MrLuje/vs-commitizen/config-schema.json",
"$schema": "https://raw.githubusercontent.com/MrLuje/vs-commitizen/master/config-schema.json",
"types": [
{
"type": "feat",
Expand Down
1 change: 1 addition & 0 deletions vs-commitizen/vs-commitizen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Compile Include="PackageRegistry.cs" />
<Compile Include="Infrastructure\PopupManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\OpenGenerateLocalConfigViewModel.cs" />
<Compile Include="VsCommitizenIds.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
Expand Down

0 comments on commit ab0da85

Please sign in to comment.