зеркало из https://github.com/github/VisualStudio.git
Add unit tests of error message display
This commit is contained in:
Родитель
27573c9cad
Коммит
6a27baa79c
|
@ -121,7 +121,7 @@ namespace GitHub.Services
|
|||
},
|
||||
{ ErrorType.ClipboardFailed, Map(Defaults("Failed to copy text to the clipboard.")) },
|
||||
{
|
||||
ErrorType.ClonedFailed, Map(Defaults("Failed to clone the repository '{0}'", "Please check your log file for more details, or email support if you are still having problems."),
|
||||
ErrorType.ClonedFailed, Map(Defaults("Failed to clone the repository '{0}'", "Email support@github.com if you continue to have problems."),
|
||||
new[]
|
||||
{
|
||||
new Translation(@"fatal: bad config file line (\d+) in (.+)", "Failed to clone the repository '{0}'", @"The config file '$2' is corrupted at line $1. You may need to open the file and try to fix any errors."),
|
||||
|
@ -154,7 +154,7 @@ namespace GitHub.Services
|
|||
|
||||
public static string GetUserFriendlyErrorMessage(this Exception exception, ErrorType errorType, params object[] messageArgs)
|
||||
{
|
||||
var translation = exception.GetUserFriendlyError(errorType, exception, messageArgs);
|
||||
var translation = exception.GetUserFriendlyError(errorType, messageArgs);
|
||||
if (translation == null) return exception.Message;
|
||||
return translation.ErrorMessage + Environment.NewLine + translation.ErrorCauseOrResolution;
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ namespace GitHub.Services
|
|||
return userError.Throw();
|
||||
}
|
||||
|
||||
public static UserError GetUserFriendlyError(this Exception exception, ErrorType errorType, params object[] messageArgs)
|
||||
static UserError GetUserFriendlyError(this Exception exception, ErrorType errorType, params object[] messageArgs)
|
||||
{
|
||||
return Translator.Value.GetUserError(errorType, exception, messageArgs);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reactive;
|
||||
|
@ -9,6 +10,7 @@ using GitHub.Models;
|
|||
using GitHub.Services;
|
||||
using NullGuard;
|
||||
using ReactiveUI;
|
||||
using Rothko;
|
||||
|
||||
namespace GitHub.ViewModels
|
||||
{
|
||||
|
@ -16,21 +18,28 @@ namespace GitHub.ViewModels
|
|||
public class RepositoryCloneViewModel : BaseViewModel, IRepositoryCloneViewModel
|
||||
{
|
||||
readonly IRepositoryCloneService cloneService;
|
||||
readonly IOperatingSystem operatingSystem;
|
||||
readonly IVSServices vsServices;
|
||||
|
||||
[ImportingConstructor]
|
||||
RepositoryCloneViewModel(
|
||||
IConnectionRepositoryHostMap connectionRepositoryHostMap,
|
||||
IRepositoryCloneService repositoryCloneService,
|
||||
IOperatingSystem operatingSystem,
|
||||
IVSServices vsServices)
|
||||
: this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, vsServices)
|
||||
: this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, vsServices)
|
||||
{ }
|
||||
|
||||
public RepositoryCloneViewModel(
|
||||
IRepositoryHost repositoryHost,
|
||||
IRepositoryCloneService cloneService,
|
||||
IOperatingSystem operatingSystem,
|
||||
IVSServices vsServices)
|
||||
{
|
||||
this.cloneService = cloneService;
|
||||
this.operatingSystem = operatingSystem;
|
||||
this.vsServices = vsServices;
|
||||
|
||||
Title = string.Format(CultureInfo.CurrentCulture, "Clone a {0} Repository", repositoryHost.Title);
|
||||
Repositories = new ReactiveList<IRepositoryModel>();
|
||||
repositoryHost.ModelService.GetRepositories()
|
||||
|
@ -54,8 +63,6 @@ namespace GitHub.ViewModels
|
|||
var canClone = this.WhenAny(x => x.SelectedRepository, x => x.Value)
|
||||
.Select(repo => repo != null);
|
||||
CloneCommand = ReactiveCommand.CreateAsyncObservable(canClone, OnCloneRepository);
|
||||
CloneCommand.ThrownExceptions.Subscribe(e =>
|
||||
vsServices.ShowError(e.GetUserFriendlyErrorMessage(ErrorType.ClonedFailed)));
|
||||
|
||||
BaseRepositoryPath = cloneService.GetLocalClonePathFromGitProvider(cloneService.DefaultClonePath);
|
||||
}
|
||||
|
@ -74,11 +81,19 @@ namespace GitHub.ViewModels
|
|||
return Observable.Start(() =>
|
||||
{
|
||||
var repository = SelectedRepository;
|
||||
if (!Directory.Exists(BaseRepositoryPath))
|
||||
Directory.CreateDirectory(BaseRepositoryPath);
|
||||
Debug.Assert(repository != null, "Should not be able to attempt to clone a repo when it's null");
|
||||
// The following is a noop if the directory already exists.
|
||||
operatingSystem.Directory.CreateDirectory(BaseRepositoryPath);
|
||||
return cloneService.CloneRepository(repository.CloneUrl, repository.Name, BaseRepositoryPath);
|
||||
})
|
||||
.SelectMany(_ => _);
|
||||
.SelectMany(_ => _)
|
||||
.Catch<Unit, Exception>(e =>
|
||||
{
|
||||
var repository = SelectedRepository;
|
||||
Debug.Assert(repository != null, "Should not be able to attempt to clone a repo when it's null");
|
||||
vsServices.ShowError(e.GetUserFriendlyErrorMessage(ErrorType.ClonedFailed, SelectedRepository.Name));
|
||||
return Observable.Return(Unit.Default);
|
||||
});
|
||||
}
|
||||
|
||||
string baseRepositoryPath;
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
using GitHub.Models;
|
||||
using System;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Models;
|
||||
using GitHub.Services;
|
||||
using GitHub.ViewModels;
|
||||
using Microsoft.Reactive.Testing;
|
||||
using NSubstitute;
|
||||
using ReactiveUI.Testing;
|
||||
using Rothko;
|
||||
using Xunit;
|
||||
|
||||
public class RepositoryCloneViewModelTests
|
||||
|
@ -13,8 +22,11 @@ public class RepositoryCloneViewModelTests
|
|||
{
|
||||
var repositoryHost = Substitute.For<IRepositoryHost>();
|
||||
var cloneService = Substitute.For<IRepositoryCloneService>();
|
||||
var avatarProvider = Substitute.For<IAvatarProvider>();
|
||||
var vm = new RepositoryCloneViewModel(repositoryHost, cloneService, avatarProvider);
|
||||
var vm = new RepositoryCloneViewModel(
|
||||
repositoryHost,
|
||||
cloneService,
|
||||
Substitute.For<IOperatingSystem>(),
|
||||
Substitute.For<IVSServices>());
|
||||
|
||||
Assert.False(vm.CloneCommand.CanExecute(null));
|
||||
|
||||
|
@ -22,5 +34,29 @@ public class RepositoryCloneViewModelTests
|
|||
|
||||
Assert.True(vm.CloneCommand.CanExecute(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisplaysErrorMessageWhenExceptionOccurs()
|
||||
{
|
||||
var repositoryHost = Substitute.For<IRepositoryHost>();
|
||||
var cloneService = Substitute.For<IRepositoryCloneService>();
|
||||
cloneService.CloneRepository(Args.String, Args.String, Args.String)
|
||||
.Returns(Observable.Throw<Unit>(new InvalidOperationException("Oh my! That was bad.")));
|
||||
var vsServices = Substitute.For<IVSServices>();
|
||||
var vm = new RepositoryCloneViewModel(
|
||||
repositoryHost,
|
||||
cloneService,
|
||||
Substitute.For<IOperatingSystem>(),
|
||||
vsServices);
|
||||
vm.BaseRepositoryPath = @"c:\fake";
|
||||
var repository = Substitute.For<IRepositoryModel>();
|
||||
repository.Name.Returns("octokit");
|
||||
vm.SelectedRepository = repository;
|
||||
|
||||
await vm.CloneCommand.ExecuteAsync(null);
|
||||
|
||||
vsServices.Received().ShowError(@"Failed to clone the repository 'octokit'
|
||||
Email support@github.com if you continue to have problems.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче