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

Commit d640ed4

Browse files
Stanley GoldmanStanleyGoldman
authored andcommitted
Fixing Account's CopyFrom
1 parent f4f8925 commit d640ed4

File tree

3 files changed

+110
-1
lines changed

3 files changed

+110
-1
lines changed

src/GitHub.App/Models/Account.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class Account : ReactiveObject, IAccount
1515
{
1616
BitmapSource avatar;
1717

18+
IObservable<BitmapSource> BitmapSource;
19+
private IDisposable _bitmapSourceSubscription;
1820
public Account(
1921
string login,
2022
bool isUser,
@@ -30,8 +32,10 @@ public Account(
3032
PrivateReposInPlan = privateRepositoryInPlanCount;
3133
IsOnFreePlan = privateRepositoryInPlanCount == 0;
3234
HasMaximumPrivateRepositories = OwnedPrivateRepos >= PrivateReposInPlan;
35+
BitmapSource = bitmapSource;
3336

34-
bitmapSource.ObserveOn(RxApp.MainThreadScheduler)
37+
_bitmapSourceSubscription = bitmapSource
38+
.ObserveOn(RxApp.MainThreadScheduler)
3539
.Subscribe(x => Avatar = x);
3640
}
3741

@@ -80,6 +84,16 @@ public void CopyFrom(IAccount other)
8084
IsOnFreePlan = other.IsOnFreePlan;
8185
HasMaximumPrivateRepositories = other.HasMaximumPrivateRepositories;
8286
Avatar = other.Avatar;
87+
88+
var otherAccount = other as Account;
89+
if (otherAccount != null)
90+
{
91+
_bitmapSourceSubscription.Dispose();
92+
93+
_bitmapSourceSubscription = otherAccount.BitmapSource
94+
.ObserveOn(RxApp.MainThreadScheduler)
95+
.Subscribe(x => Avatar = x);
96+
}
8397
}
8498

8599
public override bool Equals([AllowNull]object obj)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.Reactive.Linq;
3+
using System.Threading;
4+
using System.Windows.Media.Imaging;
5+
using GitHub.Collections;
6+
using GitHub.Models;
7+
using GitHub.Services;
8+
using ReactiveUI;
9+
using Xunit;
10+
11+
namespace UnitTests.GitHub.App.Models
12+
{
13+
public class AccountModelTests : TestBaseClass
14+
{
15+
[Fact]
16+
public void CopyFromDoesNotLoseAvatar()
17+
{
18+
//A function that will return this image in an observable after X seconds
19+
var image = AvatarProvider.CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png");
20+
Func<int, IObservable<BitmapImage>> generateObservable = seconds =>
21+
{
22+
return Observable.Generate(
23+
initialState: 0,
24+
condition: i => i < 1,
25+
iterate: state => state + 1,
26+
resultSelector: i => image,
27+
timeSelector: i => TimeSpan.FromSeconds(seconds));
28+
};
29+
30+
var evt = new ManualResetEvent(false);
31+
32+
//Creating an initial account with an observable that returns immediately
33+
const string login = "foo";
34+
const int initialOwnedPrivateRepositoryCount = 1;
35+
36+
var createdAt = DateTime.Now;
37+
var initialAccount = new Account(login, true, false, initialOwnedPrivateRepositoryCount, 0, generateObservable(0));
38+
39+
//Creating the test collection
40+
var col = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(), OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare);
41+
col.Subscribe(account =>
42+
{
43+
evt.Set();
44+
}, () => { });
45+
46+
//Adding that account to the TrackingCollection
47+
col.AddItem(initialAccount);
48+
49+
//Waiting for the collection add the item
50+
evt.WaitOne();
51+
evt.Reset();
52+
53+
//Checking some initial properties
54+
Assert.Equal(login, col[0].Login);
55+
Assert.Equal(initialOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos);
56+
57+
//Demonstrating that the avatar is present
58+
Assert.NotNull(col[0].Avatar);
59+
60+
//Creating an observable that will return in one second
61+
var updatedBitmapSourceObservable = generateObservable(1);
62+
63+
//Creating an account update with an observable
64+
const int updatedOwnedPrivateRepositoryCount = 2;
65+
66+
var updatedAccount = new Account(login, true, false, updatedOwnedPrivateRepositoryCount, 0, updatedBitmapSourceObservable);
67+
68+
//Updating the accout in the collection
69+
col.AddItem(updatedAccount);
70+
71+
//Waiting for the collection to process the update
72+
evt.WaitOne();
73+
evt.Reset();
74+
75+
updatedBitmapSourceObservable.Subscribe(bitmapImage =>
76+
{
77+
evt.Set();
78+
});
79+
80+
//Waiting for the delayed bitmap image observable
81+
evt.WaitOne();
82+
evt.Reset();
83+
84+
//Login is the id, so that should be the same
85+
Assert.Equal(login, col[0].Login);
86+
87+
//CopyFrom() should have updated this field
88+
Assert.Equal(updatedOwnedPrivateRepositoryCount, col[0].OwnedPrivateRepos);
89+
90+
//CopyFrom() should not cause a race condition here
91+
Assert.NotNull(col[0].Avatar);
92+
}
93+
}
94+
}

src/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
<Compile Include="GitHub.App\Caches\CredentialCacheTests.cs" />
161161
<Compile Include="GitHub.App\Caches\ImageCacheTests.cs" />
162162
<Compile Include="GitHub.App\Controllers\UIProviderTests.cs" />
163+
<Compile Include="GitHub.App\Models\AccountModelTests.cs" />
163164
<Compile Include="GitHub.App\Models\ModelServiceTests.cs" />
164165
<Compile Include="GitHub.App\Controllers\UIControllerTests.cs" />
165166
<Compile Include="GitHub.App\Models\PullRequestModelTests.cs" />

0 commit comments

Comments
 (0)