Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit d24080f

Browse files
committed
Fix tests
1 parent 3fa874f commit d24080f

File tree

5 files changed

+77
-39
lines changed

5 files changed

+77
-39
lines changed

src/GitHub.App/ViewModels/PullRequestListViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public override void Initialize([AllowNull] ViewWithData data)
8686
{
8787
base.Initialize(data);
8888

89-
repositoryHost.ModelService.GetPullRequests(repository, pullRequests);
89+
PullRequests = repositoryHost.ModelService.GetPullRequests(repository, pullRequests) as TrackingCollection<IPullRequestModel>;
9090
pullRequests.Subscribe(pr =>
9191
{
9292
trackingAssignees.AddItem(pr.Assignee);

src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ public class RepositoryCloneViewModel : BaseViewModel, IRepositoryCloneViewModel
3131
{
3232
static readonly Logger log = LogManager.GetCurrentClassLogger();
3333

34+
readonly IRepositoryHost repositoryHost;
3435
readonly IRepositoryCloneService cloneService;
3536
readonly IOperatingSystem operatingSystem;
3637
readonly INotificationService notificationService;
3738
readonly ReactiveCommand<object> browseForDirectoryCommand = ReactiveCommand.Create();
3839
bool isLoading;
39-
readonly ObservableAsPropertyHelper<bool> noRepositoriesFound;
40+
bool noRepositoriesFound;
4041
readonly ObservableAsPropertyHelper<bool> canClone;
4142
string baseRepositoryPath;
4243
bool loadingFailed;
@@ -56,36 +57,26 @@ public RepositoryCloneViewModel(
5657
IOperatingSystem operatingSystem,
5758
INotificationService notificationService)
5859
{
60+
this.repositoryHost = repositoryHost;
5961
this.cloneService = cloneService;
6062
this.operatingSystem = operatingSystem;
6163
this.notificationService = notificationService;
6264

6365
Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title);
64-
IsLoading = true;
6566

66-
Repositories = repositoryHost.ModelService.GetRepositories(new TrackingCollection<IRepositoryModel>()) as TrackingCollection<IRepositoryModel>;
67+
Repositories = new TrackingCollection<IRepositoryModel>();
6768
repositories.ProcessingDelay = TimeSpan.Zero;
6869
repositories.Comparer = OrderedComparer<IRepositoryModel>.OrderBy(x => x.Owner).ThenBy(x => x.Name).Compare;
6970
repositories.Filter = FilterRepository;
7071
repositories.NewerComparer = OrderedComparer<IRepositoryModel>.OrderByDescending(x => x.UpdatedAt).Compare;
7172

72-
repositories.OriginalCompleted.Subscribe(
73-
_ => { }
74-
, ex =>
75-
{
76-
LoadingFailed = true;
77-
log.Error("Error while loading repositories", ex);
78-
},
79-
() => IsLoading = false
80-
);
81-
repositories.Subscribe();
82-
83-
filterTextIsEnabled = this.WhenAny(x => x.Repositories.Count, x => x.Value > 0)
73+
filterTextIsEnabled = this.WhenAny(x => x.IsLoading, x => x.Value)
74+
.Select(x => !x && repositories.UnfilteredCount > 0)
8475
.ToProperty(this, x => x.FilterTextIsEnabled);
8576

86-
noRepositoriesFound = this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed
77+
this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed
8778
, (any, loading, failed) => !any.Value && !loading.Value && !failed.Value)
88-
.ToProperty(this, x => x.NoRepositoriesFound);
79+
.Subscribe(x => NoRepositoriesFound = x);
8980

9081
this.WhenAny(x => x.FilterText, x => x.Value)
9182
.DistinctUntilChanged(StringComparer.OrdinalIgnoreCase)
@@ -115,6 +106,26 @@ public RepositoryCloneViewModel(
115106
this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value)
116107
.Subscribe();
117108
BaseRepositoryPath = cloneService.DefaultClonePath;
109+
NoRepositoriesFound = true;
110+
}
111+
112+
public override void Initialize([AllowNull] ViewWithData data)
113+
{
114+
base.Initialize(data);
115+
116+
IsLoading = true;
117+
Repositories = repositoryHost.ModelService.GetRepositories(repositories) as TrackingCollection<IRepositoryModel>;
118+
repositories.OriginalCompleted.Subscribe(
119+
_ => { }
120+
, ex =>
121+
{
122+
LoadingFailed = true;
123+
IsLoading = false;
124+
log.Error("Error while loading repositories", ex);
125+
},
126+
() => IsLoading = false
127+
);
128+
repositories.Subscribe();
118129
}
119130

120131
bool FilterRepository(IRepositoryModel repo, int position, IList<IRepositoryModel> list)
@@ -212,13 +223,11 @@ public string BaseRepositoryPath
212223
public IReactiveCommand<Unit> CloneCommand { get; private set; }
213224

214225
TrackingCollection<IRepositoryModel> repositories;
215-
/// <summary>
216-
/// List of repositories as returned by the server
217-
/// </summary>
218226
public ObservableCollection<IRepositoryModel> Repositories
219227
{
228+
[return: AllowNull]
220229
get { return repositories; }
221-
private set { repositories = value as TrackingCollection<IRepositoryModel>; this.RaisePropertyChanged(); }
230+
private set { this.RaiseAndSetIfChanged(ref repositories, (TrackingCollection<IRepositoryModel>)value); }
222231
}
223232

224233
IRepositoryModel selectedRepository;
@@ -265,7 +274,8 @@ public bool LoadingFailed
265274

266275
public bool NoRepositoriesFound
267276
{
268-
get { return noRepositoriesFound.Value; }
277+
get { return noRepositoriesFound; }
278+
private set { this.RaiseAndSetIfChanged(ref noRepositoriesFound, value); }
269279
}
270280

271281
public ICommand BrowseForDirectory

src/GitHub.Exports.Reactive/Collections/ITrackingCollection.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace GitHub.Collections
2020
public interface ITrackingCollection<T> : IDisposable,
2121
INotifyCollectionChanged, INotifyPropertyChanged,
2222
IList<T>, ICollection<T>, IEnumerable<T>
23-
where T : ICopyable<T>
23+
where T : class, ICopyable<T>
2424
{
2525
/// <summary>
2626
/// Sets up an observable as source for the collection.
@@ -61,5 +61,11 @@ public interface ITrackingCollection<T> : IDisposable,
6161
/// </summary>
6262
TimeSpan ProcessingDelay { get; set; }
6363
IObservable<Unit> OriginalCompleted { get; }
64+
65+
/// <summary>
66+
/// Returns the number of elements that the collection contains
67+
/// regardless of filtering
68+
/// </summary>
69+
int UnfilteredCount { get; }
6470
}
6571
}

src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static ObservableCollection<T> CreateListenerCollectionAndRun<T>(IObserva
4444

4545
public static ObservableCollection<T> CreateListenerCollection<T>(this ITrackingCollection<T> tcol,
4646
IList<T> stickieItemsOnTop = null)
47-
where T : ICopyable<T>
47+
where T : class, ICopyable<T>
4848
{
4949
var col = new ObservableCollection<T>(stickieItemsOnTop);
5050
tcol.CollectionChanged += (s, e) =>
@@ -164,6 +164,12 @@ public TimeSpan ProcessingDelay
164164
set { requestedDelay = value; }
165165
}
166166

167+
/// <summary>
168+
/// Returns the number of elements that the collection contains
169+
/// regardless of filtering
170+
/// </summary>
171+
public int UnfilteredCount => original.Count;
172+
167173
bool ManualProcessing => cache.IsEmpty && originalSourceIsCompleted;
168174

169175
public TrackingCollection(Func<T, T, int> comparer = null, Func<T, int, IList<T>, bool> filter = null,

src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@
1616

1717
public class RepositoryCloneViewModelTests
1818
{
19+
static RepositoryCloneViewModel GetVM(IRepositoryHost repositoryHost, IRepositoryCloneService cloneService,
20+
IOperatingSystem os, INotificationService notificationService)
21+
{
22+
var vm = new RepositoryCloneViewModel(
23+
repositoryHost,
24+
cloneService,
25+
os,
26+
notificationService);
27+
vm.Initialize(null);
28+
return vm;
29+
}
30+
1931
public class TheLoadRepositoriesCommand : TestBaseClass
2032
{
2133
[Fact]
22-
public void LoadsRepositories()
34+
public async Task LoadsRepositories()
2335
{
2436
var repos = new IRepositoryModel[]
2537
{
@@ -32,12 +44,13 @@ public void LoadsRepositories()
3244
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
3345

3446
var cloneService = Substitute.For<IRepositoryCloneService>();
35-
var vm = new RepositoryCloneViewModel(
47+
var vm = GetVM(
3648
repositoryHost,
3749
cloneService,
3850
Substitute.For<IOperatingSystem>(),
3951
Substitute.For<INotificationService>());
4052

53+
await col.OriginalCompleted;
4154
Assert.Equal(3, vm.Repositories.Count);
4255
}
4356
}
@@ -53,13 +66,13 @@ public async Task StartsTrueBecomesFalseWhenCompleted()
5366
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
5467

5568
var cloneService = Substitute.For<IRepositoryCloneService>();
56-
var vm = new RepositoryCloneViewModel(
69+
var vm = GetVM(
5770
repositoryHost,
5871
cloneService,
5972
Substitute.For<IOperatingSystem>(),
6073
Substitute.For<INotificationService>());
6174

62-
Assert.False(vm.IsLoading);
75+
Assert.True(vm.IsLoading);
6376

6477
var done = new ReplaySubject<Unit>();
6578
done.OnNext(Unit.Default);
@@ -90,7 +103,7 @@ public void IsFalseWhenLoadingReposFailsImmediately()
90103
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
91104

92105
var cloneService = Substitute.For<IRepositoryCloneService>();
93-
var vm = new RepositoryCloneViewModel(
106+
var vm = GetVM(
94107
repositoryHost,
95108
cloneService,
96109
Substitute.For<IOperatingSystem>(),
@@ -118,18 +131,19 @@ public void IsTrueInitially()
118131
Substitute.For<IOperatingSystem>(),
119132
Substitute.For<INotificationService>());
120133

134+
Assert.False(vm.LoadingFailed);
121135
Assert.True(vm.NoRepositoriesFound);
122136
}
123137

124138
[Fact]
125-
public void IsFalseWhenLoadingAndCompletedWithRepository()
139+
public async Task IsFalseWhenLoadingAndCompletedWithRepository()
126140
{
127141
var repoSubject = new Subject<IRepositoryModel>();
128142
var col = TrackingCollection.Create(repoSubject);
129143
var repositoryHost = Substitute.For<IRepositoryHost>();
130144
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
131145
var cloneService = Substitute.For<IRepositoryCloneService>();
132-
var vm = new RepositoryCloneViewModel(
146+
var vm = GetVM(
133147
repositoryHost,
134148
cloneService,
135149
Substitute.For<IOperatingSystem>(),
@@ -141,6 +155,8 @@ public void IsFalseWhenLoadingAndCompletedWithRepository()
141155

142156
repoSubject.OnCompleted();
143157

158+
await col.OriginalCompleted;
159+
144160
Assert.Equal(1, vm.Repositories.Count);
145161
Assert.False(vm.NoRepositoriesFound);
146162
}
@@ -153,7 +169,7 @@ public void IsFalseWhenFailed()
153169
var repositoryHost = Substitute.For<IRepositoryHost>();
154170
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
155171
var cloneService = Substitute.For<IRepositoryCloneService>();
156-
var vm = new RepositoryCloneViewModel(
172+
var vm = GetVM(
157173
repositoryHost,
158174
cloneService,
159175
Substitute.For<IOperatingSystem>(),
@@ -173,7 +189,7 @@ public void IsTrueWhenLoadingCompleteNotFailedAndNoRepositories()
173189
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
174190

175191
var cloneService = Substitute.For<IRepositoryCloneService>();
176-
var vm = new RepositoryCloneViewModel(
192+
var vm = GetVM(
177193
repositoryHost,
178194
cloneService,
179195
Substitute.For<IOperatingSystem>(),
@@ -195,7 +211,7 @@ public void IsTrueIfLoadingReposFails()
195211
var repositoryHost = Substitute.For<IRepositoryHost>();
196212
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
197213
var cloneService = Substitute.For<IRepositoryCloneService>();
198-
var vm = new RepositoryCloneViewModel(
214+
var vm = GetVM(
199215
repositoryHost,
200216
cloneService,
201217
Substitute.For<IOperatingSystem>(),
@@ -230,7 +246,7 @@ public void IsInvalidWhenDestinationRepositoryExists()
230246
var directories = Substitute.For<IDirectoryFacade>();
231247
os.Directory.Returns(directories);
232248
directories.Exists(@"c:\foo\bar").Returns(true);
233-
var vm = new RepositoryCloneViewModel(
249+
var vm = GetVM(
234250
repositoryHost,
235251
cloneService,
236252
os,
@@ -253,7 +269,7 @@ public void IsEnabledWhenRepositorySelectedAndPathValid()
253269
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
254270

255271
var cloneService = Substitute.For<IRepositoryCloneService>();
256-
var vm = new RepositoryCloneViewModel(
272+
var vm = GetVM(
257273
repositoryHost,
258274
cloneService,
259275
Substitute.For<IOperatingSystem>(),
@@ -274,7 +290,7 @@ public void IsNotEnabledWhenPathIsNotValid()
274290
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
275291

276292
var cloneService = Substitute.For<IRepositoryCloneService>();
277-
var vm = new RepositoryCloneViewModel(
293+
var vm = GetVM(
278294
repositoryHost,
279295
cloneService,
280296
Substitute.For<IOperatingSystem>(),
@@ -298,7 +314,7 @@ public async Task DisplaysErrorMessageWhenExceptionOccurs()
298314
cloneService.CloneRepository(Args.String, Args.String, Args.String)
299315
.Returns(Observable.Throw<Unit>(new InvalidOperationException("Oh my! That was bad.")));
300316
var notificationService = Substitute.For<INotificationService>();
301-
var vm = new RepositoryCloneViewModel(
317+
var vm = GetVM(
302318
repositoryHost,
303319
cloneService,
304320
Substitute.For<IOperatingSystem>(),

0 commit comments

Comments
 (0)