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

Commit 37407c6

Browse files
committed
Fix tests
1 parent 143bbac commit 37407c6

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,13 +31,14 @@ 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 IUsageTracker usageTracker;
3839
readonly ReactiveCommand<object> browseForDirectoryCommand = ReactiveCommand.Create();
3940
bool isLoading;
40-
readonly ObservableAsPropertyHelper<bool> noRepositoriesFound;
41+
bool noRepositoriesFound;
4142
readonly ObservableAsPropertyHelper<bool> canClone;
4243
string baseRepositoryPath;
4344
bool loadingFailed;
@@ -59,37 +60,27 @@ public RepositoryCloneViewModel(
5960
INotificationService notificationService,
6061
IUsageTracker usageTracker)
6162
{
63+
this.repositoryHost = repositoryHost;
6264
this.cloneService = cloneService;
6365
this.operatingSystem = operatingSystem;
6466
this.notificationService = notificationService;
6567
this.usageTracker = usageTracker;
6668

6769
Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title);
68-
IsLoading = true;
6970

70-
Repositories = repositoryHost.ModelService.GetRepositories(new TrackingCollection<IRepositoryModel>()) as TrackingCollection<IRepositoryModel>;
71+
Repositories = new TrackingCollection<IRepositoryModel>();
7172
repositories.ProcessingDelay = TimeSpan.Zero;
7273
repositories.Comparer = OrderedComparer<IRepositoryModel>.OrderBy(x => x.Owner).ThenBy(x => x.Name).Compare;
7374
repositories.Filter = FilterRepository;
7475
repositories.NewerComparer = OrderedComparer<IRepositoryModel>.OrderByDescending(x => x.UpdatedAt).Compare;
7576

76-
repositories.OriginalCompleted.Subscribe(
77-
_ => { }
78-
, ex =>
79-
{
80-
LoadingFailed = true;
81-
log.Error("Error while loading repositories", ex);
82-
},
83-
() => IsLoading = false
84-
);
85-
repositories.Subscribe();
86-
87-
filterTextIsEnabled = this.WhenAny(x => x.Repositories.Count, x => x.Value > 0)
77+
filterTextIsEnabled = this.WhenAny(x => x.IsLoading, x => x.Value)
78+
.Select(x => !x && repositories.UnfilteredCount > 0)
8879
.ToProperty(this, x => x.FilterTextIsEnabled);
8980

90-
noRepositoriesFound = this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed
81+
this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed
9182
, (any, loading, failed) => !any.Value && !loading.Value && !failed.Value)
92-
.ToProperty(this, x => x.NoRepositoriesFound);
83+
.Subscribe(x => NoRepositoriesFound = x);
9384

9485
this.WhenAny(x => x.FilterText, x => x.Value)
9586
.DistinctUntilChanged(StringComparer.OrdinalIgnoreCase)
@@ -119,6 +110,26 @@ public RepositoryCloneViewModel(
119110
this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value)
120111
.Subscribe();
121112
BaseRepositoryPath = cloneService.DefaultClonePath;
113+
NoRepositoriesFound = true;
114+
}
115+
116+
public override void Initialize([AllowNull] ViewWithData data)
117+
{
118+
base.Initialize(data);
119+
120+
IsLoading = true;
121+
Repositories = repositoryHost.ModelService.GetRepositories(repositories) as TrackingCollection<IRepositoryModel>;
122+
repositories.OriginalCompleted.Subscribe(
123+
_ => { }
124+
, ex =>
125+
{
126+
LoadingFailed = true;
127+
IsLoading = false;
128+
log.Error("Error while loading repositories", ex);
129+
},
130+
() => IsLoading = false
131+
);
132+
repositories.Subscribe();
122133
}
123134

124135
bool FilterRepository(IRepositoryModel repo, int position, IList<IRepositoryModel> list)
@@ -219,13 +230,11 @@ public string BaseRepositoryPath
219230
public IReactiveCommand<Unit> CloneCommand { get; private set; }
220231

221232
TrackingCollection<IRepositoryModel> repositories;
222-
/// <summary>
223-
/// List of repositories as returned by the server
224-
/// </summary>
225233
public ObservableCollection<IRepositoryModel> Repositories
226234
{
235+
[return: AllowNull]
227236
get { return repositories; }
228-
private set { repositories = value as TrackingCollection<IRepositoryModel>; this.RaisePropertyChanged(); }
237+
private set { this.RaiseAndSetIfChanged(ref repositories, (TrackingCollection<IRepositoryModel>)value); }
229238
}
230239

231240
IRepositoryModel selectedRepository;
@@ -272,7 +281,8 @@ public bool LoadingFailed
272281

273282
public bool NoRepositoriesFound
274283
{
275-
get { return noRepositoriesFound.Value; }
284+
get { return noRepositoriesFound; }
285+
private set { this.RaiseAndSetIfChanged(ref noRepositoriesFound, value); }
276286
}
277287

278288
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,13 +44,14 @@ 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
Substitute.For<IUsageTracker>());
4153

54+
await col.OriginalCompleted;
4255
Assert.Equal(3, vm.Repositories.Count);
4356
}
4457
}
@@ -54,14 +67,14 @@ public async Task StartsTrueBecomesFalseWhenCompleted()
5467
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
5568

5669
var cloneService = Substitute.For<IRepositoryCloneService>();
57-
var vm = new RepositoryCloneViewModel(
70+
var vm = GetVM(
5871
repositoryHost,
5972
cloneService,
6073
Substitute.For<IOperatingSystem>(),
6174
Substitute.For<INotificationService>(),
6275
Substitute.For<IUsageTracker>());
6376

64-
Assert.False(vm.IsLoading);
77+
Assert.True(vm.IsLoading);
6578

6679
var done = new ReplaySubject<Unit>();
6780
done.OnNext(Unit.Default);
@@ -92,7 +105,7 @@ public void IsFalseWhenLoadingReposFailsImmediately()
92105
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
93106

94107
var cloneService = Substitute.For<IRepositoryCloneService>();
95-
var vm = new RepositoryCloneViewModel(
108+
var vm = GetVM(
96109
repositoryHost,
97110
cloneService,
98111
Substitute.For<IOperatingSystem>(),
@@ -122,18 +135,19 @@ public void IsTrueInitially()
122135
Substitute.For<INotificationService>(),
123136
Substitute.For<IUsageTracker>());
124137

138+
Assert.False(vm.LoadingFailed);
125139
Assert.True(vm.NoRepositoriesFound);
126140
}
127141

128142
[Fact]
129-
public void IsFalseWhenLoadingAndCompletedWithRepository()
143+
public async Task IsFalseWhenLoadingAndCompletedWithRepository()
130144
{
131145
var repoSubject = new Subject<IRepositoryModel>();
132146
var col = TrackingCollection.Create(repoSubject);
133147
var repositoryHost = Substitute.For<IRepositoryHost>();
134148
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
135149
var cloneService = Substitute.For<IRepositoryCloneService>();
136-
var vm = new RepositoryCloneViewModel(
150+
var vm = GetVM(
137151
repositoryHost,
138152
cloneService,
139153
Substitute.For<IOperatingSystem>(),
@@ -146,6 +160,8 @@ public void IsFalseWhenLoadingAndCompletedWithRepository()
146160

147161
repoSubject.OnCompleted();
148162

163+
await col.OriginalCompleted;
164+
149165
Assert.Equal(1, vm.Repositories.Count);
150166
Assert.False(vm.NoRepositoriesFound);
151167
}
@@ -158,7 +174,7 @@ public void IsFalseWhenFailed()
158174
var repositoryHost = Substitute.For<IRepositoryHost>();
159175
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
160176
var cloneService = Substitute.For<IRepositoryCloneService>();
161-
var vm = new RepositoryCloneViewModel(
177+
var vm = GetVM(
162178
repositoryHost,
163179
cloneService,
164180
Substitute.For<IOperatingSystem>(),
@@ -179,7 +195,7 @@ public void IsTrueWhenLoadingCompleteNotFailedAndNoRepositories()
179195
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
180196

181197
var cloneService = Substitute.For<IRepositoryCloneService>();
182-
var vm = new RepositoryCloneViewModel(
198+
var vm = GetVM(
183199
repositoryHost,
184200
cloneService,
185201
Substitute.For<IOperatingSystem>(),
@@ -202,7 +218,7 @@ public void IsTrueIfLoadingReposFails()
202218
var repositoryHost = Substitute.For<IRepositoryHost>();
203219
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
204220
var cloneService = Substitute.For<IRepositoryCloneService>();
205-
var vm = new RepositoryCloneViewModel(
221+
var vm = GetVM(
206222
repositoryHost,
207223
cloneService,
208224
Substitute.For<IOperatingSystem>(),
@@ -238,7 +254,7 @@ public void IsInvalidWhenDestinationRepositoryExists()
238254
var directories = Substitute.For<IDirectoryFacade>();
239255
os.Directory.Returns(directories);
240256
directories.Exists(@"c:\foo\bar").Returns(true);
241-
var vm = new RepositoryCloneViewModel(
257+
var vm = GetVM(
242258
repositoryHost,
243259
cloneService,
244260
os,
@@ -262,7 +278,7 @@ public void IsEnabledWhenRepositorySelectedAndPathValid()
262278
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
263279

264280
var cloneService = Substitute.For<IRepositoryCloneService>();
265-
var vm = new RepositoryCloneViewModel(
281+
var vm = GetVM(
266282
repositoryHost,
267283
cloneService,
268284
Substitute.For<IOperatingSystem>(),
@@ -284,7 +300,7 @@ public void IsNotEnabledWhenPathIsNotValid()
284300
repositoryHost.ModelService.GetRepositories(Arg.Any<ITrackingCollection<IRepositoryModel>>()).Returns(_ => col);
285301

286302
var cloneService = Substitute.For<IRepositoryCloneService>();
287-
var vm = new RepositoryCloneViewModel(
303+
var vm = GetVM(
288304
repositoryHost,
289305
cloneService,
290306
Substitute.For<IOperatingSystem>(),
@@ -309,7 +325,7 @@ public async Task DisplaysErrorMessageWhenExceptionOccurs()
309325
cloneService.CloneRepository(Args.String, Args.String, Args.String)
310326
.Returns(Observable.Throw<Unit>(new InvalidOperationException("Oh my! That was bad.")));
311327
var notificationService = Substitute.For<INotificationService>();
312-
var vm = new RepositoryCloneViewModel(
328+
var vm = GetVM(
313329
repositoryHost,
314330
cloneService,
315331
Substitute.For<IOperatingSystem>(),

0 commit comments

Comments
 (0)