forked from gitextensions/gitextensions
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Management of remote repositories
Remote repositories are accessible on a several forms, however the experience is quite inconsistent. The management of the remotes is quite poor too, UX is confusing and buggy. In the original implementation the UI and the BL concerns intertwined which makes it difficult to maintain, extend and test. * The new implementation moves the functionality concerning dealing with the remotes repositories into a separate controller abstracting the data management from the UI. * The controller enables testing * The controller also simplifies the remotes management (FormRemotes). The "remote repositories" tab's layout has also been reworked and updated. * All affected forms now need to instantiate a controller, load the remotes and bind them to the desired UI control (i.e. to a combo). The following reported bugs are fixed: - gitextensions#2550 - Remote Repositories > Separate Push URL not working (gitextensions#2550) - gitextensions#1465 - Tab Stop Order in Remote Repositories dialog is very messed up (gitextensions#1465) The following change was undone, as it introduced quite inconsistent and confusing UX: - gitextensions#1208 - Rearrange buttons in "Manage Remote Repositories" dialog (gitextensions#1208) Translations: The following items added in FormRemotes: - lblMgtPuttyPanelHeader.Text - _gitMessage.Text - _gbMgtPanelHeaderNew.Text - _gbMgtPanelHeaderEdit.Text - lblMgtDetailsPanelHeader.Text The following items removed from FormRemotes: - New.Text - Delete.Text - buttonClose.Text - PuTTYSSH.Text - _hintDelete.Text - groupBox1.Text
- Loading branch information
RussKie
committed
Aug 14, 2016
1 parent
7c3a1b1
commit 086d18a
Showing
22 changed files
with
1,405 additions
and
716 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 178 additions & 0 deletions
178
GitExtensionsTest/GitUI/Objects/GitRemoteControllerTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using FluentAssertions; | ||
using GitCommands.Config; | ||
using GitUI.Objects; | ||
using GitUIPluginInterfaces; | ||
using NSubstitute; | ||
using NUnit.Framework; | ||
|
||
namespace GitExtensionsTest.GitUI.Objects | ||
{ | ||
[TestFixture] | ||
class GitRemoteControllerTests | ||
{ | ||
private IGitModule _module; | ||
private IGitRemoteController _controller; | ||
|
||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
_module = Substitute.For<IGitModule>(); | ||
|
||
_controller = new GitRemoteController(_module); | ||
} | ||
|
||
|
||
[Test] | ||
public void LoadRemotes_should_not_throw_if_module_is_null() | ||
{ | ||
_module = null; | ||
|
||
((Action)(() => _controller.LoadRemotes())).ShouldNotThrow(); | ||
} | ||
|
||
[Test] | ||
public void LoadRemotes_should_not_populate_remotes_if_none() | ||
{ | ||
_module.GetRemotes().Returns(x => Enumerable.Empty<string>()); | ||
|
||
_controller.LoadRemotes(); | ||
|
||
_controller.Remotes.Count.Should().Be(0); | ||
_module.Received(1).GetRemotes(); | ||
_module.DidNotReceive().GetSetting(Arg.Any<string>()); | ||
_module.DidNotReceive().GetSettings(Arg.Any<string>()); | ||
} | ||
|
||
[Test] | ||
public void LoadRemotes_should_not_populate_remotes_if_those_are_null_or_whitespace() | ||
{ | ||
_module.GetRemotes().Returns(x => new[] { null, "", " ", " ", "\t" }); | ||
|
||
_controller.LoadRemotes(); | ||
|
||
_controller.Remotes.Count.Should().Be(0); | ||
_module.Received(1).GetRemotes(); | ||
_module.DidNotReceive().GetSetting(Arg.Any<string>()); | ||
_module.DidNotReceive().GetSettings(Arg.Any<string>()); | ||
} | ||
|
||
[Test] | ||
public void LoadRemotes_should_populate_remotes_if_any() | ||
{ | ||
const string remote = "a"; | ||
_module.GetRemotes().Returns(x => new[] { null, "", " ", " ", remote, "\t" }); | ||
|
||
_controller.LoadRemotes(); | ||
|
||
_controller.Remotes.Count.Should().Be(1); | ||
_module.Received(1).GetRemotes(); | ||
_module.Received(1).GetSetting(string.Format(SettingKeyString.RemoteUrl, remote)); | ||
_module.Received(1).GetSetting(string.Format(SettingKeyString.RemotePushUrl, remote)); | ||
_module.Received(1).GetSetting(string.Format(SettingKeyString.RemotePuttySshKey, remote)); | ||
_module.Received(1).GetSettings(string.Format(SettingKeyString.RemotePush, remote)); | ||
} | ||
|
||
[Test] | ||
public void RemoveRemote_should_throw_if_remote_is_null() | ||
{ | ||
((Action)(() => _controller.RemoveRemote(null))).ShouldThrow<ArgumentNullException>() | ||
.WithMessage("Value cannot be null.\r\nParameter name: remote"); | ||
} | ||
|
||
[Test] | ||
public void RemoveRemote_success() | ||
{ | ||
var remote = new GitRemote { Name = "bla" }; | ||
|
||
_controller.RemoveRemote(remote); | ||
|
||
_module.Received(1).RemoveRemote(remote.Name); | ||
} | ||
|
||
[Test] | ||
public void SaveRemote_should_throw_if_remoteName_is_null() | ||
{ | ||
((Action)(() => _controller.SaveRemote(null, null, "b", "c", "d"))).ShouldThrow<ArgumentNullException>() | ||
.WithMessage("Value cannot be null.\r\nParameter name: remoteName"); | ||
} | ||
|
||
[Test] | ||
public void SaveRemote_null_remote_should_invoke_AddRemote_and_require_update() | ||
{ | ||
const string remoteName = "a"; | ||
const string remoteUrl = "b"; | ||
const string output = "yes!"; | ||
_module.AddRemote(Arg.Any<string>(), Arg.Any<string>()).Returns(x => output); | ||
|
||
var result = _controller.SaveRemote(null, remoteName, remoteUrl, null, null); | ||
|
||
result.UserMessage.Should().Be(output); | ||
result.ShouldUpdateRemote.Should().BeTrue(); | ||
_module.Received(1).AddRemote(remoteName, remoteUrl); | ||
} | ||
|
||
[Test] | ||
public void SaveRemote_populated_remote_should_invoke_RenameRemote_if_remoteName_mismatch_no_update_required() | ||
{ | ||
const string remoteName = "a"; | ||
const string remoteUrl = "b"; | ||
const string output = "yes!"; | ||
var gitRemote = new GitRemote { Name = "old", Url = remoteUrl }; | ||
_module.RenameRemote(Arg.Any<string>(), Arg.Any<string>()).Returns(x => output); | ||
|
||
var result = _controller.SaveRemote(gitRemote, remoteName, remoteUrl, null, null); | ||
|
||
result.UserMessage.Should().Be(output); | ||
result.ShouldUpdateRemote.Should().BeFalse(); | ||
_module.Received(1).RenameRemote(gitRemote.Name, remoteName); | ||
} | ||
|
||
[Test] | ||
public void SaveRemote_populated_remote_should_require_update_if_remoteUrl_mismatch() | ||
{ | ||
const string remoteName = "a"; | ||
const string remoteUrl = "b"; | ||
const string output = "yes!"; | ||
var gitRemote = new GitRemote { Name = "old", Url = "old" }; | ||
_module.RenameRemote(Arg.Any<string>(), Arg.Any<string>()).Returns(x => output); | ||
|
||
var result = _controller.SaveRemote(gitRemote, remoteName, remoteUrl, null, null); | ||
|
||
result.UserMessage.Should().Be(output); | ||
result.ShouldUpdateRemote.Should().BeTrue(); | ||
_module.Received(1).RenameRemote(gitRemote.Name, remoteName); | ||
} | ||
|
||
[TestCase(null, null, null)] | ||
[TestCase("a", null, null)] | ||
[TestCase("a", "b", null)] | ||
[TestCase("a", "b", "c")] | ||
public void SaveRemote_should_update_settings(string remoteUrl, string remotePushUrl, string remotePuttySshKey) | ||
{ | ||
var remote = new GitRemote { Name = "bla", Url = remoteUrl }; | ||
|
||
_controller.SaveRemote(remote, remote.Name, remoteUrl, remotePushUrl, remotePuttySshKey); | ||
|
||
Action<string, string> ensure = (setting, value) => | ||
{ | ||
setting = string.Format(setting, remote.Name); | ||
if (!string.IsNullOrWhiteSpace(value)) | ||
{ | ||
_module.Received(1).SetSetting(setting, value); | ||
} | ||
else | ||
{ | ||
_module.Received(1).UnsetSetting(setting); | ||
} | ||
}; | ||
ensure(SettingKeyString.RemoteUrl, remoteUrl); | ||
ensure(SettingKeyString.RemotePushUrl, remotePushUrl); | ||
ensure(SettingKeyString.RemotePuttySshKey, remotePuttySshKey); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.