diff --git a/src/NzbDrone.Api/Extensions/RequestExtensions.cs b/src/NzbDrone.Api/Extensions/RequestExtensions.cs index 3d0329522..02686deb6 100644 --- a/src/NzbDrone.Api/Extensions/RequestExtensions.cs +++ b/src/NzbDrone.Api/Extensions/RequestExtensions.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Nancy; namespace NzbDrone.Api.Extensions diff --git a/src/NzbDrone.Api/RootFolders/RootFolderModule.cs b/src/NzbDrone.Api/RootFolders/RootFolderModule.cs index dd346d5de..6691032d8 100644 --- a/src/NzbDrone.Api/RootFolders/RootFolderModule.cs +++ b/src/NzbDrone.Api/RootFolders/RootFolderModule.cs @@ -1,15 +1,17 @@ using System.Collections.Generic; +using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.RootFolders; using NzbDrone.Api.Mapping; using NzbDrone.Api.Validation; namespace NzbDrone.Api.RootFolders { - public class RootFolderModule : NzbDroneRestModule + public class RootFolderModule : NzbDroneRestModuleWithSignalR { private readonly IRootFolderService _rootFolderService; - public RootFolderModule(IRootFolderService rootFolderService) + public RootFolderModule(IRootFolderService rootFolderService, ICommandExecutor commandExecutor) + : base(commandExecutor) { _rootFolderService = rootFolderService; @@ -18,7 +20,7 @@ namespace NzbDrone.Api.RootFolders CreateResource = CreateRootFolder; DeleteResource = DeleteFolder; - SharedValidator.RuleFor(c=>c.Path).IsValidPath(); + SharedValidator.RuleFor(c => c.Path).IsValidPath(); } private RootFolderResource GetRootFolder(int id) diff --git a/src/NzbDrone.Core.Test/RootFolderTests/FreeSpaceOnDrivesFixture.cs b/src/NzbDrone.Core.Test/RootFolderTests/FreeSpaceOnDrivesFixture.cs index ec5ade721..f236c103f 100644 --- a/src/NzbDrone.Core.Test/RootFolderTests/FreeSpaceOnDrivesFixture.cs +++ b/src/NzbDrone.Core.Test/RootFolderTests/FreeSpaceOnDrivesFixture.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.RootFolderTests [Test] public void should_return_one_drive_when_only_one_root_dir_exists() { - Mocker.GetMock>() + Mocker.GetMock() .Setup(s => s.All()) .Returns(new List { new RootFolder { Id = 1, Path = @"C:\Test\TV" } }); @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.RootFolderTests [Test] public void should_return_one_drive_when_two_rootDirs_on_the_same_drive_exist() { - Mocker.GetMock>() + Mocker.GetMock() .Setup(s => s.All()) .Returns(new List { new RootFolder { Id = 1, Path = @"C:\Test\TV" }, new RootFolder { Id = 2, Path = @"C:\Test\TV2" }}); @@ -62,7 +62,7 @@ namespace NzbDrone.Core.Test.RootFolderTests [Test] public void should_return_two_drives_when_two_rootDirs_on_the_different_drive_exist() { - Mocker.GetMock>() + Mocker.GetMock() .Setup(s => s.All()) .Returns(new List { new RootFolder { Id = 1, Path = @"C:\Test\TV" }, new RootFolder { Id = 2, Path = @"D:\Test\TV" }}); @@ -87,7 +87,7 @@ namespace NzbDrone.Core.Test.RootFolderTests [Test] public void should_skip_rootDir_if_not_found_on_disk() { - Mocker.GetMock>() + Mocker.GetMock() .Setup(s => s.All()) .Returns(new List { new RootFolder { Id = 1, Path = @"C:\Test\TV" } }); diff --git a/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs b/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs index f2dbac44a..7e09f1519 100644 --- a/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs +++ b/src/NzbDrone.Core.Test/RootFolderTests/RootFolderServiceFixture.cs @@ -1,13 +1,10 @@ - - -using System; +using System; using System.Collections.Generic; using System.IO; using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common; -using NzbDrone.Core.Datastore; using NzbDrone.Core.RootFolders; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; @@ -25,7 +22,7 @@ namespace NzbDrone.Core.Test.RootFolderTests .Setup(m => m.FolderExists(It.IsAny())) .Returns(true); - Mocker.GetMock>() + Mocker.GetMock() .Setup(s => s.All()) .Returns(new List()); } @@ -45,7 +42,7 @@ namespace NzbDrone.Core.Test.RootFolderTests Subject.Add(root); - Mocker.GetMock>().Verify(c => c.Insert(root), Times.Once()); + Mocker.GetMock().Verify(c => c.Insert(root), Times.Once()); } [Test] @@ -60,7 +57,7 @@ namespace NzbDrone.Core.Test.RootFolderTests public void should_be_able_to_remove_root_dir() { Subject.Remove(1); - Mocker.GetMock>().Verify(c => c.Delete(1), Times.Once()); + Mocker.GetMock().Verify(c => c.Delete(1), Times.Once()); } [Test] @@ -68,7 +65,7 @@ namespace NzbDrone.Core.Test.RootFolderTests { WithNoneExistingFolder(); - Mocker.GetMock>().Setup(c => c.All()).Returns(new List()); + Mocker.GetMock().Setup(c => c.All()).Returns(new List()); const string path = "d:\\bad folder"; @@ -98,7 +95,7 @@ namespace NzbDrone.Core.Test.RootFolderTests [Test] public void adding_duplicated_root_folder_should_throw() { - Mocker.GetMock>().Setup(c => c.All()).Returns(new List { new RootFolder { Path = "C:\\TV".AsOsAgnostic() } }); + Mocker.GetMock().Setup(c => c.All()).Returns(new List { new RootFolder { Path = "C:\\TV".AsOsAgnostic() } }); Assert.Throws(() => Subject.Add(new RootFolder { Path = @"C:\TV".AsOsAgnostic() })); } diff --git a/src/NzbDrone.Core/Datastore/BasicRepository.cs b/src/NzbDrone.Core/Datastore/BasicRepository.cs index f3e35930f..f82a68354 100644 --- a/src/NzbDrone.Core/Datastore/BasicRepository.cs +++ b/src/NzbDrone.Core/Datastore/BasicRepository.cs @@ -116,6 +116,8 @@ namespace NzbDrone.Core.Datastore DataMapper.Insert(model); + ModelCreated(model); + return model; } @@ -127,12 +129,15 @@ namespace NzbDrone.Core.Datastore } DataMapper.Update(model, c => c.Id == model.Id); + + ModelUpdated(model); + return model; } public void Delete(TModel model) { - DataMapper.Delete(c => c.Id == model.Id); + Delete(model.Id); } public void InsertMany(IList models) @@ -199,6 +204,8 @@ namespace NzbDrone.Core.Datastore .ColumnsIncluding(properties) .Entity(model) .Execute(); + + ModelUpdated(model); } public virtual PagingSpec GetPaged(PagingSpec pagingSpec) diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index ad79bd8e7..1ff7e672d 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -436,6 +436,7 @@ + diff --git a/src/NzbDrone.Core/RootFolders/RootFolderRepository.cs b/src/NzbDrone.Core/RootFolders/RootFolderRepository.cs new file mode 100644 index 000000000..e15fa0bd3 --- /dev/null +++ b/src/NzbDrone.Core/RootFolders/RootFolderRepository.cs @@ -0,0 +1,27 @@ +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Messaging.Events; + +namespace NzbDrone.Core.RootFolders +{ + public interface IRootFolderRepository : IBasicRepository + { + + } + + public class RootFolderRepository : BasicRepository, IRootFolderRepository + { + + public RootFolderRepository(IDatabase database, IEventAggregator eventAggregator) + : base(database, eventAggregator) + { + } + + protected override bool PublishModelEvents + { + get + { + return true; + } + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/RootFolders/RootFolderService.cs b/src/NzbDrone.Core/RootFolders/RootFolderService.cs index c507b9ef6..fe5be8169 100644 --- a/src/NzbDrone.Core/RootFolders/RootFolderService.cs +++ b/src/NzbDrone.Core/RootFolders/RootFolderService.cs @@ -25,7 +25,7 @@ namespace NzbDrone.Core.RootFolders public class RootFolderService : IRootFolderService { private static readonly Logger Logger = NzbDroneLogger.GetLogger(); - private readonly IBasicRepository _rootFolderRepository; + private readonly IRootFolderRepository _rootFolderRepository; private readonly IDiskProvider _diskProvider; private readonly ISeriesRepository _seriesRepository; private readonly IConfigService _configService; @@ -33,7 +33,7 @@ namespace NzbDrone.Core.RootFolders private static readonly HashSet SpecialFolders = new HashSet { "$recycle.bin", "system volume information", "recycler", "lost+found" }; - public RootFolderService(IBasicRepository rootFolderRepository, + public RootFolderService(IRootFolderRepository rootFolderRepository, IDiskProvider diskProvider, ISeriesRepository seriesRepository, IConfigService configService) diff --git a/src/NzbDrone.Host/MainAppContainerBuilder.cs b/src/NzbDrone.Host/MainAppContainerBuilder.cs index 299de7925..cbb9778c1 100644 --- a/src/NzbDrone.Host/MainAppContainerBuilder.cs +++ b/src/NzbDrone.Host/MainAppContainerBuilder.cs @@ -22,7 +22,6 @@ namespace NzbDrone.Host AutoRegisterImplementations(); - Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); Container.Register(); diff --git a/src/NzbDrone.Integration.Test/IntegrationTest.cs b/src/NzbDrone.Integration.Test/IntegrationTest.cs index 7442e7b0c..b0908e008 100644 --- a/src/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/src/NzbDrone.Integration.Test/IntegrationTest.cs @@ -1,4 +1,9 @@ -using NLog; +using System; +using System.Collections.Generic; +using System.Threading; +using Microsoft.AspNet.SignalR.Client; +using Microsoft.AspNet.SignalR.Client.Transports; +using NLog; using NLog.Config; using NLog.Targets; using NUnit.Framework; @@ -7,7 +12,9 @@ using NzbDrone.Api.Config; using NzbDrone.Api.History; using NzbDrone.Api.RootFolders; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Serializer; using NzbDrone.Integration.Test.Client; +using NzbDrone.SignalR; using NzbDrone.Test.Common; using NzbDrone.Test.Common.Categories; using RestSharp; @@ -30,6 +37,16 @@ namespace NzbDrone.Integration.Test protected ClientBase NamingConfig; private NzbDroneRunner _runner; + private List _signalRReceived; + private Connection _signalrConnection; + + protected IEnumerable SignalRMessages + { + get + { + return _signalRReceived; + } + } public IntegrationTest() { @@ -71,5 +88,48 @@ namespace NzbDrone.Integration.Test { _runner.KillAll(); } + + [TearDown] + public void IntegrationSetup() + { + if (_signalrConnection != null) + { + switch (_signalrConnection.State) + { + case ConnectionState.Connected: + case ConnectionState.Connecting: + { + _signalrConnection.Stop(); + break; + } + } + + _signalrConnection = null; + _signalRReceived = new List(); + } + } + + protected void ConnectSignalR() + { + _signalRReceived = new List(); + _signalrConnection = new Connection("http://localhost:8989/signalr"); + _signalrConnection.Start(new LongPollingTransport()).ContinueWith(task => + { + if (task.IsFaulted) + { + Assert.Fail("SignalrConnection failed. {0}", task.Exception.GetBaseException()); + } + }); + + + while (_signalrConnection.State != ConnectionState.Connected) + { + Console.WriteLine("Connecting to signalR" + _signalrConnection.State); + Thread.Sleep(200); + } + + _signalrConnection.Received += json => _signalRReceived.Add(Json.Deserialize(json)); ; + } + } } diff --git a/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index cfbad6bf6..e687d8621 100644 --- a/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -41,9 +41,9 @@ False ..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll - + False - ..\packages\Microsoft.AspNet.SignalR.Client.2.0.0\lib\net40\Microsoft.AspNet.SignalR.Client.dll + ..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll False @@ -138,6 +138,10 @@ {95C11A9E-56ED-456A-8447-2C89C1139266} NzbDrone.Host + + {7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36} + NzbDrone.SignalR + {CADDFCE0-7509-4430-8364-2074E1EEFCA2} NzbDrone.Test.Common diff --git a/src/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs b/src/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs index 0b7647fdf..c7984e940 100644 --- a/src/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs +++ b/src/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using FluentAssertions; -using Microsoft.AspNet.SignalR.Client; -using Microsoft.AspNet.SignalR.Client.Transports; using NUnit.Framework; using NzbDrone.Api.RootFolders; @@ -11,39 +8,25 @@ namespace NzbDrone.Integration.Test [TestFixture] public class RootFolderIntegrationTest : IntegrationTest { - private Connection _connection; - private List _signalRReceived; - [SetUp] - public void Setup() - { - _signalRReceived = new List(); - _connection = new Connection("http://localhost:8989/signalr/rootfolder"); - _connection.Start(new LongPollingTransport()).ContinueWith(task => - { - if (task.IsFaulted) - { - Assert.Fail("SignalrConnection failed. {0}", task.Exception.GetBaseException()); - } - }); - _connection.Received += _connection_Received; - } - private void _connection_Received(string obj) + [Test] + public void should_have_no_root_folder_initially() { - _signalRReceived.Add(obj); + RootFolders.All().Should().BeEmpty(); } [Test] - public void should_have_no_root_folder_initially() + public void should_add_and_delete_root_folders() { - RootFolders.All().Should().BeEmpty(); + + ConnectSignalR(); var rootFolder = new RootFolderResource - { - Path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) - }; + { + Path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + }; var postResponse = RootFolders.Post(rootFolder); @@ -56,6 +39,11 @@ namespace NzbDrone.Integration.Test RootFolders.Delete(postResponse.Id); RootFolders.All().Should().BeEmpty(); + + + SignalRMessages.Should().Contain(c => c.Name == "rootfolder"); + + } [Test] diff --git a/src/NzbDrone.Integration.Test/packages.config b/src/NzbDrone.Integration.Test/packages.config index cb7bb6120..c106593b4 100644 --- a/src/NzbDrone.Integration.Test/packages.config +++ b/src/NzbDrone.Integration.Test/packages.config @@ -2,7 +2,7 @@ - +