mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 20:57:22 +02:00
[Tests] More consistent naming (#40754)
- [x] **Tests:** Added/updated and all pass - [x] **Dev docs:** Added/updated <img width="460" height="1017" alt="image" src="https://github.com/user-attachments/assets/e72bf221-0875-48c3-b790-4ab1182c7d3a" /> I haven't touched the Run module, since we may deprecate it. Closes: #40788
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using static FancyZonesEditorCommon.Data.AppZoneHistory.AppZoneHistoryWrapper;
|
||||
using static FancyZonesEditorCommon.Data.CustomLayouts;
|
||||
|
||||
namespace FancyZonesEditorCommon.Data
|
||||
{
|
||||
public class AppZoneHistory : EditorData<AppZoneHistory.AppZoneHistoryListWrapper>
|
||||
{
|
||||
public string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\app-zone-history.json";
|
||||
}
|
||||
}
|
||||
|
||||
public struct AppZoneHistoryWrapper
|
||||
{
|
||||
public struct ZoneHistoryWrapper
|
||||
{
|
||||
public int[][] ZoneIndexSet { get; set; }
|
||||
|
||||
public DeviceIdWrapper Device { get; set; }
|
||||
|
||||
public string ZonesetUuid { get; set; }
|
||||
}
|
||||
|
||||
public struct DeviceIdWrapper
|
||||
{
|
||||
public string Monitor { get; set; }
|
||||
|
||||
public string MonitorInstance { get; set; }
|
||||
|
||||
public int MonitorNumber { get; set; }
|
||||
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
public string VirtualDesktop { get; set; }
|
||||
}
|
||||
|
||||
public string AppPath { get; set; }
|
||||
|
||||
public List<ZoneHistoryWrapper> History { get; set; }
|
||||
}
|
||||
|
||||
public struct AppZoneHistoryListWrapper
|
||||
{
|
||||
public List<AppZoneHistoryWrapper> AppZoneHistory { get; set; }
|
||||
}
|
||||
|
||||
public JsonElement ToJsonElement(ZoneHistoryWrapper info)
|
||||
{
|
||||
string json = JsonSerializer.Serialize(info, this.JsonOptions);
|
||||
return JsonSerializer.Deserialize<JsonElement>(json);
|
||||
}
|
||||
|
||||
public JsonElement ToJsonElement(DeviceIdWrapper info)
|
||||
{
|
||||
string json = JsonSerializer.Serialize(info, this.JsonOptions);
|
||||
return JsonSerializer.Deserialize<JsonElement>(json);
|
||||
}
|
||||
|
||||
public ZoneHistoryWrapper ZoneHistoryFromJsonElement(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<ZoneHistoryWrapper>(json, this.JsonOptions);
|
||||
}
|
||||
|
||||
public DeviceIdWrapper GridFromJsonElement(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<DeviceIdWrapper>(json, this.JsonOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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 FancyZonesEditorCommon.Data;
|
||||
|
||||
namespace Microsoft.FancyZonesEditor.UITests.Utils
|
||||
{
|
||||
public class FancyZonesEditorFiles
|
||||
{
|
||||
public IOTestHelper ParamsIOHelper { get; }
|
||||
|
||||
public IOTestHelper AppliedLayoutsIOHelper { get; }
|
||||
|
||||
public IOTestHelper CustomLayoutsIOHelper { get; }
|
||||
|
||||
public IOTestHelper DefaultLayoutsIOHelper { get; }
|
||||
|
||||
public IOTestHelper LayoutHotkeysIOHelper { get; }
|
||||
|
||||
public IOTestHelper LayoutTemplatesIOHelper { get; }
|
||||
|
||||
public IOTestHelper AppZoneHistoryIOHelper { get; }
|
||||
|
||||
public FancyZonesEditorFiles()
|
||||
{
|
||||
ParamsIOHelper = new IOTestHelper(new EditorParameters().File);
|
||||
AppliedLayoutsIOHelper = new IOTestHelper(new AppliedLayouts().File);
|
||||
CustomLayoutsIOHelper = new IOTestHelper(new CustomLayouts().File);
|
||||
DefaultLayoutsIOHelper = new IOTestHelper(new DefaultLayouts().File);
|
||||
LayoutHotkeysIOHelper = new IOTestHelper(new LayoutHotkeys().File);
|
||||
LayoutTemplatesIOHelper = new IOTestHelper(new LayoutTemplates().File);
|
||||
AppZoneHistoryIOHelper = new IOTestHelper(new AppZoneHistory().File);
|
||||
}
|
||||
|
||||
public void Restore()
|
||||
{
|
||||
ParamsIOHelper.RestoreData();
|
||||
AppliedLayoutsIOHelper.RestoreData();
|
||||
CustomLayoutsIOHelper.RestoreData();
|
||||
DefaultLayoutsIOHelper.RestoreData();
|
||||
LayoutHotkeysIOHelper.RestoreData();
|
||||
LayoutTemplatesIOHelper.RestoreData();
|
||||
AppZoneHistoryIOHelper.RestoreData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using FancyZonesEditorCommon.Data;
|
||||
using Microsoft.FancyZonesEditor.UITests.Utils;
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using ModernWpf.Controls;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.FancyZonesEditor.UnitTests.Utils
|
||||
{
|
||||
public class FancyZonesEditorHelper
|
||||
{
|
||||
private static FancyZonesEditorFiles? _files;
|
||||
|
||||
public static FancyZonesEditorFiles Files
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_files == null)
|
||||
{
|
||||
_files = new FancyZonesEditorFiles();
|
||||
}
|
||||
|
||||
return _files;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccessibilityId
|
||||
{
|
||||
// main window
|
||||
public const string MainWindow = "MainWindow1";
|
||||
public const string Monitors = "Monitors";
|
||||
public const string NewLayoutButton = "NewLayoutButton";
|
||||
|
||||
// layout card
|
||||
public const string EditLayoutButton = "EditLayoutButton";
|
||||
|
||||
// edit layout window: common for template and custom layouts
|
||||
public const string DialogTitle = "EditLayoutDialogTitle";
|
||||
public const string SensitivitySlider = "SensitivityInput";
|
||||
public const string SpacingSlider = "Spacing";
|
||||
public const string SpacingToggle = "spaceAroundSetting";
|
||||
public const string HorizontalDefaultButtonUnchecked = "SetLayoutAsHorizontalDefaultButton";
|
||||
public const string VerticalDefaultButtonUnchecked = "SetLayoutAsVerticalDefaultButton";
|
||||
public const string HorizontalDefaultButtonChecked = "HorizontalDefaultLayoutButton";
|
||||
public const string VerticalDefaultButtonChecked = "VerticalDefaultLayoutButton";
|
||||
|
||||
// edit template layout window
|
||||
public const string CopyTemplate = "createFromTemplateLayoutButton";
|
||||
public const string TemplateZoneSlider = "TemplateZoneCount";
|
||||
|
||||
// edit custom layout window
|
||||
public const string DuplicateLayoutButton = "duplicateLayoutButton";
|
||||
public const string DeleteLayoutButton = "deleteLayoutButton";
|
||||
public const string KeySelectionComboBox = "quickKeySelectionComboBox";
|
||||
public const string EditZonesButton = "editZoneLayoutButton";
|
||||
public const string DeleteTextButton = "DeleteButton";
|
||||
public const string HotkeyComboBox = "quickKeySelectionComboBox";
|
||||
public const string NewZoneButton = "newZoneButton";
|
||||
public const string TopRightCorner = "NEResize";
|
||||
|
||||
// layout creation dialog
|
||||
public const string GridRadioButton = "GridLayoutRadioButton";
|
||||
public const string CanvasRadioButton = "CanvasLayoutRadioButton";
|
||||
|
||||
// confirmation dialog
|
||||
public const string PrimaryButton = "PrimaryButton";
|
||||
public const string SecondaryButton = "SecondaryButton";
|
||||
}
|
||||
|
||||
public static class ElementName
|
||||
{
|
||||
public const string Save = "Save";
|
||||
public const string Cancel = "Cancel";
|
||||
|
||||
// context menu
|
||||
public const string Edit = "Edit";
|
||||
public const string EditZones = "Edit zones";
|
||||
public const string Delete = "Delete";
|
||||
public const string Duplicate = "Duplicate";
|
||||
public const string CreateCustomLayout = "Create custom layout";
|
||||
|
||||
// canvas layout editor
|
||||
public const string CanvasEditorWindow = "Canvas layout editor";
|
||||
|
||||
// grid layout editor
|
||||
public const string GridLayoutEditor = "Grid layout editor";
|
||||
public const string MergeZonesButton = "Merge zones";
|
||||
}
|
||||
|
||||
public static class ClassName
|
||||
{
|
||||
public const string ContextMenu = "ContextMenu";
|
||||
public const string TextBox = "TextBox";
|
||||
public const string Popup = "Popup";
|
||||
|
||||
// layout editor
|
||||
public const string CanvasZone = "CanvasZone";
|
||||
public const string GridZone = "GridZone";
|
||||
public const string Button = "Button";
|
||||
public const string Thumb = "Thumb";
|
||||
}
|
||||
|
||||
public static void ClickContextMenuItem(Session session, string layoutName, string menuItem)
|
||||
{
|
||||
session.Find<Element>(layoutName).Click(true);
|
||||
session.Find<Element>(By.ClassName(ClassName.ContextMenu)).Find<Element>(menuItem).Click();
|
||||
}
|
||||
|
||||
public static Custom? GetZone(Session session, int zoneNumber, string zoneClassName)
|
||||
{
|
||||
var zones = session.FindAll<Custom>(By.ClassName(zoneClassName));
|
||||
foreach (var zone in zones)
|
||||
{
|
||||
try
|
||||
{
|
||||
zone.Find<Element>(zoneNumber.ToString(CultureInfo.InvariantCulture));
|
||||
Assert.IsNotNull(zone, "zone not found");
|
||||
return zone;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// required number not found in the zone
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsNotNull(zones, $"zoneClassName : {zoneClassName} not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void MergeGridZones(Session session, int zoneNumber1, int zoneNumber2)
|
||||
{
|
||||
var zone1 = GetZone(session, zoneNumber1, ClassName.GridZone);
|
||||
var zone2 = GetZone(session, zoneNumber2, ClassName.GridZone);
|
||||
Assert.IsNotNull(zone1, "first zone not found");
|
||||
Assert.IsNotNull(zone2, "second zone not found");
|
||||
if (zone1 == null || zone2 == null)
|
||||
{
|
||||
Assert.Fail("zone is null");
|
||||
return;
|
||||
}
|
||||
|
||||
zone1.Drag(zone2);
|
||||
|
||||
session.Find<Element>(ElementName.MergeZonesButton).Click();
|
||||
}
|
||||
|
||||
public static void MoveSplitter(Session session, int index, int xOffset, int yOffset)
|
||||
{
|
||||
var thumbs = session.FindAll<Thumb>(By.ClassName(ClassName.Thumb));
|
||||
if (thumbs.Count == 0 || index >= thumbs.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
thumbs[index].Drag(xOffset, yOffset);
|
||||
Console.WriteLine($"Moving splitter {index} by ({xOffset}, {yOffset})");
|
||||
}
|
||||
|
||||
public static void ClickDeleteZone(Session session, int zoneNumber)
|
||||
{
|
||||
var zone = FancyZonesEditorHelper.GetZone(session, zoneNumber, ClassName.CanvasZone);
|
||||
Assert.IsNotNull(zone);
|
||||
var button = zone.Find<Button>(By.ClassName(ClassName.Button));
|
||||
Assert.IsNotNull(button);
|
||||
button.Click();
|
||||
}
|
||||
|
||||
public static void InitFancyZonesLayout()
|
||||
{
|
||||
// prepare files to launch Editor without errors
|
||||
EditorParameters editorParameters = new EditorParameters();
|
||||
EditorParameters.ParamsWrapper parameters = new EditorParameters.ParamsWrapper
|
||||
{
|
||||
ProcessId = 1,
|
||||
SpanZonesAcrossMonitors = false,
|
||||
Monitors = new List<EditorParameters.NativeMonitorDataWrapper>
|
||||
{
|
||||
new EditorParameters.NativeMonitorDataWrapper
|
||||
{
|
||||
Monitor = "monitor-1",
|
||||
MonitorInstanceId = "instance-id-1",
|
||||
MonitorSerialNumber = "serial-number-1",
|
||||
MonitorNumber = 1,
|
||||
VirtualDesktop = "{FF34D993-73F3-4B8C-AA03-73730A01D6A8}",
|
||||
Dpi = 96,
|
||||
LeftCoordinate = 0,
|
||||
TopCoordinate = 0,
|
||||
WorkAreaHeight = 1040,
|
||||
WorkAreaWidth = 1920,
|
||||
MonitorHeight = 1080,
|
||||
MonitorWidth = 1920,
|
||||
IsSelected = true,
|
||||
},
|
||||
},
|
||||
};
|
||||
FancyZonesEditorHelper.Files.ParamsIOHelper.WriteData(editorParameters.Serialize(parameters));
|
||||
|
||||
LayoutTemplates layoutTemplates = new LayoutTemplates();
|
||||
LayoutTemplates.TemplateLayoutsListWrapper templateLayoutsListWrapper = new LayoutTemplates.TemplateLayoutsListWrapper
|
||||
{
|
||||
LayoutTemplates = new List<LayoutTemplates.TemplateLayoutWrapper>
|
||||
{
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Empty],
|
||||
},
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Focus],
|
||||
ZoneCount = 10,
|
||||
},
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Rows],
|
||||
ZoneCount = 2,
|
||||
ShowSpacing = true,
|
||||
Spacing = 10,
|
||||
SensitivityRadius = 10,
|
||||
},
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Columns],
|
||||
ZoneCount = 2,
|
||||
ShowSpacing = true,
|
||||
Spacing = 20,
|
||||
SensitivityRadius = 20,
|
||||
},
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Grid],
|
||||
ZoneCount = 4,
|
||||
ShowSpacing = false,
|
||||
Spacing = 10,
|
||||
SensitivityRadius = 30,
|
||||
},
|
||||
new LayoutTemplates.TemplateLayoutWrapper
|
||||
{
|
||||
Type = Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.PriorityGrid],
|
||||
ZoneCount = 3,
|
||||
ShowSpacing = true,
|
||||
Spacing = 1,
|
||||
SensitivityRadius = 40,
|
||||
},
|
||||
},
|
||||
};
|
||||
FancyZonesEditorHelper.Files.LayoutTemplatesIOHelper.WriteData(layoutTemplates.Serialize(templateLayoutsListWrapper));
|
||||
|
||||
CustomLayouts customLayouts = new CustomLayouts();
|
||||
CustomLayouts.CustomLayoutListWrapper customLayoutListWrapper = new CustomLayouts.CustomLayoutListWrapper
|
||||
{
|
||||
CustomLayouts = new List<CustomLayouts.CustomLayoutWrapper> { },
|
||||
};
|
||||
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(customLayoutListWrapper));
|
||||
|
||||
DefaultLayouts defaultLayouts = new DefaultLayouts();
|
||||
DefaultLayouts.DefaultLayoutsListWrapper defaultLayoutsListWrapper = new DefaultLayouts.DefaultLayoutsListWrapper
|
||||
{
|
||||
DefaultLayouts = new List<DefaultLayouts.DefaultLayoutWrapper> { },
|
||||
};
|
||||
FancyZonesEditorHelper.Files.DefaultLayoutsIOHelper.WriteData(defaultLayouts.Serialize(defaultLayoutsListWrapper));
|
||||
|
||||
LayoutHotkeys layoutHotkeys = new LayoutHotkeys();
|
||||
LayoutHotkeys.LayoutHotkeysWrapper layoutHotkeysWrapper = new LayoutHotkeys.LayoutHotkeysWrapper
|
||||
{
|
||||
LayoutHotkeys = new List<LayoutHotkeys.LayoutHotkeyWrapper> { },
|
||||
};
|
||||
FancyZonesEditorHelper.Files.LayoutHotkeysIOHelper.WriteData(layoutHotkeys.Serialize(layoutHotkeysWrapper));
|
||||
|
||||
AppliedLayouts appliedLayouts = new AppliedLayouts();
|
||||
AppliedLayouts.AppliedLayoutsListWrapper appliedLayoutsWrapper = new AppliedLayouts.AppliedLayoutsListWrapper
|
||||
{
|
||||
AppliedLayouts = new List<AppliedLayouts.AppliedLayoutWrapper> { },
|
||||
};
|
||||
FancyZonesEditorHelper.Files.AppliedLayoutsIOHelper.WriteData(appliedLayouts.Serialize(appliedLayoutsWrapper));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// 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.IO.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.FancyZonesEditor.UITests.Utils
|
||||
{
|
||||
public class IOTestHelper
|
||||
{
|
||||
private readonly IFileSystem _fileSystem = new FileSystem();
|
||||
|
||||
private string _file;
|
||||
|
||||
private string _data = string.Empty;
|
||||
|
||||
public IOTestHelper(string file)
|
||||
{
|
||||
_file = file;
|
||||
|
||||
if (_fileSystem.File.Exists(_file))
|
||||
{
|
||||
_data = ReadFile(_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
var path = Path.GetDirectoryName(file);
|
||||
if (path != null)
|
||||
{
|
||||
_fileSystem.Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~IOTestHelper()
|
||||
{
|
||||
RestoreData();
|
||||
}
|
||||
|
||||
public void RestoreData()
|
||||
{
|
||||
if (_data != string.Empty)
|
||||
{
|
||||
WriteData(_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteFile();
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteData(string data)
|
||||
{
|
||||
var attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileSystem.File.WriteAllText(_file, data);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
// For get app zone history data
|
||||
public string GetData()
|
||||
{
|
||||
return ReadFile(_file);
|
||||
}
|
||||
|
||||
private string ReadFile(string fileName)
|
||||
{
|
||||
var attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open))
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
{
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void DeleteFile()
|
||||
{
|
||||
var attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileSystem.File.Delete(_file);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user