Skip to content

Commit ab0da85

Browse files
authored
Fix init config (#32)
* fix(config): error if user doesn't want to init config * ensure same config after init * test: ensure ioc is reset before all tests
1 parent cc9f222 commit ab0da85

File tree

7 files changed

+208
-33
lines changed

7 files changed

+208
-33
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
using AutoFixture;
2+
using AutoFixture.AutoNSubstitute;
3+
using AutoFixture.Xunit2;
4+
using NSubstitute;
5+
using NSubstitute.Extensions;
6+
using Shouldly;
7+
using System.Threading.Tasks;
8+
using vs_commitizen.Infrastructure;
9+
using vs_commitizen.Settings;
10+
using vs_commitizen.Tests.TestAttributes;
11+
using vs_commitizen.ViewModels;
12+
using Xunit;
13+
14+
namespace vs_commitizen.Tests
15+
{
16+
public class OpenGenerateLocalConfigViewModelTests
17+
{
18+
OpenGenerateLocalConfigViewModel getSut(Fixture fixture, ConfigFileProvider configFileProvider, IFileAccessor fileAccessor, string configPath, bool fileExists)
19+
{
20+
configFileProvider.Configure().TryGetLocalConfigAsync().Returns(configPath);
21+
fileAccessor.Exists(Arg.Any<string>()).ReturnsForAnyArgs(fileExists);
22+
23+
IoC.Container.EjectAllInstancesOf<IConfigFileProvider>();
24+
IoC.Container.Inject<IConfigFileProvider>(configFileProvider);
25+
26+
IoC.Container.EjectAllInstancesOf<IFileAccessor>();
27+
IoC.Container.Inject<IFileAccessor>(fileAccessor);
28+
29+
return fixture.Create<OpenGenerateLocalConfigViewModel>();
30+
}
31+
32+
[Theory]
33+
[InlineTestConventions(true, "path to config")]
34+
[InlineTestConventions(false, null)]
35+
public async Task Command_Is_Enabled_Based_On_Solution_Loaded(
36+
bool solutionLoaded,
37+
string configPath,
38+
[Frozen]IFileAccessor fileAccessor,
39+
[Frozen][Substitute] ConfigFileProvider configFileProvider,
40+
Fixture fixture
41+
)
42+
{
43+
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
44+
45+
var expectedEnabledState = solutionLoaded;
46+
(await sut.IsCommandEnabledAsync()).ShouldBe(expectedEnabledState);
47+
}
48+
49+
[Theory]
50+
[InlineTestConventions(true, "path to config")]
51+
public async Task Execute_With_Existing_Config_Opens_The_File(
52+
bool solutionLoaded,
53+
string configPath,
54+
[Frozen]IFileAccessor fileAccessor,
55+
[Frozen][Substitute] IPopupManager popupManager,
56+
[Frozen][Substitute] ConfigFileProvider configFileProvider,
57+
Fixture fixture
58+
)
59+
{
60+
// Arrange
61+
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
62+
var called = false;
63+
64+
// Act
65+
await sut.ExecuteAsync(s =>
66+
{
67+
called = true;
68+
return Task.CompletedTask;
69+
});
70+
71+
// Assert
72+
called.ShouldBeTrue();
73+
popupManager.DidNotReceiveWithAnyArgs().Confirm(Arg.Any<string>(), Arg.Any<string>());
74+
}
75+
76+
[Theory]
77+
[InlineTestConventions(false, "path to config")]
78+
public async Task Execute_With_NonExisting_Config_Asks_To_Create_It(
79+
bool solutionLoaded,
80+
string configPath,
81+
[Frozen]IFileAccessor fileAccessor,
82+
[Frozen][Substitute] IPopupManager popupManager,
83+
[Frozen][Substitute] ConfigFileProvider configFileProvider,
84+
Fixture fixture
85+
)
86+
{
87+
// Arrange
88+
IoC.Container.Inject(popupManager);
89+
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
90+
var called = false;
91+
92+
// Act
93+
await sut.ExecuteAsync(s =>
94+
{
95+
called = true;
96+
return Task.CompletedTask;
97+
});
98+
99+
// Assert
100+
called.ShouldBeFalse();
101+
popupManager.Received().Confirm(Arg.Any<string>(), Arg.Any<string>());
102+
}
103+
104+
[Theory]
105+
[InlineTestConventions(false, "path to config", true)]
106+
[InlineTestConventions(false, "path to config", false)]
107+
public async Task Response_To_Popup_Should_Open_File(
108+
bool solutionLoaded,
109+
string configPath,
110+
bool userWantsToCreateFile,
111+
[Frozen]IFileAccessor fileAccessor,
112+
[Frozen][Substitute] IPopupManager popupManager,
113+
[Frozen][Substitute] ConfigFileProvider configFileProvider,
114+
Fixture fixture
115+
)
116+
{
117+
// Arrange
118+
popupManager.Configure().Confirm(Arg.Any<string>(), Arg.Any<string>()).Returns(userWantsToCreateFile);
119+
IoC.Container.Inject(popupManager);
120+
var sut = getSut(fixture, configFileProvider, fileAccessor, configPath, solutionLoaded);
121+
var called = false;
122+
123+
// Act
124+
await sut.ExecuteAsync(s =>
125+
{
126+
called = true;
127+
return Task.CompletedTask;
128+
});
129+
130+
// Assert
131+
var expectedResult = userWantsToCreateFile;
132+
called.ShouldBe(expectedResult);
133+
popupManager.Received().Confirm(Arg.Any<string>(), Arg.Any<string>());
134+
}
135+
}
136+
}

vs-commitizen.Tests/vs-commitizen.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
<Reference Include="Microsoft.TeamFoundation.Controls">
5757
<HintPath>..\lib\vs2019\Microsoft.TeamFoundation.Controls.dll</HintPath>
5858
</Reference>
59+
<Reference Include="Microsoft.TeamFoundation.Git.Provider">
60+
<HintPath>..\lib\vs2019\Microsoft.TeamFoundation.Git.Provider.dll</HintPath>
61+
</Reference>
5962
<Reference Include="PresentationCore" />
6063
<Reference Include="PresentationFramework" />
6164
<Reference Include="System" />
@@ -73,6 +76,7 @@
7376
<Compile Include="TestAttributes\TestConventionsAttribute.cs" />
7477
<Compile Include="CommitizenViewModelTests.cs" />
7578
<Compile Include="Properties\AssemblyInfo.cs" />
79+
<Compile Include="OpenGenerateLocalConfigViewModelTests.cs" />
7680
<Compile Include="ViewTests.cs" />
7781
</ItemGroup>
7882
<ItemGroup>

vs-commitizen/Commands/OpenGenerateLocalConfig.cs

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.VisualStudio.Shell.Interop;
88
using vs_commitizen.Infrastructure;
99
using vs_commitizen.Settings;
10+
using vs_commitizen.ViewModels;
1011
using Task = System.Threading.Tasks.Task;
1112

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

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

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

5558
}
5659

57-
private static async Task HandleIsCommandVisibleAsync(object sender)
60+
private async Task HandleIsCommandVisibleAsync(object sender)
5861
{
5962
try
6063
{
@@ -63,11 +66,7 @@ private static async Task HandleIsCommandVisibleAsync(object sender)
6366
switch (menuCommand.CommandID.ID)
6467
{
6568
case (int)PackageIds.OpenGenerateLocalConfigCmd:
66-
var configFileProvider = IoC.GetInstance<IConfigFileProvider>();
67-
var fileAccessor = IoC.GetInstance<IFileAccessor>();
68-
69-
var localConfigPath = await configFileProvider.TryGetLocalConfigAsync();
70-
menuCommand.Enabled = !string.IsNullOrWhiteSpace(localConfigPath);
69+
menuCommand.Enabled = await this.viewModel.IsCommandEnabledAsync();
7170
break;
7271
}
7372
}
@@ -124,30 +123,7 @@ private void Execute(object sender, EventArgs e)
124123

125124
private async Task ProcessAsync()
126125
{
127-
var popupManager = IoC.GetInstance<IPopupManager>();
128-
129-
try
130-
{
131-
var configFileProvider = IoC.GetInstance<IConfigFileProvider>();
132-
var fileAccessor = IoC.GetInstance<IFileAccessor>();
133-
134-
var localConfigPath = await configFileProvider.TryGetLocalConfigAsync();
135-
if (string.IsNullOrWhiteSpace(localConfigPath)) return;
136-
137-
if (!fileAccessor.Exists(localConfigPath))
138-
{
139-
if (popupManager.Confirm("There is no local configuration file yet, do you want to create it for this repository ?", "Init local config file"))
140-
{
141-
fileAccessor.CopyFile(ConfigFileProvider.ConfigPathUserProfile, localConfigPath);
142-
}
143-
}
144-
145-
await OpenFileInEditorAsync(localConfigPath);
146-
}
147-
catch (Exception ex)
148-
{
149-
popupManager.Show(ex.ToString(), "An error occured");
150-
}
126+
await this.viewModel.ExecuteAsync(OpenFileInEditorAsync);
151127
}
152128

153129
private async Task OpenFileInEditorAsync(string localConfigPath)

vs-commitizen/Infrastructure/ConfigFileProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ private async Task<string> GetCacheKeyAsync()
107107
return (repository != null, repository?.RepositoryPath);
108108
}
109109

110-
public async Task<string> TryGetLocalConfigAsync()
110+
public virtual async Task<string> TryGetLocalConfigAsync()
111111
{
112112
var (isRepositoryLoaded, repositoryPath) = await GetLocalPathAsync(); // await GetCurrentSolutionAsync();
113113
if (isRepositoryLoaded)
@@ -181,7 +181,7 @@ private async Task<string> GenerateDefaultConfigFileAsync(string configFileInUse
181181
var defaultConfigFileContent = await reader.ReadToEndAsync();
182182
await fileStream.WriteAsync(defaultConfigFileContent);
183183

184-
return defaultConfigFileContent;
184+
return JObject.Parse(defaultConfigFileContent).SelectToken("types").ToString();
185185
}
186186
}
187187
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using vs_commitizen.Infrastructure;
7+
using vs_commitizen.Settings;
8+
9+
namespace vs_commitizen.ViewModels
10+
{
11+
public class OpenGenerateLocalConfigViewModel
12+
{
13+
private readonly IConfigFileProvider configFileProvider;
14+
private readonly IFileAccessor fileAccessor;
15+
private readonly IPopupManager popupManager;
16+
17+
public OpenGenerateLocalConfigViewModel()
18+
{
19+
configFileProvider = IoC.GetInstance<IConfigFileProvider>();
20+
fileAccessor = IoC.GetInstance<IFileAccessor>();
21+
popupManager = IoC.GetInstance<IPopupManager>();
22+
23+
}
24+
25+
public async Task<bool> IsCommandEnabledAsync()
26+
{
27+
var localConfigPath = await this.configFileProvider.TryGetLocalConfigAsync();
28+
29+
return !string.IsNullOrWhiteSpace(localConfigPath);
30+
}
31+
32+
public async Task ExecuteAsync(Func<string, Task> openFunc)
33+
{
34+
try
35+
{
36+
var localConfigPath = await this.configFileProvider.TryGetLocalConfigAsync();
37+
if (string.IsNullOrWhiteSpace(localConfigPath)) return;
38+
39+
if (fileAccessor.Exists(localConfigPath))
40+
{
41+
await openFunc(localConfigPath);
42+
}
43+
else
44+
{
45+
if (popupManager.Confirm("There is no local configuration file yet, do you want to create it for this repository ?", "Init local config file"))
46+
{
47+
fileAccessor.CopyFile(ConfigFileProvider.ConfigPathUserProfile, localConfigPath);
48+
await openFunc(localConfigPath);
49+
}
50+
}
51+
}
52+
catch (Exception ex)
53+
{
54+
popupManager.Show(ex.ToString(), "An error occured");
55+
}
56+
}
57+
}
58+
}

vs-commitizen/defaultConfigFile.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://github.com/MrLuje/vs-commitizen/config-schema.json",
2+
"$schema": "https://raw.githubusercontent.com/MrLuje/vs-commitizen/master/config-schema.json",
33
"types": [
44
{
55
"type": "feat",

vs-commitizen/vs-commitizen.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<Compile Include="PackageRegistry.cs" />
6565
<Compile Include="Infrastructure\PopupManager.cs" />
6666
<Compile Include="Properties\AssemblyInfo.cs" />
67+
<Compile Include="ViewModels\OpenGenerateLocalConfigViewModel.cs" />
6768
<Compile Include="VsCommitizenIds.cs">
6869
<AutoGen>True</AutoGen>
6970
<DesignTime>True</DesignTime>

0 commit comments

Comments
 (0)