Add unit tests of error message display

This commit is contained in:
Haacked 2015-04-16 14:25:30 -07:00
Родитель 27573c9cad
Коммит 6a27baa79c
3 изменённых файлов: 63 добавлений и 12 удалений

Просмотреть файл

@ -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.");
}
}
}