diff --git a/Filtration.Tests/Filtration.Tests.csproj b/Filtration.Tests/Filtration.Tests.csproj index cb218bd..042eb0d 100644 --- a/Filtration.Tests/Filtration.Tests.csproj +++ b/Filtration.Tests/Filtration.Tests.csproj @@ -50,6 +50,7 @@ + diff --git a/Filtration.Tests/Repositories/TestItemFilterScriptRepository.cs b/Filtration.Tests/Repositories/TestItemFilterScriptRepository.cs new file mode 100644 index 0000000..b73fae7 --- /dev/null +++ b/Filtration.Tests/Repositories/TestItemFilterScriptRepository.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Filtration.Repositories; +using Filtration.Services; +using Filtration.ViewModels; +using Moq; +using NUnit.Framework; + +namespace Filtration.Tests.Repositories +{ + [TestFixture] + public class TestItemFilterScriptRepository + { + [Test] + public void LoadScriptFromFile_CallsPersistenceServiceUsingPathAndReturnsViewModel() + { + // Arrange + var testInputPath = "C:\\TestPath.filter"; + + + var mockPersistenceService = new Mock(); + mockPersistenceService.Setup(p => p.LoadItemFilterScript(testInputPath)).Verifiable(); + + var mockItemFilterScriptViewModel = new Mock(); + + var mockItemFilterScriptViewModelFactory = new Mock(); + mockItemFilterScriptViewModelFactory.Setup(f => f.Create()).Returns(mockItemFilterScriptViewModel.Object); + + var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); + + // Act + var result = repository.LoadScriptFromFile(testInputPath); + + // Assert + mockPersistenceService.Verify(); + Assert.AreEqual(mockItemFilterScriptViewModel.Object, result); + } + + [Test] + public void LoadScriptFromFile_PersistenceServiceThrows_ThrowsIOException() + { + // Arrange + var testInputPath = "C:\\TestPath.filter"; + + var mockPersistenceService = new Mock(); + mockPersistenceService.Setup(p => p.LoadItemFilterScript(testInputPath)).Throws(); + + var mockItemFilterScriptViewModelFactory = new Mock(); + + var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); + + // Act + + // Assert + Assert.Throws(() => repository.LoadScriptFromFile(testInputPath)); + } + + [Test] + public void SetItemFilterScriptDirectory_CallsPersistenceServiceSetItemFilterScriptDirectory() + { + // Arrange + var testInputPath = "C:\\Test\\Path"; + + var mockPersistenceService = new Mock(); + mockPersistenceService.Setup(p => p.SetItemFilterScriptDirectory(testInputPath)).Verifiable(); + + var mockItemFilterScriptViewModelFactory = new Mock(); + + var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); + + // Act + repository.SetItemFilterScriptDirectory(testInputPath); + + // Assert + mockPersistenceService.Verify(); + } + + [Test] + public void GetItemFilterScriptDirectory_ReturnsItemFilterScriptDirectoryFromPersistenceService() + { + // Arrange + var testInputPath = "C:\\Test\\Path"; + + var mockPersistenceService = new Mock(); + mockPersistenceService.SetupGet(p => p.ItemFilterScriptDirectory).Returns(testInputPath).Verifiable(); + + var mockItemFilterScriptViewModelFactory = new Mock(); + + var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); + + // Act + string result = repository.GetItemFilterScriptDirectory(); + + // Assert + mockPersistenceService.Verify(); + Assert.AreEqual(result, testInputPath); + } + + [Test] + public void NewScript_ReturnsScriptFromViewModelFactory() + { + // Arrange + var mockPersistenceService = new Mock(); + + var mockItemFilterScriptViewModel = new Mock(); + + var mockItemFilterScriptViewModelFactory = new Mock(); + mockItemFilterScriptViewModelFactory.Setup(f => f.Create()).Returns(mockItemFilterScriptViewModel.Object); + + var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); + + // Act + IItemFilterScriptViewModel result = repository.NewScript(); + + // Assert + Assert.AreEqual(mockItemFilterScriptViewModel.Object, result); + } + } +} diff --git a/Filtration.Tests/Services/TestItemFilterPersistenceService.cs b/Filtration.Tests/Services/TestItemFilterPersistenceService.cs index 2261372..47073db 100644 --- a/Filtration.Tests/Services/TestItemFilterPersistenceService.cs +++ b/Filtration.Tests/Services/TestItemFilterPersistenceService.cs @@ -1,4 +1,5 @@ -using Filtration.Models; +using System.IO; +using Filtration.Models; using Filtration.Services; using Filtration.Translators; using Moq; @@ -79,5 +80,44 @@ namespace Filtration.Tests.Services // Assert mockFileSystemService.Verify(); } + + [Test] + public void SetItemFilterScriptDirectory_InvalidPath_ThrowsDirectoryNotFoundException() + { + // Arrange + var testInputPath = "C:\\Test\\Path"; + + var mockFileSystemService = new Mock(); + mockFileSystemService.Setup(f => f.DirectoryExists(testInputPath)).Returns(false).Verifiable(); + + var mockItemFilterScriptTranslator = new Mock(); + + var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object); + + // Act + + // Assert + Assert.Throws(() => service.SetItemFilterScriptDirectory(testInputPath)); + } + + [Test] + public void SetItemFilterScriptDirectory_ValidPath_SetsItemFilterScriptDirectory() + { + // Arrange + var testInputPath = "C:\\Test\\Path"; + + var mockFileSystemService = new Mock(); + mockFileSystemService.Setup(f => f.DirectoryExists(testInputPath)).Returns(true).Verifiable(); + + var mockItemFilterScriptTranslator = new Mock(); + + var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object); + + // Act + service.SetItemFilterScriptDirectory(testInputPath); + + // Assert + Assert.AreEqual(testInputPath, service.ItemFilterScriptDirectory); + } } } diff --git a/Filtration/Filtration.csproj b/Filtration/Filtration.csproj index 972a3d0..a40576d 100644 --- a/Filtration/Filtration.csproj +++ b/Filtration/Filtration.csproj @@ -167,6 +167,7 @@ + @@ -240,6 +241,7 @@ StartPageView.xaml + diff --git a/Filtration/Repositories/ItemFilterScriptRepository.cs b/Filtration/Repositories/ItemFilterScriptRepository.cs new file mode 100644 index 0000000..9aceccc --- /dev/null +++ b/Filtration/Repositories/ItemFilterScriptRepository.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Filtration.Models; +using Filtration.Services; +using Filtration.ViewModels; + +namespace Filtration.Repositories +{ + internal interface IItemFilterScriptRepository + { + IItemFilterScriptViewModel LoadScriptFromFile(string path); + IItemFilterScriptViewModel NewScript(); + string GetItemFilterScriptDirectory(); + void SetItemFilterScriptDirectory(string path); + } + + internal class ItemFilterScriptRepository : IItemFilterScriptRepository + { + private readonly IItemFilterPersistenceService _itemFilterPersistenceService; + private readonly IItemFilterScriptViewModelFactory _itemFilterScriptViewModelFactory; + //private List _itemFilterScripts; + + public ItemFilterScriptRepository(IItemFilterPersistenceService itemFilterPersistenceService, + IItemFilterScriptViewModelFactory itemFilterScriptViewModelFactory) + { + _itemFilterPersistenceService = itemFilterPersistenceService; + _itemFilterScriptViewModelFactory = itemFilterScriptViewModelFactory; + } + + public IItemFilterScriptViewModel LoadScriptFromFile(string path) + { + ItemFilterScript loadedScript; + try + { + loadedScript = _itemFilterPersistenceService.LoadItemFilterScript(path); + } + catch (Exception e) + { + throw new IOException("Error loading filter script - " + e.Message); + } + + var newViewModel = _itemFilterScriptViewModelFactory.Create(); + newViewModel.Initialise(loadedScript, false); + + return newViewModel; + } + + public IItemFilterScriptViewModel NewScript() + { + var newScript = new ItemFilterScript(); + var newViewModel = _itemFilterScriptViewModelFactory.Create(); + newViewModel.Initialise(newScript, true); + + return newViewModel; + } + + public void SetItemFilterScriptDirectory(string path) + { + _itemFilterPersistenceService.SetItemFilterScriptDirectory(path); + } + + public string GetItemFilterScriptDirectory() + { + return _itemFilterPersistenceService.ItemFilterScriptDirectory; + } + } +} diff --git a/Filtration/Services/ItemFilterPersistenceService.cs b/Filtration/Services/ItemFilterPersistenceService.cs index 1b1fb98..67bbe3c 100644 --- a/Filtration/Services/ItemFilterPersistenceService.cs +++ b/Filtration/Services/ItemFilterPersistenceService.cs @@ -1,11 +1,13 @@ -using Filtration.Models; +using System.IO; +using Filtration.Models; using Filtration.Translators; namespace Filtration.Services { internal interface IItemFilterPersistenceService { - string ItemFilterScriptDirectory { get; set; } + void SetItemFilterScriptDirectory(string path); + string ItemFilterScriptDirectory { get; } ItemFilterScript LoadItemFilterScript(string filePath); void SaveItemFilterScript(ItemFilterScript script); string DefaultPathOfExileDirectory(); @@ -20,9 +22,30 @@ namespace Filtration.Services { _fileSystemService = fileSystemService; _itemFilterScriptTranslator = itemFilterScriptTranslator; + + ItemFilterScriptDirectory = DefaultPathOfExileDirectory(); } - public string ItemFilterScriptDirectory { get; set; } + public string ItemFilterScriptDirectory { get; private set; } + + public string DefaultPathOfExileDirectory() + { + var defaultDir = _fileSystemService.GetUserProfilePath() + "\\Documents\\My Games\\Path of Exile"; + var defaultDirExists = _fileSystemService.DirectoryExists(defaultDir); + + return defaultDirExists ? defaultDir : string.Empty; + } + + public void SetItemFilterScriptDirectory(string path) + { + var validPath = _fileSystemService.DirectoryExists(path); + if (!validPath) + { + throw new DirectoryNotFoundException(); + } + + ItemFilterScriptDirectory = path; + } public ItemFilterScript LoadItemFilterScript(string filePath) { @@ -40,12 +63,6 @@ namespace Filtration.Services _itemFilterScriptTranslator.TranslateItemFilterScriptToString(script)); } - public string DefaultPathOfExileDirectory() - { - var defaultDir = _fileSystemService.GetUserProfilePath() + "\\Documents\\My Games\\Path of Exile"; - var defaultDirExists = _fileSystemService.DirectoryExists(defaultDir); - return defaultDirExists ? defaultDir : string.Empty; - } } } diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index 925e7cc..deea5c0 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -1,8 +1,10 @@ using System; using System.Diagnostics; +using System.IO; using System.Reflection; using System.Windows.Forms; using Filtration.Models; +using Filtration.Repositories; using Filtration.Services; using Filtration.Translators; using Filtration.Views; @@ -16,29 +18,25 @@ namespace Filtration.ViewModels { internal interface IMainWindowViewModel { - void LoadScriptFromFile(string path); RelayCommand OpenScriptCommand { get; } RelayCommand NewScriptCommand { get; } } internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel { - private readonly IItemFilterScriptViewModelFactory _itemFilterScriptViewModelFactory; - private readonly IItemFilterPersistenceService _persistenceService; + private readonly IItemFilterScriptRepository _itemFilterScriptRepository; private readonly IItemFilterScriptTranslator _itemFilterScriptTranslator; private readonly IReplaceColorsViewModel _replaceColorsViewModel; private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel; private IDocument _activeDocument; - public MainWindowViewModel(IItemFilterScriptViewModelFactory itemFilterScriptViewModelFactory, - IItemFilterPersistenceService persistenceService, + public MainWindowViewModel(IItemFilterScriptRepository itemFilterScriptRepository, IItemFilterScriptTranslator itemFilterScriptTranslator, IReplaceColorsViewModel replaceColorsViewModel, IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel) { - _itemFilterScriptViewModelFactory = itemFilterScriptViewModelFactory; - _persistenceService = persistenceService; + _itemFilterScriptRepository = itemFilterScriptRepository; _itemFilterScriptTranslator = itemFilterScriptTranslator; _replaceColorsViewModel = replaceColorsViewModel; _avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel; @@ -56,7 +54,10 @@ namespace Filtration.ViewModels //LoadScriptFromFile("C:\\ThioleLootFilter.txt"); - SetItemFilterScriptDirectory(); + if (string.IsNullOrEmpty(_itemFilterScriptRepository.GetItemFilterScriptDirectory())) + { + SetItemFilterScriptDirectory(); + } Messenger.Default.Register(this, message => { @@ -131,53 +132,40 @@ namespace Filtration.ViewModels var openFileDialog = new OpenFileDialog { Filter = "Filter Files (*.filter)|*.filter|All Files (*.*)|*.*", - InitialDirectory = _persistenceService.ItemFilterScriptDirectory + InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() }; if (openFileDialog.ShowDialog() != true) return; - LoadScriptFromFile(openFileDialog.FileName); - } + IItemFilterScriptViewModel loadedViewModel; - public void LoadScriptFromFile(string path) - { - var loadedScript = _persistenceService.LoadItemFilterScript(path); try { - + loadedViewModel = _itemFilterScriptRepository.LoadScriptFromFile(openFileDialog.FileName); } - catch (Exception e) + catch(IOException e) { - MessageBox.Show(@"Error loading filter script - " + e.Message, @"Script Load Error", MessageBoxButtons.OK, - MessageBoxIcon.Error); + MessageBox.Show(@"Error loading filter script - " + e.Message, @"Script Load Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); return; } - var newViewModel = _itemFilterScriptViewModelFactory.Create(); - newViewModel.Initialise(loadedScript, false); - _avalonDockWorkspaceViewModel.AddDocument(newViewModel); + _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); } private void SetItemFilterScriptDirectory() { - var defaultDir = _persistenceService.DefaultPathOfExileDirectory(); - if (!string.IsNullOrEmpty(defaultDir)) + var dlg = new FolderBrowserDialog { - _persistenceService.ItemFilterScriptDirectory = defaultDir; - } - else - { - var dlg = new FolderBrowserDialog - { - Description = @"Select your Path of Exile data directory, usually in Documents\My Games", - ShowNewFolderButton = false - }; - var result = dlg.ShowDialog(); + Description = @"Select your Path of Exile data directory, usually in Documents\My Games", + ShowNewFolderButton = false + }; + var result = dlg.ShowDialog(); - if (result == DialogResult.OK) - { - _persistenceService.ItemFilterScriptDirectory = dlg.SelectedPath; - } + if (result == DialogResult.OK) + { + _itemFilterScriptRepository.SetItemFilterScriptDirectory(dlg.SelectedPath); } } @@ -215,9 +203,7 @@ namespace Filtration.ViewModels private void OnNewScriptCommand() { - var newScript = new ItemFilterScript(); - var newViewModel = _itemFilterScriptViewModelFactory.Create(); - newViewModel.Initialise(newScript, true); + var newViewModel = _itemFilterScriptRepository.NewScript(); _avalonDockWorkspaceViewModel.AddDocument(newViewModel); } diff --git a/Filtration/Views/MainWindow.xaml.cs b/Filtration/Views/MainWindow.xaml.cs index eaef951..0917881 100644 --- a/Filtration/Views/MainWindow.xaml.cs +++ b/Filtration/Views/MainWindow.xaml.cs @@ -5,23 +5,14 @@ namespace Filtration.Views public interface IMainWindow { void Show(); - void OpenScriptFromCommandLineArgument(string scriptPath); } internal partial class MainWindow : IMainWindow { - private readonly IMainWindowViewModel _mainWindowViewModel; - public MainWindow(IMainWindowViewModel mainWindowViewModel) { - _mainWindowViewModel = mainWindowViewModel; InitializeComponent(); DataContext = mainWindowViewModel; } - - public void OpenScriptFromCommandLineArgument(string scriptPath) - { - _mainWindowViewModel.LoadScriptFromFile(scriptPath); - } } } diff --git a/Filtration/WindsorInstallers/RepositoriesInstaller.cs b/Filtration/WindsorInstallers/RepositoriesInstaller.cs new file mode 100644 index 0000000..be13590 --- /dev/null +++ b/Filtration/WindsorInstallers/RepositoriesInstaller.cs @@ -0,0 +1,18 @@ +using Castle.MicroKernel.Registration; +using Castle.MicroKernel.SubSystems.Configuration; +using Castle.Windsor; +using Filtration.Repositories; + +namespace Filtration.WindsorInstallers +{ + public class RepositoriesInstaller :IWindsorInstaller + { + public void Install(IWindsorContainer container, IConfigurationStore store) + { + container.Register( + Component.For() + .ImplementedBy() + .LifeStyle.Singleton); + } + } +}