Permalink
Browse files

refactored out timer bits, added tests and updated build step

  • Loading branch information...
shiftbot committed Feb 18, 2012
1 parent 016b247 commit 0e3171cbc371a2f33df214a3fb17cfb583051816
View
@@ -1,7 +1,7 @@
-@echo Off
-set config=%1
-if "%config%" == "" (
- set config=Debug
-)
-
-%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.proj /p:Configuration="%config%" /t:AppHarbor /m /v:M /fl /flp:LogFile=msbuild.log;Verbosity=Normal /nr:false
+@echo Off
+set config=%1
+if "%config%" == "" (
+ set config=Debug
+)
+
+%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild build.proj /p:Configuration="%config%" /t:package /m /v:M /fl /flp:LogFile=msbuild.log;Verbosity=Normal /nr:false
View
@@ -7,4 +7,43 @@
<MSBuild Projects="./src/Carnac.sln" Properties="Configuration=$(Configuration)" />
</Target>
+ <Target Name="Test" DependsOnTargets="Compile">
+
+ <Message Text="===========Tests===========" Importance="High" />
+
+ <ItemGroup>
+ <TestFiles Include=".\**\bin\$(Configuration)\*Tests.dll" />
+ </ItemGroup>
+
+ <xunit Assembly="@(TestFiles)" />
+ </Target>
+
+ <Target Name="Package" DependsOnTargets="Test">
+
+ <!-- workaround from http://stackoverflow.com/a/5650767-->
+ <PropertyGroup>
+ <!--MSBuild 4.0 property-->
+ <ProgramFiles32>$(MSBuildProgramFiles32)</ProgramFiles32>
+ <!--Use OS env vars as a fallback-->
+ <ProgramFiles32 Condition=" '' == '$(ProgramFiles32)'">$(ProgramFiles%28x86%29)</ProgramFiles32>
+ <ProgramFiles32 Condition=" '' == '$(ProgramFiles32)' ">$(ProgramFiles)</ProgramFiles32>
+</PropertyGroup>
+
+ <PropertyGroup>
+ <MainAssembly>.\src\Carnac\bin\$(Configuration)\Carnac.Merged.exe</MainAssembly>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <IntermediateAssembly Include=".\src\Carnac\bin\$(Configuration)\Carnac.exe" />
+ <AssembliesToMerge Include=".\src\Carnac\bin\$(Configuration)\*.dll" />
+ <Internalize Include=".\src\Carnac\bin\$(Configuration)\*.dll" />
+ </ItemGroup>
+
+ <Message Text="===========ILMerge===========" Importance="High" />
+
+ <exec command=".\tools\Ilmerge\ILMerge.exe /allowDup /out:$(MainAssembly) /targetplatform:v4,&quot;$(ProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0&quot; &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
+
+ </Target>
+
+
</Project>
@@ -33,6 +33,12 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="Caliburn.Micro">
+ <HintPath>..\packages\Caliburn.Micro.1.3.1\lib\net40\Caliburn.Micro.dll</HintPath>
+ </Reference>
+ <Reference Include="NSubstitute">
+ <HintPath>..\packages\NSubstitute.1.3.0.0\lib\NET40\NSubstitute.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Reactive">
@@ -51,6 +57,7 @@
<ItemGroup>
<Compile Include="ExampleTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ViewModels\ShellViewModelTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@@ -60,6 +67,10 @@
<Project>{614470A0-432C-46EB-B0EB-DE0A9062FC22}</Project>
<Name>Carnac.Logic</Name>
</ProjectReference>
+ <ProjectReference Include="..\Carnac\Carnac.csproj">
+ <Project>{3D54543F-9FF2-4298-A621-0C66A36412CD}</Project>
+ <Name>Carnac</Name>
+ </ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
@@ -0,0 +1,43 @@
+using System;
+using Analects.SettingsService;
+using Carnac.Logic;
+using Carnac.Models;
+using Carnac.Utilities;
+using Carnac.ViewModels;
+using NSubstitute;
+using Xunit;
+
+namespace Carnac.Tests.ViewModels
+{
+ public class ShellViewModelTests
+ {
+ readonly ISettingsService settingsService = Substitute.For<ISettingsService>();
+ readonly IScreenManager screenManager = Substitute.For<IScreenManager>();
+ readonly ITimerFactory timerFactory = Substitute.For<ITimerFactory>();
+ private ShellViewModel viewModel;
+
+ public ShellViewModelTests()
+ {
+ viewModel = new ShellViewModel(settingsService, screenManager, timerFactory);
+ }
+
+ [Fact]
+ public void Constructor_Always_StartsTimer()
+ {
+ timerFactory.Received().Start(1000, Arg.Any<Action>());
+ }
+
+ [Fact]
+ public void Constructor_Always_FetchesScreens()
+ {
+ screenManager.Received().GetScreens();
+ }
+
+ [Fact]
+ public void Constructor_Always_ChecksForSettings()
+ {
+ settingsService.Received().Get<Settings>("PopupSettings");
+ }
+
+ }
+}
@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="Rx-Main" version="1.0.11226" />
- <package id="xunit" version="1.9.0.1566" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NSubstitute" version="1.3.0.0" />
+ <package id="Rx-Main" version="1.0.11226" />
+ <package id="xunit" version="1.9.0.1566" />
</packages>
View
@@ -89,7 +89,10 @@
<Compile Include="KeyMonitor\HotKeyWinApi.cs" />
<Compile Include="Models\Settings.cs" />
<Compile Include="ReplaceKey.cs" />
+ <Compile Include="Utilities\ITimerFactory.cs" />
<Compile Include="Utilities\ProcessUtilities.cs" />
+ <Compile Include="Utilities\TimerFactory.cs" />
+ <Compile Include="Utilities\TimerState.cs" />
<Compile Include="ViewModels\KeyShowViewModel.cs" />
<Compile Include="Models\Message.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
@@ -132,7 +135,9 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
- <None Include="Analects\Loader\EmbedAssemblies.targets" />
+ <None Include="Analects\Loader\EmbedAssemblies.targets">
+ <SubType>Designer</SubType>
+ </None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@@ -160,14 +165,6 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
- <Import Project="Analects\Loader\EmbedAssemblies.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.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
<Target Name="AfterCompile">
<NotifyPropertyWeaverMsBuildTask.WeavingTask />
</Target>
@@ -0,0 +1,11 @@
+using System;
+using System.ComponentModel.Composition;
+
+namespace Carnac.Utilities
+{
+ [InheritedExport]
+ public interface ITimerFactory
+ {
+ IDisposable Start(int period, Action callback);
+ }
+}
@@ -0,0 +1,14 @@
+using System;
+
+namespace Carnac.Utilities
+{
+ public class TimerFactory : ITimerFactory
+ {
+ public IDisposable Start(int period, Action callback)
+ {
+ var timerState = new TimerState(period, callback);
+ timerState.Start();
+ return timerState;
+ }
+ }
+}
@@ -0,0 +1,38 @@
+using System;
+using System.Timers;
+using System.Windows;
+using System.Windows.Threading;
+
+namespace Carnac.Utilities
+{
+ public class TimerState : IDisposable
+ {
+ readonly Timer timer;
+ bool isDisposing;
+
+ public TimerState(int period, Action callback)
+ {
+ timer = new Timer(period);
+ timer.Elapsed +=
+ (s, e) =>
+ {
+ if (Application.Current == null || Application.Current.Dispatcher == null) return;
+ Application.Current.Dispatcher.BeginInvoke(callback, DispatcherPriority.Background, null);
+ };
+ }
+
+ public void Dispose()
+ {
+ if (isDisposing)
+ return;
+
+ isDisposing = true;
+ timer.Stop();
+ }
+
+ public void Start()
+ {
+ timer.Start();
+ }
+ }
+}
@@ -2,32 +2,33 @@
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
-using System.Threading;
-using System.Windows;
-using System.Windows.Threading;
using Analects.SettingsService;
using Caliburn.Micro;
using Carnac.Logic;
using Carnac.Logic.KeyMonitor;
using Carnac.Logic.Native;
using Carnac.Models;
+using Carnac.Utilities;
using Message = Carnac.Models.Message;
-using Timer = System.Timers.Timer;
namespace Carnac.ViewModels
{
[Export(typeof (IShell))]
public class ShellViewModel : Screen, IShell, IObserver<KeyPress>
{
IDisposable keySubscription;
+ readonly IDisposable timerToken;
readonly ISettingsService settingsService;
readonly TimeSpan fiveseconds = TimeSpan.FromSeconds(5);
readonly TimeSpan sixseconds = TimeSpan.FromSeconds(6);
-
+
[ImportingConstructor]
- public ShellViewModel(ISettingsService settingsService, IScreenManager screenManager)
+ public ShellViewModel(
+ ISettingsService settingsService,
+ IScreenManager screenManager,
+ ITimerFactory timerFactory)
{
this.settingsService = settingsService;
@@ -44,17 +45,7 @@ public ShellViewModel(ISettingsService settingsService, IScreenManager screenMan
var manager = new WindowManager();
manager.ShowWindow(new KeyShowViewModel(Keys, Settings));
- var timer = new Timer(1000);
- timer.Elapsed +=
- (s, e) =>
- {
- if (Application.Current == null || Application.Current.Dispatcher == null) return;
-
- Application.Current.Dispatcher.BeginInvoke((ThreadStart) (Cleanup),
- DispatcherPriority.Background, null);
- };
-
- timer.Start();
+ timerToken = timerFactory.Start(1000, Cleanup);
}
public ObservableCollection<Message> Keys { get; private set; }
@@ -92,6 +83,7 @@ protected override void OnActivate()
protected override void OnDeactivate(bool close)
{
keySubscription.Dispose();
+ timerToken.Dispose();
}
public void OnNext(KeyPress value)
Oops, something went wrong.

0 comments on commit 0e3171c

Please sign in to comment.