static TrackingCollection <Thing> CreateSource() { var result = new TrackingCollection <Thing>(Observable.Empty <Thing>()); result.Subscribe(); result.AddItem(new Thing(1, "item1", DateTimeOffset.MinValue)); result.AddItem(new Thing(2, "item2", DateTimeOffset.MinValue)); result.AddItem(new Thing(3, "item3", DateTimeOffset.MinValue)); return(result); }
public override void Initialize([AllowNull] ViewWithData data) { base.Initialize(data); IsLoaded = false; PullRequests = repositoryHost.ModelService.GetPullRequests(repository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); pullRequests.OriginalCompleted .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { if (listSettings.SelectedAuthor != null) { SelectedAuthor = Authors.FirstOrDefault(x => x.Login == listSettings.SelectedAuthor); } if (listSettings.SelectedAssignee != null) { SelectedAssignee = Assignees.FirstOrDefault(x => x.Login == listSettings.SelectedAssignee); } IsLoaded = true; UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor); }); }
async Task Load() { IsBusy = true; if (modelService == null) { modelService = await modelServiceFactory.CreateAsync(connection); } if (remoteRepository == null) { remoteRepository = await modelService.GetRepository( localRepository.Owner, localRepository.Name); Repositories = remoteRepository.IsFork ? new[] { remoteRepository.Parent, remoteRepository } : new[] { remoteRepository }; SelectedRepository = Repositories[0]; } PullRequests = modelService.GetPullRequests(SelectedRepository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); pullRequests.OriginalCompleted .ObserveOn(RxApp.MainThreadScheduler) ////.Catch<System.Reactive.Unit, Octokit.AuthorizationException>(ex => ////{ //// log.Info("Received AuthorizationException reading pull requests", ex); //// return repositoryHost.LogOut(); ////}) .Catch <System.Reactive.Unit, Exception>(ex => { // Occurs on network error, when the repository was deleted on GitHub etc. log.Error(ex, "Received Exception reading pull requests"); return(Observable.Empty <System.Reactive.Unit>()); }) .Subscribe(_ => { if (listSettings.SelectedAuthor != null) { SelectedAuthor = Authors.FirstOrDefault(x => x.Login == listSettings.SelectedAuthor); } if (listSettings.SelectedAssignee != null) { SelectedAssignee = Assignees.FirstOrDefault(x => x.Login == listSettings.SelectedAssignee); } IsBusy = false; UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor, SearchQuery); }); }
public void OrderByUpdatedNoFilter() { var count = 6; ITrackingCollection<Thing> col = new TrackingCollection<Thing>( Observable.Never<Thing>(), OrderedComparer<Thing>.OrderBy(x => x.UpdatedAt).Compare); col.NewerComparer = OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare; col.ProcessingDelay = TimeSpan.Zero; var list1 = new List<Thing>(Enumerable.Range(1, count).Select(i => GetThing(i, i, count - i, "Run 1")).ToList()); var list2 = new List<Thing>(Enumerable.Range(1, count).Select(i => GetThing(i, i, i + count, "Run 2")).ToList()); var evt = new ManualResetEvent(false); col.Subscribe(t => { if (++count == list1.Count) evt.Set(); }, () => { }); count = 0; // add first items foreach (var l in list1) col.AddItem(l); evt.WaitOne(); evt.Reset(); Assert.AreEqual(list1.Count, col.Count); list1.Sort(new LambdaComparer<Thing>(OrderedComparer<Thing>.OrderByDescending(x => x.CreatedAt).Compare)); CollectionAssert.AreEqual(col, list1); count = 0; // replace items foreach (var l in list2) col.AddItem(l); evt.WaitOne(); evt.Reset(); Assert.AreEqual(list2.Count, col.Count); CollectionAssert.AreEqual(col, list2); col.Dispose(); }
public override void Initialize([AllowNull] ViewWithData data) { base.Initialize(data); repositoryHost.ModelService.GetPullRequests(repository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); }
public override void Initialize([AllowNull] ViewWithData data) { base.Initialize(data); IsLoaded = false; PullRequests = repositoryHost.ModelService.GetPullRequests(repository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); pullRequests.OriginalCompleted .ObserveOn(RxApp.MainThreadScheduler) .Catch <System.Reactive.Unit, Octokit.AuthorizationException>(ex => { log.Info("Received AuthorizationException reading pull requests", ex); return(repositoryHost.LogOut()); }) .Catch <System.Reactive.Unit, Exception>(ex => { // Occurs on network error, when the repository was deleted on GitHub etc. log.Info("Received Exception reading pull requests", ex); return(Observable.Empty <System.Reactive.Unit>()); }) .Subscribe(_ => { if (listSettings.SelectedAuthor != null) { SelectedAuthor = Authors.FirstOrDefault(x => x.Login == listSettings.SelectedAuthor); } if (listSettings.SelectedAssignee != null) { SelectedAssignee = Assignees.FirstOrDefault(x => x.Login == listSettings.SelectedAssignee); } IsLoaded = true; UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor); }); }
public override void Initialize([AllowNull] ViewWithData data) { base.Initialize(data); IsLoaded = false; PullRequests = repositoryHost.ModelService.GetPullRequests(repository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); pullRequests.OriginalCompleted .ObserveOn(RxApp.MainThreadScheduler) .Catch <System.Reactive.Unit, Octokit.AuthorizationException>(ex => { // TODO: Do some decent logging here return(repositoryHost.LogOut()); }) .Catch <System.Reactive.Unit, Octokit.NotFoundException>(ex => { //this is caused when repository was deleted on github return(Observable.Empty <System.Reactive.Unit>()); }) .Subscribe(_ => { if (listSettings.SelectedAuthor != null) { SelectedAuthor = Authors.FirstOrDefault(x => x.Login == listSettings.SelectedAuthor); } if (listSettings.SelectedAssignee != null) { SelectedAssignee = Assignees.FirstOrDefault(x => x.Login == listSettings.SelectedAssignee); } IsLoaded = true; UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor); }); }
Task Load() { IsBusy = true; PullRequests = modelService.GetPullRequests(SelectedRepository, pullRequests); pullRequests.Subscribe(pr => { trackingAssignees.AddItem(pr.Assignee); trackingAuthors.AddItem(pr.Author); }, () => { }); pullRequests.OriginalCompleted .ObserveOn(RxApp.MainThreadScheduler) .Catch <System.Reactive.Unit, Exception>(ex => { // Occurs on network error, when the repository was deleted on GitHub etc. log.Error(ex, "Received Exception reading pull requests"); return(Observable.Empty <System.Reactive.Unit>()); }) .Subscribe(_ => { if (listSettings.SelectedAuthor != null) { SelectedAuthor = Authors.FirstOrDefault(x => x.Login == listSettings.SelectedAuthor); } if (listSettings.SelectedAssignee != null) { SelectedAssignee = Assignees.FirstOrDefault(x => x.Login == listSettings.SelectedAssignee); } IsBusy = false; UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor, SearchQuery); }); return(Task.CompletedTask); }
public void OrderByMatchesOriginalOrder() { var count = 0; var total = 1000; var list1 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, total - i, "Run 1")).ToList()); var list2 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, total - i, "Run 2")).ToList()); var col = new TrackingCollection<Thing>( list1.ToObservable(), OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare, (item, position, list) => item.Title.Equals("Run 2")); col.ProcessingDelay = TimeSpan.Zero; count = 0; var evt = new ManualResetEvent(false); col.Subscribe(t => { if (++count == list1.Count) evt.Set(); }, () => { }); evt.WaitOne(); evt.Reset(); Assert.AreEqual(total, count); Assert.AreEqual(0, col.Count); count = 0; // add new items foreach (var l in list2) col.AddItem(l); evt.WaitOne(); evt.Reset(); Assert.AreEqual(total, count); Assert.AreEqual(total, col.Count); CollectionAssert.AreEqual(col, list2); col.Dispose(); }
public void DisposingThrows() { var col = new TrackingCollection<Thing>(Observable.Empty<Thing>()); col.Dispose(); Assert.Throws<ObjectDisposedException>(() => col.SetFilter(null)); Assert.Throws<ObjectDisposedException>(() => col.SetComparer(null)); Assert.Throws<ObjectDisposedException>(() => col.Subscribe()); Assert.Throws<ObjectDisposedException>(() => col.AddItem(GetThing(1))); Assert.Throws<ObjectDisposedException>(() => col.RemoveItem(GetThing(1))); }
public void NoChangingAfterDisposed1() { var col = new TrackingCollection<Thing>(Observable.Never<Thing>(), OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare); col.Dispose(); Assert.Throws<ObjectDisposedException>(() => col.AddItem(new Thing())); }
public void CopyFromDoesNotLoseAvatar() { var userImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png"); var orgImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_org_avatar.png"); var initialBitmapImageSubject = new Subject <BitmapImage>(); var collectionEvent = new ManualResetEvent(false); var avatarPropertyEvent = new ManualResetEvent(false); //Creating an initial account with an observable that returns immediately const string login = "******"; const int initialOwnedPrivateRepositoryCount = 1; var initialAccount = new Account(login, true, false, initialOwnedPrivateRepositoryCount, 0, initialBitmapImageSubject); //Creating the test collection var col = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); col.Subscribe(account => { collectionEvent.Set(); }, () => { }); //Adding that account to the TrackingCollection col.AddItem(initialAccount); //Waiting for the collection add the item collectionEvent.WaitOne(); collectionEvent.Reset(); //Checking some initial properties Assert.That(login, Is.EqualTo(col[0].Login)); Assert.That(initialOwnedPrivateRepositoryCount, Is.EqualTo(col[0].OwnedPrivateRepos)); //Demonstrating that the avatar is not yet present Assert.That(col[0].Avatar, Is.Null); //Adding a listener to check for the changing of the Avatar property initialAccount.Changed.Subscribe(args => { if (args.PropertyName == "Avatar") { avatarPropertyEvent.Set(); } }); //Providing the first avatar initialBitmapImageSubject.OnNext(userImage); initialBitmapImageSubject.OnCompleted(); //Waiting for the avatar to be added avatarPropertyEvent.WaitOne(); avatarPropertyEvent.Reset(); //Demonstrating that the avatar is present Assert.That(col[0].Avatar, Is.Not.Null); Assert.True(BitmapSourcesAreEqual(col[0].Avatar, userImage)); Assert.False(BitmapSourcesAreEqual(col[0].Avatar, orgImage)); //Creating an account update const int updatedOwnedPrivateRepositoryCount = 2; var updatedBitmapImageSubject = new Subject <BitmapImage>(); var updatedAccount = new Account(login, true, false, updatedOwnedPrivateRepositoryCount, 0, updatedBitmapImageSubject); //Updating the account in the collection col.AddItem(updatedAccount); //Waiting for the collection to process the update collectionEvent.WaitOne(); collectionEvent.Reset(); //Providing the second avatar updatedBitmapImageSubject.OnNext(orgImage); updatedBitmapImageSubject.OnCompleted(); //Waiting for the delayed bitmap image observable avatarPropertyEvent.WaitOne(); avatarPropertyEvent.Reset(); //Login is the id, so that should be the same Assert.That(login, Is.EqualTo(col[0].Login)); //CopyFrom() should have updated this field Assert.That(updatedOwnedPrivateRepositoryCount, Is.EqualTo(col[0].OwnedPrivateRepos)); //CopyFrom() should not cause a race condition here Assert.That(col[0].Avatar, Is.Not.Null); Assert.True(BitmapSourcesAreEqual(col[0].Avatar, orgImage)); Assert.False(BitmapSourcesAreEqual(col[0].Avatar, userImage)); }
public void OnlyTimesEqualOrHigherThan3Minutes() { var count = 6; var list1 = new List<Thing>(Enumerable.Range(1, count).Select(i => GetThing(i, i, count - i, "Run 1")).ToList()); var col = new TrackingCollection<Thing>( Observable.Never<Thing>(), OrderedComparer<Thing>.OrderBy(x => x.UpdatedAt).Compare, (item, position, list) => item.UpdatedAt >= Now + TimeSpan.FromMinutes(3) && item.UpdatedAt <= Now + TimeSpan.FromMinutes(5)); col.ProcessingDelay = TimeSpan.Zero; var evt = new ManualResetEvent(false); col.Subscribe(t => { if (++count == list1.Count) evt.Set(); }, () => { }); count = 0; // add first items foreach (var l in list1) col.AddItem(l); evt.WaitOne(); evt.Reset(); Assert.AreEqual(3, col.Count); #if DEBUG CollectionAssert.AreEqual(list1.Reverse<Thing>(), col.DebugInternalList); #endif CollectionAssert.AreEqual(col, new List<Thing>() { list1[2], list1[1], list1[0] }); col.Dispose(); }
public void OrderByDoesntMatchOriginalOrderTimings() { var count = 0; var total = 1000; var list1 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, i, "Run 1")).ToList()); var list2 = new List<Thing>(Enumerable.Range(1, total).Select(i => GetThing(i, i, i, "Run 2")).ToList()); ITrackingCollection<Thing> col = new TrackingCollection<Thing>( list1.ToObservable(), OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare, (item, position, list) => item.Title.Equals("Run 2")); col.NewerComparer = OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare; col.ProcessingDelay = TimeSpan.Zero; var evt = new ManualResetEvent(false); var start = DateTimeOffset.UtcNow; col.Subscribe(t => { if (++count == list1.Count) evt.Set(); }, () => { }); evt.WaitOne(); var time = (DateTimeOffset.UtcNow - start).TotalMilliseconds; Assert.LessOrEqual(time, 100); evt.Reset(); Assert.AreEqual(total, count); Assert.AreEqual(0, col.Count); count = 0; start = DateTimeOffset.UtcNow; // add new items foreach (var l in list2) col.AddItem(l); evt.WaitOne(); time = (DateTimeOffset.UtcNow - start).TotalMilliseconds; Assert.LessOrEqual(time, 200); evt.Reset(); Assert.AreEqual(total, count); Assert.AreEqual(total, col.Count); CollectionAssert.AreEqual(col, list2.Reverse<Thing>()); col.Dispose(); }
public void CopyFromDoesNotLoseAvatar() { var userImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png"); var orgImage = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_org_avatar.png"); var initialBitmapImageSubject = new Subject<BitmapImage>(); var collectionEvent = new ManualResetEvent(false); var avatarPropertyEvent = new ManualResetEvent(false); //Creating an initial account with an observable that returns immediately const string login = "******"; const int initialOwnedPrivateRepositoryCount = 1; var initialAccount = new Account(login, true, false, initialOwnedPrivateRepositoryCount, 0, initialBitmapImageSubject); //Creating the test collection var col = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(), OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare); col.Subscribe(account => { collectionEvent.Set(); }, () => { }); //Adding that account to the TrackingCollection col.AddItem(initialAccount); //Waiting for the collection add the item collectionEvent.WaitOne(); collectionEvent.Reset(); //Checking some initial properties Assert.Equal(login, col[0].Login); Assert.Equal(initialOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos); //Demonstrating that the avatar is not yet present Assert.Null(col[0].Avatar); //Adding a listener to check for the changing of the Avatar property initialAccount.Changed.Subscribe(args => { if (args.PropertyName == "Avatar") { avatarPropertyEvent.Set(); } }); //Providing the first avatar initialBitmapImageSubject.OnNext(userImage); initialBitmapImageSubject.OnCompleted(); //Waiting for the avatar to be added avatarPropertyEvent.WaitOne(); avatarPropertyEvent.Reset(); //Demonstrating that the avatar is present Assert.NotNull(col[0].Avatar); Assert.True(BitmapSourcesAreEqual(col[0].Avatar, userImage)); Assert.False(BitmapSourcesAreEqual(col[0].Avatar, orgImage)); //Creating an account update const int updatedOwnedPrivateRepositoryCount = 2; var updatedBitmapImageSubject = new Subject<BitmapImage>(); var updatedAccount = new Account(login, true, false, updatedOwnedPrivateRepositoryCount, 0, updatedBitmapImageSubject); //Updating the account in the collection col.AddItem(updatedAccount); //Waiting for the collection to process the update collectionEvent.WaitOne(); collectionEvent.Reset(); //Providing the second avatar updatedBitmapImageSubject.OnNext(orgImage); updatedBitmapImageSubject.OnCompleted(); //Waiting for the delayed bitmap image observable avatarPropertyEvent.WaitOne(); avatarPropertyEvent.Reset(); //Login is the id, so that should be the same Assert.Equal(login, col[0].Login); //CopyFrom() should have updated this field Assert.Equal(updatedOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos); //CopyFrom() should not cause a race condition here Assert.NotNull(col[0].Avatar); Assert.True(BitmapSourcesAreEqual(col[0].Avatar, orgImage)); Assert.False(BitmapSourcesAreEqual(col[0].Avatar, userImage)); }
public void AddingWithNoObservableSetThrows() { ITrackingCollection<Thing> col = new TrackingCollection<Thing>(); Assert.Throws<InvalidOperationException>(() => col.AddItem(new Thing())); }
public void OnlyIndexes2To4() { var count = 6; var list1 = new List<Thing>(Enumerable.Range(1, count).Select(i => GetThing(i, i, count - i, "Run 1")).ToList()); ITrackingCollection<Thing> col = new TrackingCollection<Thing>( Observable.Never<Thing>(), OrderedComparer<Thing>.OrderBy(x => x.UpdatedAt).Compare, (item, position, list) => position >= 2 && position <= 4); col.NewerComparer = OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare; col.ProcessingDelay = TimeSpan.Zero; var evt = new ManualResetEvent(false); col.Subscribe(t => { if (++count == list1.Count) evt.Set(); }, () => { }); count = 0; // add first items foreach (var l in list1) col.AddItem(l); evt.WaitOne(); evt.Reset(); Assert.AreEqual(3, col.Count); #if DEBUG CollectionAssert.AreEqual(list1.Reverse<Thing>(), (col as TrackingCollection<Thing>).DebugInternalList); #endif CollectionAssert.AreEqual(col, new List<Thing>() { list1[3], list1[2], list1[1] }); col.Dispose(); }
public async void AddingBeforeSubscribingWorks() { ITrackingCollection<Thing> col = new TrackingCollection<Thing>(Observable.Empty<Thing>()); ReplaySubject<Thing> done = new ReplaySubject<Thing>(); col.AddItem(GetThing(1)); col.AddItem(GetThing(2)); var count = 0; done.OnNext(null); col.Subscribe(t => { done.OnNext(t); if (++count == 2) done.OnCompleted(); }, () => {}); await Observable.Timeout(done, TimeSpan.FromMilliseconds(500)); Assert.AreEqual(2, col.Count); }
public void DoesUpdateThingIfTimeIsNewer() { ITrackingCollection<Thing> col = new TrackingCollection<Thing>( Observable.Never<Thing>(), OrderedComparer<Thing>.OrderBy(x => x.UpdatedAt).Compare); col.NewerComparer = OrderedComparer<Thing>.OrderByDescending(x => x.UpdatedAt).Compare; col.ProcessingDelay = TimeSpan.Zero; var evt = new ManualResetEvent(false); col.Subscribe(t => { evt.Set(); }, () => { }); var createdAndUpdatedTime = DateTimeOffset.Now; var newerUpdateTime = createdAndUpdatedTime.Add(TimeSpan.FromMinutes(1)); const string originalTitle = "Original Thing"; var originalThing = new Thing(1, originalTitle, createdAndUpdatedTime, createdAndUpdatedTime); col.AddItem(originalThing); evt.WaitOne(); evt.Reset(); Assert.AreEqual(originalTitle, col[0].Title); const string updatedTitle = "Updated Thing"; var updatedThing = new Thing(1, updatedTitle, createdAndUpdatedTime, newerUpdateTime); col.AddItem(updatedThing); evt.WaitOne(); evt.Reset(); Assert.AreEqual(updatedTitle, col[0].Title); col.Dispose(); }
TrackingCollection<Thing> CreateSource() { var result = new TrackingCollection<Thing>(Observable.Empty<Thing>()); result.Subscribe(); result.AddItem(new Thing(1, "item1", DateTimeOffset.MinValue)); result.AddItem(new Thing(2, "item2", DateTimeOffset.MinValue)); result.AddItem(new Thing(3, "item3", DateTimeOffset.MinValue)); return result; }