Skip to content

Commit

Permalink
Merge pull request #6 from vgertman/enrollment
Browse files Browse the repository at this point in the history
Refactor and add tests
  • Loading branch information
ashokgelal authored Apr 26, 2017
2 parents 3cfc585 + 334f76b commit fd29578
Show file tree
Hide file tree
Showing 25 changed files with 511 additions and 28 deletions.
3 changes: 3 additions & 0 deletions src/Magpie/Magpie.Example/Magpie.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
<Name>Magpie</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="magpie.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
4 changes: 2 additions & 2 deletions src/Magpie/Magpie.Example/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ private void ForceCheck_OnClick(object sender, RoutedEventArgs e)

private static AppInfo MakeAppInfo(int id)
{
var appInfo = new AppInfo("https://dl.dropbox.com/s/j6i7s64ooice8rt/appcast.json", id);
appInfo.SetAppIcon("Magpie.Example", "logo64x64.tiff");
var appInfo = new AppInfo("https://dl.dropbox.com/s/byii1f3d7qqliwx/appcast_email_enrollment.json?dl=0", id);
appInfo.SetAppIcon("MagpieExample", "magpie.png");
return appInfo;
}

Expand Down
Binary file added src/Magpie/Magpie.Example/magpie.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/Magpie/Magpie.Tests/Magpie.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<Compile Include="Models\HelpersTest.cs" />
<Compile Include="Services\MagpieTest.cs" />
<Compile Include="Services\UpdateDeciderTest.cs" />
<Compile Include="ViewModels\EnrollmentViewModelTest.cs" />
<Compile Include="ViewModels\MainWindowViewModelTest.cs" />
<Compile Include="Mocks\MockMagpie.cs" />
<Compile Include="Mocks\MockMainWindowViewModel.cs" />
Expand Down
4 changes: 3 additions & 1 deletion src/Magpie/Magpie.Tests/Mocks/MockChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ namespace Magpie.Tests.Mocks
{
internal class MockChannel : Channel
{
internal MockChannel(int id, string version = null)
internal MockChannel(int id, string version = null, string build = null, string enrollmentEula = null)
{
Id = id;
if (version != null)
{
Version = new Version(version);
}
Build = build;
EnrollmentEulaUrl = enrollmentEula;
}

internal void SetArtifactUrl(string url)
Expand Down
16 changes: 13 additions & 3 deletions src/Magpie/Magpie.Tests/Mocks/MockMagpie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ namespace Magpie.Tests.Mocks
internal class MockMagpie : MagpieUpdater.Services.Magpie
{
private readonly string VALID_JSON =
@"{'foo': 'bar', 'channels': [{ 'id': 2, 'version': '5.8.8', 'release_notes_url': 'release_notes_url_http', 'artifact_url': 'artifact_url_http', 'build_date': '01/28/2017'}, { 'id': 3, 'version': '6.8.8', 'release_notes_url': 'release_notes_url_http', 'artifact_url': 'artifact_url_http', 'build_date': '01/28/2017'}]}"
@"{'foo': 'bar', 'channels': [{ 'id': 2, 'version': '5.8.8', 'release_notes_url': 'release_notes_url_http', 'artifact_url': 'artifact_url_http', 'build_date': '01/28/2017'}, { 'id': 3, 'version': '6.8.8', 'release_notes_url': 'release_notes_url_http', 'artifact_url': 'artifact_url_http', 'build_date': '01/28/2017'}, { 'id': 4, 'version': '7.8.8', 'release_notes_url': 'release_notes_url_http', 'artifact_url': 'artifact_url_http', 'build_date': '01/28/2017', 'requires_enrollment': 'true', 'enrollment_eula_url': 'enrollment_url'}]}"
.MakeJson();


internal RemoteAppcast RemoteAppcast { get; private set; }
internal bool _showUpdateWindowFlag;
internal bool _showNoUpdatesWindowFlag;
internal IRemoteContentDownloader _remoteContentDownloader;
internal bool _showEnrollmentWindow;
internal Enrollment _enrollmentToReturn;

public MockMagpie(string validUrl, IDebuggingInfoLogger infoLogger = null)
: base(new AppInfo(validUrl), infoLogger)
public MockMagpie(string validUrl, IDebuggingInfoLogger infoLogger = null, IAnalyticsLogger analyticsLogger = null)
: base(new AppInfo(validUrl), infoLogger, analyticsLogger)
{
_remoteContentDownloader = Substitute.For<IRemoteContentDownloader>();
_remoteContentDownloader.DownloadStringContent(validUrl, Arg.Any<IDebuggingInfoLogger>()).Returns(Task.FromResult(VALID_JSON));
Expand Down Expand Up @@ -47,5 +50,12 @@ protected override void ShowNoUpdatesWindow()
protected override void ShowErrorWindow()
{
}

protected override void ShowEnrollmentWindow(Enrollment enrollment)
{
_showEnrollmentWindow = true;
enrollment.IsEnrolled = _enrollmentToReturn.IsEnrolled;
enrollment.Email = _enrollmentToReturn.Email;
}
}
}
96 changes: 95 additions & 1 deletion src/Magpie/Magpie.Tests/Services/MagpieTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ namespace Magpie.Tests.Services
public class MagpieTest
{
private MockMagpie _mockMagpie;
private IAnalyticsLogger _analyticsLogger;

[TestInitialize]
public void Initialize()
{
AssemblyInjector.Inject();
_mockMagpie = new MockMagpie("validContentUrl");
_analyticsLogger = Substitute.For<IAnalyticsLogger>();
_mockMagpie = new MockMagpie("validContentUrl", analyticsLogger: _analyticsLogger);
}

[TestMethod]
Expand Down Expand Up @@ -109,5 +111,97 @@ public void SwitchingSubscribedThenCallingForceUpdateChecksNewChannel()
_mockMagpie.ForceCheckInBackground();
updateDecider.Received(2).ShouldUpdate(Arg.Is<Channel>(e => e.Id == 3), true);
}

[TestMethod]
public void SwitchingToChannelThatDoesNotRequireEnrollment_ChecksForUpdates()
{
var updateDecider = Substitute.For<UpdateDecider>(new DebuggingWindowViewModel());
updateDecider.ShouldUpdate(Arg.Any<Channel>(), true).Returns(false);
_mockMagpie.UpdateDecider = updateDecider;
_mockMagpie.SwitchSubscribedChannel(3);

Assert.IsFalse(_mockMagpie._showEnrollmentWindow);
updateDecider.Received(1).ShouldUpdate(Arg.Is<Channel>(e => e.Id == 3), true);
}

[TestMethod]
public void SwitchingToChannelThatRequiresEnrollment_ShowsEnrollmentWindow()
{
_mockMagpie.SwitchSubscribedChannel(4);
Assert.IsTrue(_mockMagpie._showEnrollmentWindow);
}

[TestMethod]
public void SwitchingChannel_FailingToEnroll_DoesNotCheckForUpdates()
{
var updateDecider = Substitute.For<UpdateDecider>(new DebuggingWindowViewModel());
_mockMagpie.UpdateDecider = updateDecider;
_mockMagpie._enrollmentToReturn = new Enrollment(new Channel()){IsEnrolled = false};
_mockMagpie.SwitchSubscribedChannel(4);

Assert.IsTrue(_mockMagpie._showEnrollmentWindow);
updateDecider.DidNotReceive().ShouldUpdate(Arg.Any<Channel>(), Arg.Any<bool>());
}

[TestMethod]
public void SwitchingChannel_SuccessfullyEnrolled_CheckForUpdates()
{
var updateDecider = Substitute.For<UpdateDecider>(new DebuggingWindowViewModel());
_mockMagpie.UpdateDecider = updateDecider;
updateDecider.ShouldUpdate(Arg.Any<Channel>(), true).Returns(false);
_mockMagpie._enrollmentToReturn = new Enrollment(new Channel()) { IsEnrolled = true };
_mockMagpie.SwitchSubscribedChannel(4);

Assert.IsTrue(_mockMagpie._showEnrollmentWindow);
updateDecider.Received(1).ShouldUpdate(Arg.Is<Channel>(e => e.Id == 4), true);
}

[TestMethod]
public void SwitchingChannel_LogsEnrollment()
{
_mockMagpie.SwitchSubscribedChannel(3);
_analyticsLogger.Received(1).LogEnrollment(Arg.Any<Enrollment>());
}

[TestMethod]
public void SwitchingChannel_EnrollmentAvailableEventGetsFired()
{
var raised = false;
_mockMagpie.EnrollmentAvailableEvent += (s, a) => { raised = true; };
_mockMagpie.SwitchSubscribedChannel(3);
Assert.IsTrue(raised);
}

[TestMethod]
public void SwitchingChannel_SuccessfullyEnrolled_UpdatesSubscribedChannel()
{
var updateDecider = Substitute.For<UpdateDecider>(new DebuggingWindowViewModel());
_mockMagpie.UpdateDecider = updateDecider;
updateDecider.ShouldUpdate(Arg.Any<Channel>(), true).Returns(false);
_mockMagpie._enrollmentToReturn = new Enrollment(new Channel()) { IsEnrolled = true };
_mockMagpie.SwitchSubscribedChannel(4);

Assert.AreEqual(4, _mockMagpie.AppInfo.SubscribedChannel);
}

[TestMethod]
public void SwitchingChannel_FailingToEnroll_DoesNotUpdateSubscribedChannel()
{
_mockMagpie._enrollmentToReturn = new Enrollment(new Channel()) { IsEnrolled = false };
_mockMagpie.SwitchSubscribedChannel(4);

Assert.AreNotEqual(4, _mockMagpie.AppInfo.SubscribedChannel);
}

[TestMethod]
public void SwitchingToChannelThatDoesNotRequireEnrollment_UpdatesSubscribedChannel()
{
var updateDecider = Substitute.For<UpdateDecider>(new DebuggingWindowViewModel());
updateDecider.ShouldUpdate(Arg.Any<Channel>(), true).Returns(false);
_mockMagpie.UpdateDecider = updateDecider;
_mockMagpie.SwitchSubscribedChannel(3);

Assert.AreEqual(3, _mockMagpie.AppInfo.SubscribedChannel);
}
}
}
63 changes: 63 additions & 0 deletions src/Magpie/Magpie.Tests/ViewModels/EnrollmentViewModelTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Magpie.Tests.Mocks;
using MagpieUpdater.Models;
using MagpieUpdater.Services;
using MagpieUpdater.ViewModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Magpie.Tests.ViewModels
{
[TestClass]
public class EnrollmentViewModelTest
{
[TestMethod]
public void PropertiesAreInitializedCorrectly()
{
var channel = new MockChannel(1, build: "Test Build", enrollmentEula: "www.example.com");
var enrollment = new Enrollment(channel);
var appInfo = new AppInfo("testString") {AppIconPath = "iconPath"};
var sut = new EnrollmentViewModel(enrollment, appInfo);
Assert.AreEqual("Test Build", sut.ChannelName);
Assert.AreEqual("www.example.com", sut.EnrollmentEulaUrl);
Assert.AreEqual("iconPath", sut.AppIconPath);
}

[TestMethod]
public void CanNotEnrollWithInvalidEmail()
{
var sut = new EnrollmentViewModel(new Enrollment(new Channel()), new AppInfo("testString"))
{
EmailAddress = "test"
};
Assert.IsFalse(sut.EnrollCommand.CanExecute(null));
sut.EmailAddress = null;
Assert.IsFalse(sut.EnrollCommand.CanExecute(null));
sut.EmailAddress = string.Empty;
Assert.IsFalse(sut.EnrollCommand.CanExecute(null));
sut.EmailAddress = "test@";
Assert.IsFalse(sut.EnrollCommand.CanExecute(null));
}

[TestMethod]
public void CanEnrollWithValidEmail()
{
var sut = new EnrollmentViewModel(new Enrollment(new Channel()), new AppInfo("testString"))
{
EmailAddress = "[email protected]"
};
Assert.IsTrue(sut.EnrollCommand.CanExecute(null));
}

[TestMethod]
public void ExecuteEnrollCommand_FillsInEnrollment()
{
var enrollment = new Enrollment(new Channel());
var sut = new EnrollmentViewModel(enrollment, new AppInfo("testString"))
{
EmailAddress = "[email protected]"
};
sut.EnrollCommand.Execute(null);
Assert.IsTrue(enrollment.IsEnrolled);
Assert.AreEqual("[email protected]", enrollment.Email);
}
}
}
Binary file modified src/Magpie/Magpie.latest.nupkg
Binary file not shown.
8 changes: 7 additions & 1 deletion src/Magpie/Magpie/Interfaces/IAnalyticsLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,14 @@ public interface IAnalyticsLogger

/// <summary>
/// Log analytics when update is available.
/// <param name="channel">Channel that has the latest update available.</param>
/// <param name="channel">Channel that has the latest update available</param>
/// </summary>
void LogUpdateAvailable(Channel channel);

/// <summary>
/// Log enrollment status.
/// </summary>
/// <param name="enrollment">Enrollment status</param>
void LogEnrollment(Enrollment enrollment);
}
}
13 changes: 13 additions & 0 deletions src/Magpie/Magpie/Magpie.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@
<Compile Include="Services\AnalyticsLogger.cs" />
<Compile Include="Services\AppInfo.cs" />
<Compile Include="Services\AssemblyAccessor.cs" />
<Compile Include="Services\CheckState.cs" />
<Compile Include="Services\DefaultRemoteContentDownloader.cs" />
<Compile Include="Services\MainAssembly.cs" />
<Compile Include="Services\SignatureVerifier.cs" />
<Compile Include="Models\Enrollment.cs" />
<Compile Include="ViewModels\DownloadWindowViewModel.cs" />
<Compile Include="Services\Helpers.cs" />
<Compile Include="Services\MagicStrings.cs" />
Expand All @@ -81,9 +83,13 @@
<Compile Include="ViewModels\DelegateCommand.cs" />
<Compile Include="ViewModels\MainWindowViewModel.cs" />
<Compile Include="ViewModels\SignatureVerificationWindowViewModel.cs" />
<Compile Include="ViewModels\EnrollmentViewModel.cs" />
<Compile Include="Views\DownloadWindow.xaml.cs">
<DependentUpon>DownloadWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\EnrollmentWindow.xaml.cs">
<DependentUpon>EnrollmentWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ErrorWindow.xaml.cs">
<DependentUpon>ErrorWindow.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -138,6 +144,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\EnrollmentWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ErrorWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand All @@ -164,6 +174,9 @@
<ItemGroup>
<Resource Include="Resources\download.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\mail.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
8 changes: 7 additions & 1 deletion src/Magpie/Magpie/Models/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class Channel
public int Id { get; protected set; }

[DataMember(Name = "build", IsRequired = false)]
public string Build { get; private set; }
public string Build { get; protected set; }

[DataMember(Name = "version", IsRequired = true)] private string _version;
public Version Version { get; protected set; }
Expand All @@ -27,6 +27,12 @@ public class Channel
[DataMember(Name = "dsa_signature", IsRequired = false)]
public string DSASignature { get; private set; }

[DataMember(Name = "requires_enrollment", IsRequired = false)]
public bool RequiresEnrollment { get; private set; }

[DataMember(Name = "enrollment_eula_url", IsRequired = false)]
public string EnrollmentEulaUrl { get; protected set; }

// Dates example:
// e.g. January 30, 2015 18:15:00 +0200
// 10/03/2015
Expand Down
15 changes: 15 additions & 0 deletions src/Magpie/Magpie/Models/Enrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace MagpieUpdater.Models
{
public class Enrollment
{
public Channel Channel { get; private set; }
public bool IsRequired { get; internal set; }
public bool IsEnrolled { get; internal set; }
public string Email { get; internal set; }

public Enrollment(Channel channel)
{
Channel = channel;
}
}
}
4 changes: 4 additions & 0 deletions src/Magpie/Magpie/Resources/Strings.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@
<system:String x:Key="_downloadNow">Download Now</system:String>
<system:String x:Key="_skipVersion">Skip this Version</system:String>
<system:String x:Key="_remindMeLater">Remind Me Later</system:String>
<system:String x:Key="_dontEnroll">I don't want to</system:String>
<system:String x:Key="_enroll">I don't want to</system:String>
<system:String x:Key="_enrollMsg">Please provide your email address to join the {0} Program</system:String>
<system:String x:Key="_eulaMsg" xml:space="preserve">By enrolling in this program you agree with our </system:String>
</ResourceDictionary>
Loading

0 comments on commit fd29578

Please sign in to comment.