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>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
<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.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Abstractions;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
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 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}"));
}
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}");
_file = file ?? throw new ArgumentNullException(nameof(file));
_settingsPath = settingPath;
}
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>
@@ -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
// 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
var jsonSettingsString = _ioProvider.ReadAllText(GetSettingsPath(powertoyFolderName, fileName)).Trim('\0');
var jsonSettingsString = _file.ReadAllText(_settingsPath.GetSettingsPath(powertoyFolderName, fileName)).Trim('\0');
return JsonSerializer.Deserialize<T>(jsonSettingsString);
}
@@ -118,12 +104,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
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)
@@ -137,10 +123,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library
#endif
}
}
private static string LocalApplicationDataFolder()
{
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}
}
}

View File

@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.PowerToys.Settings.UI.Library.CustomAction;
@@ -13,6 +14,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
public static class Helper
{
public static readonly IFileSystem FileSystem = new FileSystem();
public static bool AllowRunnerToForeground()
{
var result = false;
@@ -47,22 +50,20 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
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
{
Path = path,
Filter = fileName,
NotifyFilter = NotifyFilters.LastWrite,
EnableRaisingEvents = true,
};
var watcher = FileSystem.FileSystemWatcher.CreateNew();
watcher.Path = path;
watcher.Filter = fileName;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.EnableRaisingEvents = true;
watcher.Changed += (o, e) => onChangedCallback();

View File

@@ -5,12 +5,16 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
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");
static Logger()

View File

@@ -2,41 +2,61 @@
// 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.IO;
using System;
using System.IO.Abstractions;
namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
{
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)
{
var directioryInfo = Directory.CreateDirectory(path);
var directioryInfo = _directory.CreateDirectory(path);
return directioryInfo != null;
}
public void DeleteDirectory(string path)
{
Directory.Delete(path, recursive: true);
_directory.Delete(path, recursive: true);
}
public bool DirectoryExists(string path)
{
return Directory.Exists(path);
return _directory.Exists(path);
}
public bool FileExists(string path)
{
return File.Exists(path);
return _file.Exists(path);
}
public string ReadAllText(string path)
{
return File.ReadAllText(path);
return _file.ReadAllText(path);
}
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.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Moq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO.Abstractions;
using System.Linq.Expressions;
using System.Text;
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}";
// 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()
{
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);
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal);
var mockIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression);
return mockIOProvider;
var stubSettingsPath = StubSettingsPath(version, module, fileName);
Expression<Func<string, bool>> filterExpression = ModuleFilterExpression(module);
return IIOProviderMocks.GetMockIOReadWithStubFile(stubSettingsPath, filterExpression);
}
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)
{
throw new ArgumentNullException(nameof(provider));
}
// Using Ordinal since this is used internally
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains(module, StringComparison.Ordinal);
Expression<Func<string, bool>> filterExpression = ModuleFilterExpression(module);
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
var stubGeneralSettingsPath = string.Format(CultureInfo.InvariantCulture, BackCompatTestProperties.RootPathStubFiles, version, string.Empty, "settings.json");
Expression<Func<string, bool>> filterExpression = (string s) => s.Contains("Microsoft\\PowerToys\\settings.json", StringComparison.Ordinal);
var mockGeneralIOProvider = IIOProviderMocks.GetMockIOReadWithStubFile(stubGeneralSettingsPath, filterExpression);
return mockGeneralIOProvider;
// Using Ordinal since this is used internally for a path
return s => s == null || s.Contains(module, StringComparison.Ordinal);
}
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)
{
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, filterExpression, expectedCallCount);
IIOProviderMocks.VerifyIOReadWithStubFile(provider, SettingsFilterExpression, expectedCallCount);
}
}

View File

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

View File

@@ -1,10 +1,9 @@
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Moq;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using System.Linq.Expressions;
using System.Text;
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>
/// 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.
@@ -48,25 +49,25 @@ namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks
/// <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>
/// <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);
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();
mockIOProvider.Setup(x => x.FileExists(It.Is<string>(filterExpression)))
fileMock.Setup(x => x.Exists(It.Is<string>(filterExpression)))
.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.Utilities;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using System.IO.Abstractions.TestingHelpers;
using Microsoft.PowerToys.Settings.UnitTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
@@ -25,11 +25,8 @@ namespace CommonLibTest
public void ToJsonStringShouldReturnValidJSONOfModelWhenSuccessful()
{
//Mock Disk access
string saveContent = string.Empty;
string savePath = string.Empty;
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
var settingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockFileSystem);
// Arrange
string file_name = "test\\BasePTModuleSettingsTest";

View File

@@ -2,9 +2,7 @@
// 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.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.VisualStudio.TestTools.UnitTesting;

View File

@@ -3,7 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
@@ -25,8 +26,8 @@ namespace CommonLibTest
public void SaveSettingsSaveSettingsToFileWhenFilePathExists()
{
// Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
var settingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name = "\\test";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -45,8 +46,8 @@ namespace CommonLibTest
public void SaveSettingsShouldCreateFileWhenFilePathIsNotFound()
{
// Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
var settingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name = "test\\Test Folder";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -63,8 +64,8 @@ namespace CommonLibTest
public void SettingsFolderExistsShouldReturnFalseWhenFilePathIsNotFound()
{
// Arrange
var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists();
var settingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockFileSystem = new MockFileSystem();
var settingsUtils = new SettingsUtils(mockFileSystem);
string file_name_random = "test\\" + RandomString();
string file_name_exists = "test\\exists";
string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}";
@@ -84,8 +85,8 @@ namespace CommonLibTest
public void SettingsUtilsMustReturnDefaultItemWhenFileIsCorrupt()
{
// Arrange
var mockIOProvider = BackCompatTestProperties.GetModuleIOProvider("CorruptJson", string.Empty, "settings.json");
var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object);
var mockFileSystem = new MockFileSystem();
var mockSettingsUtils = new SettingsUtils(mockFileSystem);
// Act
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.
// See the LICENSE file in the project root for more information.
using System.Globalization;
using System.IO;
using System.Text.Json;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility;
using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace ViewModelTests
{
@@ -27,11 +26,14 @@ namespace ViewModelTests
{
//Arrange
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);
var mockGeneralIOProvider = BackCompatTestProperties.GetGeneralSettingsIOProvider(version);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object);
var mockGeneralSettingsUtils = new SettingsUtils(mockGeneralIOProvider.Object, settingPathMock.Object);
GeneralSettings originalGeneralSettings = mockGeneralSettingsUtils.GetSettings<GeneralSettings>();
var generalSettingsRepository = new BackCompatTestProperties.MockSettingsRepository<GeneralSettings>(mockGeneralSettingsUtils);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@
// 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.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -15,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public ColorPickerPage()
{
var settingsUtils = new SettingsUtils(new SystemIOProvider());
var settingsUtils = new SettingsUtils();
ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
@@ -24,7 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private const string PowerToyName = "Keyboard Manager";
private readonly CoreDispatcher dispatcher;
private readonly FileSystemWatcher watcher;
private readonly IFileSystemWatcher watcher;
public KeyboardManagerViewModel ViewModel { get; }
@@ -32,7 +32,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
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);
watcher = Helper.GetFileWatcher(

View File

@@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public PowerLauncherPage()
{
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);
DataContext = ViewModel;

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,23 +5,24 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
namespace ColorPicker.Helpers
{
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()
{
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
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));

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.IO.Abstractions;
using ColorPicker.Helpers;
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")]
private const int SPIF_SENDCHANGE = 0x02;
private static readonly IFileSystem _fileSystem = new FileSystem();
public static void SetColorPickerCursor()
{
BackupOriginalCursors();
var colorPickerCursorPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName);
var colorPickerCursorPath = _fileSystem.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ColorPickerCursorName);
ChangeCursor(colorPickerCursorPath, ArrowRegistryName);
ChangeCursor(colorPickerCursorPath, IBeamRegistryName);
}

View File

@@ -5,6 +5,7 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.IO.Abstractions;
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@@ -20,14 +21,14 @@ namespace ColorPicker.Settings
private const int MaxNumberOfRetry = 5;
[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();
[ImportingConstructor]
public UserSettings()
{
_settingsUtils = new SettingsUtils(new SystemIOProvider());
_settingsUtils = new SettingsUtils();
ChangeCursor = new SettingItem<bool>(true);
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
CopiedColorRepresentation = new SettingItem<ColorRepresentationType>(ColorRepresentationType.HEX);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.IO.Abstractions;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Windows;
@@ -39,6 +40,8 @@ namespace FancyZonesEditor
Debug,
}
private static readonly IFileSystem _fileSystem = new FileSystem();
private static CanvasLayoutModel _blankCustomModel;
private readonly CanvasLayoutModel _focusModel;
private readonly GridLayoutModel _rowsModel;
@@ -137,7 +140,7 @@ namespace FancyZonesEditor
public Settings()
{
string tmpDirPath = Path.GetTempPath();
string tmpDirPath = _fileSystem.Path.GetTempPath();
ActiveZoneSetTmpFile = tmpDirPath + ActiveZoneSetsTmpFileName;
AppliedZoneSetTmpFile = tmpDirPath + AppliedZoneSetsTmpFileName;
@@ -441,9 +444,9 @@ namespace FancyZonesEditor
ActiveZoneSetUUid = NullUuidStr;
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;
inputStream.Close();
UniqueKey = jsonObject.GetProperty(DeviceIdJsonTag).GetString();

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Threading;
using System.Threading.Tasks;
using ImageResizer.Properties;
@@ -14,6 +15,8 @@ namespace ImageResizer.Models
{
public class ResizeBatch
{
private readonly IFileSystem _fileSystem = new FileSystem();
public string DestinationDirectory { get; set; }
public ICollection<string> Files { get; } = new List<string>();
@@ -71,7 +74,7 @@ namespace ImageResizer.Models
catch (Exception ex)
#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);

View File

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

View File

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

View File

@@ -5,11 +5,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Plugin.Folder.Sources;
using Microsoft.Plugin.Folder.Sources.Result;
using Moq;
using NUnit.Framework;
namespace Microsoft.Plugin.Folder.UnitTests
@@ -17,117 +16,45 @@ namespace Microsoft.Plugin.Folder.UnitTests
[TestFixture]
public class InternalQueryFolderTests
{
private static readonly HashSet<string> DirectoryExist = new HashSet<string>()
{
@"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;
private static IQueryFileSystemInfo _queryFileSystemInfoMock;
private static MockFileSystem _fileSystem;
[SetUp]
public void SetupMock()
{
var queryFileSystemInfoMock = new Mock<IQueryFileSystemInfo>();
queryFileSystemInfoMock.Setup(r => r.Exists(It.IsAny<string>()))
.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)
// Note: This mock filesystem adds a 'c:\temp' directory.
_fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>()
{
return DirectoryExist.Contains(TrimDirectoryEnd(path));
}
private static string TrimDirectoryEnd(string path)
{
var trimEnd = path.TrimEnd('\\');
if (path.EndsWith('\\'))
{
trimEnd += '\\';
}
return trimEnd;
}
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,
{ @"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() },
});
var files = FilesExist.Where(s => fileSearchFunc(s))
.Select(file => new DisplayFileInfo()
{
Type = DisplayType.File,
FullName = file,
});
return directories.Concat(files);
_queryFileSystemInfoMock = new QueryFileSystemInfo(_fileSystem.DirectoryInfo);
}
[Test]
public void Query_ThrowsException_WhenCalledNull()
{
// Setup
var queryInternalDirectory = new QueryInternalDirectory(new FolderSettings(), _queryFileSystemInfoMock.Object);
var queryInternalDirectory = new QueryInternalDirectory(new FolderSettings(), _queryFileSystemInfoMock, _fileSystem.Directory);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => queryInternalDirectory.Query(null).ToArray());
}
[TestCase(@"c", 0, 0, false, Reason = "String empty is nothing")]
[TestCase(@"c:", 1, 1, false, Reason = "Root without \\")]
[TestCase(@"c:\", 1, 1, false, Reason = "Normal root")]
[TestCase(@"c:\Test", 1, 2, false, Reason = "Select yourself")]
[TestCase(@"c:\>", 2, 2, true, Reason = "Max Folder test recursive")]
[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:", 2, 1, false, Reason = "Root without \\")]
[TestCase(@"c:\", 2, 1, false, Reason = "Normal root")]
[TestCase(@"c:\Test", 2, 2, false, Reason = "Select yourself")]
[TestCase(@"c:\not-exist", 2, 1, 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", 1, 1, false, Reason = "Partial match file")]
[TestCase(@"c:\bla.t", 2, 1, false, Reason = "Partial match file")]
public void Query_WhenCalled(string search, int folders, int files, bool truncated)
{
const int maxFolderSetting = 2;
const int maxFolderSetting = 3;
// Setup
var folderSettings = new FolderSettings()
@@ -136,7 +63,42 @@ namespace Microsoft.Plugin.Folder.UnitTests
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
var isDriveOrSharedFolder = queryInternalDirectory.Query(search)

View File

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

View File

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

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using System.Windows.Controls;
using ManagedCommon;
@@ -21,9 +22,10 @@ namespace Microsoft.Plugin.Folder
public const string DeleteFileFolderImagePath = "Images\\delete.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 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 ICollection<IFolderProcessor> _processors = new IFolderProcessor[]

View File

@@ -78,6 +78,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<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" />
</ItemGroup>

View File

@@ -2,17 +2,6 @@
// 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.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
{
public class SearchResult

View File

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

View File

@@ -4,22 +4,22 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
namespace Microsoft.Plugin.Folder.Sources
{
internal class DriveInformation : IDriveInformation
{
private static readonly IFileSystem _fileSystem = new FileSystem();
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")]
private static IEnumerable<string> InitialDriverList()
{
var directorySeparatorChar = System.IO.Path.DirectorySeparatorChar;
// 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));
}

View File

@@ -2,20 +2,26 @@
// 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.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using Wox.Infrastructure.FileSystemHelper;
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)
{
// search folder and add results
var directoryInfo = new DirectoryInfo(search);
var directoryInfo = _directoryInfoFactory.FromDirectoryName(search);
var fileSystemInfos = directoryInfo.EnumerateFileSystemInfos(incompleteName, new EnumerationOptions()
{
MatchType = MatchType.Win32,
@@ -30,7 +36,7 @@ namespace Microsoft.Plugin.Folder.Sources
.Select(CreateDisplayFileInfo);
}
private static DisplayFileInfo CreateDisplayFileInfo(FileSystemInfo fileSystemInfo)
private static DisplayFileInfo CreateDisplayFileInfo(IFileSystemInfo fileSystemInfo)
{
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;
}

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using ManagedCommon;
using Microsoft.Plugin.Folder.Sources.Result;
@@ -18,6 +19,7 @@ namespace Microsoft.Plugin.Folder.Sources
{
private readonly FolderSettings _settings;
private readonly IQueryFileSystemInfo _queryFileSystemInfo;
private readonly IDirectory _directory;
private static readonly HashSet<char> SpecialSearchChars = new HashSet<char>
{
@@ -26,10 +28,11 @@ namespace Microsoft.Plugin.Folder.Sources
private static string _warningIconPath;
public QueryInternalDirectory(FolderSettings folderSettings, IQueryFileSystemInfo queryFileSystemInfo)
public QueryInternalDirectory(FolderSettings folderSettings, IQueryFileSystemInfo queryFileSystemInfo, IDirectory directory)
{
_settings = folderSettings;
_queryFileSystemInfo = queryFileSystemInfo;
_directory = directory;
}
private static bool HasSpecialChars(string search)
@@ -47,7 +50,7 @@ namespace Microsoft.Plugin.Folder.Sources
private (string search, string incompleteName) Process(string search)
{
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
// find the right folder.
@@ -64,7 +67,7 @@ namespace Microsoft.Plugin.Folder.Sources
incompleteName = search.Substring(index + 1)
.ToLower(CultureInfo.InvariantCulture) + "*";
search = search.Substring(0, index + 1);
if (!_queryFileSystemInfo.Exists(search))
if (!_directory.Exists(search))
{
return default;
}

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using Wox.Infrastructure;
using Wox.Plugin;
@@ -13,15 +13,27 @@ namespace Microsoft.Plugin.Folder.Sources.Result
{
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 Title => Path.GetFileName(FilePath);
public string Title => _path.GetFileName(FilePath);
public string Search { get; set; }
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,

View File

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

View File

@@ -7,7 +7,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Controls;
@@ -24,6 +24,8 @@ namespace Microsoft.Plugin.Indexer
{
internal class Main : ISettingProvider, IPlugin, ISavable, IPluginI18n, IContextMenu, IDisposable, IDelayedExecutionPlugin
{
private static readonly IFileSystem _fileSystem = new FileSystem();
// This variable contains metadata about the Plugin
private PluginInitContext _context;
@@ -38,7 +40,7 @@ namespace Microsoft.Plugin.Indexer
private readonly WindowsSearchAPI _api = new WindowsSearchAPI(_search);
// 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
private readonly string reservedStringPattern = @"^[\/\\\$\%]+$|^.*[<>].*$";
@@ -117,7 +119,7 @@ namespace Microsoft.Plugin.Indexer
string workingDir = null;
if (_settings.UseLocationAsWorkingDir)
{
workingDir = Path.GetDirectoryName(path);
workingDir = _fileSystem.Path.GetDirectoryName(path);
}
Result r = new Result();
@@ -151,7 +153,7 @@ namespace Microsoft.Plugin.Indexer
r.ContextData = searchResult;
// 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;
}

View File

@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using Microsoft.Plugin.Program.Programs;
using Microsoft.Plugin.Program.Storage;
@@ -209,7 +210,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path);
// 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" });
Win32Program.FileWrapper = mockFile.Object;
@@ -256,7 +257,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
// 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" });
Win32Program.FileWrapper = mockFile.Object;
@@ -279,7 +280,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath);
// 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" });
Win32Program.FileWrapper = mockFile.Object;

View File

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

View File

@@ -2,7 +2,7 @@
// 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.IO;
using System.IO.Abstractions;
namespace Microsoft.Plugin.Program
{
@@ -16,11 +16,13 @@ namespace Microsoft.Plugin.Program
/// </remarks>
public class ProgramSource
{
private static readonly IFileSystem FileSystem = new FileSystem();
private string name;
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;

View File

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

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -31,6 +32,10 @@ namespace Microsoft.Plugin.Program.Programs
[Serializable]
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 UniqueIdentifier { get; set; }

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using System.Security;
@@ -20,12 +21,18 @@ using Wox.Infrastructure;
using Wox.Infrastructure.FileSystemHelper;
using Wox.Plugin;
using Wox.Plugin.Logger;
using DirectoryWrapper = Wox.Infrastructure.FileSystemHelper.DirectoryWrapper;
namespace Microsoft.Plugin.Program.Programs
{
[Serializable]
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 UniqueIdentifier { get; set; }
@@ -57,7 +64,7 @@ namespace Microsoft.Plugin.Program.Programs
// Wrappers for File Operations
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();

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Threading.Tasks;
using Wox.Infrastructure.Storage;
using Wox.Plugin.Logger;
@@ -17,6 +18,9 @@ namespace Microsoft.Plugin.Program.Storage
{
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 UrlExtension = ".url";

View File

@@ -8,6 +8,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
@@ -23,6 +24,11 @@ namespace Microsoft.Plugin.Shell
{
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 PluginJsonStorage<ShellPluginSettings> _storage;

View File

@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Text;
using ManagedCommon;
using Microsoft.Plugin.Uri.UriHelper;
@@ -17,6 +17,10 @@ namespace Microsoft.Plugin.Uri
{
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 UriResolver _uriResolver;
private readonly PluginJsonStorage<UriSettings> _storage;

View File

@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.IO.Pipes;
using System.Text;
using System.Threading;
@@ -29,6 +30,10 @@ namespace PowerLauncher.Helper
public static class SingleInstance<TApplication>
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>
/// String delimiter used in channel names.
/// </summary>

View File

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

View File

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

View File

@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
@@ -15,6 +15,11 @@ namespace Wox.Core.Plugin
{
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 static readonly List<PluginMetadata> PluginMetadatas = new List<PluginMetadata>();

View File

@@ -4,6 +4,7 @@
using System;
using System.IO;
using System.IO.Abstractions;
using System.Reflection;
using System.Windows;
using ICSharpCode.SharpZipLib.Zip;
@@ -15,6 +16,11 @@ namespace Wox.Core.Plugin
{
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)
{
if (File.Exists(path))
@@ -35,7 +41,7 @@ namespace Wox.Core.Plugin
}
PluginMetadata plugin = GetMetadataFromJson(tempFolder);
if (plugin == null || plugin.Name == null)
if (plugin?.Name == null)
{
MessageBox.Show("Install failed: plugin config is invalid");
return;
@@ -196,7 +202,7 @@ namespace Wox.Core.Plugin
{
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];
while (true)

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -23,6 +23,9 @@ namespace Wox.Core.Plugin
/// </summary>
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>();
/// <summary>

View File

@@ -4,18 +4,27 @@
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
namespace Wox.Infrastructure.FileSystemHelper
{
public class FileVersionInfoWrapper : IFileVersionInfoWrapper
{
private readonly IFile _file;
public FileVersionInfoWrapper()
: this(new FileSystem().File)
{
}
public FileVersionInfoWrapper(IFile file)
{
_file = file;
}
public FileVersionInfo GetVersionInfo(string path)
{
if (File.Exists(path))
if (_file.Exists(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.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -14,6 +14,12 @@ namespace Wox.Infrastructure
{
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>
/// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy
/// </summary>
@@ -54,8 +60,8 @@ namespace Wox.Infrastructure
}
else
{
var time1 = new FileInfo(bundledDataPath).LastWriteTimeUtc;
var time2 = new FileInfo(dataPath).LastWriteTimeUtc;
var time1 = FileInfo.FromFileName(bundledDataPath).LastWriteTimeUtc;
var time2 = FileInfo.FromFileName(dataPath).LastWriteTimeUtc;
if (time1 != time2)
{
File.Copy(bundledDataPath, dataPath, true);

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -21,6 +21,11 @@ namespace Wox.Infrastructure.Image
{
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 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.
using System;
using System.IO;
using System.IO.Abstractions;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
@@ -24,6 +24,9 @@ namespace Wox.Infrastructure.Image
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
private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";

View File

@@ -4,6 +4,7 @@
using System;
using System.IO;
using System.IO.Abstractions;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
@@ -19,18 +20,28 @@ namespace Wox.Infrastructure.Storage
/// </summary>
public class BinaryStorage<T> : IStorage<T>
{
private readonly IFileSystem _fileSystem;
// This storage helper returns whether or not to delete the binary storage items
private const int _binaryStorage = 0;
private StoragePowerToysVersionInfo _storageHelper;
public BinaryStorage(string filename)
: this(filename, new FileSystem())
{
}
public BinaryStorage(string filename, IFileSystem fileSystem)
{
_fileSystem = fileSystem;
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);
const string fileSuffix = ".cache";
FilePath = Path.Combine(directoryPath, $"{filename}{fileSuffix}");
FilePath = path.Combine(directoryPath, $"{filename}{fileSuffix}");
}
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
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());
}
}
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());
@@ -60,7 +71,7 @@ namespace Wox.Infrastructure.Storage
return defaultData;
}
using (var stream = new FileStream(FilePath, FileMode.Open))
using (var stream = _fileSystem.FileStream.Create(FilePath, FileMode.Open))
{
var d = Deserialize(stream, defaultData);
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")]
private T Deserialize(FileStream stream, T defaultData)
private T Deserialize(Stream stream, T defaultData)
{
// http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

View File

@@ -5,6 +5,7 @@
using System;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using Newtonsoft.Json;
using Wox.Plugin.Logger;
@@ -15,6 +16,10 @@ namespace Wox.Infrastructure.Storage
/// </summary>
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 T _data;

View File

@@ -2,7 +2,7 @@
// 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.IO;
using System.IO.Abstractions;
using Wox.Plugin;
namespace Wox.Infrastructure.Storage
@@ -10,6 +10,9 @@ namespace Wox.Infrastructure.Storage
public class PluginJsonStorage<T> : JsonStorage<T>
where T : new()
{
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
public PluginJsonStorage()
{
// C# related, add python related below

View File

@@ -3,12 +3,15 @@
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.IO.Abstractions;
namespace Wox.Infrastructure.Storage
{
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
public bool ClearCache { get; set; }

View File

@@ -2,7 +2,7 @@
// 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.IO;
using System.IO.Abstractions;
using Wox.Plugin;
namespace Wox.Infrastructure.Storage
@@ -10,6 +10,9 @@ namespace Wox.Infrastructure.Storage
public class WoxJsonStorage<T> : JsonStorage<T>
where T : new()
{
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
public WoxJsonStorage()
{
var directoryPath = Path.Combine(Constant.DataDirectory, DirectoryName);

View File

@@ -62,6 +62,7 @@
</PackageReference>
<PackageReference Include="NLog.Schema" Version="4.7.4" />
<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" />
</ItemGroup>

View File

@@ -4,7 +4,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Reflection;
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 ModuleLocation = "Microsoft\\PowerToys\\PowerToys Run";
public const string Plugins = "Plugins";

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.IO.Abstractions;
using System.Runtime.CompilerServices;
using NLog;
using NLog.Config;
@@ -13,6 +13,10 @@ namespace Wox.Plugin.Logger
{
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 static string CurrentLogDirectory { get; }

View File

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

View File

@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Windows;
using System.Windows.Media;
@@ -13,6 +13,9 @@ namespace Wox.Plugin
{
public class Result
{
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private string _title;
private ToolTipData _toolTipData;
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.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using Markdig;
using Markdig.Extensions.Figures;
using Markdig.Extensions.Tables;

View File

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

View File

@@ -4,7 +4,7 @@
using System;
using System.Drawing;
using System.IO;
using System.IO.Abstractions;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Common;
@@ -21,6 +21,10 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
/// </summary>
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>
/// Extension to modify markdown AST.
/// </summary>

View File

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

View File

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

View File

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

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