Io abstraction (#7293)

Co-authored-by: p-storm <paul.de.man@gmail.com>
This commit is contained in:
P-Storm
2020-11-02 18:33:43 +01:00
committed by GitHub
parent 5c3eef0112
commit 0d4017fe1a
109 changed files with 700 additions and 678 deletions

View File

@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.PowerToys.Settings.UI.Library
{
public interface ISettingsPath
{
bool SettingsFolderExists(string powertoy);
void CreateSettingsFolder(string powertoy);
void DeleteSettings(string powertoy = "");
string GetSettingsPath(string powertoy, string fileName);
}
}

View File

@@ -41,6 +41,7 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.Text.Json" Version="4.7.2" /> <PackageReference Include="System.Text.Json" Version="4.7.2" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers"> <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
<Version>3.3.0</Version> <Version>3.3.0</Version>

View File

@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class SettingPath : ISettingsPath
{
private const string DefaultFileName = "settings.json";
private readonly IDirectory _directory;
private readonly IPath _path;
public SettingPath(IDirectory directory, IPath path)
{
_directory = directory ?? throw new ArgumentNullException(nameof(directory));
_path = path ?? throw new ArgumentNullException(nameof(path));
}
public bool SettingsFolderExists(string powertoy)
{
return _directory.Exists(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
}
public void CreateSettingsFolder(string powertoy)
{
_directory.CreateDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
}
public void DeleteSettings(string powertoy = "")
{
_directory.Delete(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
}
private static string LocalApplicationDataFolder()
{
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}
/// <summary>
/// Get path to the json settings file.
/// </summary>
/// <returns>string path.</returns>
public string GetSettingsPath(string powertoy, string fileName = DefaultFileName)
{
if (string.IsNullOrWhiteSpace(powertoy))
{
return _path.Combine(
LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\{fileName}");
}
return _path.Combine(
LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\{powertoy}\\{fileName}");
}
}
}

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -15,49 +16,34 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{ {
private const string DefaultFileName = "settings.json"; private const string DefaultFileName = "settings.json";
private const string DefaultModuleName = ""; private const string DefaultModuleName = "";
private IIOProvider _ioProvider; private readonly IFile _file;
private readonly ISettingsPath _settingsPath;
public SettingsUtils(IIOProvider ioProvider) public SettingsUtils()
: this(new FileSystem())
{ {
_ioProvider = ioProvider ?? throw new ArgumentNullException(nameof(ioProvider));
} }
private bool SettingsFolderExists(string powertoy) public SettingsUtils(IFileSystem fileSystem)
: this(fileSystem?.File, new SettingPath(fileSystem?.Directory, fileSystem?.Path))
{ {
return _ioProvider.DirectoryExists(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
} }
private void CreateSettingsFolder(string powertoy) public SettingsUtils(IFile file, ISettingsPath settingPath)
{ {
_ioProvider.CreateDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); _file = file ?? throw new ArgumentNullException(nameof(file));
} _settingsPath = settingPath;
public void DeleteSettings(string powertoy = "")
{
_ioProvider.DeleteDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"));
}
/// <summary>
/// Get path to the json settings file.
/// </summary>
/// <returns>string path.</returns>
public static string GetSettingsPath(string powertoy, string fileName = DefaultFileName)
{
if (string.IsNullOrWhiteSpace(powertoy))
{
return System.IO.Path.Combine(
LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\{fileName}");
}
return System.IO.Path.Combine(
LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\{powertoy}\\{fileName}");
} }
public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName) public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName)
{ {
return _ioProvider.FileExists(GetSettingsPath(powertoy, fileName)); var settingsPath = _settingsPath.GetSettingsPath(powertoy, fileName);
return _file.Exists(settingsPath);
}
public void DeleteSettings(string powertoy = "")
{
_settingsPath.DeleteSettings(powertoy);
} }
/// <summary> /// <summary>
@@ -106,7 +92,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
// Look at issue https://github.com/microsoft/PowerToys/issues/6413 you'll see the file has a large sum of \0 to fill up a 4096 byte buffer for writing to disk // Look at issue https://github.com/microsoft/PowerToys/issues/6413 you'll see the file has a large sum of \0 to fill up a 4096 byte buffer for writing to disk
// This, while not totally ideal, does work around the problem by trimming the end. // This, while not totally ideal, does work around the problem by trimming the end.
// The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug // The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug
var jsonSettingsString = _ioProvider.ReadAllText(GetSettingsPath(powertoyFolderName, fileName)).Trim('\0'); var jsonSettingsString = _file.ReadAllText(_settingsPath.GetSettingsPath(powertoyFolderName, fileName)).Trim('\0');
return JsonSerializer.Deserialize<T>(jsonSettingsString); return JsonSerializer.Deserialize<T>(jsonSettingsString);
} }
@@ -118,12 +104,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{ {
if (jsonSettings != null) if (jsonSettings != null)
{ {
if (!SettingsFolderExists(powertoy)) if (!_settingsPath.SettingsFolderExists(powertoy))
{ {
CreateSettingsFolder(powertoy); _settingsPath.CreateSettingsFolder(powertoy);
} }
_ioProvider.WriteAllText(GetSettingsPath(powertoy, fileName), jsonSettings); _file.WriteAllText(_settingsPath.GetSettingsPath(powertoy, fileName), jsonSettings);
} }
} }
catch (Exception e) catch (Exception e)
@@ -137,10 +123,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library
#endif #endif
} }
} }
private static string LocalApplicationDataFolder()
{
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}
} }
} }

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.PowerToys.Settings.UI.Library.CustomAction; using Microsoft.PowerToys.Settings.UI.Library.CustomAction;
@@ -13,6 +14,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{ {
public static class Helper public static class Helper
{ {
public static readonly IFileSystem FileSystem = new FileSystem();
public static bool AllowRunnerToForeground() public static bool AllowRunnerToForeground()
{ {
var result = false; var result = false;
@@ -47,22 +50,20 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
return sendCustomAction.ToJsonString(); return sendCustomAction.ToJsonString();
} }
public static FileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback) public static IFileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback)
{ {
var path = Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}"); var path = FileSystem.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}");
if (!Directory.Exists(path)) if (!FileSystem.Directory.Exists(path))
{ {
Directory.CreateDirectory(path); FileSystem.Directory.CreateDirectory(path);
} }
var watcher = new FileSystemWatcher var watcher = FileSystem.FileSystemWatcher.CreateNew();
{ watcher.Path = path;
Path = path, watcher.Filter = fileName;
Filter = fileName, watcher.NotifyFilter = NotifyFilters.LastWrite;
NotifyFilter = NotifyFilters.LastWrite, watcher.EnableRaisingEvents = true;
EnableRaisingEvents = true,
};
watcher.Changed += (o, e) => onChangedCallback(); watcher.Changed += (o, e) => onChangedCallback();

View File

@@ -5,12 +5,16 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{ {
public static class Logger public static class Logger
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IDirectory Directory = FileSystem.Directory;
private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\Settings Logs"); private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\Settings Logs");
static Logger() static Logger()

View File

@@ -2,41 +2,61 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.IO; using System;
using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{ {
public class SystemIOProvider : IIOProvider public class SystemIOProvider : IIOProvider
{ {
private readonly IDirectory _directory;
private readonly IFile _file;
public SystemIOProvider()
: this(new FileSystem())
{
}
public SystemIOProvider(IFileSystem fileSystem)
: this(fileSystem?.Directory, fileSystem?.File)
{
}
private SystemIOProvider(IDirectory directory, IFile file)
{
_directory = directory ?? throw new ArgumentNullException(nameof(directory));
_file = file ?? throw new ArgumentNullException(nameof(file));
}
public bool CreateDirectory(string path) public bool CreateDirectory(string path)
{ {
var directioryInfo = Directory.CreateDirectory(path); var directioryInfo = _directory.CreateDirectory(path);
return directioryInfo != null; return directioryInfo != null;
} }
public void DeleteDirectory(string path) public void DeleteDirectory(string path)
{ {
Directory.Delete(path, recursive: true); _directory.Delete(path, recursive: true);
} }
public bool DirectoryExists(string path) public bool DirectoryExists(string path)
{ {
return Directory.Exists(path); return _directory.Exists(path);
} }
public bool FileExists(string path) public bool FileExists(string path)
{ {
return File.Exists(path); return _file.Exists(path);
} }
public string ReadAllText(string path) public string ReadAllText(string path)
{ {
return File.ReadAllText(path); return _file.ReadAllText(path);
} }
public void WriteAllText(string path, string content) public void WriteAllText(string path, string content)
{ {
File.WriteAllText(path, content); _file.WriteAllText(path, content);
} }
} }
} }

View File

@@ -1,13 +1,11 @@
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Moq; using Moq;
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO.Abstractions;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text;
namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
{ {
@@ -15,6 +13,9 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
{ {
public const string RootPathStubFiles = "..\\..\\..\\..\\src\\core\\Microsoft.PowerToys.Settings.UI.UnitTests\\BackwardsCompatibility\\TestFiles\\{0}\\Microsoft\\PowerToys\\{1}\\{2}"; public const string RootPathStubFiles = "..\\..\\..\\..\\src\\core\\Microsoft.PowerToys.Settings.UI.UnitTests\\BackwardsCompatibility\\TestFiles\\{0}\\Microsoft\\PowerToys\\{1}\\{2}";
// Using Ordinal since this is used internally for a path
private static readonly Expression<Func<string, bool>> SettingsFilterExpression = s => s == null || s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
internal class MockSettingsRepository<T> : ISettingsRepository<T> where T : ISettingsConfig, new() internal class MockSettingsRepository<T> : ISettingsRepository<T> where T : ISettingsConfig, new()
{ {
T _settingsConfig; T _settingsConfig;
@@ -43,46 +44,56 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility
} }
public static Mock<IIOProvider>GetModuleIOProvider(string version, string module, string fileName) public static Mock<IFile>GetModuleIOProvider(string version, string module, string fileName)
{ {
// Using StringComparison.Ordinal / CultureInfo.InvariantCulture since this is used internally
var stubSettingsPath = string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, module, fileName); var stubSettingsPath = StubSettingsPath(version, module, fileName);
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal); Expression<Func<string, bool>> filterExpression = ModuleFilterExpression(module);
var mockIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression); return IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression);
return mockIOProvider;
} }
public static void VerifyModuleIOProviderWasRead(Mock<IIOProvider> provider, string module, int expectedCallCount) public static string StubGeneralSettingsPath(string version)
{
return StubSettingsPath(version, string.Empty, "settings.json");
}
public static string StubSettingsPath(string version, string module, string fileName)
{
return string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, module, fileName);
}
public static void VerifyModuleIOProviderWasRead(Mock<IFile> provider, string module, int expectedCallCount)
{ {
if(provider == null) if(provider == null)
{ {
throw new ArgumentNullException(nameof(provider)); throw new ArgumentNullException(nameof(provider));
} }
// Using Ordinal since this is used internally Expression<Func<string, bool>> filterExpression = ModuleFilterExpression(module);
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal);
IIOProviderMocks.VerifyIOReadWithStubFile(provider, filterExpression, expectedCallCount); IIOProviderMocks.VerifyIOReadWithStubFile(provider, filterExpression, expectedCallCount);
} }
public static Mock<IIOProvider> GetGeneralSettingsIOProvider(string version) private static Expression<Func<string, bool>> ModuleFilterExpression(string module)
{ {
// Using StringComparison.Ordinal / CultureInfo.InvariantCulture since this is used internally for a path // Using Ordinal since this is used internally for a path
var stubGeneralSettingsPath = string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, string.Empty, "settings.json"); return s => s == null || s.Contains(module, StringComparison.Ordinal);
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
var mockGeneralIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubGeneralSettingsPath, filterExpression);
return mockGeneralIOProvider;
} }
public static void VerifyGeneralSettingsIOProviderWasRead(Mock<IIOProvider> provider, int expectedCallCount) public static Mock<IFile> GetGeneralSettingsIOProvider(string version)
{
var stubGeneralSettingsPath = StubGeneralSettingsPath(version);
return IIOProviderMocks.GetMockIOReadWithStubFile(stubGeneralSettingsPath, SettingsFilterExpression);
}
public static void VerifyGeneralSettingsIOProviderWasRead(Mock<IFile> provider, int expectedCallCount)
{ {
if (provider == null) if (provider == null)
{ {
throw new ArgumentNullException(nameof(provider)); throw new ArgumentNullException(nameof(provider));
} }
// Using Ordinal since this is used internally for a path
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal); IIOProviderMocks.VerifyIOReadWithStubFile(provider, SettingsFilterExpression, expectedCallCount);
IIOProviderMocks.VerifyIOReadWithStubFile(provider, filterExpression, expectedCallCount);
} }
} }

View File

@@ -29,6 +29,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="12.2.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,10 +1,9 @@
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Moq; using Moq;
using System; using System;
using System.Collections.Generic; using System.IO.Abstractions;
using System.IO; using System.IO.Abstractions.TestingHelpers;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text;
namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
{ {
@@ -41,6 +40,8 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IFile File = FileSystem.File;
/// <summary> /// <summary>
/// This method mocks an IO provider so that it will always return data at the savePath location. /// This method mocks an IO provider so that it will always return data at the savePath location.
/// This mock is specific to a given module, and is verifiable that the stub file was read. /// This mock is specific to a given module, and is verifiable that the stub file was read.
@@ -48,25 +49,25 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
/// <param name="savePath">The path to the stub settings file</param> /// <param name="savePath">The path to the stub settings file</param>
/// <param name="expectedPathSubstring">The substring in the path that identifies the module eg. Microsoft\\PowerToys\\ColorPicker</param> /// <param name="expectedPathSubstring">The substring in the path that identifies the module eg. Microsoft\\PowerToys\\ColorPicker</param>
/// <returns></returns> /// <returns></returns>
internal static Mock<IIOProvider> GetMockIOReadWithStubFile(string savePath, Expression<Func<string, bool>> filterExpression) internal static Mock<IFile> GetMockIOReadWithStubFile(string savePath, Expression<Func<string, bool>> filterExpression)
{ {
string saveContent = File.ReadAllText(savePath); string saveContent = File.ReadAllText(savePath);
var mockIOProvider = new Mock<IIOProvider>(); var fileMock = new Mock<IFile>();
mockIOProvider.Setup(x => x.ReadAllText(It.Is<string>(filterExpression))) fileMock.Setup(x => x.ReadAllText(It.Is<string>(filterExpression)))
.Returns(() => saveContent).Verifiable(); .Returns(() => saveContent).Verifiable();
mockIOProvider.Setup(x => x.FileExists(It.Is<string>(filterExpression))) fileMock.Setup(x => x.Exists(It.Is<string>(filterExpression)))
.Returns(true); .Returns(true);
return mockIOProvider; return fileMock;
} }
internal static void VerifyIOReadWithStubFile(Mock<IIOProvider> mockIOProvider, Expression<Func<string, bool>> filterExpression, int expectedCallCount) internal static void VerifyIOReadWithStubFile(Mock<IFile> fileMock, Expression<Func<string, bool>> filterExpression, int expectedCallCount)
{ {
mockIOProvider.Verify(x => x.ReadAllText(It.Is<string>(filterExpression)), Times.Exactly(expectedCallCount)); fileMock.Verify(x => x.ReadAllText(It.Is<string>(filterExpression)), Times.Exactly(expectedCallCount));
} }
} }
} }

View File

@@ -6,9 +6,9 @@ using System;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using System.IO.Abstractions.TestingHelpers;
using Microsoft.PowerToys.Settings.UnitTest; using Microsoft.PowerToys.Settings.UnitTest;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema; using Newtonsoft.Json.Schema;
@@ -25,11 +25,8 @@ namespace CommonLibTest
public void ToJsonStringShouldReturnValidJSONOfModelWhenSuccessful() public void ToJsonStringShouldReturnValidJSONOfModelWhenSuccessful()
{ {
//Mock Disk access //Mock Disk access
string saveContent = string.Empty; var mockFileSystem = new MockFileSystem();
string savePath = string.Empty; var settingsUtils = new SettingsUtils(mockFileSystem);
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
var settingsUtils = new SettingsUtils(mockIOProvider.Object);
// Arrange // Arrange
string file_name = "test\\BasePTModuleSettingsTest"; string file_name = "test\\BasePTModuleSettingsTest";

View File

@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;

View File

@@ -3,7 +3,8 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
@@ -25,9 +26,9 @@ namespace CommonLibTest
public void SaveSettingsSaveSettingsToFileWhenFilePathExists() public void SaveSettingsSaveSettingsToFileWhenFilePathExists()
{ {
// Arrange // Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockIOProvider.Object); var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name = "\\test"; string file_name = "\\test";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -45,8 +46,8 @@ namespace CommonLibTest
public void SaveSettingsShouldCreateFileWhenFilePathIsNotFound() public void SaveSettingsShouldCreateFileWhenFilePathIsNotFound()
{ {
// Arrange // Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockIOProvider.Object); var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name = "test\\Test Folder"; string file_name = "test\\Test Folder";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -63,8 +64,8 @@ namespace CommonLibTest
public void SettingsFolderExistsShouldReturnFalseWhenFilePathIsNotFound() public void SettingsFolderExistsShouldReturnFalseWhenFilePathIsNotFound()
{ {
// Arrange // Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockIOProvider.Object); var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name_random = "test\\" + RandomString(); string file_name_random = "test\\" + RandomString();
string file_name_exists = "test\\exists"; string file_name_exists = "test\\exists";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -84,8 +85,8 @@ namespace CommonLibTest
public void SettingsUtilsMustReturnDefaultItemWhenFileIsCorrupt() public void SettingsUtilsMustReturnDefaultItemWhenFileIsCorrupt()
{ {
// Arrange // Arrange
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider("CorruptJson", string.Empty, "settings.json"); var mockFileSystem = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(mockFileSystem);
// Act // Act
TestClass settings = mockSettingsUtils.GetSettings<TestClass>(string.Empty); TestClass settings = mockSettingsUtils.GetSettings<TestClass>(string.Empty);

View File

@@ -2,14 +2,13 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Globalization;
using System.IO;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility; using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace ViewModelTests namespace ViewModelTests
{ {
@@ -27,11 +26,14 @@ namespace ViewModelTests
{ {
//Arrange //Arrange
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ColorPickerSettings.ModuleName, fileName); var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ColorPickerSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var settingPathMock = new Mock<ISettingsPath>();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
ColorPickerSettings originalSettings = mockSettingsUtils.GetSettings<ColorPickerSettings>(ColorPickerSettings.ModuleName); ColorPickerSettings originalSettings = mockSettingsUtils.GetSettings<ColorPickerSettings>(ColorPickerSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);

View File

@@ -3,9 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text.Json; using System.Text.Json;
using CommonLibTest; using CommonLibTest;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
@@ -33,13 +30,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")] [DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, FancyZonesSettings.ModuleName, fileName); var settingPathMock = new Mock<ISettingsPath>();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, FancyZonesSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
FancyZonesSettings originalSettings = mockSettingsUtils.GetSettings<FancyZonesSettings>(FancyZonesSettings.ModuleName); FancyZonesSettings originalSettings = mockSettingsUtils.GetSettings<FancyZonesSettings>(FancyZonesSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
var fancyZonesRepository = new BackCompatTestProperties.MockSettingsRepository<FancyZonesSettings>(mockSettingsUtils); var fancyZonesRepository = new BackCompatTestProperties.MockSettingsRepository<FancyZonesSettings>(mockSettingsUtils);
@@ -71,7 +71,7 @@ namespace ViewModelTests
//Verify that the stub file was used //Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>) var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>)
BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, FancyZonesSettings.ModuleName, expectedCallCount); BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, FancyZonesSettings.ModuleName, expectedCallCount);
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount); BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
} }

View File

@@ -4,7 +4,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -12,7 +11,7 @@ using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq; using Moq;
using NuGet.Frameworks; using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ViewModelTests namespace ViewModelTests
{ {
@@ -40,16 +39,20 @@ namespace ViewModelTests
[DataRow("v0.22.0")] [DataRow("v0.22.0")]
public void OriginalFilesModificationTest(string version) public void OriginalFilesModificationTest(string version)
{ {
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var settingPathMock = new Mock<ISettingsPath>();
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var fileMock = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
// Initialise View Model with test Config files // Initialise View Model with test Config files
// Arrange // Arrange
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => 0;
Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; }; Func<string, int> SendRestartAdminIPCMessage = msg => 0;
Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; }; Func<string, int> SendCheckForUpdatesIPCMessage = msg => 0;
var viewModel = new GeneralViewModel( var viewModel = new GeneralViewModel(
settingsRepository: generalSettingsRepository, settingsRepository: generalSettingsRepository,
runAsAdminText: "GeneralSettings_RunningAsAdminText", runAsAdminText: "GeneralSettings_RunningAsAdminText",
@@ -71,7 +74,7 @@ namespace ViewModelTests
//Verify that the stub file was used //Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>) var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>)
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount); BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(fileMock, expectedCallCount);
} }
[TestMethod] [TestMethod]
@@ -82,7 +85,7 @@ namespace ViewModelTests
Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; }; Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; };
Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; }; Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel( GeneralViewModel viewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText", "GeneralSettings_RunningAsUserText",
false, false,
@@ -119,7 +122,7 @@ namespace ViewModelTests
Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; }; Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; };
Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; }; Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel( GeneralViewModel viewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText", "GeneralSettings_RunningAsUserText",
false, false,
@@ -151,7 +154,7 @@ namespace ViewModelTests
// Arrange // Arrange
GeneralViewModel viewModel = new GeneralViewModel( GeneralViewModel viewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText", "GeneralSettings_RunningAsUserText",
false, false,
@@ -184,7 +187,7 @@ namespace ViewModelTests
Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; }; Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; };
Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; }; Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; };
viewModel = new GeneralViewModel( viewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText", "GeneralSettings_RunningAsUserText",
false, false,
@@ -215,7 +218,7 @@ namespace ViewModelTests
Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; }; Func<string, int> SendRestartAdminIPCMessage = msg => { return 0; };
Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; }; Func<string, int> SendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new GeneralViewModel( GeneralViewModel viewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText", "GeneralSettings_RunningAsUserText",
false, false,

View File

@@ -3,8 +3,8 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Globalization; using System.IO.Abstractions;
using System.IO; using System.IO.Abstractions.TestingHelpers;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
@@ -20,16 +20,15 @@ namespace ViewModelTests
[TestClass] [TestClass]
public class ImageResizer public class ImageResizer
{ {
private Mock<ISettingsUtils> _mockGeneralSettingsUtils;
private Mock<ISettingsUtils> mockGeneralSettingsUtils; private Mock<ISettingsUtils> _mockImgResizerSettingsUtils;
private Mock<ISettingsUtils> mockImgResizerSettingsUtils;
[TestInitialize] [TestInitialize]
public void SetUpStubSettingUtils() public void SetUpStubSettingUtils()
{ {
mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<GeneralSettings>(); _mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<GeneralSettings>();
mockImgResizerSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>(); _mockImgResizerSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
} }
@@ -44,13 +43,17 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")] [DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ImageResizerSettings.ModuleName, fileName); var settingPathMock = new Mock<ISettingsPath>();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, ImageResizerSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
ImageResizerSettings originalSettings = mockSettingsUtils.GetSettings<ImageResizerSettings>(ImageResizerSettings.ModuleName); ImageResizerSettings originalSettings = mockSettingsUtils.GetSettings<ImageResizerSettings>(ImageResizerSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralFileMock = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralFileMock.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
// Initialise View Model with test Config files // Initialise View Model with test Config files
@@ -69,8 +72,8 @@ namespace ViewModelTests
//Verify that the stub file was used //Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>) var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>)
BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, ImageResizerSettings.ModuleName, expectedCallCount); BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, ImageResizerSettings.ModuleName, expectedCallCount);
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount); BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralFileMock, expectedCallCount);
} }
[TestMethod] [TestMethod]
@@ -85,7 +88,7 @@ namespace ViewModelTests
}; };
// arrange // arrange
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockImgResizerSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(_mockImgResizerSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.IsEnabled = true; viewModel.IsEnabled = true;
@@ -95,16 +98,16 @@ namespace ViewModelTests
public void JPEGQualityLevelShouldSetValueToTenWhenSuccessful() public void JPEGQualityLevelShouldSetValueToTenWhenSuccessful()
{ {
// arrange // arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var fileSystemMock = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.JPEGQualityLevel = 10; viewModel.JPEGQualityLevel = 10;
// Assert // Assert
viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.JPEGQualityLevel); Assert.AreEqual(10, viewModel.JPEGQualityLevel);
} }
@@ -112,16 +115,16 @@ namespace ViewModelTests
public void PngInterlaceOptionShouldSetValueToTenWhenSuccessful() public void PngInterlaceOptionShouldSetValueToTenWhenSuccessful()
{ {
// arrange // arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var fileSystemMock = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.PngInterlaceOption = 10; viewModel.PngInterlaceOption = 10;
// Assert // Assert
viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.PngInterlaceOption); Assert.AreEqual(10, viewModel.PngInterlaceOption);
} }
@@ -129,16 +132,16 @@ namespace ViewModelTests
public void TiffCompressOptionShouldSetValueToTenWhenSuccessful() public void TiffCompressOptionShouldSetValueToTenWhenSuccessful()
{ {
// arrange // arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var fileSystemMock = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.TiffCompressOption = 10; viewModel.TiffCompressOption = 10;
// Assert // Assert
viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(10, viewModel.TiffCompressOption); Assert.AreEqual(10, viewModel.TiffCompressOption);
} }
@@ -146,17 +149,17 @@ namespace ViewModelTests
public void FileNameShouldUpdateValueWhenSuccessful() public void FileNameShouldUpdateValueWhenSuccessful()
{ {
// arrange // arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var fileSystemMock = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
string expectedValue = "%1 (%3)"; string expectedValue = "%1 (%3)";
// act // act
viewModel.FileName = expectedValue; viewModel.FileName = expectedValue;
// Assert // Assert
viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual(expectedValue, viewModel.FileName); Assert.AreEqual(expectedValue, viewModel.FileName);
} }
@@ -175,7 +178,7 @@ namespace ViewModelTests
.Verifiable(); .Verifiable();
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(settingUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(settingUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.KeepDateModified = true; viewModel.KeepDateModified = true;
@@ -188,16 +191,16 @@ namespace ViewModelTests
public void EncoderShouldUpdateValueWhenSuccessful() public void EncoderShouldUpdateValueWhenSuccessful()
{ {
// arrange // arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); var fileSystemMock = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(fileSystemMock);
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
// act // act
viewModel.Encoder = 3; viewModel.Encoder = 3;
// Assert // Assert
viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
Assert.AreEqual("163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", viewModel.EncoderGuid); Assert.AreEqual("163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", viewModel.EncoderGuid);
Assert.AreEqual(3, viewModel.Encoder); Assert.AreEqual(3, viewModel.Encoder);
} }
@@ -208,7 +211,7 @@ namespace ViewModelTests
// arrange // arrange
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>(); var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
int sizeOfOriginalArray = viewModel.Sizes.Count; int sizeOfOriginalArray = viewModel.Sizes.Count;
// act // act
@@ -224,7 +227,7 @@ namespace ViewModelTests
// arrange // arrange
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>(); var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
Func<string, int> SendMockIPCConfigMSG = msg => { return 0; }; Func<string, int> SendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG);
int sizeOfOriginalArray = viewModel.Sizes.Count; int sizeOfOriginalArray = viewModel.Sizes.Count;
ImageSize deleteCandidate = viewModel.Sizes.Where<ImageSize>(x => x.Id == 0).First(); ImageSize deleteCandidate = viewModel.Sizes.Where<ImageSize>(x => x.Id == 0).First();

View File

@@ -10,6 +10,7 @@ using Moq;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility; using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using System.Globalization; using System.Globalization;
using System.IO.Abstractions;
namespace ViewModelTests namespace ViewModelTests
{ {
@@ -52,13 +53,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")] [DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var settingPathMock = new Mock<ISettingsPath>();
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerLauncherSettings.ModuleName, fileName); var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerLauncherSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
PowerLauncherSettings originalSettings = mockSettingsUtils.GetSettings<PowerLauncherSettings>(PowerLauncherSettings.ModuleName); PowerLauncherSettings originalSettings = mockSettingsUtils.GetSettings<PowerLauncherSettings>(PowerLauncherSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
// Initialise View Model with test Config files // Initialise View Model with test Config files

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -40,13 +40,15 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")] [DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerPreviewSettings.ModuleName, fileName); var settingPathMock = new Mock<ISettingsPath>();
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var fileMock = BackCompatTestProperties.GetModuleIOProvider(version, PowerPreviewSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(fileMock.Object, settingPathMock.Object);
PowerPreviewSettings originalSettings = mockSettingsUtils.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName); PowerPreviewSettings originalSettings = mockSettingsUtils.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName);
var repository = new BackCompatTestProperties.MockSettingsRepository<PowerPreviewSettings>(mockSettingsUtils); var repository = new BackCompatTestProperties.MockSettingsRepository<PowerPreviewSettings>(mockSettingsUtils);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
@@ -62,7 +64,7 @@ namespace ViewModelTests
//Verify that the stub file was used //Verify that the stub file was used
var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>) var expectedCallCount = 2; //once via the view model, and once by the test (GetSettings<T>)
BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, PowerPreviewSettings.ModuleName, expectedCallCount); BackCompatTestProperties.VerifyModuleIOProviderWasRead(fileMock, PowerPreviewSettings.ModuleName, expectedCallCount);
} }

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -40,12 +40,16 @@ namespace ViewModelTests
[DataRow("v0.22.0", "power-rename-settings.json")] [DataRow("v0.22.0", "power-rename-settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var settingPathMock = new Mock<ISettingsPath>();
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerRenameSettings.ModuleName, fileName); var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, PowerRenameSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
PowerRenameLocalProperties originalSettings = mockSettingsUtils.GetSettings<PowerRenameLocalProperties>(PowerRenameSettings.ModuleName); PowerRenameLocalProperties originalSettings = mockSettingsUtils.GetSettings<PowerRenameLocalProperties>(PowerRenameSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO;
using System.Text.Json; using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -30,12 +29,13 @@ namespace ViewModelTests
[DataRow("v0.22.0", "settings.json")] [DataRow("v0.22.0", "settings.json")]
public void OriginalFilesModificationTest(string version, string fileName) public void OriginalFilesModificationTest(string version, string fileName)
{ {
var settingPathMock = new Mock<ISettingsPath>();
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ShortcutGuideSettings.ModuleName, fileName); var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider(version, ShortcutGuideSettings.ModuleName, fileName);
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object, settingPathMock.Object);
ShortcutGuideSettings originalSettings = mockSettingsUtils.GetSettings<ShortcutGuideSettings>(ShortcutGuideSettings.ModuleName); ShortcutGuideSettings originalSettings = mockSettingsUtils.GetSettings<ShortcutGuideSettings>(ShortcutGuideSettings.ModuleName);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version); var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object); var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>(); GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils); var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);
var shortcutSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<ShortcutGuideSettings>(mockSettingsUtils); var shortcutSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<ShortcutGuideSettings>(mockSettingsUtils);

View File

@@ -5,7 +5,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
@@ -14,7 +13,7 @@ namespace Microsoft.PowerToys.Settings.UI.Converters
{ {
public sealed class ModuleEnabledToForegroundConverter : IValueConverter public sealed class ModuleEnabledToForegroundConverter : IValueConverter
{ {
private readonly ISettingsUtils settingsUtils = new SettingsUtils(new SystemIOProvider()); private readonly ISettingsUtils settingsUtils = new SettingsUtils();
private string selectedTheme = string.Empty; private string selectedTheme = string.Empty;

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -15,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public ColorPickerPage() public ColorPickerPage()
{ {
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
InitializeComponent(); InitializeComponent();

View File

@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public FancyZonesPage() public FancyZonesPage()
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new FancyZonesViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new FancyZonesViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
} }

View File

@@ -36,7 +36,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
// Load string resources // Load string resources
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse(); ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new GeneralViewModel( ViewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),

View File

@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public ImageResizerPage() public ImageResizerPage()
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
} }

View File

@@ -5,7 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels; using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -24,7 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private const string PowerToyName = "Keyboard Manager"; private const string PowerToyName = "Keyboard Manager";
private readonly CoreDispatcher dispatcher; private readonly CoreDispatcher dispatcher;
private readonly FileSystemWatcher watcher; private readonly IFileSystemWatcher watcher;
public KeyboardManagerViewModel ViewModel { get; } public KeyboardManagerViewModel ViewModel { get; }
@@ -32,7 +32,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{ {
dispatcher = Window.Current.Dispatcher; dispatcher = Window.Current.Dispatcher;
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, FilterRemapKeysList); ViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, FilterRemapKeysList);
watcher = Helper.GetFileWatcher( watcher = Helper.GetFileWatcher(

View File

@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerLauncherPage() public PowerLauncherPage()
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new PowerLauncherViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, (int)Windows.System.VirtualKey.Space); ViewModel = new PowerLauncherViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, (int)Windows.System.VirtualKey.Space);
DataContext = ViewModel; DataContext = ViewModel;

View File

@@ -19,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerPreviewPage() public PowerPreviewPage()
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new PowerPreviewViewModel(SettingsRepository<PowerPreviewSettings>.GetInstance(settingsUtils), SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new PowerPreviewViewModel(SettingsRepository<PowerPreviewSettings>.GetInstance(settingsUtils), SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
} }

View File

@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerRenamePage() public PowerRenamePage()
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new PowerRenameViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new PowerRenameViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;

View File

@@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{ {
InitializeComponent(); InitializeComponent();
var settingsUtils = new SettingsUtils(new SystemIOProvider()); var settingsUtils = new SettingsUtils();
ViewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
} }

View File

@@ -225,6 +225,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
<PackageReference Include="System.Windows.Interactivity.WPF"> <PackageReference Include="System.Windows.Interactivity.WPF">
<Version>2.0.20525</Version> <Version>2.0.20525</Version>
</PackageReference> </PackageReference>

View File

@@ -5,23 +5,24 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
namespace ColorPicker.Helpers namespace ColorPicker.Helpers
{ {
public static class Logger public static class Logger
{ {
private static readonly string ApplicationLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ColorPicker"); private static readonly IFileSystem _fileSystem = new FileSystem();
private static readonly string ApplicationLogPath = _fileSystem.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ColorPicker");
static Logger() static Logger()
{ {
if (!Directory.Exists(ApplicationLogPath)) if (!_fileSystem.Directory.Exists(ApplicationLogPath))
{ {
Directory.CreateDirectory(ApplicationLogPath); _fileSystem.Directory.CreateDirectory(ApplicationLogPath);
} }
// Using InvariantCulture since this is used for a log file name // Using InvariantCulture since this is used for a log file name
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt"); var logFilePath = _fileSystem.Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath)); Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using ColorPicker.Helpers; using ColorPicker.Helpers;
using Microsoft.Win32; using Microsoft.Win32;
@@ -28,11 +28,13 @@ namespace ColorPicker.Mouse
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
private const int SPIF_SENDCHANGE = 0x02; private const int SPIF_SENDCHANGE = 0x02;
private static readonly IFileSystem _fileSystem = new FileSystem();
public static void SetColorPickerCursor() public static void SetColorPickerCursor()
{ {
BackupOriginalCursors(); BackupOriginalCursors();
var colorPickerCursorPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName); var colorPickerCursorPath = _fileSystem.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName);
ChangeCursor(colorPickerCursorPath, ArrowRegistryName); ChangeCursor(colorPickerCursorPath, ArrowRegistryName);
ChangeCursor(colorPickerCursorPath, IBeamRegistryName); ChangeCursor(colorPickerCursorPath, IBeamRegistryName);
} }

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Threading; using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -20,14 +21,14 @@ namespace ColorPicker.Settings
private const int MaxNumberOfRetry = 5; private const int MaxNumberOfRetry = 5;
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Actually, call back is LoadSettingsFromJson")] [System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Actually, call back is LoadSettingsFromJson")]
private readonly FileSystemWatcher _watcher; private readonly IFileSystemWatcher _watcher;
private readonly object _loadingSettingsLock = new object(); private readonly object _loadingSettingsLock = new object();
[ImportingConstructor] [ImportingConstructor]
public UserSettings() public UserSettings()
{ {
_settingsUtils = new SettingsUtils(new SystemIOProvider()); _settingsUtils = new SettingsUtils();
ChangeCursor = new SettingItem<bool>(true); ChangeCursor = new SettingItem<bool>(true);
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut); ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
CopiedColorRepresentation = new SettingItem<ColorRepresentationType>(ColorRepresentationType.HEX); CopiedColorRepresentation = new SettingItem<ColorRepresentationType>(ColorRepresentationType.HEX);

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -41,6 +42,8 @@ namespace FancyZonesEditor
private const string CrashReportDynamicAssemblyTag = "dynamic assembly doesn't have location"; private const string CrashReportDynamicAssemblyTag = "dynamic assembly doesn't have location";
private const string CrashReportLocationNullTag = "location is null or empty"; private const string CrashReportLocationNullTag = "location is null or empty";
private readonly IFileSystem _fileSystem = new FileSystem();
public Settings ZoneSettings { get; } public Settings ZoneSettings { get; }
public App() public App()

View File

@@ -250,6 +250,9 @@
<PackageReference Include="MahApps.Metro"> <PackageReference Include="MahApps.Metro">
<Version>2.3.0</Version> <Version>2.3.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
<PackageReference Include="System.Text.Json"> <PackageReference Include="System.Text.Json">
<Version>4.7.2</Version> <Version>4.7.2</Version>
</PackageReference> </PackageReference>

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO.Abstractions;
using System.Text.Json; using System.Text.Json;
using System.Windows; using System.Windows;
@@ -201,7 +201,7 @@ namespace FancyZonesEditor.Models
try try
{ {
string jsonString = JsonSerializer.Serialize(jsonObj, options); string jsonString = JsonSerializer.Serialize(jsonObj, options);
File.WriteAllText(Settings.AppliedZoneSetTmpFile, jsonString); FileSystem.File.WriteAllText(Settings.AppliedZoneSetTmpFile, jsonString);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Windows; using System.Windows;
@@ -237,7 +236,7 @@ namespace FancyZonesEditor.Models
try try
{ {
string jsonString = JsonSerializer.Serialize(jsonObj, options); string jsonString = JsonSerializer.Serialize(jsonObj, options);
File.WriteAllText(Settings.AppliedZoneSetTmpFile, jsonString); FileSystem.File.WriteAllText(Settings.AppliedZoneSetTmpFile, jsonString);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text.Json; using System.Text.Json;
@@ -29,6 +30,8 @@ namespace FancyZonesEditor.Models
// Manages common properties and base persistence // Manages common properties and base persistence
public abstract class LayoutModel : INotifyPropertyChanged public abstract class LayoutModel : INotifyPropertyChanged
{ {
protected static readonly IFileSystem FileSystem = new FileSystem();
// Localizable strings // Localizable strings
private const string ErrorMessageBoxTitle = "FancyZones Editor Exception Handler"; private const string ErrorMessageBoxTitle = "FancyZones Editor Exception Handler";
private const string ErrorMessageBoxMessage = "Please report the bug to "; private const string ErrorMessageBoxMessage = "Please report the bug to ";
@@ -194,7 +197,7 @@ namespace FancyZonesEditor.Models
try try
{ {
string jsonString = JsonSerializer.Serialize(deletedLayouts, options); string jsonString = JsonSerializer.Serialize(deletedLayouts, options);
File.WriteAllText(Settings.DeletedCustomZoneSetsTmpFile, jsonString); FileSystem.File.WriteAllText(Settings.DeletedCustomZoneSetsTmpFile, jsonString);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -209,7 +212,7 @@ namespace FancyZonesEditor.Models
try try
{ {
FileStream inputStream = File.Open(Settings.FancyZonesSettingsFile, FileMode.Open); Stream inputStream = FileSystem.File.Open(Settings.FancyZonesSettingsFile, FileMode.Open);
JsonDocument jsonObject = JsonDocument.Parse(inputStream, options: default); JsonDocument jsonObject = JsonDocument.Parse(inputStream, options: default);
JsonElement.ArrayEnumerator customZoneSetsEnumerator = jsonObject.RootElement.GetProperty(CustomZoneSetsJsonTag).EnumerateArray(); JsonElement.ArrayEnumerator customZoneSetsEnumerator = jsonObject.RootElement.GetProperty(CustomZoneSetsJsonTag).EnumerateArray();
@@ -437,7 +440,7 @@ namespace FancyZonesEditor.Models
try try
{ {
string jsonString = JsonSerializer.Serialize(zoneSet, options); string jsonString = JsonSerializer.Serialize(zoneSet, options);
File.WriteAllText(Settings.ActiveZoneSetTmpFile, jsonString); FileSystem.File.WriteAllText(Settings.ActiveZoneSetTmpFile, jsonString);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text.Json; using System.Text.Json;
using System.Windows; using System.Windows;
@@ -39,6 +40,8 @@ namespace FancyZonesEditor
Debug, Debug,
} }
private static readonly IFileSystem _fileSystem = new FileSystem();
private static CanvasLayoutModel _blankCustomModel; private static CanvasLayoutModel _blankCustomModel;
private readonly CanvasLayoutModel _focusModel; private readonly CanvasLayoutModel _focusModel;
private readonly GridLayoutModel _rowsModel; private readonly GridLayoutModel _rowsModel;
@@ -137,7 +140,7 @@ namespace FancyZonesEditor
public Settings() public Settings()
{ {
string tmpDirPath = Path.GetTempPath(); string tmpDirPath = _fileSystem.Path.GetTempPath();
ActiveZoneSetTmpFile = tmpDirPath + ActiveZoneSetsTmpFileName; ActiveZoneSetTmpFile = tmpDirPath + ActiveZoneSetsTmpFileName;
AppliedZoneSetTmpFile = tmpDirPath + AppliedZoneSetsTmpFileName; AppliedZoneSetTmpFile = tmpDirPath + AppliedZoneSetsTmpFileName;
@@ -441,9 +444,9 @@ namespace FancyZonesEditor
ActiveZoneSetUUid = NullUuidStr; ActiveZoneSetUUid = NullUuidStr;
JsonElement jsonObject = default(JsonElement); JsonElement jsonObject = default(JsonElement);
if (File.Exists(Settings.ActiveZoneSetTmpFile)) if (_fileSystem.File.Exists(Settings.ActiveZoneSetTmpFile))
{ {
FileStream inputStream = File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Open); Stream inputStream = _fileSystem.File.Open(Settings.ActiveZoneSetTmpFile, FileMode.Open);
jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement; jsonObject = JsonDocument.Parse(inputStream, options: default).RootElement;
inputStream.Close(); inputStream.Close();
UniqueKey = jsonObject.GetProperty(DeviceIdJsonTag).GetString(); UniqueKey = jsonObject.GetProperty(DeviceIdJsonTag).GetString();

View File

@@ -69,6 +69,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118"> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">

View File

@@ -5,7 +5,6 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO.Abstractions;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Xunit; using Xunit;
@@ -14,6 +14,8 @@ namespace ImageResizer.Test
{ {
internal static class AssertEx internal static class AssertEx
{ {
private static readonly IFileSystem _fileSystem = new FileSystem();
public static void All<T>(IEnumerable<T> collection, Action<T> action) public static void All<T>(IEnumerable<T> collection, Action<T> action)
{ {
foreach (var item in collection) foreach (var item in collection)
@@ -24,7 +26,7 @@ namespace ImageResizer.Test
public static void Image(string path, Action<BitmapDecoder> action) public static void Image(string path, Action<BitmapDecoder> action)
{ {
using (var stream = File.OpenRead(path)) using (var stream = _fileSystem.File.OpenRead(path))
{ {
var image = BitmapDecoder.Create( var image = BitmapDecoder.Create(
stream, stream,

View File

@@ -69,6 +69,9 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118"> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\common\interop\interop.vcxproj" /> <ProjectReference Include="..\..\..\common\interop\interop.vcxproj" />

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ImageResizer.Properties; using ImageResizer.Properties;
@@ -14,6 +15,8 @@ namespace ImageResizer.Models
{ {
public class ResizeBatch public class ResizeBatch
{ {
private readonly IFileSystem _fileSystem = new FileSystem();
public string DestinationDirectory { get; set; } public string DestinationDirectory { get; set; }
public ICollection<string> Files { get; } = new List<string>(); public ICollection<string> Files { get; } = new List<string>();
@@ -71,7 +74,7 @@ namespace ImageResizer.Models
catch (Exception ex) catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types #pragma warning restore CA1031 // Do not catch general exception types
{ {
errors.Add(new ResizeError { File = Path.GetFileName(file), Error = ex.Message }); errors.Add(new ResizeError { File = _fileSystem.Path.GetFileName(file), Error = ex.Message });
} }
Interlocked.Increment(ref completed); Interlocked.Increment(ref completed);

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
@@ -12,11 +13,14 @@ using System.Windows.Media.Imaging;
using ImageResizer.Properties; using ImageResizer.Properties;
using ImageResizer.Utilities; using ImageResizer.Utilities;
using Microsoft.VisualBasic.FileIO; using Microsoft.VisualBasic.FileIO;
using FileSystem = Microsoft.VisualBasic.FileIO.FileSystem;
namespace ImageResizer.Models namespace ImageResizer.Models
{ {
internal class ResizeOperation internal class ResizeOperation
{ {
private readonly IFileSystem _fileSystem = new System.IO.Abstractions.FileSystem();
private readonly string _file; private readonly string _file;
private readonly string _destinationDirectory; private readonly string _destinationDirectory;
private readonly Settings _settings; private readonly Settings _settings;
@@ -31,7 +35,7 @@ namespace ImageResizer.Models
public void Execute() public void Execute()
{ {
string path; string path;
using (var inputStream = File.OpenRead(_file)) using (var inputStream = _fileSystem.File.OpenRead(_file))
{ {
var decoder = BitmapDecoder.Create( var decoder = BitmapDecoder.Create(
inputStream, inputStream,
@@ -87,8 +91,8 @@ namespace ImageResizer.Models
} }
path = GetDestinationPath(encoder); path = GetDestinationPath(encoder);
Directory.CreateDirectory(Path.GetDirectoryName(path)); _fileSystem.Directory.CreateDirectory(_fileSystem.Path.GetDirectoryName(path));
using (var outputStream = File.Open(path, FileMode.CreateNew, FileAccess.Write)) using (var outputStream = _fileSystem.File.Open(path, FileMode.CreateNew, FileAccess.Write))
{ {
encoder.Save(outputStream); encoder.Save(outputStream);
} }
@@ -96,13 +100,13 @@ namespace ImageResizer.Models
if (_settings.KeepDateModified) if (_settings.KeepDateModified)
{ {
File.SetLastWriteTimeUtc(path, File.GetLastWriteTimeUtc(_file)); _fileSystem.File.SetLastWriteTimeUtc(path, _fileSystem.File.GetLastWriteTimeUtc(_file));
} }
if (_settings.Replace) if (_settings.Replace)
{ {
var backup = GetBackupPath(); var backup = GetBackupPath();
File.Replace(path, _file, backup, ignoreMetadataErrors: true); _fileSystem.File.Replace(path, _file, backup, ignoreMetadataErrors: true);
FileSystem.DeleteFile(backup, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin); FileSystem.DeleteFile(backup, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
} }
} }
@@ -179,11 +183,11 @@ namespace ImageResizer.Models
private string GetDestinationPath(BitmapEncoder encoder) private string GetDestinationPath(BitmapEncoder encoder)
{ {
var directory = _destinationDirectory ?? Path.GetDirectoryName(_file); var directory = _destinationDirectory ?? _fileSystem.Path.GetDirectoryName(_file);
var originalFileName = Path.GetFileNameWithoutExtension(_file); var originalFileName = _fileSystem.Path.GetFileNameWithoutExtension(_file);
var supportedExtensions = encoder.CodecInfo.FileExtensions.Split(','); var supportedExtensions = encoder.CodecInfo.FileExtensions.Split(',');
var extension = Path.GetExtension(_file); var extension = _fileSystem.Path.GetExtension(_file);
if (!supportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) if (!supportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{ {
extension = supportedExtensions.FirstOrDefault(); extension = supportedExtensions.FirstOrDefault();
@@ -199,11 +203,11 @@ namespace ImageResizer.Models
_settings.SelectedSize.Height, _settings.SelectedSize.Height,
encoder.Frames[0].PixelWidth, encoder.Frames[0].PixelWidth,
encoder.Frames[0].PixelHeight); encoder.Frames[0].PixelHeight);
var path = Path.Combine(directory, fileName + extension); var path = _fileSystem.Path.Combine(directory, fileName + extension);
var uniquifier = 1; var uniquifier = 1;
while (File.Exists(path)) while (_fileSystem.File.Exists(path))
{ {
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + extension); path = _fileSystem.Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + extension);
} }
return path; return path;
@@ -211,15 +215,15 @@ namespace ImageResizer.Models
private string GetBackupPath() private string GetBackupPath()
{ {
var directory = Path.GetDirectoryName(_file); var directory = _fileSystem.Path.GetDirectoryName(_file);
var fileName = Path.GetFileNameWithoutExtension(_file); var fileName = _fileSystem.Path.GetFileNameWithoutExtension(_file);
var extension = Path.GetExtension(_file); var extension = _fileSystem.Path.GetExtension(_file);
var path = Path.Combine(directory, fileName + ".bak" + extension); var path = _fileSystem.Path.Combine(directory, fileName + ".bak" + extension);
var uniquifier = 1; var uniquifier = 1;
while (File.Exists(path)) while (_fileSystem.File.Exists(path))
{ {
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + ".bak" + extension); path = _fileSystem.Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + ".bak" + extension);
} }
return path; return path;

View File

@@ -9,7 +9,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Threading; using System.Threading;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ImageResizer.Models; using ImageResizer.Models;
@@ -22,9 +22,11 @@ namespace ImageResizer.Properties
[JsonObject(MemberSerialization.OptIn)] [JsonObject(MemberSerialization.OptIn)]
public sealed partial class Settings : IDataErrorInfo, INotifyPropertyChanged public sealed partial class Settings : IDataErrorInfo, INotifyPropertyChanged
{ {
private static readonly IFileSystem _fileSystem = new FileSystem();
// Used to synchronize access to the settings.json file // Used to synchronize access to the settings.json file
private static Mutex _jsonMutex = new Mutex(); private static Mutex _jsonMutex = new Mutex();
private static string _settingsPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "ImageResizer", "settings.json"); private static string _settingsPath = _fileSystem.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "ImageResizer", "settings.json");
private string _fileNameFormat; private string _fileNameFormat;
private bool _shrinkOnly; private bool _shrinkOnly;
private int _selectedSizeIndex; private int _selectedSizeIndex;
@@ -384,25 +386,25 @@ namespace ImageResizer.Properties
jsonData += "}"; jsonData += "}";
// Create directory if it doesn't exist // Create directory if it doesn't exist
FileInfo file = new FileInfo(SettingsPath); IFileInfo file = _fileSystem.FileInfo.FromFileName(SettingsPath);
file.Directory.Create(); file.Directory.Create();
// write string to file // write string to file
File.WriteAllText(SettingsPath, jsonData); _fileSystem.File.WriteAllText(SettingsPath, jsonData);
_jsonMutex.ReleaseMutex(); _jsonMutex.ReleaseMutex();
} }
public void Reload() public void Reload()
{ {
_jsonMutex.WaitOne(); _jsonMutex.WaitOne();
if (!File.Exists(SettingsPath)) if (!_fileSystem.File.Exists(SettingsPath))
{ {
_jsonMutex.ReleaseMutex(); _jsonMutex.ReleaseMutex();
Save(); Save();
return; return;
} }
string jsonData = File.ReadAllText(SettingsPath); string jsonData = _fileSystem.File.ReadAllText(SettingsPath);
JObject imageResizerSettings = JObject.Parse(jsonData); JObject imageResizerSettings = JObject.Parse(jsonData);
// Replace the { "value": <Value> } with <Value> to match the Settings object format // Replace the { "value": <Value> } with <Value> to match the Settings object format

View File

@@ -5,11 +5,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Plugin.Folder.Sources; using Microsoft.Plugin.Folder.Sources;
using Microsoft.Plugin.Folder.Sources.Result; using Microsoft.Plugin.Folder.Sources.Result;
using Moq;
using NUnit.Framework; using NUnit.Framework;
namespace Microsoft.Plugin.Folder.UnitTests namespace Microsoft.Plugin.Folder.UnitTests
@@ -17,117 +16,45 @@ namespace Microsoft.Plugin.Folder.UnitTests
[TestFixture] [TestFixture]
public class InternalQueryFolderTests public class InternalQueryFolderTests
{ {
private static readonly HashSet<string> DirectoryExist = new HashSet<string>() private static IQueryFileSystemInfo _queryFileSystemInfoMock;
{ private static MockFileSystem _fileSystem;
@"c:",
@"c:\",
@"c:\Test\",
@"c:\Test\A\",
@"c:\Test\b\",
};
private static readonly HashSet<string> FilesExist = new HashSet<string>()
{
@"c:\bla.txt",
@"c:\Test\test.txt",
@"c:\Test\more-test.png",
};
private static Mock<IQueryFileSystemInfo> _queryFileSystemInfoMock;
[SetUp] [SetUp]
public void SetupMock() public void SetupMock()
{ {
var queryFileSystemInfoMock = new Mock<IQueryFileSystemInfo>(); // Note: This mock filesystem adds a 'c:\temp' directory.
queryFileSystemInfoMock.Setup(r => r.Exists(It.IsAny<string>())) _fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>()
.Returns<string>(path => ContainsDirectory(path));
queryFileSystemInfoMock.Setup(r => r.MatchFileSystemInfo(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns<string, string, bool>(MatchFileSystemInfo);
_queryFileSystemInfoMock = queryFileSystemInfoMock;
}
// Windows supports C:\\\\\ => C:\
private static bool ContainsDirectory(string path)
{
return DirectoryExist.Contains(TrimDirectoryEnd(path));
}
private static string TrimDirectoryEnd(string path)
{
var trimEnd = path.TrimEnd('\\');
if (path.EndsWith('\\'))
{ {
trimEnd += '\\'; { @"c:\bla.txt", new MockFileData(string.Empty) },
} { @"c:\Test\test.txt", new MockFileData(string.Empty) },
{ @"c:\Test\more-test.png", new MockFileData(string.Empty) },
{ @"c:\Test\A\deep-nested.png", new MockFileData(string.Empty) },
{ @"c:\Test\b\", new MockDirectoryData() },
});
return trimEnd; _queryFileSystemInfoMock = new QueryFileSystemInfo(_fileSystem.DirectoryInfo);
}
private static IEnumerable<DisplayFileInfo> MatchFileSystemInfo(string search, string incompleteName, bool isRecursive)
{
Func<string, bool> folderSearchFunc;
Func<string, bool> fileSearchFunc;
switch (isRecursive)
{
case false:
// Using Ordinal since this is internal
folderSearchFunc = s => s.Equals(search, StringComparison.Ordinal);
var regexSearch = TrimDirectoryEnd(search);
fileSearchFunc = s => Regex.IsMatch(s, $"^{Regex.Escape(regexSearch)}[^\\\\]*$");
break;
case true:
// Using Ordinal since this is internal
folderSearchFunc = s => s.StartsWith(search, StringComparison.Ordinal);
fileSearchFunc = s => s.StartsWith(search, StringComparison.Ordinal);
break;
}
var directories = DirectoryExist.Where(s => folderSearchFunc(s))
.Select(dir => new DisplayFileInfo()
{
Type = DisplayType.Directory,
FullName = dir,
});
var files = FilesExist.Where(s => fileSearchFunc(s))
.Select(file => new DisplayFileInfo()
{
Type = DisplayType.File,
FullName = file,
});
return directories.Concat(files);
} }
[Test] [Test]
public void Query_ThrowsException_WhenCalledNull() public void Query_ThrowsException_WhenCalledNull()
{ {
// Setup // Setup
var queryInternalDirectory = new QueryInternalDirectory(new FolderSettings(), _queryFileSystemInfoMock.Object); var queryInternalDirectory = new QueryInternalDirectory(new FolderSettings(), _queryFileSystemInfoMock, _fileSystem.Directory);
// Act & Assert // Act & Assert
Assert.Throws<ArgumentNullException>(() => queryInternalDirectory.Query(null).ToArray()); Assert.Throws<ArgumentNullException>(() => queryInternalDirectory.Query(null).ToArray());
} }
[TestCase(@"c", 0, 0, false, Reason = "String empty is nothing")] [TestCase(@"c", 0, 0, false, Reason = "String empty is nothing")]
[TestCase(@"c:", 1, 1, false, Reason = "Root without \\")] [TestCase(@"c:", 2, 1, false, Reason = "Root without \\")]
[TestCase(@"c:\", 1, 1, false, Reason = "Normal root")] [TestCase(@"c:\", 2, 1, false, Reason = "Normal root")]
[TestCase(@"c:\Test", 1, 2, false, Reason = "Select yourself")] [TestCase(@"c:\Test", 2, 2, false, Reason = "Select yourself")]
[TestCase(@"c:\>", 2, 2, true, Reason = "Max Folder test recursive")] [TestCase(@"c:\not-exist", 2, 1, false, Reason = "Folder not exist, return root")]
[TestCase(@"c:\Test>", 2, 2, true, Reason = "2 Folders recursive")]
[TestCase(@"c:\not-exist", 1, 1, false, Reason = "Folder not exist, return root")]
[TestCase(@"c:\not-exist>", 2, 2, true, Reason = "Folder not exist, return root recursive")]
[TestCase(@"c:\not-exist\not-exist2", 0, 0, false, Reason = "Folder not exist, return root")] [TestCase(@"c:\not-exist\not-exist2", 0, 0, false, Reason = "Folder not exist, return root")]
[TestCase(@"c:\not-exist\not-exist2>", 0, 0, false, Reason = "Folder not exist, return root recursive")] [TestCase(@"c:\bla.t", 2, 1, false, Reason = "Partial match file")]
[TestCase(@"c:\bla.t", 1, 1, false, Reason = "Partial match file")]
public void Query_WhenCalled(string search, int folders, int files, bool truncated) public void Query_WhenCalled(string search, int folders, int files, bool truncated)
{ {
const int maxFolderSetting = 2; const int maxFolderSetting = 3;
// Setup // Setup
var folderSettings = new FolderSettings() var folderSettings = new FolderSettings()
@@ -136,7 +63,42 @@ namespace Microsoft.Plugin.Folder.UnitTests
MaxFolderResults = maxFolderSetting, MaxFolderResults = maxFolderSetting,
}; };
var queryInternalDirectory = new QueryInternalDirectory(folderSettings, _queryFileSystemInfoMock.Object); var queryInternalDirectory = new QueryInternalDirectory(folderSettings, _queryFileSystemInfoMock, _fileSystem.Directory);
// Act
var isDriveOrSharedFolder = queryInternalDirectory.Query(search)
.ToLookup(r => r.GetType());
// Assert
Assert.AreEqual(files, isDriveOrSharedFolder[typeof(FileItemResult)].Count(), "File count doesn't match");
Assert.AreEqual(folders, isDriveOrSharedFolder[typeof(FolderItemResult)].Count(), "folder count doesn't match");
// Always check if there is less than max folders
Assert.LessOrEqual(isDriveOrSharedFolder[typeof(FileItemResult)].Count(), maxFolderSetting, "Files are not limited");
Assert.LessOrEqual(isDriveOrSharedFolder[typeof(FolderItemResult)].Count(), maxFolderSetting, "Folders are not limited");
// Checks if CreateOpenCurrentFolder is displayed
Assert.AreEqual(Math.Min(folders + files, 1), isDriveOrSharedFolder[typeof(CreateOpenCurrentFolderResult)].Count(), "CreateOpenCurrentFolder displaying is incorrect");
Assert.AreEqual(truncated, isDriveOrSharedFolder[typeof(TruncatedItemResult)].Count() == 1, "CreateOpenCurrentFolder displaying is incorrect");
}
[TestCase(@"c:\>", 3, 3, true, Reason = "Max Folder test recursive")]
[TestCase(@"c:\Test>", 3, 3, true, Reason = "2 Folders recursive")]
[TestCase(@"c:\not-exist>", 3, 3, true, Reason = "Folder not exist, return root recursive")]
[TestCase(@"c:\not-exist\not-exist2>", 0, 0, false, Reason = "Folder not exist, return root recursive")]
public void Query_Recursive_WhenCalled(string search, int folders, int files, bool truncated)
{
const int maxFolderSetting = 3;
// Setup
var folderSettings = new FolderSettings()
{
MaxFileResults = maxFolderSetting,
MaxFolderResults = maxFolderSetting,
};
var queryInternalDirectory = new QueryInternalDirectory(folderSettings, _queryFileSystemInfoMock, _fileSystem.Directory);
// Act // Act
var isDriveOrSharedFolder = queryInternalDirectory.Query(search) var isDriveOrSharedFolder = queryInternalDirectory.Query(search)

View File

@@ -14,6 +14,7 @@
<PackageReference Include="nunit" Version="3.12.0" /> <PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="12.2.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -5,7 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@@ -17,6 +17,7 @@ namespace Microsoft.Plugin.Folder
{ {
internal class ContextMenuLoader : IContextMenu internal class ContextMenuLoader : IContextMenu
{ {
private readonly IFileSystem _fileSystem = new FileSystem();
private readonly PluginInitContext _context; private readonly PluginInitContext _context;
public ContextMenuLoader(PluginInitContext context) public ContextMenuLoader(PluginInitContext context)
@@ -76,7 +77,7 @@ namespace Microsoft.Plugin.Folder
{ {
if (record.Type == ResultType.File) if (record.Type == ResultType.File)
{ {
Helper.OpenInConsole(Path.GetDirectoryName(record.FullPath)); Helper.OpenInConsole(_fileSystem.Path.GetDirectoryName(record.FullPath));
} }
else else
{ {

View File

@@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Windows.Controls; using System.Windows.Controls;
using ManagedCommon; using ManagedCommon;
@@ -21,9 +22,10 @@ namespace Microsoft.Plugin.Folder
public const string DeleteFileFolderImagePath = "Images\\delete.dark.png"; public const string DeleteFileFolderImagePath = "Images\\delete.dark.png";
public const string CopyImagePath = "Images\\copy.dark.png"; public const string CopyImagePath = "Images\\copy.dark.png";
private static readonly IFileSystem _fileSystem = new FileSystem();
private static readonly PluginJsonStorage<FolderSettings> _storage = new PluginJsonStorage<FolderSettings>(); private static readonly PluginJsonStorage<FolderSettings> _storage = new PluginJsonStorage<FolderSettings>();
private static readonly FolderSettings _settings = _storage.Load(); private static readonly FolderSettings _settings = _storage.Load();
private static readonly IQueryInternalDirectory _internalDirectory = new QueryInternalDirectory(_settings, new QueryFileSystemInfo()); private static readonly IQueryInternalDirectory _internalDirectory = new QueryInternalDirectory(_settings, new QueryFileSystemInfo(_fileSystem.DirectoryInfo), _fileSystem.Directory);
private static readonly FolderHelper _folderHelper = new FolderHelper(new DriveInformation(), new FolderLinksSettings(_settings)); private static readonly FolderHelper _folderHelper = new FolderHelper(new DriveInformation(), new FolderLinksSettings(_settings));
private static readonly ICollection<IFolderProcessor> _processors = new IFolderProcessor[] private static readonly ICollection<IFolderProcessor> _processors = new IFolderProcessor[]

View File

@@ -78,6 +78,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.Runtime" Version="4.3.1" /> <PackageReference Include="System.Runtime" Version="4.3.1" />
</ItemGroup> </ItemGroup>

View File

@@ -2,17 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using Wox.Infrastructure;
using Wox.Plugin;
using Wox.Plugin.Logger;
namespace Microsoft.Plugin.Folder namespace Microsoft.Plugin.Folder
{ {
public class SearchResult public class SearchResult

View File

@@ -3,12 +3,10 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Wox.Infrastructure.FileSystemHelper;
namespace Microsoft.Plugin.Folder.Sources namespace Microsoft.Plugin.Folder.Sources
{ {
public interface IQueryFileSystemInfo : IDirectoryWrapper public interface IQueryFileSystemInfo
{ {
IEnumerable<DisplayFileInfo> MatchFileSystemInfo(string search, string incompleteName, bool isRecursive); IEnumerable<DisplayFileInfo> MatchFileSystemInfo(string search, string incompleteName, bool isRecursive);
} }

View File

@@ -4,22 +4,22 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
namespace Microsoft.Plugin.Folder.Sources namespace Microsoft.Plugin.Folder.Sources
{ {
internal class DriveInformation : IDriveInformation internal class DriveInformation : IDriveInformation
{ {
private static readonly IFileSystem _fileSystem = new FileSystem();
private static readonly List<string> DriverNames = InitialDriverList().ToList(); private static readonly List<string> DriverNames = InitialDriverList().ToList();
[System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "Do not want to change the behavior of the application, but want to enforce static analysis")]
private static IEnumerable<string> InitialDriverList() private static IEnumerable<string> InitialDriverList()
{ {
var directorySeparatorChar = System.IO.Path.DirectorySeparatorChar;
// Using InvariantCulture since this is internal // Using InvariantCulture since this is internal
return DriveInfo.GetDrives() var directorySeparatorChar = _fileSystem.Path.DirectorySeparatorChar;
return _fileSystem.DriveInfo.GetDrives()
.Select(driver => driver.Name.ToLower(CultureInfo.InvariantCulture).TrimEnd(directorySeparatorChar)); .Select(driver => driver.Name.ToLower(CultureInfo.InvariantCulture).TrimEnd(directorySeparatorChar));
} }

View File

@@ -2,20 +2,26 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using Wox.Infrastructure.FileSystemHelper;
namespace Microsoft.Plugin.Folder.Sources namespace Microsoft.Plugin.Folder.Sources
{ {
public class QueryFileSystemInfo : DirectoryWrapper, IQueryFileSystemInfo public class QueryFileSystemInfo : IQueryFileSystemInfo
{ {
private readonly IDirectoryInfoFactory _directoryInfoFactory;
public QueryFileSystemInfo(IDirectoryInfoFactory directoryInfoFactory)
{
_directoryInfoFactory = directoryInfoFactory;
}
public IEnumerable<DisplayFileInfo> MatchFileSystemInfo(string search, string incompleteName, bool isRecursive) public IEnumerable<DisplayFileInfo> MatchFileSystemInfo(string search, string incompleteName, bool isRecursive)
{ {
// search folder and add results // search folder and add results
var directoryInfo = new DirectoryInfo(search); var directoryInfo = _directoryInfoFactory.FromDirectoryName(search);
var fileSystemInfos = directoryInfo.EnumerateFileSystemInfos(incompleteName, new EnumerationOptions() var fileSystemInfos = directoryInfo.EnumerateFileSystemInfos(incompleteName, new EnumerationOptions()
{ {
MatchType = MatchType.Win32, MatchType = MatchType.Win32,
@@ -30,7 +36,7 @@ namespace Microsoft.Plugin.Folder.Sources
.Select(CreateDisplayFileInfo); .Select(CreateDisplayFileInfo);
} }
private static DisplayFileInfo CreateDisplayFileInfo(FileSystemInfo fileSystemInfo) private static DisplayFileInfo CreateDisplayFileInfo(IFileSystemInfo fileSystemInfo)
{ {
return new DisplayFileInfo() return new DisplayFileInfo()
{ {
@@ -40,9 +46,9 @@ namespace Microsoft.Plugin.Folder.Sources
}; };
} }
private static DisplayType GetDisplayType(FileSystemInfo fileSystemInfo) private static DisplayType GetDisplayType(IFileSystemInfo fileSystemInfo)
{ {
if (fileSystemInfo is DirectoryInfo) if (fileSystemInfo is IDirectoryInfo)
{ {
return DisplayType.Directory; return DisplayType.Directory;
} }

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using ManagedCommon; using ManagedCommon;
using Microsoft.Plugin.Folder.Sources.Result; using Microsoft.Plugin.Folder.Sources.Result;
@@ -18,6 +19,7 @@ namespace Microsoft.Plugin.Folder.Sources
{ {
private readonly FolderSettings _settings; private readonly FolderSettings _settings;
private readonly IQueryFileSystemInfo _queryFileSystemInfo; private readonly IQueryFileSystemInfo _queryFileSystemInfo;
private readonly IDirectory _directory;
private static readonly HashSet<char> SpecialSearchChars = new HashSet<char> private static readonly HashSet<char> SpecialSearchChars = new HashSet<char>
{ {
@@ -26,10 +28,11 @@ namespace Microsoft.Plugin.Folder.Sources
private static string _warningIconPath; private static string _warningIconPath;
public QueryInternalDirectory(FolderSettings folderSettings, IQueryFileSystemInfo queryFileSystemInfo) public QueryInternalDirectory(FolderSettings folderSettings, IQueryFileSystemInfo queryFileSystemInfo, IDirectory directory)
{ {
_settings = folderSettings; _settings = folderSettings;
_queryFileSystemInfo = queryFileSystemInfo; _queryFileSystemInfo = queryFileSystemInfo;
_directory = directory;
} }
private static bool HasSpecialChars(string search) private static bool HasSpecialChars(string search)
@@ -47,7 +50,7 @@ namespace Microsoft.Plugin.Folder.Sources
private (string search, string incompleteName) Process(string search) private (string search, string incompleteName) Process(string search)
{ {
string incompleteName = string.Empty; string incompleteName = string.Empty;
if (HasSpecialChars(search) || !_queryFileSystemInfo.Exists($@"{search}\")) if (HasSpecialChars(search) || !_directory.Exists($@"{search}\"))
{ {
// if folder doesn't exist, we want to take the last part and use it afterwards to help the user // if folder doesn't exist, we want to take the last part and use it afterwards to help the user
// find the right folder. // find the right folder.
@@ -64,7 +67,7 @@ namespace Microsoft.Plugin.Folder.Sources
incompleteName = search.Substring(index + 1) incompleteName = search.Substring(index + 1)
.ToLower(CultureInfo.InvariantCulture) + "*"; .ToLower(CultureInfo.InvariantCulture) + "*";
search = search.Substring(0, index + 1); search = search.Substring(0, index + 1);
if (!_queryFileSystemInfo.Exists(search)) if (!_directory.Exists(search))
{ {
return default; return default;
} }

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using Wox.Infrastructure; using Wox.Infrastructure;
using Wox.Plugin; using Wox.Plugin;
@@ -13,15 +13,27 @@ namespace Microsoft.Plugin.Folder.Sources.Result
{ {
private static readonly IShellAction ShellAction = new ShellAction(); private static readonly IShellAction ShellAction = new ShellAction();
private readonly IPath _path;
public FileItemResult()
: this(new FileSystem().Path)
{
}
private FileItemResult(IPath path)
{
_path = path;
}
public string FilePath { get; set; } public string FilePath { get; set; }
public string Title => Path.GetFileName(FilePath); public string Title => _path.GetFileName(FilePath);
public string Search { get; set; } public string Search { get; set; }
public Wox.Plugin.Result Create(IPublicAPI contextApi) public Wox.Plugin.Result Create(IPublicAPI contextApi)
{ {
var result = new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData) var result = new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, _path.GetFileName(FilePath)).MatchData)
{ {
Title = Title, Title = Title,

View File

@@ -5,7 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@@ -19,6 +19,8 @@ namespace Microsoft.Plugin.Indexer
{ {
internal class ContextMenuLoader : IContextMenu internal class ContextMenuLoader : IContextMenu
{ {
private readonly IPath _path = new FileSystem().Path;
private readonly PluginInitContext _context; private readonly PluginInitContext _context;
public enum ResultType public enum ResultType
@@ -41,7 +43,7 @@ namespace Microsoft.Plugin.Indexer
var contextMenus = new List<ContextMenuResult>(); var contextMenus = new List<ContextMenuResult>();
if (selectedResult.ContextData is SearchResult record) if (selectedResult.ContextData is SearchResult record)
{ {
ResultType type = Path.HasExtension(record.Path) ? ResultType.File : ResultType.Folder; ResultType type = _path.HasExtension(record.Path) ? ResultType.File : ResultType.Folder;
if (type == ResultType.File) if (type == ResultType.File)
{ {
@@ -95,7 +97,7 @@ namespace Microsoft.Plugin.Indexer
{ {
if (type == ResultType.File) if (type == ResultType.File)
{ {
Helper.OpenInConsole(Path.GetDirectoryName(record.Path)); Helper.OpenInConsole(_path.GetDirectoryName(record.Path));
} }
else else
{ {
@@ -147,7 +149,7 @@ namespace Microsoft.Plugin.Indexer
// Function to test if the file can be run as admin // Function to test if the file can be run as admin
private bool CanFileBeRunAsAdmin(string path) private bool CanFileBeRunAsAdmin(string path)
{ {
string fileExtension = Path.GetExtension(path); string fileExtension = _path.GetExtension(path);
foreach (string extension in appExtensions) foreach (string extension in appExtensions)
{ {
// Using OrdinalIgnoreCase since this is internal // Using OrdinalIgnoreCase since this is internal

View File

@@ -7,7 +7,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Controls; using System.Windows.Controls;
@@ -24,6 +24,8 @@ namespace Microsoft.Plugin.Indexer
{ {
internal class Main : ISettingProvider, IPlugin, ISavable, IPluginI18n, IContextMenu, IDisposable, IDelayedExecutionPlugin internal class Main : ISettingProvider, IPlugin, ISavable, IPluginI18n, IContextMenu, IDisposable, IDelayedExecutionPlugin
{ {
private static readonly IFileSystem _fileSystem = new FileSystem();
// This variable contains metadata about the Plugin // This variable contains metadata about the Plugin
private PluginInitContext _context; private PluginInitContext _context;
@@ -38,7 +40,7 @@ namespace Microsoft.Plugin.Indexer
private readonly WindowsSearchAPI _api = new WindowsSearchAPI(_search); private readonly WindowsSearchAPI _api = new WindowsSearchAPI(_search);
// To obtain information regarding the drives that are indexed // To obtain information regarding the drives that are indexed
private readonly IndexerDriveDetection _driveDetection = new IndexerDriveDetection(new RegistryWrapper(), new DriveInfoWrapper()); private readonly IndexerDriveDetection _driveDetection = new IndexerDriveDetection(new RegistryWrapper(), new DriveDetection.DriveInfoWrapper());
// Reserved keywords in oleDB // Reserved keywords in oleDB
private readonly string reservedStringPattern = @"^[\/\\\$\%]+$|^.*[<>].*$"; private readonly string reservedStringPattern = @"^[\/\\\$\%]+$|^.*[<>].*$";
@@ -117,7 +119,7 @@ namespace Microsoft.Plugin.Indexer
string workingDir = null; string workingDir = null;
if (_settings.UseLocationAsWorkingDir) if (_settings.UseLocationAsWorkingDir)
{ {
workingDir = Path.GetDirectoryName(path); workingDir = _fileSystem.Path.GetDirectoryName(path);
} }
Result r = new Result(); Result r = new Result();
@@ -151,7 +153,7 @@ namespace Microsoft.Plugin.Indexer
r.ContextData = searchResult; r.ContextData = searchResult;
// If the result is a directory, then it's display should show a directory. // If the result is a directory, then it's display should show a directory.
if (Directory.Exists(path)) if (_fileSystem.Directory.Exists(path))
{ {
r.QueryTextDisplay = path; r.QueryTextDisplay = path;
} }

View File

@@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using Microsoft.Plugin.Program.Programs; using Microsoft.Plugin.Program.Programs;
using Microsoft.Plugin.Program.Storage; using Microsoft.Plugin.Program.Storage;
@@ -209,7 +210,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path); FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path);
// File.ReadAllLines must be mocked for url applications // File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFileWrapper>(); var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" }); mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" });
Win32Program.FileWrapper = mockFile.Object; Win32Program.FileWrapper = mockFile.Object;
@@ -256,7 +257,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path); FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
// File.ReadAllLines must be mocked for url applications // File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFileWrapper>(); var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" }); mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" });
Win32Program.FileWrapper = mockFile.Object; Win32Program.FileWrapper = mockFile.Object;
@@ -279,7 +280,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath); RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath);
// File.ReadAllLines must be mocked for url applications // File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFileWrapper>(); var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" }); mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" });
Win32Program.FileWrapper = mockFile.Object; Win32Program.FileWrapper = mockFile.Object;

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security; using System.Security;

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.IO; using System.IO.Abstractions;
namespace Microsoft.Plugin.Program namespace Microsoft.Plugin.Program
{ {
@@ -16,11 +16,13 @@ namespace Microsoft.Plugin.Program
/// </remarks> /// </remarks>
public class ProgramSource public class ProgramSource
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private string name; private string name;
public string Location { get; set; } public string Location { get; set; }
public string Name { get => name ?? new DirectoryInfo(Location).Name; set => name = value; } public string Name { get => name ?? FileSystem.DirectoryInfo.FromDirectoryName(Location).Name; set => name = value; }
public bool Enabled { get; set; } = true; public bool Enabled { get; set; } = true;

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -19,6 +19,8 @@ namespace Microsoft.Plugin.Program.Programs
[Serializable] [Serializable]
public partial class UWP public partial class UWP
{ {
private static readonly IPath Path = new FileSystem().Path;
public string Name { get; } public string Name { get; }
public string FullName { get; } public string FullName { get; }

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -31,6 +32,10 @@ namespace Microsoft.Plugin.Program.Programs
[Serializable] [Serializable]
public class UWPApplication : IProgram public class UWPApplication : IProgram
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
public string AppListEntry { get; set; } public string AppListEntry { get; set; }
public string UniqueIdentifier { get; set; } public string UniqueIdentifier { get; set; }

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security; using System.Security;
@@ -20,12 +21,18 @@ using Wox.Infrastructure;
using Wox.Infrastructure.FileSystemHelper; using Wox.Infrastructure.FileSystemHelper;
using Wox.Plugin; using Wox.Plugin;
using Wox.Plugin.Logger; using Wox.Plugin.Logger;
using DirectoryWrapper = Wox.Infrastructure.FileSystemHelper.DirectoryWrapper;
namespace Microsoft.Plugin.Program.Programs namespace Microsoft.Plugin.Program.Programs
{ {
[Serializable] [Serializable]
public class Win32Program : IProgram public class Win32Program : IProgram
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IDirectory Directory = FileSystem.Directory;
public string Name { get; set; } public string Name { get; set; }
public string UniqueIdentifier { get; set; } public string UniqueIdentifier { get; set; }
@@ -57,7 +64,7 @@ namespace Microsoft.Plugin.Program.Programs
// Wrappers for File Operations // Wrappers for File Operations
public static IFileVersionInfoWrapper FileVersionInfoWrapper { get; set; } = new FileVersionInfoWrapper(); public static IFileVersionInfoWrapper FileVersionInfoWrapper { get; set; } = new FileVersionInfoWrapper();
public static IFileWrapper FileWrapper { get; set; } = new FileWrapper(); public static IFile FileWrapper { get; set; } = new FileSystem().File;
public static IShellLinkHelper Helper { get; set; } = new ShellLinkHelper(); public static IShellLinkHelper Helper { get; set; } = new ShellLinkHelper();

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
using Wox.Plugin.Logger; using Wox.Plugin.Logger;
@@ -17,6 +18,9 @@ namespace Microsoft.Plugin.Program.Storage
{ {
internal class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository internal class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private const string LnkExtension = ".lnk"; private const string LnkExtension = ".lnk";
private const string UrlExtension = ".url"; private const string UrlExtension = ".url";

View File

@@ -8,6 +8,7 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Windows.Input; using System.Windows.Input;
@@ -23,6 +24,11 @@ namespace Microsoft.Plugin.Shell
{ {
public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu, ISavable public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu, ISavable
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IDirectory Directory = FileSystem.Directory;
private readonly ShellPluginSettings _settings; private readonly ShellPluginSettings _settings;
private readonly PluginJsonStorage<ShellPluginSettings> _storage; private readonly PluginJsonStorage<ShellPluginSettings> _storage;

View File

@@ -5,7 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO.Abstractions;
using System.Text; using System.Text;
using ManagedCommon; using ManagedCommon;
using Microsoft.Plugin.Uri.UriHelper; using Microsoft.Plugin.Uri.UriHelper;
@@ -17,6 +17,10 @@ namespace Microsoft.Plugin.Uri
{ {
public class Main : IPlugin, IPluginI18n, IContextMenu, ISavable, IDisposable public class Main : IPlugin, IPluginI18n, IContextMenu, ISavable, IDisposable
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private readonly ExtendedUriParser _uriParser; private readonly ExtendedUriParser _uriParser;
private readonly UriResolver _uriResolver; private readonly UriResolver _uriResolver;
private readonly PluginJsonStorage<UriSettings> _storage; private readonly PluginJsonStorage<UriSettings> _storage;

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.IO.Pipes; using System.IO.Pipes;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@@ -29,6 +30,10 @@ namespace PowerLauncher.Helper
public static class SingleInstance<TApplication> public static class SingleInstance<TApplication>
where TApplication : Application, ISingleInstanceApp where TApplication : Application, ISingleInstanceApp
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
/// <summary> /// <summary>
/// String delimiter used in channel names. /// String delimiter used in channel names.
/// </summary> /// </summary>

View File

@@ -6,6 +6,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
@@ -21,6 +22,9 @@ namespace PowerLauncher
{ {
internal partial class ReportWindow internal partial class ReportWindow
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IFile File = FileSystem.File;
public ReportWindow(Exception exception) public ReportWindow(Exception exception)
{ {
InitializeComponent(); InitializeComponent();

View File

@@ -4,6 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Threading; using System.Threading;
using System.Windows.Input; using System.Windows.Input;
using ManagedCommon; using ManagedCommon;
@@ -26,14 +27,14 @@ namespace PowerLauncher
private const int MaxRetries = 10; private const int MaxRetries = 10;
private static readonly object _watcherSyncObject = new object(); private static readonly object _watcherSyncObject = new object();
private readonly FileSystemWatcher _watcher; private readonly IFileSystemWatcher _watcher;
private readonly PowerToysRunSettings _settings; private readonly PowerToysRunSettings _settings;
private readonly ThemeManager _themeManager; private readonly ThemeManager _themeManager;
public SettingsWatcher(PowerToysRunSettings settings, ThemeManager themeManager) public SettingsWatcher(PowerToysRunSettings settings, ThemeManager themeManager)
{ {
_settingsUtils = new SettingsUtils(new SystemIOProvider()); _settingsUtils = new SettingsUtils();
_settings = settings; _settings = settings;
_themeManager = themeManager; _themeManager = themeManager;

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -15,6 +15,11 @@ namespace Wox.Core.Plugin
{ {
internal abstract class PluginConfig internal abstract class PluginConfig
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IDirectory Directory = FileSystem.Directory;
private const string PluginConfigName = "plugin.json"; private const string PluginConfigName = "plugin.json";
private static readonly List<PluginMetadata> PluginMetadatas = new List<PluginMetadata>(); private static readonly List<PluginMetadata> PluginMetadatas = new List<PluginMetadata>();

View File

@@ -4,6 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using System.Windows; using System.Windows;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
@@ -15,6 +16,11 @@ namespace Wox.Core.Plugin
{ {
internal class PluginInstaller internal class PluginInstaller
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IDirectory Directory = FileSystem.Directory;
internal static void Install(string path) internal static void Install(string path)
{ {
if (File.Exists(path)) if (File.Exists(path))
@@ -35,7 +41,7 @@ namespace Wox.Core.Plugin
} }
PluginMetadata plugin = GetMetadataFromJson(tempFolder); PluginMetadata plugin = GetMetadataFromJson(tempFolder);
if (plugin == null || plugin.Name == null) if (plugin?.Name == null)
{ {
MessageBox.Show("Install failed: plugin config is invalid"); MessageBox.Show("Install failed: plugin config is invalid");
return; return;
@@ -196,7 +202,7 @@ namespace Wox.Core.Plugin
{ {
if ((File.Exists(strDirectory + directoryName + fileName) && overWrite) || (!File.Exists(strDirectory + directoryName + fileName))) if ((File.Exists(strDirectory + directoryName + fileName) && overWrite) || (!File.Exists(strDirectory + directoryName + fileName)))
{ {
using (FileStream streamWriter = File.Create(strDirectory + directoryName + fileName)) using (Stream streamWriter = File.Create(strDirectory + directoryName + fileName))
{ {
byte[] data = new byte[2048]; byte[] data = new byte[2048];
while (true) while (true)

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -23,6 +23,9 @@ namespace Wox.Core.Plugin
/// </summary> /// </summary>
public static class PluginManager public static class PluginManager
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IDirectory Directory = FileSystem.Directory;
private static IEnumerable<PluginPair> _contextMenuPlugins = new List<PluginPair>(); private static IEnumerable<PluginPair> _contextMenuPlugins = new List<PluginPair>();
/// <summary> /// <summary>

View File

@@ -4,18 +4,27 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Abstractions;
namespace Wox.Infrastructure.FileSystemHelper namespace Wox.Infrastructure.FileSystemHelper
{ {
public class FileVersionInfoWrapper : IFileVersionInfoWrapper public class FileVersionInfoWrapper : IFileVersionInfoWrapper
{ {
private readonly IFile _file;
public FileVersionInfoWrapper() public FileVersionInfoWrapper()
: this(new FileSystem().File)
{ {
} }
public FileVersionInfoWrapper(IFile file)
{
_file = file;
}
public FileVersionInfo GetVersionInfo(string path) public FileVersionInfo GetVersionInfo(string path)
{ {
if (File.Exists(path)) if (_file.Exists(path))
{ {
return FileVersionInfo.GetVersionInfo(path); return FileVersionInfo.GetVersionInfo(path);
} }

View File

@@ -1,32 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Security;
using Wox.Plugin.Logger;
namespace Wox.Infrastructure.FileSystemHelper
{
public class FileWrapper : IFileWrapper
{
public FileWrapper()
{
}
public string[] ReadAllLines(string path)
{
try
{
return File.ReadAllLines(path);
}
catch (System.Exception ex) when (ex is SecurityException || ex is UnauthorizedAccessException || ex is IOException)
{
Log.Info($"Unable to read File: {path}| {ex.Message}", GetType());
return new string[] { string.Empty };
}
}
}
}

View File

@@ -1,11 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Wox.Infrastructure.FileSystemHelper
{
public interface IFileWrapper
{
string[] ReadAllLines(string path);
}
}

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
@@ -14,6 +14,12 @@ namespace Wox.Infrastructure
{ {
public static class Helper public static class Helper
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IFileInfoFactory FileInfo = FileSystem.FileInfo;
private static readonly IDirectory Directory = FileSystem.Directory;
/// <summary> /// <summary>
/// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy /// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy
/// </summary> /// </summary>
@@ -54,8 +60,8 @@ namespace Wox.Infrastructure
} }
else else
{ {
var time1 = new FileInfo(bundledDataPath).LastWriteTimeUtc; var time1 = FileInfo.FromFileName(bundledDataPath).LastWriteTimeUtc;
var time2 = new FileInfo(dataPath).LastWriteTimeUtc; var time2 = FileInfo.FromFileName(dataPath).LastWriteTimeUtc;
if (time1 != time2) if (time1 != time2)
{ {
File.Copy(bundledDataPath, dataPath, true); File.Copy(bundledDataPath, dataPath, true);

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -21,6 +21,11 @@ namespace Wox.Infrastructure.Image
{ {
public static class ImageLoader public static class ImageLoader
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private static readonly IDirectory Directory = FileSystem.Directory;
private static readonly ImageCache ImageCache = new ImageCache(); private static readonly ImageCache ImageCache = new ImageCache();
private static readonly ConcurrentDictionary<string, string> GuidToKey = new ConcurrentDictionary<string, string>(); private static readonly ConcurrentDictionary<string, string> GuidToKey = new ConcurrentDictionary<string, string>();

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
using System.Windows.Interop; using System.Windows.Interop;
@@ -24,6 +24,9 @@ namespace Wox.Infrastructure.Image
public static class WindowsThumbnailProvider public static class WindowsThumbnailProvider
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
// Based on https://stackoverflow.com/questions/21751747/extract-thumbnail-for-any-file-in-windows // Based on https://stackoverflow.com/questions/21751747/extract-thumbnail-for-any-file-in-windows
private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93"; private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";

View File

@@ -4,6 +4,7 @@
using System; using System;
using System.IO; using System.IO;
using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters;
@@ -19,18 +20,28 @@ namespace Wox.Infrastructure.Storage
/// </summary> /// </summary>
public class BinaryStorage<T> : IStorage<T> public class BinaryStorage<T> : IStorage<T>
{ {
private readonly IFileSystem _fileSystem;
// This storage helper returns whether or not to delete the binary storage items // This storage helper returns whether or not to delete the binary storage items
private const int _binaryStorage = 0; private const int _binaryStorage = 0;
private StoragePowerToysVersionInfo _storageHelper; private StoragePowerToysVersionInfo _storageHelper;
public BinaryStorage(string filename) public BinaryStorage(string filename)
: this(filename, new FileSystem())
{ {
}
public BinaryStorage(string filename, IFileSystem fileSystem)
{
_fileSystem = fileSystem;
const string directoryName = "Cache"; const string directoryName = "Cache";
var directoryPath = Path.Combine(Constant.DataDirectory, directoryName); var path = _fileSystem.Path;
var directoryPath = path.Combine(Constant.DataDirectory, directoryName);
Helper.ValidateDirectory(directoryPath); Helper.ValidateDirectory(directoryPath);
const string fileSuffix = ".cache"; const string fileSuffix = ".cache";
FilePath = Path.Combine(directoryPath, $"{filename}{fileSuffix}"); FilePath = path.Combine(directoryPath, $"{filename}{fileSuffix}");
} }
public string FilePath { get; } public string FilePath { get; }
@@ -42,17 +53,17 @@ namespace Wox.Infrastructure.Storage
// Depending on the version number of the previously installed PT Run, delete the cache if it is found to be incompatible // Depending on the version number of the previously installed PT Run, delete the cache if it is found to be incompatible
if (_storageHelper.ClearCache) if (_storageHelper.ClearCache)
{ {
if (File.Exists(FilePath)) if (_fileSystem.File.Exists(FilePath))
{ {
File.Delete(FilePath); _fileSystem.File.Delete(FilePath);
Log.Info($"Deleting cached data at <{FilePath}>", GetType()); Log.Info($"Deleting cached data at <{FilePath}>", GetType());
} }
} }
if (File.Exists(FilePath)) if (_fileSystem.File.Exists(FilePath))
{ {
if (new FileInfo(FilePath).Length == 0) if (_fileSystem.FileInfo.FromFileName(FilePath).Length == 0)
{ {
Log.Error($"Zero length cache file <{FilePath}>", GetType()); Log.Error($"Zero length cache file <{FilePath}>", GetType());
@@ -60,7 +71,7 @@ namespace Wox.Infrastructure.Storage
return defaultData; return defaultData;
} }
using (var stream = new FileStream(FilePath, FileMode.Open)) using (var stream = _fileSystem.FileStream.Create(FilePath, FileMode.Open))
{ {
var d = Deserialize(stream, defaultData); var d = Deserialize(stream, defaultData);
return d; return d;
@@ -76,7 +87,7 @@ namespace Wox.Infrastructure.Storage
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
private T Deserialize(FileStream stream, T defaultData) private T Deserialize(Stream stream, T defaultData)
{ {
// http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception // http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

View File

@@ -5,6 +5,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Abstractions;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Plugin.Logger; using Wox.Plugin.Logger;
@@ -15,6 +16,10 @@ namespace Wox.Infrastructure.Storage
/// </summary> /// </summary>
public class JsonStorage<T> public class JsonStorage<T>
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
private readonly JsonSerializerSettings _serializerSettings; private readonly JsonSerializerSettings _serializerSettings;
private T _data; private T _data;

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.IO; using System.IO.Abstractions;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Infrastructure.Storage namespace Wox.Infrastructure.Storage
@@ -10,6 +10,9 @@ namespace Wox.Infrastructure.Storage
public class PluginJsonStorage<T> : JsonStorage<T> public class PluginJsonStorage<T> : JsonStorage<T>
where T : new() where T : new()
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
public PluginJsonStorage() public PluginJsonStorage()
{ {
// C# related, add python related below // C# related, add python related below

View File

@@ -3,12 +3,15 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
namespace Wox.Infrastructure.Storage namespace Wox.Infrastructure.Storage
{ {
public class StoragePowerToysVersionInfo public class StoragePowerToysVersionInfo
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IFile File = FileSystem.File;
// This detail is accessed by the storage items and is used to decide if the cache must be deleted or not // This detail is accessed by the storage items and is used to decide if the cache must be deleted or not
public bool ClearCache { get; set; } public bool ClearCache { get; set; }

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.IO; using System.IO.Abstractions;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.Infrastructure.Storage namespace Wox.Infrastructure.Storage
@@ -10,6 +10,9 @@ namespace Wox.Infrastructure.Storage
public class WoxJsonStorage<T> : JsonStorage<T> public class WoxJsonStorage<T> : JsonStorage<T>
where T : new() where T : new()
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
public WoxJsonStorage() public WoxJsonStorage()
{ {
var directoryPath = Path.Combine(Constant.DataDirectory, DirectoryName); var directoryPath = Path.Combine(Constant.DataDirectory, DirectoryName);

View File

@@ -62,6 +62,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="NLog.Schema" Version="4.7.4" /> <PackageReference Include="NLog.Schema" Version="4.7.4" />
<PackageReference Include="System.Drawing.Common" Version="4.7.0" /> <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.Runtime" Version="4.3.1" /> <PackageReference Include="System.Runtime" Version="4.3.1" />
</ItemGroup> </ItemGroup>

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
namespace Wox.Plugin namespace Wox.Plugin
@@ -26,6 +26,10 @@ namespace Wox.Plugin
} }
} }
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IDirectory Directory = FileSystem.Directory;
public const string ExeFileName = "PowerLauncher"; public const string ExeFileName = "PowerLauncher";
public const string ModuleLocation = "Microsoft\\PowerToys\\PowerToys Run"; public const string ModuleLocation = "Microsoft\\PowerToys\\PowerToys Run";
public const string Plugins = "Plugins"; public const string Plugins = "Plugins";

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO; using System.IO.Abstractions;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using NLog; using NLog;
using NLog.Config; using NLog.Config;
@@ -13,6 +13,10 @@ namespace Wox.Plugin.Logger
{ {
public static class Log public static class Log
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IDirectory Directory = FileSystem.Directory;
public const string DirectoryName = "Logs"; public const string DirectoryName = "Logs";
public static string CurrentLogDirectory { get; } public static string CurrentLogDirectory { get; }

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO.Abstractions;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Wox.Plugin namespace Wox.Plugin
@@ -12,6 +12,9 @@ namespace Wox.Plugin
[JsonObject(MemberSerialization.OptOut)] [JsonObject(MemberSerialization.OptOut)]
public class PluginMetadata : BaseModel public class PluginMetadata : BaseModel
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private string _pluginDirectory; private string _pluginDirectory;
private List<string> _actionKeywords; private List<string> _actionKeywords;

View File

@@ -5,7 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO.Abstractions;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
@@ -13,6 +13,9 @@ namespace Wox.Plugin
{ {
public class Result public class Result
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private string _title; private string _title;
private ToolTipData _toolTipData; private ToolTipData _toolTipData;
private string _pluginDirectory; private string _pluginDirectory;

View File

@@ -1,131 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using Wox.Plugin.Logger;
using Wox.Plugin.Properties;
namespace Wox.Plugin.SharedCommands
{
public static class FilesFolders
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
public static void Copy(this string sourcePath, string targetPath)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourcePath);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourcePath);
}
try
{
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(targetPath, file.Name);
file.CopyTo(temppath, false);
}
// Recursively copy subdirectories by calling itself on each subdirectory until there are no more to copy
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(targetPath, subdir.Name);
Copy(subdir.FullName, temppath);
}
}
#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
{
string error = $"Copying path {targetPath} has failed";
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
#if DEBUG
throw;
#else
// Using CurrentCulture since this is user facing
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_copy_failed, targetPath));
RemoveFolder(targetPath);
#endif
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath)
{
try
{
var fromDir = new DirectoryInfo(fromPath);
var toDir = new DirectoryInfo(toPath);
if (fromDir.GetFiles("*", SearchOption.AllDirectories).Length != toDir.GetFiles("*", SearchOption.AllDirectories).Length)
{
return false;
}
if (fromDir.GetDirectories("*", SearchOption.AllDirectories).Length != toDir.GetDirectories("*", SearchOption.AllDirectories).Length)
{
return false;
}
return true;
}
#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
{
string error = $"Unable to verify folders and files between {fromPath} and {toPath}";
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
#if DEBUG
throw;
#else
// Using CurrentCulture since this is user facing
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_verifybothfolderfilesequal_failed, fromPath, toPath));
return false;
#endif
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Suppressing this to enable FxCop. We are logging the exception, and going forward general exceptions should not be caught")]
public static void RemoveFolder(this string path)
{
try
{
if (Directory.Exists(path))
{
Directory.Delete(path, true);
}
}
#pragma warning disable CS0168 // Variable is declared but never used. Due to #if debug vs release statement
catch (Exception e)
#pragma warning restore CS0168 // Variable is declared but never used
{
string error = $"Not able to delete folder {path}";
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
#if DEBUG
throw;
#else
// Using CurrentCulture since this is user facing
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_removefolder_failed, path));
#endif
}
}
}
}

View File

@@ -1,78 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Wox.Plugin.SharedCommands
{
public static class SearchWeb
{
/// <summary>
/// Opens search in a new browser. If no browser path is passed in then Chrome is used.
/// Leave browser path blank to use Chrome.
/// </summary>
public static void NewBrowserWindow(this Uri url, string browserPath)
{
if (url == null)
{
throw new ArgumentNullException(nameof(url));
}
var browserExecutableName = browserPath?
.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None)
.Last();
var browser = string.IsNullOrEmpty(browserExecutableName) ? "chrome" : browserPath;
// Internet Explorer will open url in new browser window, and does not take the --new-window parameter
var browserArguments = browserExecutableName == "iexplore.exe" ? url.AbsoluteUri : "--new-window " + url.AbsoluteUri;
try
{
Process.Start(browser, browserArguments);
}
catch (System.ComponentModel.Win32Exception)
{
var psi = new ProcessStartInfo
{
FileName = url.AbsoluteUri,
UseShellExecute = true,
};
Process.Start(psi);
}
}
/// <summary>
/// Opens search as a tab in the default browser chosen in Windows settings.
/// </summary>
public static void NewTabInBrowser(this Uri url, string browserPath)
{
if (url == null)
{
throw new ArgumentNullException(nameof(url));
}
try
{
if (!string.IsNullOrEmpty(browserPath))
{
Process.Start(browserPath, url.AbsoluteUri);
}
else
{
Process.Start(url.AbsoluteUri);
}
}
// This error may be thrown for Process.Start(browserPath, url)
catch (System.ComponentModel.Win32Exception)
{
Process.Start(url.AbsoluteUri);
}
}
}
}

View File

@@ -2,8 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.IO;
using Markdig; using Markdig;
using Markdig.Extensions.Figures; using Markdig.Extensions.Figures;
using Markdig.Extensions.Tables; using Markdig.Extensions.Tables;

View File

@@ -137,6 +137,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="..\..\..\codeAnalysis\StyleCop.json"> <AdditionalFiles Include="..\..\..\codeAnalysis\StyleCop.json">

View File

@@ -4,7 +4,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO.Abstractions;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Forms; using System.Windows.Forms;
using Common; using Common;
@@ -21,6 +21,10 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
/// </summary> /// </summary>
public class MarkdownPreviewHandlerControl : FormHandlerControl public class MarkdownPreviewHandlerControl : FormHandlerControl
{ {
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private static readonly IFile File = FileSystem.File;
/// <summary> /// <summary>
/// Extension to modify markdown AST. /// Extension to modify markdown AST.
/// </summary> /// </summary>

View File

@@ -148,6 +148,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes; using System.Runtime.InteropServices.ComTypes;

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
namespace Common namespace Common

Some files were not shown because too many files have changed in this diff Show More