PowerToys/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/ServicesTests/CustomActionKernelQueryCacheServiceTests.cs

173 lines
6.7 KiB
C#
Raw Normal View History

// 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.TestingHelpers;
using System.Linq;
using System.Threading.Tasks;
using AdvancedPaste.Models;
using AdvancedPaste.Models.KernelQueryCache;
using AdvancedPaste.Services;
using AdvancedPaste.Settings;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace AdvancedPaste.UnitTests.ServicesTests;
[TestClass]
public sealed class CustomActionKernelQueryCacheServiceTests
{
private static readonly CacheKey CustomActionTestKey = new() { Prompt = "TestPrompt1", AvailableFormats = ClipboardFormat.Text };
private static readonly CacheKey CustomActionTestKey2 = new() { Prompt = "TestPrompt2", AvailableFormats = ClipboardFormat.File | ClipboardFormat.Image };
private static readonly CacheKey MarkdownTestKey = new() { Prompt = "Paste as Markdown", AvailableFormats = ClipboardFormat.Text };
private static readonly CacheKey JSONTestKey = new() { Prompt = "Paste as JSON", AvailableFormats = ClipboardFormat.Text };
private static readonly CacheKey PasteAsTxtFileKey = new() { Prompt = "Paste as .txt file", AvailableFormats = ClipboardFormat.File };
private static readonly CacheKey PasteAsPngFileKey = new() { Prompt = "Paste as .png file", AvailableFormats = ClipboardFormat.Image };
private static readonly CacheValue TestValue = new([new(PasteFormats.PlainText, [])]);
private static readonly CacheValue TestValue2 = new([new(PasteFormats.KernelQuery, new() { { "a", "b" }, { "c", "d" } })]);
private CustomActionKernelQueryCacheService _cacheService;
private Mock<IUserSettings> _userSettings;
private MockFileSystem _fileSystem;
[TestInitialize]
public void TestInitialize()
{
_userSettings = new();
UpdateUserActions([], []);
_fileSystem = new();
_cacheService = new(_userSettings.Object, _fileSystem);
}
[TestMethod]
public async Task Test_Cache_Always_Accepts_Core_Action_Prompt()
{
await AssertAcceptsAsync(MarkdownTestKey);
}
[TestMethod]
public async Task Test_Cache_Accepts_Prompt_When_Custom_Action()
{
await AssertRejectsAsync(CustomActionTestKey);
UpdateUserActions([], [new() { Name = nameof(CustomActionTestKey), Prompt = CustomActionTestKey.Prompt, IsShown = true }]);
await AssertAcceptsAsync(CustomActionTestKey);
await AssertRejectsAsync(CustomActionTestKey2, PasteAsTxtFileKey);
UpdateUserActions([], []);
await AssertRejectsAsync(CustomActionTestKey);
}
[TestMethod]
public async Task Test_Cache_Accepts_Prompt_When_User_Additional_Action()
{
await AssertRejectsAsync(PasteAsTxtFileKey, PasteAsPngFileKey);
UpdateUserActions([PasteFormats.PasteAsHtmlFile, PasteFormats.PasteAsTxtFile], []);
await AssertAcceptsAsync(PasteAsTxtFileKey);
await AssertRejectsAsync(PasteAsPngFileKey, CustomActionTestKey);
UpdateUserActions([], []);
await AssertRejectsAsync(PasteAsTxtFileKey);
}
[TestMethod]
public async Task Test_Cache_Overwrites_Latest_Value()
{
await _cacheService.WriteAsync(JSONTestKey, TestValue);
await _cacheService.WriteAsync(MarkdownTestKey, TestValue2);
await _cacheService.WriteAsync(JSONTestKey, TestValue2);
await _cacheService.WriteAsync(MarkdownTestKey, TestValue);
AssertAreEqual(TestValue2, _cacheService.ReadOrNull(JSONTestKey));
AssertAreEqual(TestValue, _cacheService.ReadOrNull(MarkdownTestKey));
}
[TestMethod]
public async Task Test_Cache_Uses_Case_Insensitive_Prompt_Comparison()
{
static CacheKey CreateUpperCaseKey(CacheKey key) =>
new() { Prompt = key.Prompt.ToUpperInvariant(), AvailableFormats = key.AvailableFormats };
await _cacheService.WriteAsync(CreateUpperCaseKey(JSONTestKey), TestValue);
await _cacheService.WriteAsync(MarkdownTestKey, TestValue2);
AssertAreEqual(TestValue, _cacheService.ReadOrNull(JSONTestKey));
AssertAreEqual(TestValue2, _cacheService.ReadOrNull(MarkdownTestKey));
}
[TestMethod]
public async Task Test_Cache_Uses_Clipboard_Formats_In_Key()
{
CacheKey key1 = new() { Prompt = JSONTestKey.Prompt, AvailableFormats = ClipboardFormat.File };
CacheKey key2 = new() { Prompt = JSONTestKey.Prompt, AvailableFormats = ClipboardFormat.Image };
await _cacheService.WriteAsync(key1, TestValue);
Assert.IsNotNull(_cacheService.ReadOrNull(key1));
Assert.IsNull(_cacheService.ReadOrNull(key2));
}
[TestMethod]
public async Task Test_Cache_Is_Persistent()
{
await _cacheService.WriteAsync(JSONTestKey, TestValue);
await _cacheService.WriteAsync(MarkdownTestKey, TestValue2);
_cacheService = new(_userSettings.Object, _fileSystem); // recreate using same mock file-system to simulate app restart
AssertAreEqual(TestValue, _cacheService.ReadOrNull(JSONTestKey));
AssertAreEqual(TestValue2, _cacheService.ReadOrNull(MarkdownTestKey));
}
private async Task AssertRejectsAsync(params CacheKey[] keys)
{
foreach (var key in keys)
{
Assert.IsNull(_cacheService.ReadOrNull(key));
await _cacheService.WriteAsync(key, TestValue);
Assert.IsNull(_cacheService.ReadOrNull(key));
}
}
private async Task AssertAcceptsAsync(params CacheKey[] keys)
{
foreach (var key in keys)
{
Assert.IsNull(_cacheService.ReadOrNull(key));
await _cacheService.WriteAsync(key, TestValue);
AssertAreEqual(TestValue, _cacheService.ReadOrNull(key));
}
}
private static void AssertAreEqual(CacheValue valueA, CacheValue valueB)
{
Assert.IsNotNull(valueA);
Assert.IsNotNull(valueB);
Assert.AreEqual(valueA.ActionChain.Count, valueB.ActionChain.Count);
foreach (var (itemA, itemB) in valueA.ActionChain.Zip(valueB.ActionChain))
{
Assert.AreEqual(itemA.Format, itemB.Format);
Assert.AreEqual(itemA.Arguments.Count, itemB.Arguments.Count);
Assert.IsFalse(itemA.Arguments.Except(itemB.Arguments).Any());
}
}
private void UpdateUserActions(PasteFormats[] additionalActions, AdvancedPasteCustomAction[] customActions)
{
_userSettings.Setup(settingsObj => settingsObj.AdditionalActions).Returns(additionalActions);
_userSettings.Setup(settingsObj => settingsObj.CustomActions).Returns(customActions);
_userSettings.Raise(settingsObj => settingsObj.Changed += null, EventArgs.Empty);
}
}