From f6e7635a4e143def0a6bb2ada4d562c0de318059 Mon Sep 17 00:00:00 2001 From: Seraphima Zykova Date: Fri, 22 Mar 2024 13:10:10 +0100 Subject: [PATCH] [FancyZones]UI testing that works in CI (#29453) * added test project * run fz test * rename proj * editor test project * check if FZ is running * rename * added assert messages * spelling * dev docs * spelling * update to latest stable * exclude ui tests deps * update packages list in notice.md * added sample tests * added file for tests run * removed unrecognized * removed run * fix test configuration * rename job * change dependance * run test template * removed condition * tabulation fix * removed arg * removed dependance * removed log * removed parameters * test * test * added parameters * pool * pool * vs test * dependance * download artifact * publish artifact * artifact publish conditions * artifact name, default download path * set folders * prepare dotnet and vstest platform * copy all * target dotnet8 * test build agents * set vs test version * spellcheck * set test platform version * package feed selector * hardcoded vstest location * are other tests running? * location * vstest.console * upd command * script path * search vstest.console * vs path * tools dir * check files * try full path * try vstest task * try full path in vstest task * change path, remove unnecessary * test with full vsconsole path * winappdriver task * changed args and condition * default address * added start operation type * task name * remove resolution * Update run-ui-tests-ci.yml * Update run-ui-tests-ci.yml * Update run-ui-tests-ci.yml * Update run-ui-tests-ci.yml * AgentResolution should be a string * Update run-ui-tests-ci.yml testing against what WinUI gallery has for agent * Update run-ui-tests-ci.yml * Update run-ui-tests-ci.yml * added WinAppDriver.exe * spellcheck * remove task * checkout * path * src dir variable * added init to the second project * set longer timeout * try waiting * rerun * log session info * exclude WinAppDriver files from spell-check * split io class: editor params * remove unnecessary * move data to the common project * io test helper * write retry * Moved constants * file utils * prepare editor files before launch * remove unused file * spellcheck * create directory * fixed cleaning up * remove WinAppDriver from deps * start WinAppDriver from the default installation path * installation script * Revert "spellcheck" This reverts commit 4bdc3957305daa20a5901aae83de0622ec41a93d. * Revert "exclude WinAppDriver files from spell-check" This reverts commit 21ee6db3f5afb4cae9ea51d9468c07caa8dbc0f4. * install * installation argument * spellcheck * change winappdriver path in fz tests * delete iohelper * update docs * deleted obsolete winappdriver tests * net version * try without vstest location * spellcheck * Revert "try without vstest location" This reverts commit 7cd39f3ae6735f53f7deea8d91312a8046309459. * moved json tag constants to the common project --- .github/actions/spell-check/expect.txt | 4 +- .pipelines/InstallWinAppDriver.ps1 | 15 + .pipelines/ci/ci.yml | 5 +- .../ci/templates/build-powertoys-steps.yml | 15 + .pipelines/ci/templates/run-ui-tests-ci.yml | 72 ++ .pipelines/verifyDepsJsonLibraryVersions.ps1 | 3 +- Directory.Packages.props | 2 +- NOTICE.md | 1 + PowerToys.sln | 45 + doc/devdocs/modules/fancyzones.md | 91 +- .../Data/AppliedLayouts.cs | 59 ++ .../FancyZonesEditorCommon/Data/Constants.cs | 35 + .../Data/CustomLayouts.cs | 100 +++ .../Data/DefaultLayouts.cs | 47 + .../Data/EditorData`1.cs | 42 + .../Data/EditorParameters.cs | 89 ++ .../Data/LayoutDefaultSettings.cs | 20 + .../Data/LayoutHotkeys.cs | 32 + .../Data/LayoutTemplates.cs | 38 + .../FancyZonesEditorCommon.csproj | 21 + .../Utils}/DashCaseNamingPolicy.cs | 4 +- .../FancyZonesEditorCommon/Utils/IOUtils.cs | 54 ++ .../Utils}/StringUtils.cs | 2 +- .../fancyzones/UITests-FancyZones/Init.cs | 35 + .../UITests-FancyZones/RunFancyZonesTest.cs | 33 + .../UITests-FancyZones.csproj | 30 + .../Utils/FancyZonesSession.cs | 66 ++ .../UITests-FancyZonesEditor/Init.cs | 35 + .../RunFancyZonesEditorTest.cs | 177 ++++ .../UITests-FancyZonesEditor/TestConstants.cs | 22 + .../UITests-FancyZonesEditor.csproj | 35 + .../Utils/FancyZonesEditorFiles.cs | 43 + .../Utils/FancyZonesEditorSession.cs | 137 +++ .../Utils/IOTestHelper.cs | 113 +++ .../FancyZonesEditor/FancyZonesEditor.csproj | 1 + .../Models/GridLayoutModel.cs | 5 +- .../FancyZonesEditor/Models/LayoutModel.cs | 7 +- .../FancyZonesEditor/Models/LayoutSettings.cs | 20 +- .../Properties/Resources.Designer.cs | 9 + .../Properties/Resources.resx | 3 + .../Utils/FancyZonesEditorIO.cs | 819 +++++------------- .../FancyZonesEditor/Utils/ParsingResult.cs | 22 + .../EditorCanvasZoneResizeTests.cs | 301 ------- .../EditorCustomLayoutsTests.cs | 258 ------ .../EditorGridZoneResizeTests.cs | 438 ---------- .../FancyZonesTests/EditorOpeningTests.cs | 300 ------- .../FancyZonesTests/EditorSettingsTests.cs | 206 ----- .../EditorTemplatesApplyTests.cs | 99 --- .../EditorTemplatesEditTests.cs | 207 ----- .../FancyZonesTests/FancyZonesEditor.cs | 106 --- .../FancyZonesSettingsTests.cs | 776 ----------------- .../win-app-driver/FancyZonesTests/README.md | 41 - src/tests/win-app-driver/PowerToysSession.cs | 335 ------- .../win-app-driver/PowerToysTrayTests.cs | 121 --- src/tests/win-app-driver/README.md | 81 -- .../win-app-driver/TestShortcutGuideHelper.cs | 166 ---- .../win-app-driver/win-app-driver.csproj | 21 - 57 files changed, 1692 insertions(+), 4172 deletions(-) create mode 100644 .pipelines/InstallWinAppDriver.ps1 create mode 100644 .pipelines/ci/templates/run-ui-tests-ci.yml create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/AppliedLayouts.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/Constants.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/CustomLayouts.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/DefaultLayouts.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorData`1.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorParameters.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutDefaultSettings.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutHotkeys.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutTemplates.cs create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/FancyZonesEditorCommon.csproj rename src/modules/fancyzones/{editor/FancyZonesEditor => FancyZonesEditorCommon/Utils}/DashCaseNamingPolicy.cs (89%) create mode 100644 src/modules/fancyzones/FancyZonesEditorCommon/Utils/IOUtils.cs rename src/modules/fancyzones/{editor/FancyZonesEditor => FancyZonesEditorCommon/Utils}/StringUtils.cs (94%) create mode 100644 src/modules/fancyzones/UITests-FancyZones/Init.cs create mode 100644 src/modules/fancyzones/UITests-FancyZones/RunFancyZonesTest.cs create mode 100644 src/modules/fancyzones/UITests-FancyZones/UITests-FancyZones.csproj create mode 100644 src/modules/fancyzones/UITests-FancyZones/Utils/FancyZonesSession.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/Init.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/RunFancyZonesEditorTest.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/TestConstants.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/UITests-FancyZonesEditor.csproj create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorFiles.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorSession.cs create mode 100644 src/modules/fancyzones/UITests-FancyZonesEditor/Utils/IOTestHelper.cs create mode 100644 src/modules/fancyzones/editor/FancyZonesEditor/Utils/ParsingResult.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorCanvasZoneResizeTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorCustomLayoutsTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorGridZoneResizeTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorOpeningTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorSettingsTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorTemplatesApplyTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/EditorTemplatesEditTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/FancyZonesEditor.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs delete mode 100644 src/tests/win-app-driver/FancyZonesTests/README.md delete mode 100644 src/tests/win-app-driver/PowerToysSession.cs delete mode 100644 src/tests/win-app-driver/PowerToysTrayTests.cs delete mode 100644 src/tests/win-app-driver/README.md delete mode 100644 src/tests/win-app-driver/TestShortcutGuideHelper.cs delete mode 100644 src/tests/win-app-driver/win-app-driver.csproj diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 41a9796d15..a60ecf2414 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -54,7 +54,7 @@ Apm APPBARDATA appdata APPEXECLINK -appium +Appium Applicationcan appmanifest APPNAME @@ -929,6 +929,7 @@ mscorlib msdata msedge MSGFLT +msiexec MSIFASTINSTALL MSIHANDLE msiquery @@ -1716,6 +1717,7 @@ VSM vso vsonline vstemplate +vstest VSTHRD VSTT vswhere diff --git a/.pipelines/InstallWinAppDriver.ps1 b/.pipelines/InstallWinAppDriver.ps1 new file mode 100644 index 0000000000..1b722a207d --- /dev/null +++ b/.pipelines/InstallWinAppDriver.ps1 @@ -0,0 +1,15 @@ +$ProgressPreference = 'SilentlyContinue' + +$WinAppDriverDownloadUrl = "https://github.com/microsoft/WinAppDriver/releases/download/v1.2.1/WindowsApplicationDriver_1.2.1.msi" + +# Download WinAppDriver and verify their hash sums +Invoke-WebRequest -Uri $WinAppDriverDownloadUrl -OutFile "$($ENV:Temp)\WindowsApplicationDriver_1.2.1.msi" +$Hash = (Get-FileHash -Algorithm SHA256 "$($ENV:Temp)\WindowsApplicationDriver_1.2.1.msi").Hash +if ($Hash -ne 'a76a8f4e44b29bad331acf6b6c248fcc65324f502f28826ad2acd5f3c80857fe') +{ + Write-Error "$WinAppDriverHash" + throw "WindowsApplicationDriver_1.2.1.msi has unexpected SHA256 hash: $Hash" +} + +# Install WinAppDriver +Start-Process msiexec.exe -Wait -ArgumentList "/I $($ENV:Temp)\WindowsApplicationDriver_1.2.1.msi /quiet /passive" diff --git a/.pipelines/ci/ci.yml b/.pipelines/ci/ci.yml index 982487c435..4505a0b30a 100644 --- a/.pipelines/ci/ci.yml +++ b/.pipelines/ci/ci.yml @@ -33,4 +33,7 @@ jobs: platform: x64 - template: ./templates/build-powertoys-ci.yml parameters: - platform: arm64 \ No newline at end of file + platform: arm64 + - template: ./templates/run-ui-tests-ci.yml + parameters: + platform: x64 diff --git a/.pipelines/ci/templates/build-powertoys-steps.yml b/.pipelines/ci/templates/build-powertoys-steps.yml index 8152927111..ba575b5713 100644 --- a/.pipelines/ci/templates/build-powertoys-steps.yml +++ b/.pipelines/ci/templates/build-powertoys-steps.yml @@ -299,3 +299,18 @@ steps: displayName: Publish Logs artifact: '$(System.JobDisplayName) logs' condition: always() + +- task: CopyFiles@2 + displayName: Copy Build Files + condition: and(succeeded(), ne(variables['BuildPlatform'],'arm64')) + inputs: + sourceFolder: '$(Build.SourcesDirectory)' + contents: '$(BuildPlatform)/$(BuildConfiguration)/**/*' + targetFolder: '$(Build.ArtifactStagingDirectory)\$(BuildPlatform)\$(BuildConfiguration)' + +- task: PublishBuildArtifacts@1 + displayName: Publish Build Artifacts + condition: and(succeeded(), ne(variables['BuildPlatform'],'arm64')) + inputs: + pathToPublish: '$(Build.ArtifactStagingDirectory)\$(BuildPlatform)\$(BuildConfiguration)' + artifactName: build-$(BuildPlatform)-$(BuildConfiguration) diff --git a/.pipelines/ci/templates/run-ui-tests-ci.yml b/.pipelines/ci/templates/run-ui-tests-ci.yml new file mode 100644 index 0000000000..40c2210867 --- /dev/null +++ b/.pipelines/ci/templates/run-ui-tests-ci.yml @@ -0,0 +1,72 @@ +parameters: + configuration: 'Release' + platform: '' + +jobs: +- job: UITest + displayName: UI Test ${{ parameters.platform }} ${{ parameters.configuration }} + dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }} + variables: + SrcPath: $(Build.Repository.LocalPath) + pool: + ${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}: + name: SHINE-OSS-Testing-x64 + ${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}: + name: SHINE-INT-Testing-x64 + steps: + - checkout: self + fetchDepth: 1 + submodules: false + clean: true + fetchTags: false + + - task: DownloadPipelineArtifact@2 + displayName: Download artifacts + inputs: + artifact: build-${{ parameters.platform }}-${{ parameters.configuration }} + path: $(Build.ArtifactStagingDirectory) + + - task: UseDotNet@2 + displayName: 'Use .NET 6 SDK' + inputs: + packageType: sdk + version: '6.x' + + - task: UseDotNet@2 + displayName: 'Use .NET 8 SDK' + inputs: + packageType: sdk + version: '8.x' + includePreviewVersions: true + + - task: VisualStudioTestPlatformInstaller@1 + displayName: Ensure VSTest Platform + + - task: PowerShell@2 + displayName: Download and install WinAppDriver + inputs: + targetType: filePath + filePath: '$(build.sourcesdirectory)\.pipelines\InstallWinAppDriver.ps1' + + - task: ScreenResolutionUtility@1 + inputs: + displaySettings: 'optimal' + + - task: VSTest@2 + displayName: 'UI Tests' + condition: and(succeeded(), ne(variables['BuildPlatform'],'arm64')) # No arm64 agents to run the tests. + inputs: + platform: '$(BuildPlatform)' + configuration: '$(BuildConfiguration)' + testSelector: 'testAssemblies' + searchFolder: '$(Build.ArtifactStagingDirectory)' + vstestLocationMethod: 'location' # otherwise fails to find vstest.console.exe + #vstestLocation: '$(Agent.ToolsDirectory)\VsTest\**\${{ parameters.platform }}\tools\net462\Common7\IDE\Extensions\TestPlatform' + vstestLocation: '$(Agent.ToolsDirectory)\VsTest\17.10.0-preview-24080-01\x64\tools\net462\Common7\IDE\Extensions\TestPlatform' + uiTests: true + rerunFailedTests: true + testAssemblyVer2: | + **\UITests-FancyZones.dll + **\UITests-FancyZonesEditor.dll + !**\obj\** + !**\ref\** diff --git a/.pipelines/verifyDepsJsonLibraryVersions.ps1 b/.pipelines/verifyDepsJsonLibraryVersions.ps1 index 5dc941fa91..f6cf4c86da 100644 --- a/.pipelines/verifyDepsJsonLibraryVersions.ps1 +++ b/.pipelines/verifyDepsJsonLibraryVersions.ps1 @@ -15,7 +15,8 @@ Param( $referencedFileVersionsPerDll = @{} $totalFailures = 0 -Get-ChildItem $targetDir -Recurse -Filter *.deps.json | ForEach-Object { +Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones* | ForEach-Object { + # Temporarily exclude FancyZones UI tests because of Appium.WebDriver dependencies $depsJsonFullFileName = $_.FullName $depsJsonFileName = $_.Name $depsJson = Get-Content $depsJsonFullFileName | ConvertFrom-Json diff --git a/Directory.Packages.props b/Directory.Packages.props index 87e82f0d37..3ab3cb294d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ true - + diff --git a/NOTICE.md b/NOTICE.md index a6cbccb7a5..4d4983e41f 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1296,6 +1296,7 @@ EXHIBIT A -Mozilla Public License. ## NuGet Packages used by PowerToys +- Appium.WebDriver 4.4.5 - CommunityToolkit.Mvvm 8.2.2 - CommunityToolkit.WinUI.Animations 8.0.240109 - CommunityToolkit.WinUI.Collections 8.0.240109 diff --git a/PowerToys.sln b/PowerToys.sln index 4cd3e110c6..9f8aac046c 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -568,6 +568,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithContextMenu", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLib", "src\modules\FileLocksmith\FileLocksmithLib\FileLocksmithLib.vcxproj", "{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITests-FancyZones", "src\modules\fancyzones\UITests-FancyZones\UITests-FancyZones.csproj", "{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITests-FancyZonesEditor", "src\modules\fancyzones\UITests-FancyZonesEditor\UITests-FancyZonesEditor.csproj", "{3A9A791E-94A9-49F8-8401-C11CE288D5FB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditorCommon", "src\modules\fancyzones\FancyZonesEditorCommon\FancyZonesEditorCommon.csproj", "{C0974915-8A1D-4BF0-977B-9587D3807AB7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -2494,6 +2500,42 @@ Global {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x64.Build.0 = Release|x64 {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.ActiveCfg = Release|x64 {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.Build.0 = Release|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|ARM64.Build.0 = Debug|ARM64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x64.ActiveCfg = Debug|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x64.Build.0 = Debug|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x86.ActiveCfg = Debug|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x86.Build.0 = Debug|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|ARM64.ActiveCfg = Release|ARM64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|ARM64.Build.0 = Release|ARM64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x64.ActiveCfg = Release|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x64.Build.0 = Release|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x86.ActiveCfg = Release|x64 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x86.Build.0 = Release|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|ARM64.Build.0 = Debug|ARM64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x64.ActiveCfg = Debug|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x64.Build.0 = Debug|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x86.ActiveCfg = Debug|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x86.Build.0 = Debug|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|ARM64.ActiveCfg = Release|ARM64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|ARM64.Build.0 = Release|ARM64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x64.ActiveCfg = Release|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x64.Build.0 = Release|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x86.ActiveCfg = Release|x64 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x86.Build.0 = Release|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.Build.0 = Debug|ARM64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x64.ActiveCfg = Debug|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x64.Build.0 = Debug|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x86.ActiveCfg = Debug|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x86.Build.0 = Debug|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|ARM64.ActiveCfg = Release|ARM64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|ARM64.Build.0 = Release|ARM64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x64.ActiveCfg = Release|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x64.Build.0 = Release|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x86.ActiveCfg = Release|x64 + {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x86.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2703,6 +2745,9 @@ Global {0014D652-901F-4456-8D65-06FC5F997FB0} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA} = {AB82E5DD-C32D-4F28-9746-2C780846188E} {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F} = {AB82E5DD-C32D-4F28-9746-2C780846188E} + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} + {3A9A791E-94A9-49F8-8401-C11CE288D5FB} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} + {C0974915-8A1D-4BF0-977B-9587D3807AB7} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} diff --git a/doc/devdocs/modules/fancyzones.md b/doc/devdocs/modules/fancyzones.md index a536dce50e..61a7ea58fa 100644 --- a/doc/devdocs/modules/fancyzones.md +++ b/doc/devdocs/modules/fancyzones.md @@ -1,85 +1,26 @@ -## FancyZones Lib +# FancyZones UI tests -#### [`FancyZones.cpp`](/src/modules/fancyzones/lib/FancyZones.cpp) -TODO +UI tests are implemented using [Windows Application Driver](https://github.com/microsoft/WinAppDriver). -#### [`Settings.cpp`](/src/modules/fancyzones/lib/Settings.cpp) -TODO +## Before running tests -#### [`trace.cpp`](/src/modules/fancyzones/lib/trace.cpp) -TODO + - Install Windows Application Driver v1.2.1 from https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1. + - Enable Developer Mode in Windows settings -#### [`Zone.cpp`](/src/modules/fancyzones/lib/Zone.cpp) -TODO +## Running tests + + - Exit PowerToys if it's running + - Run WinAppDriver.exe from the installation directory. Skip this step if installed in the default directory (`C:\Program Files (x86)\Windows Application Driver`); in this case, it'll be launched automatically during tests. + - Open `PowerToys.sln` in Visual Studio and build the solution. + - Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`). -#### [`ZoneSet.cpp`](/src/modules/fancyzones/lib/ZoneSet.cpp) -TODO +>Note: notifications or other application windows, that are shown above the window under test, can disrupt the testing process. -#### [`WorkArea.cpp`](/src/modules/fancyzones/lib/WorkArea.cpp) -TODO -## FancyZones Editor +## Extra tools and information -#### [`App.xaml.cs`](/src/modules/fancyzones/editor/App.xaml.cs) -TODO +**Test samples**: https://github.com/microsoft/WinAppDriver/tree/master/Samples -#### [`Properties\AssemblyInfo.cs`](/src/modules/fancyzones/editor/Properties\AssemblyInfo.cs) -TODO - -#### [`CanvasEditor.xaml.cs`](/src/modules/fancyzones/editor/CanvasEditor.xaml.cs) -TODO - -#### [`CanvasEditorWindow.xaml.cs`](/src/modules/fancyzones/editor/CanvasEditorWindow.xaml.cs) -TODO - -#### [`Models\CanvasLayoutModel.cs`](/src/modules/fancyzones/editor/Models\CanvasLayoutModel.cs) -TODO - -#### [`CanvasZone.xaml.cs`](/src/modules/fancyzones/editor/CanvasZone.xaml.cs) -TODO - -#### [`EditorOverlay.xaml.cs`](/src/modules/fancyzones/editor/EditorOverlay.xaml.cs) -TODO - -#### [`EditorWindow.cs`](/src/modules/fancyzones/editor/EditorWindow.cs) -TODO - -#### [`GridEditor.xaml.cs`](/src/modules/fancyzones/editor/GridEditor.xaml.cs) -TODO - -#### [`GridEditorWindow.xaml.cs`](/src/modules/fancyzones/editor/GridEditorWindow.xaml.cs) -TODO - -#### [`Models\GridLayoutModel.cs`](/src/modules/fancyzones/editor/Models\GridLayoutModel.cs) -TODO - -#### [`GridResizer.xaml.cs`](/src/modules/fancyzones/editor/GridResizer.xaml.cs) -TODO - -#### [`GridZone.xaml.cs`](/src/modules/fancyzones/editor/GridZone.xaml.cs) -TODO - -#### [`Models\LayoutModel.cs`](/src/modules/fancyzones/editor/Models/LayoutModel.cs) -TODO - -#### [`LayoutPreview.xaml.cs`](/src/modules/fancyzones/editor/LayoutPreview.xaml.cs) -TODO - -#### [`MainWindow.xaml.cs`](/src/modules/fancyzones/editor/MainWindow.xaml.cs) -TODO - -#### [`Properties\Resources.Designer.cs`](/src/modules/fancyzones/editor/Properties/Resources.Designer.cs) -TODO - -#### [`RowColInfo.cs`](/src/modules/fancyzones/editor/RowColInfo.cs) -TODO - -#### [`Models\Settings.cs`](/src/modules/fancyzones/editor/Models/Settings.cs) -TODO - -#### [`Properties\Settings.Designer.cs`](/src/modules/fancyzones/editor/Properties/Settings.Designer.cs) -TODO - -#### [`WindowLayout.xaml.cs`](/src/modules/fancyzones/editor/WindowLayout.xaml.cs) -TODO +While working on tests, you may need a tool that helps you to view the element's accessibility data, e.g. for finding the button to click. For this purpose, you could use [AccessibilityInsights](https://accessibilityinsights.io/docs/windows/overview) or [WinAppDriver UI Recorder](https://github.com/microsoft/WinAppDriver/wiki/WinAppDriver-UI-Recorder). +>Note: close helper tools while running tests. Overlapping windows can affect test results. \ No newline at end of file diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/AppliedLayouts.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/AppliedLayouts.cs new file mode 100644 index 0000000000..188e834b37 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/AppliedLayouts.cs @@ -0,0 +1,59 @@ +// 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; + +namespace FancyZonesEditorCommon.Data +{ + public class AppliedLayouts : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\applied-layouts.json"; + } + } + + public struct AppliedLayoutWrapper + { + 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 struct LayoutWrapper + { + public string Uuid { get; set; } + + public string Type { get; set; } + + public bool ShowSpacing { get; set; } + + public int Spacing { get; set; } + + public int ZoneCount { get; set; } + + public int SensitivityRadius { get; set; } + } + + public DeviceIdWrapper Device { get; set; } + + public LayoutWrapper AppliedLayout { get; set; } + } + + public struct AppliedLayoutsListWrapper + { + public List AppliedLayouts { get; set; } + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/Constants.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/Constants.cs new file mode 100644 index 0000000000..1cd8402689 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/Constants.cs @@ -0,0 +1,35 @@ +// 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.Collections.ObjectModel; + +namespace FancyZonesEditorCommon.Data +{ + public static class Constants + { + public enum TemplateLayout + { + Empty, + Focus, + Rows, + Columns, + Grid, + PriorityGrid, + } + + public static readonly ReadOnlyDictionary TemplateLayoutJsonTags = new ReadOnlyDictionary( + new Dictionary() + { + { TemplateLayout.Empty, "blank" }, + { TemplateLayout.Focus, "focus" }, + { TemplateLayout.Rows, "rows" }, + { TemplateLayout.Columns, "columns" }, + { TemplateLayout.Grid, "grid" }, + { TemplateLayout.PriorityGrid, "priority-grid" }, + }); + + public const string CustomLayoutJsonTag = "custom"; + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/CustomLayouts.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/CustomLayouts.cs new file mode 100644 index 0000000000..92f31892aa --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/CustomLayouts.cs @@ -0,0 +1,100 @@ +// 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.CustomLayouts; + +namespace FancyZonesEditorCommon.Data +{ + public class CustomLayouts : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json"; + } + } + + public sealed class CanvasInfoWrapper + { + public struct CanvasZoneWrapper + { + public int X { get; set; } + + public int Y { get; set; } + + public int Width { get; set; } + + public int Height { get; set; } + } + + public int RefWidth { get; set; } + + public int RefHeight { get; set; } + + public List Zones { get; set; } + + public int SensitivityRadius { get; set; } = LayoutDefaultSettings.DefaultSensitivityRadius; + } + + public sealed class GridInfoWrapper + { + public int Rows { get; set; } + + public int Columns { get; set; } + + public List RowsPercentage { get; set; } + + public List ColumnsPercentage { get; set; } + + public int[][] CellChildMap { get; set; } + + public bool ShowSpacing { get; set; } = LayoutDefaultSettings.DefaultShowSpacing; + + public int Spacing { get; set; } = LayoutDefaultSettings.DefaultSpacing; + + public int SensitivityRadius { get; set; } = LayoutDefaultSettings.DefaultSensitivityRadius; + } + + public struct CustomLayoutWrapper + { + public string Uuid { get; set; } + + public string Name { get; set; } + + public string Type { get; set; } + + public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper + } + + public struct CustomLayoutListWrapper + { + public List CustomLayouts { get; set; } + } + + public JsonElement ToJsonElement(CanvasInfoWrapper info) + { + string json = JsonSerializer.Serialize(info, this.JsonOptions); + return JsonSerializer.Deserialize(json); + } + + public JsonElement ToJsonElement(GridInfoWrapper info) + { + string json = JsonSerializer.Serialize(info, this.JsonOptions); + return JsonSerializer.Deserialize(json); + } + + public CanvasInfoWrapper CanvasFromJsonElement(string json) + { + return JsonSerializer.Deserialize(json, this.JsonOptions); + } + + public GridInfoWrapper GridFromJsonElement(string json) + { + return JsonSerializer.Deserialize(json, this.JsonOptions); + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/DefaultLayouts.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/DefaultLayouts.cs new file mode 100644 index 0000000000..307d33adc1 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/DefaultLayouts.cs @@ -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 System.Collections.Generic; +using static FancyZonesEditorCommon.Data.DefaultLayouts; + +namespace FancyZonesEditorCommon.Data +{ + public class DefaultLayouts : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\default-layouts.json"; + } + } + + public struct DefaultLayoutWrapper + { + public struct LayoutWrapper + { + public string Uuid { get; set; } + + public string Type { get; set; } + + public bool ShowSpacing { get; set; } + + public int Spacing { get; set; } + + public int ZoneCount { get; set; } + + public int SensitivityRadius { get; set; } + } + + public string MonitorConfiguration { get; set; } + + public LayoutWrapper Layout { get; set; } + } + + public struct DefaultLayoutsListWrapper + { + public List DefaultLayouts { get; set; } + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorData`1.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorData`1.cs new file mode 100644 index 0000000000..913881a72e --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorData`1.cs @@ -0,0 +1,42 @@ +// 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.Text.Json; +using FancyZonesEditorCommon.Utils; + +namespace FancyZonesEditorCommon.Data +{ + public class EditorData + { + public string GetDataFolder() + { + return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + } + + protected JsonSerializerOptions JsonOptions + { + get + { + return new JsonSerializerOptions + { + PropertyNamingPolicy = new DashCaseNamingPolicy(), + WriteIndented = true, + }; + } + } + + public T Read(string file) + { + IOUtils ioUtils = new IOUtils(); + string data = ioUtils.ReadFile(file); + return JsonSerializer.Deserialize(data, JsonOptions); + } + + public string Serialize(T data) + { + return JsonSerializer.Serialize(data, JsonOptions); + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorParameters.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorParameters.cs new file mode 100644 index 0000000000..e973c6070f --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/EditorParameters.cs @@ -0,0 +1,89 @@ +// 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.Globalization; +using System.Text; + +namespace FancyZonesEditorCommon.Data +{ + public class EditorParameters : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json"; + } + } + + public struct NativeMonitorDataWrapper + { + public string Monitor { get; set; } + + public string MonitorInstanceId { get; set; } + + public string MonitorSerialNumber { get; set; } + + public int MonitorNumber { get; set; } + + public string VirtualDesktop { get; set; } + + public int Dpi { get; set; } + + public int LeftCoordinate { get; set; } + + public int TopCoordinate { get; set; } + + public int WorkAreaWidth { get; set; } + + public int WorkAreaHeight { get; set; } + + public int MonitorWidth { get; set; } + + public int MonitorHeight { get; set; } + + public bool IsSelected { get; set; } + + public override string ToString() + { + var sb = new StringBuilder(); + + // using CultureInfo.InvariantCulture since this is internal data + sb.Append("Monitor: "); + sb.AppendLine(Monitor); + sb.Append("Virtual desktop: "); + sb.AppendLine(VirtualDesktop); + sb.Append("DPI: "); + sb.AppendLine(Dpi.ToString(CultureInfo.InvariantCulture)); + + sb.Append("X: "); + sb.AppendLine(LeftCoordinate.ToString(CultureInfo.InvariantCulture)); + sb.Append("Y: "); + sb.AppendLine(TopCoordinate.ToString(CultureInfo.InvariantCulture)); + + sb.Append("Width: "); + sb.AppendLine(MonitorWidth.ToString(CultureInfo.InvariantCulture)); + sb.Append("Height: "); + sb.AppendLine(MonitorHeight.ToString(CultureInfo.InvariantCulture)); + + return sb.ToString(); + } + } + + public struct ParamsWrapper + { + public int ProcessId { get; set; } + + public bool SpanZonesAcrossMonitors { get; set; } + + public List Monitors { get; set; } + } + + public EditorParameters() + : base() + { + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutDefaultSettings.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutDefaultSettings.cs new file mode 100644 index 0000000000..8045113566 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutDefaultSettings.cs @@ -0,0 +1,20 @@ +// 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 FancyZonesEditorCommon.Data +{ + public class LayoutDefaultSettings + { + // TODO: share the constants b/w C# Editor and FancyZoneLib + public const bool DefaultShowSpacing = true; + + public const int DefaultSpacing = 16; + + public const int DefaultZoneCount = 3; + + public const int DefaultSensitivityRadius = 20; + + public const int MaxZones = 128; + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutHotkeys.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutHotkeys.cs new file mode 100644 index 0000000000..4b0ad7672e --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutHotkeys.cs @@ -0,0 +1,32 @@ +// 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 static FancyZonesEditorCommon.Data.LayoutHotkeys; + +namespace FancyZonesEditorCommon.Data +{ + public class LayoutHotkeys : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json"; + } + } + + public struct LayoutHotkeyWrapper + { + public int Key { get; set; } + + public string LayoutId { get; set; } + } + + public struct LayoutHotkeysWrapper + { + public List LayoutHotkeys { get; set; } + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutTemplates.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutTemplates.cs new file mode 100644 index 0000000000..2b7cfdd551 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Data/LayoutTemplates.cs @@ -0,0 +1,38 @@ +// 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 static FancyZonesEditorCommon.Data.LayoutTemplates; + +namespace FancyZonesEditorCommon.Data +{ + public class LayoutTemplates : EditorData + { + public string File + { + get + { + return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json"; + } + } + + public struct TemplateLayoutWrapper + { + public string Type { get; set; } + + public bool ShowSpacing { get; set; } + + public int Spacing { get; set; } + + public int ZoneCount { get; set; } + + public int SensitivityRadius { get; set; } + } + + public struct TemplateLayoutsListWrapper + { + public List LayoutTemplates { get; set; } + } + } +} diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/FancyZonesEditorCommon.csproj b/src/modules/fancyzones/FancyZonesEditorCommon/FancyZonesEditorCommon.csproj new file mode 100644 index 0000000000..cb92563985 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/FancyZonesEditorCommon.csproj @@ -0,0 +1,21 @@ + + + + + net8.0-windows10.0.20348.0 + win-x64;win-arm64 + $(Version).0 + Microsoft Corporation + PowerToys + PowerToys FancyZonesEditorCommon + PowerToys.FancyZonesEditorCommon + + + + + + + + ..\..\..\..\$(Platform)\$(Configuration)\FancyZonesEditorCommon\ + + diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/DashCaseNamingPolicy.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/DashCaseNamingPolicy.cs similarity index 89% rename from src/modules/fancyzones/editor/FancyZonesEditor/DashCaseNamingPolicy.cs rename to src/modules/fancyzones/FancyZonesEditorCommon/Utils/DashCaseNamingPolicy.cs index b88f25d7e4..529ff11d7c 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/DashCaseNamingPolicy.cs +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/DashCaseNamingPolicy.cs @@ -4,9 +4,7 @@ using System.Text.Json; -using FancyZonesEditor.Utils; - -namespace FancyZonesEditor +namespace FancyZonesEditorCommon.Utils { public class DashCaseNamingPolicy : JsonNamingPolicy { diff --git a/src/modules/fancyzones/FancyZonesEditorCommon/Utils/IOUtils.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/IOUtils.cs new file mode 100644 index 0000000000..f48a341695 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/IOUtils.cs @@ -0,0 +1,54 @@ +// 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 FancyZonesEditorCommon.Utils +{ + public class IOUtils + { + private readonly IFileSystem _fileSystem = new FileSystem(); + + public IOUtils() + { + } + + public void WriteFile(string fileName, string data) + { + _fileSystem.File.WriteAllText(fileName, data); + } + + public string ReadFile(string fileName) + { + if (_fileSystem.File.Exists(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; + } + } +} diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/StringUtils.cs similarity index 94% rename from src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs rename to src/modules/fancyzones/FancyZonesEditorCommon/Utils/StringUtils.cs index 027003477b..6584559faf 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/StringUtils.cs +++ b/src/modules/fancyzones/FancyZonesEditorCommon/Utils/StringUtils.cs @@ -4,7 +4,7 @@ using System.Linq; -namespace FancyZonesEditor.Utils +namespace FancyZonesEditorCommon.Utils { public static class StringUtils { diff --git a/src/modules/fancyzones/UITests-FancyZones/Init.cs b/src/modules/fancyzones/UITests-FancyZones/Init.cs new file mode 100644 index 0000000000..77629bf1d6 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZones/Init.cs @@ -0,0 +1,35 @@ +// 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.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.FancyZonesEditor.UITests +{ + [TestClass] + public class Init + { + private static Process? appDriver; + + [AssemblyInitialize] + public static void SetupAll(TestContext context) + { + string winAppDriverPath = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe"; + context.WriteLine($"Attempting to launch WinAppDriver at: {winAppDriverPath}"); + appDriver = Process.Start(winAppDriverPath); + } + + [AssemblyCleanup] + public static void CleanupAll() + { + try + { + appDriver?.Kill(); + } + catch + { + } + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZones/RunFancyZonesTest.cs b/src/modules/fancyzones/UITests-FancyZones/RunFancyZonesTest.cs new file mode 100644 index 0000000000..c67d9c04c0 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZones/RunFancyZonesTest.cs @@ -0,0 +1,33 @@ +// 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 Microsoft.FancyZones.UnitTests.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace UITests_FancyZones +{ + [TestClass] + public class RunFancyZonesTest + { + private static FancyZonesSession? _session; + + [ClassInitialize] + public static void ClassInitialize(TestContext testContext) + { + _session = new FancyZonesSession(testContext); + } + + [ClassCleanup] + public static void ClassCleanup() + { + _session?.Close(); + } + + [TestMethod] + public void RunFancyZones() + { + Assert.IsNotNull(_session?.FancyZonesProcess); + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZones/UITests-FancyZones.csproj b/src/modules/fancyzones/UITests-FancyZones/UITests-FancyZones.csproj new file mode 100644 index 0000000000..1a0a085fbc --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZones/UITests-FancyZones.csproj @@ -0,0 +1,30 @@ + + + + + net8.0-windows10.0.20348.0 + 10.0.19041.0 + 10.0.19041.0 + {FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52} + Microsoft.FancyZones.UITests + false + enable + Library + $(Version).0 + + + + ..\..\..\..\$(Platform)\$(Configuration)\tests\UITests-FancyZones\ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/fancyzones/UITests-FancyZones/Utils/FancyZonesSession.cs b/src/modules/fancyzones/UITests-FancyZones/Utils/FancyZonesSession.cs new file mode 100644 index 0000000000..401c5511bf --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZones/Utils/FancyZonesSession.cs @@ -0,0 +1,66 @@ +// 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.Reflection; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.FancyZones.UnitTests.Utils +{ + public class FancyZonesSession + { + private const string FancyZonesPath = @"\..\..\..\PowerToys.FancyZones.exe"; + private const string FancyZonesProcessName = "PowerToys.FancyZones"; + + private bool stopFancyZones = true; + + public Process? FancyZonesProcess { get; } + + public FancyZonesSession(TestContext testContext) + { + try + { + // Check if FancyZones is already running + Process[] runningFZ = Process.GetProcessesByName(FancyZonesProcessName); + if (runningFZ.Length > 0) + { + FancyZonesProcess = runningFZ[0]; + stopFancyZones = false; + } + else + { + // Launch FancyZones + string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + path += FancyZonesPath; + + ProcessStartInfo info = new ProcessStartInfo(path); + FancyZonesProcess = Process.Start(info); + } + } + catch (Exception ex) + { + testContext.WriteLine(ex.Message); + } + + Assert.IsNotNull(FancyZonesProcess, "FancyZones process not started"); + } + + public void Close() + { + // Close the application + if (FancyZonesProcess != null) + { + if (stopFancyZones) + { + FancyZonesProcess.Kill(); + } + + FancyZonesProcess.Close(); + FancyZonesProcess.Dispose(); + } + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/Init.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/Init.cs new file mode 100644 index 0000000000..77629bf1d6 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/Init.cs @@ -0,0 +1,35 @@ +// 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.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.FancyZonesEditor.UITests +{ + [TestClass] + public class Init + { + private static Process? appDriver; + + [AssemblyInitialize] + public static void SetupAll(TestContext context) + { + string winAppDriverPath = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe"; + context.WriteLine($"Attempting to launch WinAppDriver at: {winAppDriverPath}"); + appDriver = Process.Start(winAppDriverPath); + } + + [AssemblyCleanup] + public static void CleanupAll() + { + try + { + appDriver?.Kill(); + } + catch + { + } + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/RunFancyZonesEditorTest.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/RunFancyZonesEditorTest.cs new file mode 100644 index 0000000000..a20559f130 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/RunFancyZonesEditorTest.cs @@ -0,0 +1,177 @@ +// 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 FancyZonesEditorCommon.Data; +using Microsoft.FancyZonesEditor.UITests; +using Microsoft.FancyZonesEditor.UnitTests.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace UITests_FancyZonesEditor +{ + [TestClass] + public class RunFancyZonesEditorTest + { + private static FancyZonesEditorSession? _session; + private static TestContext? _context; + + [ClassInitialize] + public static void ClassInitialize(TestContext testContext) + { + _context = testContext; + + // prepare files to launch Editor without errors + EditorParameters editorParameters = new EditorParameters(); + EditorParameters.ParamsWrapper parameters = new EditorParameters.ParamsWrapper + { + ProcessId = 1, + SpanZonesAcrossMonitors = false, + Monitors = new List + { + 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, + }, + }, + }; + FancyZonesEditorSession.Files.ParamsIOHelper.WriteData(editorParameters.Serialize(parameters)); + + LayoutTemplates layoutTemplates = new LayoutTemplates(); + LayoutTemplates.TemplateLayoutsListWrapper templateLayoutsListWrapper = new LayoutTemplates.TemplateLayoutsListWrapper + { + LayoutTemplates = new List + { + 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, + }, + }, + }; + FancyZonesEditorSession.Files.LayoutTemplatesIOHelper.WriteData(layoutTemplates.Serialize(templateLayoutsListWrapper)); + + CustomLayouts customLayouts = new CustomLayouts(); + CustomLayouts.CustomLayoutListWrapper customLayoutListWrapper = new CustomLayouts.CustomLayoutListWrapper + { + CustomLayouts = new List { }, + }; + FancyZonesEditorSession.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(customLayoutListWrapper)); + + DefaultLayouts defaultLayouts = new DefaultLayouts(); + DefaultLayouts.DefaultLayoutsListWrapper defaultLayoutsListWrapper = new DefaultLayouts.DefaultLayoutsListWrapper + { + DefaultLayouts = new List { }, + }; + FancyZonesEditorSession.Files.DefaultLayoutsIOHelper.WriteData(defaultLayouts.Serialize(defaultLayoutsListWrapper)); + + LayoutHotkeys layoutHotkeys = new LayoutHotkeys(); + LayoutHotkeys.LayoutHotkeysWrapper layoutHotkeysWrapper = new LayoutHotkeys.LayoutHotkeysWrapper + { + LayoutHotkeys = new List { }, + }; + FancyZonesEditorSession.Files.LayoutHotkeysIOHelper.WriteData(layoutHotkeys.Serialize(layoutHotkeysWrapper)); + + AppliedLayouts appliedLayouts = new AppliedLayouts(); + AppliedLayouts.AppliedLayoutsListWrapper appliedLayoutsWrapper = new AppliedLayouts.AppliedLayoutsListWrapper + { + AppliedLayouts = new List { }, + }; + FancyZonesEditorSession.Files.AppliedLayoutsIOHelper.WriteData(appliedLayouts.Serialize(appliedLayoutsWrapper)); + } + + [ClassCleanup] + public static void ClassCleanup() + { + FancyZonesEditorSession.Files.Restore(); + _context = null; + } + + [TestInitialize] + public void TestInitialize() + { + _session = new FancyZonesEditorSession(_context!); + } + + [TestCleanup] + public void TestCleanup() + { + _session?.Close(_context!); + } + + [TestMethod] + public void OpenEditorWindow() // verify the session is initialized + { + Assert.IsNotNull(_session?.Session); + } + + [TestMethod] + public void OpenNewLayoutDialog() // verify the new layout dialog is opened + { + _session?.Click_CreateNewLayout(); + Assert.IsNotNull(_session?.Session?.FindElementsByName("Choose layout type")); // check the pane header + } + + [TestMethod] + public void OpenEditLayoutDialog() // verify the edit layout dialog is opened + { + _session?.Click_EditLayout(TestConstants.TemplateLayoutNames[Constants.TemplateLayout.Grid]); + Assert.IsNotNull(_session?.Session?.FindElementByAccessibilityId("EditLayoutDialogTitle")); // check the pane header + Assert.IsNotNull(_session?.Session?.FindElementsByName("Edit 'Grid'")); // verify it's opened for the correct layout + } + + [TestMethod] + public void OpenContextMenu() // verify the context menu is opened + { + Assert.IsNotNull(_session?.OpenContextMenu(TestConstants.TemplateLayoutNames[Constants.TemplateLayout.Columns])); + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/TestConstants.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/TestConstants.cs new file mode 100644 index 0000000000..1a6b9b5d66 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/TestConstants.cs @@ -0,0 +1,22 @@ +// 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 static FancyZonesEditorCommon.Data.Constants; + +namespace Microsoft.FancyZonesEditor.UITests +{ + public static class TestConstants + { + public static readonly Dictionary TemplateLayoutNames = new Dictionary() + { + { TemplateLayout.Empty, "No layout" }, + { TemplateLayout.Focus, "Focus" }, + { TemplateLayout.Rows, "Rows" }, + { TemplateLayout.Columns, "Columns" }, + { TemplateLayout.Grid, "Grid" }, + { TemplateLayout.PriorityGrid, "PriorityGrid" }, + }; + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/UITests-FancyZonesEditor.csproj b/src/modules/fancyzones/UITests-FancyZonesEditor/UITests-FancyZonesEditor.csproj new file mode 100644 index 0000000000..4ce3ce7c53 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/UITests-FancyZonesEditor.csproj @@ -0,0 +1,35 @@ + + + + + net8.0-windows10.0.20348.0 + 10.0.19041.0 + 10.0.19041.0 + {3A9A791E-94A9-49F8-8401-C11CE288D5FB} + Microsoft.FancyZonesEditor.UITests + false + enable + Library + $(Version).0 + + + + ..\..\..\..\$(Platform)\$(Configuration)\tests\UITests-FancyZonesEditor\ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorFiles.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorFiles.cs new file mode 100644 index 0000000000..cc969f39b0 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorFiles.cs @@ -0,0 +1,43 @@ +// 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 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); + } + + public void Restore() + { + ParamsIOHelper.RestoreData(); + AppliedLayoutsIOHelper.RestoreData(); + CustomLayoutsIOHelper.RestoreData(); + DefaultLayoutsIOHelper.RestoreData(); + LayoutHotkeysIOHelper.RestoreData(); + LayoutTemplatesIOHelper.RestoreData(); + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorSession.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorSession.cs new file mode 100644 index 0000000000..e87c5576f3 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/FancyZonesEditorSession.cs @@ -0,0 +1,137 @@ +// 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.Reflection; +using Microsoft.FancyZonesEditor.UITests.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Interactions; + +namespace Microsoft.FancyZonesEditor.UnitTests.Utils +{ + public class FancyZonesEditorSession + { + protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723"; + private const string FancyZonesEditorPath = @"\..\..\..\PowerToys.FancyZonesEditor.exe"; + + private static FancyZonesEditorFiles? _files; + + public static FancyZonesEditorFiles Files + { + get + { + if (_files == null) + { + _files = new FancyZonesEditorFiles(); + } + + return _files; + } + } + + public WindowsDriver? Session { get; } + + public WindowsElement? MainEditorWindow { get; } + + public FancyZonesEditorSession(TestContext testContext) + { + try + { + // Launch FancyZonesEditor + string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + path += FancyZonesEditorPath; + + AppiumOptions opts = new AppiumOptions(); + opts.AddAdditionalCapability("app", path); + Session = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), opts); + } + catch (Exception ex) + { + testContext.WriteLine(ex.Message); + } + + Assert.IsNotNull(Session, "Session not initialized"); + + testContext.WriteLine("Session: " + Session.SessionId.ToString()); + testContext.WriteLine("Title: " + Session.Title); + + // Set implicit timeout to make element search to retry every 500 ms + Session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(3); + + // Find main editor window + try + { + MainEditorWindow = Session.FindElementByAccessibilityId("MainWindow1"); + } + catch + { + Assert.IsNotNull(MainEditorWindow, "Main editor window not found"); + } + } + + public void Close(TestContext testContext) + { + // Close the session + if (Session != null) + { + try + { + // FZEditor application can be closed by explicitly closing main editor window + MainEditorWindow?.SendKeys(Keys.Alt + Keys.F4); + } + catch (Exception ex) + { + testContext.WriteLine(ex.Message); + } + + Session.Quit(); + Session.Dispose(); + } + } + + private WindowsElement? GetLayout(string layoutName) + { + var listItem = Session?.FindElementByName(layoutName); + Assert.IsNotNull(listItem, "Layout " + layoutName + " not found"); + return listItem; + } + + public WindowsElement? OpenContextMenu(string layoutName) + { + RightClick_Layout(layoutName); + var menu = Session?.FindElementByClassName("ContextMenu"); + Assert.IsNotNull(menu, "Context menu not found"); + return menu; + } + + public void Click_CreateNewLayout() + { + var button = Session?.FindElementByAccessibilityId("NewLayoutButton"); + Assert.IsNotNull(button, "Create new layout button not found"); + button?.Click(); + } + + public void Click_EditLayout(string layoutName) + { + var layout = GetLayout(layoutName); + var editButton = layout?.FindElementByAccessibilityId("EditLayoutButton"); + Assert.IsNotNull(editButton, "Edit button not found"); + editButton.Click(); + } + + public void RightClick_Layout(string layoutName) + { + var layout = GetLayout(layoutName); + Actions actions = new Actions(Session); + actions.MoveToElement(layout); + actions.MoveByOffset(30, 30); + actions.ContextClick(); + actions.Build().Perform(); + } + } +} diff --git a/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/IOTestHelper.cs b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/IOTestHelper.cs new file mode 100644 index 0000000000..d472154ac5 --- /dev/null +++ b/src/modules/fancyzones/UITests-FancyZonesEditor/Utils/IOTestHelper.cs @@ -0,0 +1,113 @@ +// 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 + { + _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(file)); + } + } + + ~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++; + } + } + + 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++; + } + } + } +} diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj b/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj index dae02ff5ba..98b9c0874c 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj +++ b/src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj @@ -69,6 +69,7 @@ + diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs index 537dd741d1..9808c1b2e1 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/GridLayoutModel.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using FancyZonesEditorCommon.Data; namespace FancyZonesEditor.Models { @@ -99,7 +100,7 @@ namespace FancyZonesEditor.Models } } - private bool _showSpacing = LayoutSettings.DefaultShowSpacing; + private bool _showSpacing = LayoutDefaultSettings.DefaultShowSpacing; // Spacing - free space between cells public int Spacing @@ -129,7 +130,7 @@ namespace FancyZonesEditor.Models get { return 1000; } } - private int _spacing = LayoutSettings.DefaultSpacing; + private int _spacing = LayoutDefaultSettings.DefaultSpacing; public GridLayoutModel() : base() diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs index ef2b2a4617..028bcd26b1 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutModel.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Runtime.CompilerServices; +using FancyZonesEditorCommon.Data; namespace FancyZonesEditor.Models { @@ -195,7 +196,7 @@ namespace FancyZonesEditor.Models } } - private int _sensitivityRadius = LayoutSettings.DefaultSensitivityRadius; + private int _sensitivityRadius = LayoutDefaultSettings.DefaultSensitivityRadius; public int SensitivityRadiusMinimum { @@ -304,13 +305,13 @@ namespace FancyZonesEditor.Models } } - private int _zoneCount = LayoutSettings.DefaultZoneCount; + private int _zoneCount = LayoutDefaultSettings.DefaultZoneCount; public bool IsZoneAddingAllowed { get { - return TemplateZoneCount < LayoutSettings.MaxZones; + return TemplateZoneCount < LayoutDefaultSettings.MaxZones; } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutSettings.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutSettings.cs index dd0f7dc53c..dfc3258745 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutSettings.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/LayoutSettings.cs @@ -3,32 +3,22 @@ // See the LICENSE file in the project root for more information. using FancyZonesEditor.Models; +using FancyZonesEditorCommon.Data; namespace FancyZonesEditor { public class LayoutSettings { - // TODO: share the constants b/w C# Editor and FancyZoneLib - public const bool DefaultShowSpacing = true; - - public const int DefaultSpacing = 16; - - public const int DefaultZoneCount = 3; - - public const int DefaultSensitivityRadius = 20; - - public const int MaxZones = 128; - public string ZonesetUuid { get; set; } = string.Empty; public LayoutType Type { get; set; } = LayoutType.PriorityGrid; - public bool ShowSpacing { get; set; } = DefaultShowSpacing; + public bool ShowSpacing { get; set; } = LayoutDefaultSettings.DefaultShowSpacing; - public int Spacing { get; set; } = DefaultSpacing; + public int Spacing { get; set; } = LayoutDefaultSettings.DefaultSpacing; - public int ZoneCount { get; set; } = DefaultZoneCount; + public int ZoneCount { get; set; } = LayoutDefaultSettings.DefaultZoneCount; - public int SensitivityRadius { get; set; } = DefaultSensitivityRadius; + public int SensitivityRadius { get; set; } = LayoutDefaultSettings.DefaultSensitivityRadius; } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs index deee65388c..21dd44a195 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.Designer.cs @@ -487,6 +487,15 @@ namespace FancyZonesEditor.Properties { } } + /// + /// Looks up a localized string similar to An error occurred while parsing editor parameters.. + /// + public static string Error_Parsing_Editor_Parameters_Message { + get { + return ResourceManager.GetString("Error_Parsing_Editor_Parameters_Message", resourceCulture); + } + } + /// /// Looks up a localized string similar to An error occurred while parsing layout hotkeys.. /// diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx index f98e90b9ba..265866eba0 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Properties/Resources.resx @@ -435,4 +435,7 @@ Set layout as a default for vertical monitor orientation + + An error occurred while parsing editor parameters. + \ No newline at end of file diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs index e5ecc31a5c..612e6597d8 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/FancyZonesEditorIO.cs @@ -6,13 +6,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; -using System.IO; -using System.IO.Abstractions; -using System.Text; using System.Text.Json; -using System.Threading.Tasks; using System.Windows; using FancyZonesEditor.Models; +using FancyZonesEditorCommon.Data; +using FancyZonesEditorCommon.Utils; using ManagedCommon; namespace FancyZonesEditor.Utils @@ -20,394 +18,51 @@ namespace FancyZonesEditor.Utils public class FancyZonesEditorIO { // Non-localizable strings: JSON tags - private const string BlankJsonTag = "blank"; - private const string FocusJsonTag = "focus"; - private const string ColumnsJsonTag = "columns"; - private const string RowsJsonTag = "rows"; - private const string GridJsonTag = "grid"; - private const string PriorityGridJsonTag = "priority-grid"; - private const string CustomJsonTag = "custom"; private const string HorizontalJsonTag = "horizontal"; private const string VerticalJsonTag = "vertical"; - // Non-localizable strings: Files - private const string AppliedLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\applied-layouts.json"; - private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json"; - private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json"; - private const string CustomLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json"; - private const string DefaultLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\default-layouts.json"; - private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json"; - // Non-localizable string: default virtual desktop id private const string DefaultVirtualDesktopGuid = "{00000000-0000-0000-0000-000000000000}"; - private readonly IFileSystem _fileSystem = new FileSystem(); - - private readonly JsonSerializerOptions _options = new JsonSerializerOptions - { - PropertyNamingPolicy = new DashCaseNamingPolicy(), - WriteIndented = true, - }; - - private List _unusedLayouts = new List(); - - public string FancyZonesAppliedLayoutsFile { get; private set; } - - public string FancyZonesLayoutHotkeysFile { get; private set; } - - public string FancyZonesLayoutTemplatesFile { get; private set; } - - public string FancyZonesCustomLayoutsFile { get; private set; } - - public string FancyZonesDefaultLayoutsFile { get; private set; } - - public string FancyZonesEditorParamsFile { get; private set; } - - private enum CmdArgs - { - PowerToysPID = 0, - SpanZones, - TargetMonitorId, - MonitorsCount, - MonitorId, - DPI, - MonitorLeft, - MonitorTop, - MonitorWidth, - MonitorHeight, - } - - // parsing cmd args - private struct NativeMonitorData - { - public string Monitor { get; set; } - - public string MonitorInstanceId { get; set; } - - public string MonitorSerialNumber { get; set; } - - public int MonitorNumber { get; set; } - - public string VirtualDesktop { get; set; } - - public int Dpi { get; set; } - - public int LeftCoordinate { get; set; } - - public int TopCoordinate { get; set; } - - public int WorkAreaWidth { get; set; } - - public int WorkAreaHeight { get; set; } - - public int MonitorWidth { get; set; } - - public int MonitorHeight { get; set; } - - public bool IsSelected { get; set; } - - public override string ToString() - { - var sb = new StringBuilder(); - - // using CultureInfo.InvariantCulture since this is internal data - sb.Append("Monitor: "); - sb.AppendLine(Monitor); - sb.Append("Virtual desktop: "); - sb.AppendLine(VirtualDesktop); - sb.Append("DPI: "); - sb.AppendLine(Dpi.ToString(CultureInfo.InvariantCulture)); - - sb.Append("X: "); - sb.AppendLine(LeftCoordinate.ToString(CultureInfo.InvariantCulture)); - sb.Append("Y: "); - sb.AppendLine(TopCoordinate.ToString(CultureInfo.InvariantCulture)); - - sb.Append("Width: "); - sb.AppendLine(MonitorWidth.ToString(CultureInfo.InvariantCulture)); - sb.Append("Height: "); - sb.AppendLine(MonitorHeight.ToString(CultureInfo.InvariantCulture)); - - return sb.ToString(); - } - } - - // applied-layouts.json - private struct AppliedLayoutWrapper - { - 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 struct LayoutWrapper - { - public string Uuid { get; set; } - - public string Type { get; set; } - - public bool ShowSpacing { get; set; } - - public int Spacing { get; set; } - - public int ZoneCount { get; set; } - - public int SensitivityRadius { get; set; } - } - - public DeviceIdWrapper Device { get; set; } - - public LayoutWrapper AppliedLayout { get; set; } - } - - // applied-layouts.json - private struct AppliedLayoutsListWrapper - { - public List AppliedLayouts { get; set; } - } - - // custom-layouts.json - private sealed class CanvasInfoWrapper - { - public struct CanvasZoneWrapper - { - public int X { get; set; } - - public int Y { get; set; } - - public int Width { get; set; } - - public int Height { get; set; } - } - - public int RefWidth { get; set; } - - public int RefHeight { get; set; } - - public List Zones { get; set; } - - public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius; - } - - // custom-layouts.json - private sealed class GridInfoWrapper - { - public int Rows { get; set; } - - public int Columns { get; set; } - - public List RowsPercentage { get; set; } - - public List ColumnsPercentage { get; set; } - - public int[][] CellChildMap { get; set; } - - public bool ShowSpacing { get; set; } = LayoutSettings.DefaultShowSpacing; - - public int Spacing { get; set; } = LayoutSettings.DefaultSpacing; - - public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius; - } - - // custom-layouts.json - private struct CustomLayoutWrapper - { - public string Uuid { get; set; } - - public string Name { get; set; } - - public string Type { get; set; } - - public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper - } - - // custom-layouts.json - private struct CustomLayoutListWrapper - { - public List CustomLayouts { get; set; } - } - - // layout-templates.json - private struct TemplateLayoutWrapper - { - public string Type { get; set; } - - public bool ShowSpacing { get; set; } - - public int Spacing { get; set; } - - public int ZoneCount { get; set; } - - public int SensitivityRadius { get; set; } - } - - // layout-templates.json - private struct TemplateLayoutsListWrapper - { - public List LayoutTemplates { get; set; } - } - - // layout-hotkeys.json - private struct LayoutHotkeyWrapper - { - public int Key { get; set; } - - public string LayoutId { get; set; } - } - - // layout-hotkeys.json - private struct LayoutHotkeysWrapper - { - public List LayoutHotkeys { get; set; } - } - - // default-layouts.json - private struct DefaultLayoutWrapper - { - public struct LayoutWrapper - { - public string Uuid { get; set; } - - public string Type { get; set; } - - public bool ShowSpacing { get; set; } - - public int Spacing { get; set; } - - public int ZoneCount { get; set; } - - public int SensitivityRadius { get; set; } - } - - public string MonitorConfiguration { get; set; } - - public LayoutWrapper Layout { get; set; } - } - - // default-layouts.json - private struct DefaultLayoutsListWrapper - { - public List DefaultLayouts { get; set; } - } - - private struct EditorParams - { - public int ProcessId { get; set; } - - public bool SpanZonesAcrossMonitors { get; set; } - - public List Monitors { get; set; } - } - - public struct ParsingResult - { - public bool Result { get; } - - public string Message { get; } - - public string MalformedData { get; } - - public ParsingResult(bool result, string message = "", string data = "") - { - Result = result; - Message = message; - MalformedData = data; - } - } + private List _unusedLayouts = new List(); public FancyZonesEditorIO() { - var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - FancyZonesAppliedLayoutsFile = localAppDataDir + AppliedLayoutsFile; - FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile; - FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile; - FancyZonesCustomLayoutsFile = localAppDataDir + CustomLayoutsFile; - FancyZonesDefaultLayoutsFile = localAppDataDir + DefaultLayoutsFile; - FancyZonesEditorParamsFile = localAppDataDir + ParamsFile; } public ParsingResult ParseParams() { Logger.LogTrace(); - if (_fileSystem.File.Exists(FancyZonesEditorParamsFile)) + try { - string data = string.Empty; + EditorParameters parser = new EditorParameters(); + var editorParams = parser.Read(parser.File); - try + // Process ID + App.PowerToysPID = editorParams.ProcessId; + + // Span zones across monitors + App.Overlay.SpanZonesAcrossMonitors = editorParams.SpanZonesAcrossMonitors; + + if (!App.Overlay.SpanZonesAcrossMonitors) { - data = ReadFile(FancyZonesEditorParamsFile); - EditorParams editorParams = JsonSerializer.Deserialize(data, _options); + string targetMonitorId = string.Empty; + string targetMonitorSerialNumber = string.Empty; + string targetVirtualDesktop = string.Empty; + int targetMonitorNumber = 0; - // Process ID - App.PowerToysPID = editorParams.ProcessId; - - // Span zones across monitors - App.Overlay.SpanZonesAcrossMonitors = editorParams.SpanZonesAcrossMonitors; - - if (!App.Overlay.SpanZonesAcrossMonitors) + foreach (EditorParameters.NativeMonitorDataWrapper nativeData in editorParams.Monitors) { - string targetMonitorId = string.Empty; - string targetMonitorSerialNumber = string.Empty; - string targetVirtualDesktop = string.Empty; - int targetMonitorNumber = 0; - - foreach (NativeMonitorData nativeData in editorParams.Monitors) - { - Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.WorkAreaWidth, nativeData.WorkAreaHeight); - if (nativeData.IsSelected) - { - targetMonitorId = nativeData.Monitor; - targetMonitorSerialNumber = nativeData.MonitorSerialNumber; - targetMonitorNumber = nativeData.MonitorNumber; - targetVirtualDesktop = nativeData.VirtualDesktop; - } - - Size monitorSize = new Size(nativeData.MonitorWidth, nativeData.MonitorHeight); - - var monitor = new Monitor(workArea, monitorSize); - monitor.Device.MonitorName = nativeData.Monitor; - monitor.Device.MonitorInstanceId = nativeData.MonitorInstanceId; - monitor.Device.MonitorSerialNumber = nativeData.MonitorSerialNumber; - monitor.Device.MonitorNumber = nativeData.MonitorNumber; - monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop; - monitor.Device.Dpi = nativeData.Dpi; - - App.Overlay.AddMonitor(monitor); - } - - // Set active desktop - var monitors = App.Overlay.Monitors; - for (int i = 0; i < monitors.Count; i++) - { - var monitor = monitors[i]; - if (monitor.Device.MonitorName == targetMonitorId && - monitor.Device.MonitorSerialNumber == targetMonitorSerialNumber && - monitor.Device.MonitorNumber == targetMonitorNumber && - monitor.Device.VirtualDesktopId == targetVirtualDesktop) - { - App.Overlay.CurrentDesktop = i; - break; - } - } - } - else - { - if (editorParams.Monitors.Count != 1) - { - return new ParsingResult(false); - } - - var nativeData = editorParams.Monitors[0]; Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.WorkAreaWidth, nativeData.WorkAreaHeight); + if (nativeData.IsSelected) + { + targetMonitorId = nativeData.Monitor; + targetMonitorSerialNumber = nativeData.MonitorSerialNumber; + targetMonitorNumber = nativeData.MonitorNumber; + targetVirtualDesktop = nativeData.VirtualDesktop; + } + Size monitorSize = new Size(nativeData.MonitorWidth, nativeData.MonitorHeight); var monitor = new Monitor(workArea, monitorSize); @@ -416,21 +71,52 @@ namespace FancyZonesEditor.Utils monitor.Device.MonitorSerialNumber = nativeData.MonitorSerialNumber; monitor.Device.MonitorNumber = nativeData.MonitorNumber; monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop; + monitor.Device.Dpi = nativeData.Dpi; App.Overlay.AddMonitor(monitor); } + + // Set active desktop + var monitors = App.Overlay.Monitors; + for (int i = 0; i < monitors.Count; i++) + { + var monitor = monitors[i]; + if (monitor.Device.MonitorName == targetMonitorId && + monitor.Device.MonitorSerialNumber == targetMonitorSerialNumber && + monitor.Device.MonitorNumber == targetMonitorNumber && + monitor.Device.VirtualDesktopId == targetVirtualDesktop) + { + App.Overlay.CurrentDesktop = i; + break; + } + } } - catch (Exception ex) + else { - Logger.LogError("Editor params parsing error", ex); - return new ParsingResult(false, ex.Message, data); + if (editorParams.Monitors.Count != 1) + { + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Editor_Parameters_Message); + } + + var nativeData = editorParams.Monitors[0]; + Rect workArea = new Rect(nativeData.LeftCoordinate, nativeData.TopCoordinate, nativeData.WorkAreaWidth, nativeData.WorkAreaHeight); + Size monitorSize = new Size(nativeData.MonitorWidth, nativeData.MonitorHeight); + + var monitor = new Monitor(workArea, monitorSize); + monitor.Device.MonitorName = nativeData.Monitor; + monitor.Device.MonitorInstanceId = nativeData.MonitorInstanceId; + monitor.Device.MonitorSerialNumber = nativeData.MonitorSerialNumber; + monitor.Device.MonitorNumber = nativeData.MonitorNumber; + monitor.Device.VirtualDesktopId = nativeData.VirtualDesktop; + + App.Overlay.AddMonitor(monitor); } return new ParsingResult(true); } - else + catch (Exception e) { - return new ParsingResult(false); + return new ParsingResult(false, e.Message); } } @@ -440,36 +126,22 @@ namespace FancyZonesEditor.Utils _unusedLayouts.Clear(); - if (_fileSystem.File.Exists(FancyZonesAppliedLayoutsFile)) + try { - AppliedLayoutsListWrapper appliedLayouts; - string settingsString = string.Empty; + AppliedLayouts parser = new AppliedLayouts(); + var appliedLayouts = parser.Read(parser.File); - try + bool parsingResult = SetAppliedLayouts(appliedLayouts.AppliedLayouts); + if (!parsingResult) { - settingsString = ReadFile(FancyZonesAppliedLayoutsFile); - appliedLayouts = JsonSerializer.Deserialize(settingsString, _options); - } - catch (Exception ex) - { - Logger.LogError("Applied layouts parsing error", ex); - return new ParsingResult(false, ex.Message, settingsString); - } - - try - { - bool parsingResult = SetAppliedLayouts(appliedLayouts.AppliedLayouts); - if (!parsingResult) - { - return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Applied_Layouts_Message, settingsString); - } - } - catch (Exception ex) - { - Logger.LogError("Applied layouts parsing error", ex); - return new ParsingResult(false, ex.Message, settingsString); + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Applied_Layouts_Message); } } + catch (Exception ex) + { + Logger.LogError("Applied layouts parsing error", ex); + return new ParsingResult(false, ex.Message); + } return new ParsingResult(true); } @@ -478,167 +150,105 @@ namespace FancyZonesEditor.Utils { Logger.LogTrace(); - if (_fileSystem.File.Exists(FancyZonesLayoutHotkeysFile)) + try { - LayoutHotkeysWrapper layoutHotkeys; - string dataString = string.Empty; + LayoutHotkeys parser = new LayoutHotkeys(); + var layoutHotkeys = parser.Read(parser.File); - try + bool layoutHotkeysParsingResult = SetLayoutHotkeys(layoutHotkeys); + + if (!layoutHotkeysParsingResult) { - dataString = ReadFile(FancyZonesLayoutHotkeysFile); - layoutHotkeys = JsonSerializer.Deserialize(dataString, _options); - } - catch (Exception ex) - { - Logger.LogError("Layout hotkeys parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Hotkeys_Message); } - try - { - bool layoutHotkeysParsingResult = SetLayoutHotkeys(layoutHotkeys); - - if (!layoutHotkeysParsingResult) - { - return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Hotkeys_Message, dataString); - } - } - catch (Exception ex) - { - Logger.LogError("Layout hotkeys parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); - } + return new ParsingResult(true); + } + catch (Exception ex) + { + Logger.LogError("Layout hotkeys parsing error", ex); + return new ParsingResult(false, ex.Message); } - - return new ParsingResult(true); } public ParsingResult ParseLayoutTemplates() { Logger.LogTrace(); - if (_fileSystem.File.Exists(FancyZonesLayoutTemplatesFile)) + try { - TemplateLayoutsListWrapper templates; - string dataString = string.Empty; + LayoutTemplates parser = new LayoutTemplates(); + var templates = parser.Read(parser.File); - try + bool parsingResult = SetTemplateLayouts(templates.LayoutTemplates); + if (parsingResult) { - dataString = ReadFile(FancyZonesLayoutTemplatesFile); - templates = JsonSerializer.Deserialize(dataString, _options); - } - catch (Exception ex) - { - Logger.LogError("Layout templates parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); + return new ParsingResult(true); } - try - { - bool parsingResult = SetTemplateLayouts(templates.LayoutTemplates); - if (parsingResult) - { - return new ParsingResult(true); - } - - return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Templates_Message, dataString); - } - catch (Exception ex) - { - Logger.LogError("Layout templates parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); - } + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Templates_Message); + } + catch (Exception ex) + { + Logger.LogError("Layout templates parsing error", ex); + return new ParsingResult(false, ex.Message); } - - return new ParsingResult(true); } public ParsingResult ParseCustomLayouts() { Logger.LogTrace(); - if (_fileSystem.File.Exists(FancyZonesCustomLayoutsFile)) + try { - CustomLayoutListWrapper wrapper; - string dataString = string.Empty; + CustomLayouts parser = new CustomLayouts(); + var wrapper = parser.Read(parser.File); - try + bool parsingResult = SetCustomLayouts(wrapper.CustomLayouts); + if (parsingResult) { - dataString = ReadFile(FancyZonesCustomLayoutsFile); - wrapper = JsonSerializer.Deserialize(dataString, _options); - } - catch (Exception ex) - { - Logger.LogError("Custom layouts parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); + return new ParsingResult(true); } - try - { - bool parsingResult = SetCustomLayouts(wrapper.CustomLayouts); - if (parsingResult) - { - return new ParsingResult(true); - } - - return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message, dataString); - } - catch (Exception ex) - { - Logger.LogError("Custom layouts parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); - } + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message); + } + catch (Exception ex) + { + Logger.LogError("Custom layouts parsing error", ex); + return new ParsingResult(false, ex.Message); } - - return new ParsingResult(true); } public ParsingResult ParseDefaultLayouts() { Logger.LogTrace(); - if (_fileSystem.File.Exists(FancyZonesDefaultLayoutsFile)) + try { - DefaultLayoutsListWrapper wrapper; - string dataString = string.Empty; + DefaultLayouts parser = new DefaultLayouts(); + var wrapper = parser.Read(parser.File); - try + bool parsingResult = SetDefaultLayouts(wrapper.DefaultLayouts); + if (parsingResult) { - dataString = ReadFile(FancyZonesDefaultLayoutsFile); - wrapper = JsonSerializer.Deserialize(dataString, _options); - } - catch (Exception ex) - { - Logger.LogError("Default layouts parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); + return new ParsingResult(true); } - try - { - bool parsingResult = SetDefaultLayouts(wrapper.DefaultLayouts); - if (parsingResult) - { - return new ParsingResult(true); - } - - return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Default_Layouts_Message, dataString); - } - catch (Exception ex) - { - Logger.LogError("Default layouts parsing error", ex); - return new ParsingResult(false, ex.Message, dataString); - } + return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Default_Layouts_Message); + } + catch (Exception ex) + { + Logger.LogError("Default layouts parsing error", ex); + return new ParsingResult(false, ex.Message); } - - return new ParsingResult(true); } public void SerializeAppliedLayouts() { Logger.LogTrace(); - AppliedLayoutsListWrapper layouts = new AppliedLayoutsListWrapper { }; - layouts.AppliedLayouts = new List(); + AppliedLayouts.AppliedLayoutsListWrapper layouts = new AppliedLayouts.AppliedLayoutsListWrapper { }; + layouts.AppliedLayouts = new List(); // Serialize used layouts foreach (var monitor in App.Overlay.Monitors) @@ -649,9 +259,9 @@ namespace FancyZonesEditor.Utils continue; } - layouts.AppliedLayouts.Add(new AppliedLayoutWrapper + layouts.AppliedLayouts.Add(new AppliedLayouts.AppliedLayoutWrapper { - Device = new AppliedLayoutWrapper.DeviceIdWrapper + Device = new AppliedLayouts.AppliedLayoutWrapper.DeviceIdWrapper { Monitor = monitor.Device.MonitorName, MonitorInstance = monitor.Device.MonitorInstanceId, @@ -660,7 +270,7 @@ namespace FancyZonesEditor.Utils VirtualDesktop = monitor.Device.VirtualDesktopId, }, - AppliedLayout = new AppliedLayoutWrapper.LayoutWrapper + AppliedLayout = new AppliedLayouts.AppliedLayoutWrapper.LayoutWrapper { Uuid = zoneset.ZonesetUuid, Type = LayoutTypeToJsonTag(zoneset.Type), @@ -680,8 +290,9 @@ namespace FancyZonesEditor.Utils try { - string jsonString = JsonSerializer.Serialize(layouts, _options); - _fileSystem.File.WriteAllText(FancyZonesAppliedLayoutsFile, jsonString); + AppliedLayouts serializer = new AppliedLayouts(); + IOUtils ioUtils = new IOUtils(); + ioUtils.WriteFile(serializer.File, serializer.Serialize(layouts)); } catch (Exception ex) { @@ -692,8 +303,8 @@ namespace FancyZonesEditor.Utils public void SerializeLayoutHotkeys() { - LayoutHotkeysWrapper hotkeys = new LayoutHotkeysWrapper { }; - hotkeys.LayoutHotkeys = new List(); + LayoutHotkeys.LayoutHotkeysWrapper hotkeys = new LayoutHotkeys.LayoutHotkeysWrapper { }; + hotkeys.LayoutHotkeys = new List(); foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys) { @@ -701,7 +312,7 @@ namespace FancyZonesEditor.Utils { try { - LayoutHotkeyWrapper wrapper = new LayoutHotkeyWrapper + LayoutHotkeys.LayoutHotkeyWrapper wrapper = new LayoutHotkeys.LayoutHotkeyWrapper { Key = int.Parse(pair.Key, CultureInfo.CurrentCulture), LayoutId = pair.Value, @@ -718,8 +329,9 @@ namespace FancyZonesEditor.Utils try { - string jsonString = JsonSerializer.Serialize(hotkeys, _options); - _fileSystem.File.WriteAllText(FancyZonesLayoutHotkeysFile, jsonString); + LayoutHotkeys serializer = new LayoutHotkeys(); + IOUtils ioUtils = new IOUtils(); + ioUtils.WriteFile(serializer.File, serializer.Serialize(hotkeys)); } catch (Exception ex) { @@ -730,12 +342,12 @@ namespace FancyZonesEditor.Utils public void SerializeLayoutTemplates() { - TemplateLayoutsListWrapper templates = new TemplateLayoutsListWrapper { }; - templates.LayoutTemplates = new List(); + LayoutTemplates.TemplateLayoutsListWrapper templates = new LayoutTemplates.TemplateLayoutsListWrapper { }; + templates.LayoutTemplates = new List(); foreach (LayoutModel layout in MainWindowSettingsModel.TemplateModels) { - TemplateLayoutWrapper wrapper = new TemplateLayoutWrapper + LayoutTemplates.TemplateLayoutWrapper wrapper = new LayoutTemplates.TemplateLayoutWrapper { Type = LayoutTypeToJsonTag(layout.Type), SensitivityRadius = layout.SensitivityRadius, @@ -753,8 +365,9 @@ namespace FancyZonesEditor.Utils try { - string jsonString = JsonSerializer.Serialize(templates, _options); - _fileSystem.File.WriteAllText(FancyZonesLayoutTemplatesFile, jsonString); + LayoutTemplates serializer = new LayoutTemplates(); + IOUtils ioUtils = new IOUtils(); + ioUtils.WriteFile(serializer.File, serializer.Serialize(templates)); } catch (Exception ex) { @@ -765,8 +378,9 @@ namespace FancyZonesEditor.Utils public void SerializeCustomLayouts() { - CustomLayoutListWrapper layouts = new CustomLayoutListWrapper { }; - layouts.CustomLayouts = new List(); + CustomLayouts serializer = new CustomLayouts(); + CustomLayouts.CustomLayoutListWrapper layouts = new CustomLayouts.CustomLayoutListWrapper { }; + layouts.CustomLayouts = new List(); foreach (LayoutModel layout in MainWindowSettingsModel.CustomModels) { @@ -784,17 +398,17 @@ namespace FancyZonesEditor.Utils canvasRect = App.Overlay.WorkArea; } - var wrapper = new CanvasInfoWrapper + var wrapper = new CustomLayouts.CanvasInfoWrapper { RefWidth = (int)canvasRect.Width, RefHeight = (int)canvasRect.Height, - Zones = new List(), + Zones = new List(), SensitivityRadius = canvasLayout.SensitivityRadius, }; foreach (var zone in canvasLayout.Zones) { - wrapper.Zones.Add(new CanvasInfoWrapper.CanvasZoneWrapper + wrapper.Zones.Add(new CustomLayouts.CanvasInfoWrapper.CanvasZoneWrapper { X = zone.X, Y = zone.Y, @@ -803,8 +417,7 @@ namespace FancyZonesEditor.Utils }); } - string json = JsonSerializer.Serialize(wrapper, _options); - info = JsonSerializer.Deserialize(json); + info = serializer.ToJsonElement(wrapper); } else if (layout is GridLayoutModel) { @@ -821,7 +434,7 @@ namespace FancyZonesEditor.Utils } } - var wrapper = new GridInfoWrapper + var wrapper = new CustomLayouts.GridInfoWrapper { Rows = gridLayout.Rows, Columns = gridLayout.Columns, @@ -833,8 +446,7 @@ namespace FancyZonesEditor.Utils SensitivityRadius = gridLayout.SensitivityRadius, }; - string json = JsonSerializer.Serialize(wrapper, _options); - info = JsonSerializer.Deserialize(json); + info = serializer.ToJsonElement(wrapper); } else { @@ -842,7 +454,7 @@ namespace FancyZonesEditor.Utils continue; } - CustomLayoutWrapper customLayout = new CustomLayoutWrapper + CustomLayouts.CustomLayoutWrapper customLayout = new CustomLayouts.CustomLayoutWrapper { Uuid = layout.Uuid, Name = layout.Name, @@ -855,8 +467,8 @@ namespace FancyZonesEditor.Utils try { - string jsonString = JsonSerializer.Serialize(layouts, _options); - _fileSystem.File.WriteAllText(FancyZonesCustomLayoutsFile, jsonString); + IOUtils ioUtils = new IOUtils(); + ioUtils.WriteFile(serializer.File, serializer.Serialize(layouts)); } catch (Exception ex) { @@ -867,14 +479,14 @@ namespace FancyZonesEditor.Utils public void SerializeDefaultLayouts() { - DefaultLayoutsListWrapper layouts = new DefaultLayoutsListWrapper { }; - layouts.DefaultLayouts = new List(); + DefaultLayouts.DefaultLayoutsListWrapper layouts = new DefaultLayouts.DefaultLayoutsListWrapper { }; + layouts.DefaultLayouts = new List(); foreach (LayoutModel layout in MainWindowSettingsModel.TemplateModels) { if (layout.IsHorizontalDefault || layout.IsVerticalDefault) { - DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayoutWrapper.LayoutWrapper + DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper { Uuid = string.Empty, Type = LayoutTypeToJsonTag(layout.Type), @@ -891,7 +503,7 @@ namespace FancyZonesEditor.Utils // can be both horizontal and vertical, so check separately if (layout.IsHorizontalDefault) { - DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper + DefaultLayouts.DefaultLayoutWrapper wrapper = new DefaultLayouts.DefaultLayoutWrapper { MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Horizontal), Layout = layoutWrapper, @@ -902,7 +514,7 @@ namespace FancyZonesEditor.Utils if (layout.IsVerticalDefault) { - DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper + DefaultLayouts.DefaultLayoutWrapper wrapper = new DefaultLayouts.DefaultLayoutWrapper { MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Vertical), Layout = layoutWrapper, @@ -917,7 +529,7 @@ namespace FancyZonesEditor.Utils { if (layout.IsHorizontalDefault || layout.IsVerticalDefault) { - DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayoutWrapper.LayoutWrapper + DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper { Uuid = layout.Uuid, Type = LayoutTypeToJsonTag(LayoutType.Custom), @@ -932,7 +544,7 @@ namespace FancyZonesEditor.Utils // can be both horizontal and vertical, so check separately if (layout.IsHorizontalDefault) { - DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper + DefaultLayouts.DefaultLayoutWrapper wrapper = new DefaultLayouts.DefaultLayoutWrapper { MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Horizontal), Layout = layoutWrapper, @@ -943,7 +555,7 @@ namespace FancyZonesEditor.Utils if (layout.IsVerticalDefault) { - DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper + DefaultLayouts.DefaultLayoutWrapper wrapper = new DefaultLayouts.DefaultLayoutWrapper { MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Vertical), Layout = layoutWrapper, @@ -956,8 +568,9 @@ namespace FancyZonesEditor.Utils try { - string jsonString = JsonSerializer.Serialize(layouts, _options); - _fileSystem.File.WriteAllText(FancyZonesDefaultLayoutsFile, jsonString); + DefaultLayouts serializer = new DefaultLayouts(); + IOUtils ioUtils = new IOUtils(); + ioUtils.WriteFile(serializer.File, serializer.Serialize(layouts)); } catch (Exception ex) { @@ -966,36 +579,7 @@ namespace FancyZonesEditor.Utils } } - private string ReadFile(string fileName) - { - Logger.LogTrace(); - - 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) - { - Logger.LogError("File reading error, retry"); - Task.Delay(10).Wait(); - } - - attempts++; - } - - return string.Empty; - } - - private bool SetAppliedLayouts(List layouts) + private bool SetAppliedLayouts(List layouts) { Logger.LogTrace(); @@ -1082,7 +666,7 @@ namespace FancyZonesEditor.Utils return result; } - private bool SetCustomLayouts(List customLayouts) + private bool SetCustomLayouts(List customLayouts) { Logger.LogTrace(); @@ -1135,7 +719,7 @@ namespace FancyZonesEditor.Utils return result; } - private bool SetTemplateLayouts(List templateLayouts) + private bool SetTemplateLayouts(List templateLayouts) { Logger.LogTrace(); @@ -1164,7 +748,7 @@ namespace FancyZonesEditor.Utils return true; } - private bool SetLayoutHotkeys(LayoutHotkeysWrapper layoutHotkeys) + private bool SetLayoutHotkeys(LayoutHotkeys.LayoutHotkeysWrapper layoutHotkeys) { Logger.LogTrace(); @@ -1177,7 +761,7 @@ namespace FancyZonesEditor.Utils return true; } - private bool SetDefaultLayouts(List layouts) + private bool SetDefaultLayouts(List layouts) { Logger.LogTrace(); @@ -1234,9 +818,10 @@ namespace FancyZonesEditor.Utils return true; } - private CanvasLayoutModel ParseCanvasInfo(CustomLayoutWrapper wrapper) + private CanvasLayoutModel ParseCanvasInfo(CustomLayouts.CustomLayoutWrapper wrapper) { - var info = JsonSerializer.Deserialize(wrapper.Info.GetRawText(), _options); + CustomLayouts deserializer = new CustomLayouts(); + var info = deserializer.CanvasFromJsonElement(wrapper.Info.GetRawText()); var zones = new List(); foreach (var zone in info.Zones) @@ -1256,9 +841,10 @@ namespace FancyZonesEditor.Utils return layout; } - private GridLayoutModel ParseGridInfo(CustomLayoutWrapper wrapper) + private GridLayoutModel ParseGridInfo(CustomLayouts.CustomLayoutWrapper wrapper) { - var info = JsonSerializer.Deserialize(wrapper.Info.GetRawText(), _options); + CustomLayouts deserializer = new CustomLayouts(); + var info = deserializer.GridFromJsonElement(wrapper.Info.GetRawText()); // Check if rows and columns are valid if (info.Rows <= 0 || info.Columns <= 0) @@ -1308,25 +894,32 @@ namespace FancyZonesEditor.Utils private LayoutType JsonTagToLayoutType(string tag) { - switch (tag) + if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Empty]) { - case BlankJsonTag: - return LayoutType.Blank; - case FocusJsonTag: - return LayoutType.Focus; - case ColumnsJsonTag: - return LayoutType.Columns; - case RowsJsonTag: - return LayoutType.Rows; - case GridJsonTag: - return LayoutType.Grid; - case PriorityGridJsonTag: - return LayoutType.PriorityGrid; - case CustomJsonTag: - return LayoutType.Custom; + return LayoutType.Blank; + } + else if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Focus]) + { + return LayoutType.Focus; + } + else if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Rows]) + { + return LayoutType.Rows; + } + else if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Columns]) + { + return LayoutType.Columns; + } + else if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Grid]) + { + return LayoutType.Grid; + } + else if (tag == Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.PriorityGrid]) + { + return LayoutType.PriorityGrid; } - return LayoutType.Blank; + return LayoutType.Custom; } private string LayoutTypeToJsonTag(LayoutType type) @@ -1334,19 +927,19 @@ namespace FancyZonesEditor.Utils switch (type) { case LayoutType.Blank: - return BlankJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Empty]; case LayoutType.Focus: - return FocusJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Focus]; case LayoutType.Columns: - return ColumnsJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Columns]; case LayoutType.Rows: - return RowsJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Rows]; case LayoutType.Grid: - return GridJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.Grid]; case LayoutType.PriorityGrid: - return PriorityGridJsonTag; + return Constants.TemplateLayoutJsonTags[Constants.TemplateLayout.PriorityGrid]; case LayoutType.Custom: - return CustomJsonTag; + return Constants.CustomLayoutJsonTag; default: return string.Empty; } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Utils/ParsingResult.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/ParsingResult.cs new file mode 100644 index 0000000000..adaff7de73 --- /dev/null +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Utils/ParsingResult.cs @@ -0,0 +1,22 @@ +// 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 FancyZonesEditor.Utils +{ + public struct ParsingResult + { + public bool Result { get; } + + public string Message { get; } + + public string MalformedData { get; } + + public ParsingResult(bool result, string message = "", string data = "") + { + Result = result; + Message = message; + MalformedData = data; + } + } +} diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorCanvasZoneResizeTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorCanvasZoneResizeTests.cs deleted file mode 100644 index a191c5341f..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorCanvasZoneResizeTests.cs +++ /dev/null @@ -1,301 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; -using System.Windows.Forms; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorCanvasZoneResizeTests : FancyZonesEditor - { - private void MoveCorner(WindowsElement corner, bool shiftLeft, bool shiftUp, int xOffset, int yOffset) - { - int shiftX = shiftLeft ? -(corner.Rect.Width / 2) + 1 : (corner.Rect.Width / 2) - 1; - int shiftY = shiftUp ? -(corner.Rect.Height / 2) + 1 : (corner.Rect.Height / 2) - 1; - - new Actions(session).MoveToElement(corner) - .MoveByOffset(shiftX, shiftY) - .ClickAndHold().MoveByOffset(xOffset, yOffset).Release().Perform(); - } - - [TestMethod] - public void MoveTopBorder() - { - WindowsElement topBorder = session.FindElementByAccessibilityId("NResize"); - WindowsElement bottomBorder = session.FindElementByAccessibilityId("SResize"); - Assert.IsNotNull(topBorder); - Assert.IsNotNull(bottomBorder); - - int height = bottomBorder.Rect.Y - topBorder.Rect.Y; - - //up - new Actions(session).MoveToElement(topBorder).ClickAndHold().MoveByOffset(0, -5000).Release().Perform(); - Assert.IsTrue(topBorder.Rect.Y >= 0); - Assert.IsTrue(height < bottomBorder.Rect.Y - topBorder.Rect.Y); - height = bottomBorder.Rect.Y - topBorder.Rect.Y; - - //down - new Actions(session).MoveToElement(topBorder).ClickAndHold().MoveByOffset(0, 5000).Release().Perform(); - Assert.IsTrue(topBorder.Rect.Y <= bottomBorder.Rect.Y); - Assert.IsTrue(height > bottomBorder.Rect.Y - topBorder.Rect.Y); - } - - [TestMethod] - public void MoveBottomBorder() - { - WindowsElement topBorder = session.FindElementByAccessibilityId("NResize"); - WindowsElement bottomBorder = session.FindElementByAccessibilityId("SResize"); - Assert.IsNotNull(topBorder); - Assert.IsNotNull(bottomBorder); - - int height = bottomBorder.Rect.Y - topBorder.Rect.Y; - - //up - new Actions(session).MoveToElement(bottomBorder).ClickAndHold().MoveByOffset(0, -5000).Release().Perform(); - Assert.IsTrue(topBorder.Rect.Y <= bottomBorder.Rect.Y); - Assert.IsTrue(height > bottomBorder.Rect.Y - topBorder.Rect.Y); - height = bottomBorder.Rect.Y - topBorder.Rect.Y; - - //down - new Actions(session).MoveToElement(bottomBorder).ClickAndHold().MoveByOffset(0, 5000).Release().Perform(); - Assert.IsTrue(bottomBorder.Rect.Y <= Screen.PrimaryScreen.WorkingArea.Bottom); - Assert.IsTrue(height < bottomBorder.Rect.Y - topBorder.Rect.Y); - } - - [TestMethod] - public void MoveLeftBorder() - { - WindowsElement leftBorder = session.FindElementByAccessibilityId("WResize"); - WindowsElement rightBorder = session.FindElementByAccessibilityId("EResize"); - Assert.IsNotNull(leftBorder); - Assert.IsNotNull(rightBorder); - - int width = rightBorder.Rect.X - leftBorder.Rect.X; - - //to the left - new Actions(session).MoveToElement(leftBorder).ClickAndHold().MoveByOffset(-5000, 0).Release().Perform(); - Assert.IsTrue(leftBorder.Rect.Y <= Screen.PrimaryScreen.WorkingArea.Bottom); - Assert.IsTrue(width < rightBorder.Rect.X - leftBorder.Rect.X); - width = rightBorder.Rect.X - leftBorder.Rect.X; - - //to the right - new Actions(session).MoveToElement(leftBorder).ClickAndHold().MoveByOffset(5000, 0).Release().Perform(); - Assert.IsTrue(leftBorder.Rect.X <= rightBorder.Rect.X); - Assert.IsTrue(width > rightBorder.Rect.X - leftBorder.Rect.X); - } - - [TestMethod] - public void MoveRightBorder() - { - WindowsElement leftBorder = session.FindElementByAccessibilityId("WResize"); - WindowsElement rightBorder = session.FindElementByAccessibilityId("EResize"); - Assert.IsNotNull(leftBorder); - Assert.IsNotNull(rightBorder); - - int width = rightBorder.Rect.X - leftBorder.Rect.X; - - //to the left - new Actions(session).MoveToElement(rightBorder).ClickAndHold().MoveByOffset(-5000, 0).Release().Perform(); - Assert.IsTrue(leftBorder.Rect.X <= rightBorder.Rect.X); - Assert.IsTrue(width > rightBorder.Rect.X - leftBorder.Rect.X); - width = rightBorder.Rect.X - leftBorder.Rect.X; - - //to the right - new Actions(session).MoveToElement(rightBorder).ClickAndHold().MoveByOffset(5000, 0).Release().Perform(); - Assert.IsTrue(leftBorder.Rect.X <= Screen.PrimaryScreen.WorkingArea.Right); - Assert.IsTrue(width < rightBorder.Rect.X - leftBorder.Rect.X); - } - - [TestMethod] - public void MoveTopLeftCorner() - { - WindowsElement topLeftCorner = session.FindElementByAccessibilityId("NWResize"); - WindowsElement bottomBorder = session.FindElementByAccessibilityId("SResize"); - WindowsElement rightBorder = session.FindElementByAccessibilityId("EResize"); - Assert.IsNotNull(topLeftCorner); - Assert.IsNotNull(bottomBorder); - Assert.IsNotNull(rightBorder); - - int expectedWidth = rightBorder.Rect.X - topLeftCorner.Rect.X; - int expectedHeight = bottomBorder.Rect.Y - topLeftCorner.Rect.Y; - int actualWidth, actualHeight; - - //up-left - MoveCorner(topLeftCorner, true, true, -5000, -5000); - actualHeight = bottomBorder.Rect.Y - topLeftCorner.Rect.Y; - actualWidth = rightBorder.Rect.X - topLeftCorner.Rect.X; - - Assert.IsTrue(topLeftCorner.Rect.Y >= 0); - Assert.IsTrue(topLeftCorner.Rect.X >= 0); - Assert.IsTrue(actualHeight > expectedHeight); - Assert.IsTrue(actualWidth > expectedWidth); - - expectedHeight = actualHeight; - expectedWidth = actualWidth; - - //down-right - MoveCorner(topLeftCorner, true, true, 5000, 5000); - actualHeight = bottomBorder.Rect.Y - topLeftCorner.Rect.Y; - actualWidth = rightBorder.Rect.X - topLeftCorner.Rect.X; - - Assert.IsTrue(topLeftCorner.Rect.Y <= bottomBorder.Rect.Y); - Assert.IsTrue(topLeftCorner.Rect.X <= rightBorder.Rect.X); - Assert.IsTrue(actualHeight < expectedHeight); - Assert.IsTrue(actualWidth < expectedWidth); - } - - [TestMethod] - public void MoveTopRightCorner() - { - WindowsElement topRightCorner = session.FindElementByAccessibilityId("NEResize"); - WindowsElement bottomBorder = session.FindElementByAccessibilityId("SResize"); - WindowsElement leftBorder = session.FindElementByAccessibilityId("WResize"); - Assert.IsNotNull(topRightCorner); - Assert.IsNotNull(bottomBorder); - Assert.IsNotNull(leftBorder); - - int expectedWidth = topRightCorner.Rect.X - leftBorder.Rect.X; - int expectedHeight = bottomBorder.Rect.Y - topRightCorner.Rect.Y; - int actualWidth, actualHeight; - - //up-right - MoveCorner(topRightCorner, false, true, 5000, -5000); - actualHeight = bottomBorder.Rect.Y - topRightCorner.Rect.Y; - actualWidth = topRightCorner.Rect.X - leftBorder.Rect.X; - - Assert.IsTrue(topRightCorner.Rect.Y >= 0); - Assert.IsTrue(leftBorder.Rect.X <= Screen.PrimaryScreen.WorkingArea.Right); - Assert.IsTrue(actualHeight > expectedHeight); - Assert.IsTrue(actualWidth > expectedWidth); - - expectedHeight = actualHeight; - expectedWidth = actualWidth; - - //down-left - MoveCorner(topRightCorner, false, true, -5000, 5000); - actualHeight = bottomBorder.Rect.Y - topRightCorner.Rect.Y; - actualWidth = topRightCorner.Rect.X - leftBorder.Rect.X; - - Assert.IsTrue(topRightCorner.Rect.Y <= bottomBorder.Rect.Y); - Assert.IsTrue(topRightCorner.Rect.X >= leftBorder.Rect.X); - Assert.IsTrue(actualHeight < expectedHeight); - Assert.IsTrue(actualWidth < expectedWidth); - } - - [TestMethod] - public void MoveBottomLeftCorner() - { - WindowsElement bottomLeftCorner = session.FindElementByAccessibilityId("SWResize"); - WindowsElement topBorder = session.FindElementByAccessibilityId("NResize"); - WindowsElement rightBorder = session.FindElementByAccessibilityId("EResize"); - Assert.IsNotNull(bottomLeftCorner); - Assert.IsNotNull(topBorder); - Assert.IsNotNull(rightBorder); - - int expectedWidth = rightBorder.Rect.X - bottomLeftCorner.Rect.X; - int expectedHeight = bottomLeftCorner.Rect.Y - topBorder.Rect.Y; - int actualWidth, actualHeight; - - //up-left - MoveCorner(bottomLeftCorner, true, false, 5000, -5000); - actualHeight = bottomLeftCorner.Rect.Y - topBorder.Rect.Y; - actualWidth = rightBorder.Rect.X - bottomLeftCorner.Rect.X; - - Assert.IsTrue(bottomLeftCorner.Rect.Y >= topBorder.Rect.Y); - Assert.IsTrue(bottomLeftCorner.Rect.X <= rightBorder.Rect.X); - Assert.IsTrue(actualHeight < expectedHeight); - Assert.IsTrue(actualWidth < expectedWidth); - - expectedHeight = actualHeight; - expectedWidth = actualWidth; - - //down-right - MoveCorner(bottomLeftCorner, true, false, -5000, 5000); - actualHeight = bottomLeftCorner.Rect.Y - topBorder.Rect.Y; - actualWidth = rightBorder.Rect.X - bottomLeftCorner.Rect.X; - - Assert.IsTrue(bottomLeftCorner.Rect.Y <= Screen.PrimaryScreen.WorkingArea.Bottom); - Assert.IsTrue(bottomLeftCorner.Rect.X >= 0); - Assert.IsTrue(actualHeight > expectedHeight); - Assert.IsTrue(actualWidth > expectedWidth); - } - - [TestMethod] - public void MoveBottomRightCorner() - { - WindowsElement zone = session.FindElementByAccessibilityId("Caption"); - Assert.IsNotNull(zone, "Unable to move zone"); - new Actions(session).MoveToElement(zone).ClickAndHold().MoveByOffset(creatorWindow.Rect.Width / 2, 0).Release().Perform(); - WindowsElement bottomRightCorner = session.FindElementByAccessibilityId("SEResize"); - WindowsElement topBorder = session.FindElementByAccessibilityId("NResize"); - WindowsElement leftBorder = session.FindElementByAccessibilityId("WResize"); - Assert.IsNotNull(bottomRightCorner); - Assert.IsNotNull(topBorder); - Assert.IsNotNull(leftBorder); - - int expectedWidth = bottomRightCorner.Rect.X - leftBorder.Rect.X; - int expectedHeight = bottomRightCorner.Rect.Y - topBorder.Rect.Y; - int actualWidth, actualHeight; - - //up-left - MoveCorner(bottomRightCorner, false, false, -5000, -5000); - actualHeight = bottomRightCorner.Rect.Y - topBorder.Rect.Y; - actualWidth = bottomRightCorner.Rect.X - leftBorder.Rect.X; - - Assert.IsTrue(bottomRightCorner.Rect.Y >= topBorder.Rect.Y); - Assert.IsTrue(bottomRightCorner.Rect.X >= leftBorder.Rect.X); - Assert.IsTrue(actualHeight < expectedHeight); - Assert.IsTrue(actualWidth < expectedWidth); - - expectedHeight = actualHeight; - expectedWidth = actualWidth; - - //down-right - MoveCorner(bottomRightCorner, false, false, 5000, 5000); - actualHeight = bottomRightCorner.Rect.Y - topBorder.Rect.Y; - actualWidth = bottomRightCorner.Rect.X - leftBorder.Rect.X; - - Assert.IsTrue(bottomRightCorner.Rect.Y <= Screen.PrimaryScreen.WorkingArea.Bottom); - Assert.IsTrue(bottomRightCorner.Rect.X <= Screen.PrimaryScreen.WorkingArea.Right); - Assert.IsTrue(actualHeight > expectedHeight); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - - EnableModules(false, true, false, false, false, false, false, false); - ResetSettings(); - - Assert.IsTrue(OpenEditor()); - OpenCustomLayouts(); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseEditor(); - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - //create canvas zone - OpenCreatorWindow("Create new custom"); - creatorWindow.FindElementByAccessibilityId("newZoneButton").Click(); - } - - [TestCleanup] - public void TestCleanup() - { - AppiumWebElement cancelButton = creatorWindow.FindElementByName("Cancel"); - Assert.IsNotNull(cancelButton); - new Actions(session).MoveToElement(cancelButton).Click().Perform(); - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorCustomLayoutsTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorCustomLayoutsTests.cs deleted file mode 100644 index 1f75ba18a9..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorCustomLayoutsTests.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System.IO.Abstractions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorCustomLayoutsTests : FancyZonesEditor - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - - private void SetLayoutName(string name) - { - AppiumWebElement textBox = creatorWindow.FindElementByClassName("TextBox"); - textBox.Click(); - textBox.SendKeys(Keys.Control + "a"); - textBox.SendKeys(Keys.Backspace); - textBox.SendKeys(name); - } - - private void CancelTest() - { - AppiumWebElement cancelButton = creatorWindow.FindElementByXPath("//Button[@Name=\"Cancel\"]"); - new Actions(session).MoveToElement(cancelButton).Click().Perform(); - WaitSeconds(1); - - Assert.AreEqual(_initialZoneSettings, File.ReadAllText(_zoneSettingsPath), "Settings were changed"); - } - - private void SaveTest(string type, string name, int zoneCount) - { - new Actions(session).MoveToElement(editorWindow.FindElementByName("Save and apply")).Click().Perform(); - WaitSeconds(1); - - JObject settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual(name, settings["custom-zone-sets"][0]["name"]); - Assert.AreEqual(settings["custom-zone-sets"][0]["uuid"], settings["devices"][0]["active-zoneset"]["uuid"]); - Assert.AreEqual(type, settings["custom-zone-sets"][0]["type"]); - Assert.AreEqual(zoneCount, settings["custom-zone-sets"][0]["info"]["zones"].ToObject().Count); - } - - [TestMethod] - public void CreateCancel() - { - OpenCreatorWindow("Create new custom"); - ZoneCountTest(0, 0); - - editorWindow.FindElementByAccessibilityId("newZoneButton").Click(); - ZoneCountTest(1, 0); - - CancelTest(); - } - - [TestMethod] - public void CreateEmpty() - { - OpenCreatorWindow("Create new custom"); - ZoneCountTest(0, 0); - - SaveTest("canvas", "Custom Layout 1", 0); - } - - [TestMethod] - public void CreateSingleZone() - { - OpenCreatorWindow("Create new custom"); - ZoneCountTest(0, 0); - - editorWindow.FindElementByAccessibilityId("newZoneButton").Click(); - ZoneCountTest(1, 0); - - SaveTest("canvas", "Custom Layout 1", 1); - } - - [TestMethod] - public void CreateManyZones() - { - OpenCreatorWindow("Create new custom"); - ZoneCountTest(0, 0); - - const int expectedZoneCount = 20; - AppiumWebElement addButton = editorWindow.FindElementByAccessibilityId("newZoneButton"); - for (int i = 0; i < expectedZoneCount; i++) - { - addButton.Click(); - } - - ZoneCountTest(expectedZoneCount, 0); - SaveTest("canvas", "Custom Layout 1", expectedZoneCount); - } - - [TestMethod] - public void CreateDeleteZone() - { - OpenCreatorWindow("Create new custom"); - ZoneCountTest(0, 0); - - AppiumWebElement addButton = editorWindow.FindElementByAccessibilityId("newZoneButton"); - - for (int i = 0; i < 5; i++) - { - //add zone - addButton.Click(); - WindowsElement zone = session.FindElementByClassName("CanvasZone"); - Assert.IsNotNull(zone, "Zone was not created"); - Assert.IsTrue(zone.Displayed, "Zone was not displayed"); - - //remove zone - zone.FindElementByClassName("Button").Click(); - } - - ZoneCountTest(0, 0); - CancelTest(); - } - - [TestMethod] - public void CreateWithName() - { - OpenCreatorWindow("Create new custom"); - string name = "My custom zone layout name"; - SetLayoutName(name); - SaveTest("canvas", name, 0); - } - - [TestMethod] - public void CreateWithEmptyName() - { - OpenCreatorWindow("Create new custom"); - string name = ""; - SetLayoutName(name); - SaveTest("canvas", name, 0); - } - - [TestMethod] - public void CreateWithUnicodeCharactersName() - { - OpenCreatorWindow("Create new custom"); - string name = "ёÖ±¬āݾᵩὡ√ﮘﻹտ"; - SetLayoutName(name); - SaveTest("canvas", name, 0); - } - - [TestMethod] - public void RenameLayout() - { - //create layout - OpenCreatorWindow("Create new custom"); - string name = "My custom zone layout name"; - SetLayoutName(name); - SaveTest("canvas", name, 0); - WaitSeconds(1); - - //rename layout - Assert.IsTrue(OpenEditor()); - OpenCustomLayouts(); - OpenCreatorWindow(name); - name = "New name"; - SetLayoutName(name); - SaveTest("canvas", name, 0); - } - - [TestMethod] - public void AddRemoveSameLayoutNames() - { - string name = "Name"; - - for (int i = 0; i < 3; i++) - { - //create layout - OpenCreatorWindow("Create new custom"); - SetLayoutName(name); - - new Actions(session).MoveToElement(editorWindow.FindElementByName("Save and apply")).Click().Perform(); - - //remove layout - Assert.IsTrue(OpenEditor()); - OpenCustomLayouts(); - AppiumWebElement nameLabel = editorWindow.FindElementByXPath("//Text[@Name=\"" + name + "\"]"); - new Actions(session).MoveToElement(nameLabel).MoveByOffset(nameLabel.Rect.Width / 2 + 10, 0).Click().Perform(); - } - - //settings are saved on window closing - new Actions(session).MoveToElement(editorWindow.FindElementByAccessibilityId("PART_Close")).Click().Perform(); - WaitSeconds(1); - - //check settings - JObject settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual(0, settings["custom-zone-sets"].ToObject().Count); - } - - [TestMethod] - public void RemoveApply() - { - string name = "Name"; - - //create layout - OpenCreatorWindow("Create new custom"); - SetLayoutName(name); - new Actions(session).MoveToElement(editorWindow.FindElementByName("Save and apply")).Click().Perform(); - WaitSeconds(1); - - //save layout id - JObject settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual(1, settings["custom-zone-sets"].ToObject().Count); - - //remove layout - Assert.IsTrue(OpenEditor()); - OpenCustomLayouts(); - AppiumWebElement nameLabel = editorWindow.FindElementByXPath("//Text[@Name=\"" + name + "\"]"); - new Actions(session).MoveToElement(nameLabel).MoveByOffset(nameLabel.Rect.Width / 2 + 10, 0).Click().Perform(); - - //apply - new Actions(session).MoveToElement(editorWindow.FindElementByName("Apply")).Click().Perform(); - WaitSeconds(1); - - //check settings - settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual(0, settings["custom-zone-sets"].ToObject().Count); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - - ResetDefaultFancyZonesSettings(false); - } - - [ClassCleanup] - public static void ClassCleanup() - { - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - ResetDefaultZoneSettings(true); - Assert.IsTrue(OpenEditor()); - OpenCustomLayouts(); - } - - [TestCleanup] - public void TestCleanup() - { - CloseEditor(); - ExitPowerToys(); - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorGridZoneResizeTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorGridZoneResizeTests.cs deleted file mode 100644 index 5a39a28423..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorGridZoneResizeTests.cs +++ /dev/null @@ -1,438 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; -using System; -using System.Collections.ObjectModel; -using System.Windows.Forms; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorGridZoneResizeTests : FancyZonesEditor - { - private const int moveStep = 5; - - private void Move(AppiumWebElement thumb, int border, bool moveAscending, bool moveHorizontally, int clickShift = 0) - { - Actions action = new Actions(session); - action.MoveToElement(thumb).MoveByOffset(0, clickShift).ClickAndHold(); - - int thumbCenter = 0; - if (moveHorizontally) - { - thumbCenter = thumb.Rect.X + thumb.Rect.Width / 2; - } - else - { - thumbCenter = thumb.Rect.Y + thumb.Rect.Height / 2; - } - - int moves = Math.Abs(thumbCenter - border) / moveStep; - for (int j = 0; j < moves; j++) - { - int step = moveAscending ? moveStep : -moveStep; - if (moveHorizontally) - { - action.MoveByOffset(step, 0); - } - else - { - action.MoveByOffset(0, step); - } - } - - action.Release().Perform(); - } - - [TestMethod] - public void MoveVerticalSplitter() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(2, thumbs.Count); - - //move left - for (int i = 0; i < thumbs.Count; i++) - { - AppiumWebElement thumb = thumbs[i]; - int border = i == 0 ? 0 : thumbs[i - 1].Rect.Right; - Move(thumb, border, false, true); - - Assert.IsTrue(thumb.Rect.Left - border <= moveStep); - Assert.IsTrue(thumb.Rect.Right > border); - } - - //move right - for (int i = thumbs.Count - 1; i >= 0; i--) - { - AppiumWebElement thumb = thumbs[i]; - int border = i == thumbs.Count - 1 ? Screen.PrimaryScreen.WorkingArea.Right : thumbs[i + 1].Rect.Left; - Move(thumb, border, true, true); - - Assert.IsTrue(border - thumb.Rect.Right <= moveStep); - Assert.IsTrue(thumb.Rect.Left < border); - } - - //move up - foreach (AppiumWebElement thumb in thumbs) - { - int expected = thumb.Rect.X; - - Move(thumb, 0, false, false); - int actual = thumb.Rect.X; - - Assert.AreEqual(expected, actual); - } - - //move down - foreach (AppiumWebElement thumb in thumbs) - { - int expected = thumb.Rect.X; - - Move(thumb, Screen.PrimaryScreen.WorkingArea.Right, true, false); - int actual = thumb.Rect.X; - - Assert.AreEqual(expected, actual); - } - } - - [TestMethod] - public void MoveHorizontalSplitter() - { - OpenCreatorWindow("Rows", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(2, thumbs.Count); - - //move up - for (int i = 0; i < thumbs.Count; i++) - { - AppiumWebElement thumb = thumbs[i]; - int border = i == 0 ? 0 : thumbs[i - 1].Rect.Bottom; - Move(thumb, border, false, false); - - Assert.IsTrue(thumb.Rect.Top - border <= moveStep); - Assert.IsTrue(thumb.Rect.Right > border); - } - - //move down - for (int i = thumbs.Count - 1; i >= 0; i--) - { - AppiumWebElement thumb = thumbs[i]; - int border = i == thumbs.Count - 1 ? Screen.PrimaryScreen.WorkingArea.Bottom : thumbs[i + 1].Rect.Top; - Move(thumb, border, true, false); - - Assert.IsTrue(border - thumb.Rect.Bottom <= moveStep); - Assert.IsTrue(thumb.Rect.Top < border); - } - - //move left - foreach (AppiumWebElement thumb in thumbs) - { - int expected = thumb.Rect.Y; - - Move(thumb, 0, false, true); - int actual = thumb.Rect.Y; - - Assert.AreEqual(expected, actual); - } - - //move right - foreach (AppiumWebElement thumb in thumbs) - { - int expected = thumb.Rect.Y; - - Move(thumb, Screen.PrimaryScreen.WorkingArea.Right, true, true); - int actual = thumb.Rect.Y; - - Assert.AreEqual(expected, actual); - } - } - - [TestMethod] - public void CreateSplitter() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(3, zones.Count, "Zones count invalid"); - - const int defaultSpacing = 16; - int splitPos = zones[0].Rect.Y + zones[0].Rect.Height / 2; - - new Actions(session).MoveToElement(zones[0]).Click().Perform(); - - zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(4, zones.Count); - - //check splitted zone - Assert.AreEqual(defaultSpacing, zones[0].Rect.Top); - Assert.IsTrue(Math.Abs(zones[0].Rect.Bottom - splitPos + defaultSpacing / 2) <= 2); - Assert.IsTrue(Math.Abs(zones[1].Rect.Top - splitPos - defaultSpacing / 2) <= 2); - Assert.AreEqual(Screen.PrimaryScreen.Bounds.Bottom - defaultSpacing, zones[1].Rect.Bottom); - } - - [TestMethod] - public void TestSplitterShiftAfterCreation() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(3, zones.Count, "Zones count invalid"); - - const int defaultSpacing = 16; - - //create first split - int firstSplitPos = zones[0].Rect.Y + zones[0].Rect.Height / 4; - new Actions(session).MoveToElement(zones[0]).MoveByOffset(0, -(zones[0].Rect.Height / 4)).Click().Perform(); - - zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(4, zones.Count); - - Assert.AreEqual(defaultSpacing, zones[0].Rect.Top); - Assert.IsTrue(Math.Abs(zones[0].Rect.Bottom - firstSplitPos + defaultSpacing / 2) <= 2); - Assert.IsTrue(Math.Abs(zones[1].Rect.Top - firstSplitPos - defaultSpacing / 2) <= 2); - Assert.AreEqual(Screen.PrimaryScreen.Bounds.Bottom - defaultSpacing, zones[3].Rect.Bottom); - - //create second split - int secondSplitPos = zones[3].Rect.Y + zones[3].Rect.Height / 2; - int expectedTop = zones[3].Rect.Top; - - new Actions(session).MoveToElement(zones[3]).Click().Perform(); - - zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(5, zones.Count); - - //check first split on same position - Assert.AreEqual(defaultSpacing, zones[0].Rect.Top); - Assert.IsTrue(Math.Abs(zones[0].Rect.Bottom - firstSplitPos + defaultSpacing / 2) <= 2); - - //check second split - Assert.AreEqual(expectedTop, zones[3].Rect.Top); - Assert.IsTrue(Math.Abs(zones[3].Rect.Bottom - secondSplitPos + defaultSpacing / 2) <= 2); - Assert.IsTrue(Math.Abs(zones[4].Rect.Top - secondSplitPos - defaultSpacing / 2) <= 2); - Assert.AreEqual(Screen.PrimaryScreen.Bounds.Bottom - defaultSpacing, zones[4].Rect.Bottom); - } - - [TestMethod] - public void CreateSplitterWithShiftPressed() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - Assert.AreEqual(2, thumbs.Count); - - new Actions(session).MoveToElement(thumbs[0]).Click().MoveByOffset(-100, 0) - .KeyDown(OpenQA.Selenium.Keys.Shift).Click().KeyUp(OpenQA.Selenium.Keys.Shift) - .Perform(); - Assert.AreEqual(3, gridEditor.FindElementsByClassName("Thumb").Count); - - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(4, zones.Count); - - //check that zone was splitted vertically - Assert.AreEqual(zones[0].Rect.Height, zones[1].Rect.Height); - Assert.AreEqual(zones[1].Rect.Height, zones[2].Rect.Height); - Assert.AreEqual(zones[2].Rect.Height, zones[3].Rect.Height); - } - - [TestMethod] - public void CreateSplitterWithShiftPressedFocusOnGridEditor() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - Assert.AreEqual(2, thumbs.Count); - - new Actions(session).MoveToElement(thumbs[0]).Click().MoveByOffset(-100, 0) - .KeyDown(OpenQA.Selenium.Keys.Shift).Click().KeyUp(OpenQA.Selenium.Keys.Shift) - .Perform(); - Assert.AreEqual(3, gridEditor.FindElementsByClassName("Thumb").Count); - - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - Assert.AreEqual(4, zones.Count); - - //check that zone was splitted vertically - Assert.AreEqual(zones[0].Rect.Height, zones[1].Rect.Height); - Assert.AreEqual(zones[1].Rect.Height, zones[2].Rect.Height); - Assert.AreEqual(zones[2].Rect.Height, zones[3].Rect.Height); - } - - [TestMethod] - public void MoveHorizontallyWithLimiter() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(2, thumbs.Count); - - //create new zones - new Actions(session).MoveToElement(thumbs[0]).Click().MoveByOffset(-30, 0) - .KeyDown(OpenQA.Selenium.Keys.Shift).Click().KeyUp(OpenQA.Selenium.Keys.Shift) - .Perform(); - thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(4, gridEditor.FindElementsByClassName("GridZone").Count); - Assert.AreEqual(3, thumbs.Count); - - //move thumbs - AppiumWebElement limiter = gridEditor.FindElementsByClassName("Thumb")[0]; - AppiumWebElement movable = gridEditor.FindElementsByClassName("Thumb")[1]; - - Move(movable, 0, false, true); - Assert.IsTrue(movable.Rect.X > limiter.Rect.X); - Assert.IsTrue(movable.Rect.X - limiter.Rect.X < movable.Rect.Width); - - Move(limiter, limiter.Rect.X - (limiter.Rect.X / 2), false, true); - - Move(movable, 0, false, true); - Assert.IsTrue(movable.Rect.X > limiter.Rect.X); - Assert.IsTrue(movable.Rect.X - limiter.Rect.X < movable.Rect.Width); - } - - [TestMethod] - public void MoveVerticallyWithLimiter() - { - OpenCreatorWindow("Rows", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - Assert.AreEqual(3, gridEditor.FindElementsByClassName("GridZone").Count); - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(2, thumbs.Count); - - //create new zones - new Actions(session).MoveToElement(thumbs[0]).Click().MoveByOffset(0, -(thumbs[0].Rect.Y / 2)) - .KeyDown(OpenQA.Selenium.Keys.Shift).Click().KeyUp(OpenQA.Selenium.Keys.Shift) - .Perform(); - thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(4, gridEditor.FindElementsByClassName("GridZone").Count); - Assert.AreEqual(3, thumbs.Count); - - //move thumbs - AppiumWebElement limiter = gridEditor.FindElementsByClassName("Thumb")[0]; - AppiumWebElement movable = gridEditor.FindElementsByClassName("Thumb")[1]; - - Move(movable, 0, false, false); - Assert.IsTrue(movable.Rect.Y > limiter.Rect.Y); - Assert.IsTrue(movable.Rect.Y - limiter.Rect.Y < movable.Rect.Height); - - Move(limiter, limiter.Rect.Y - (limiter.Rect.Y / 2), false, false, -5); - - Move(movable, 0, false, false); - Assert.IsTrue(movable.Rect.Y > limiter.Rect.Y); - Assert.IsTrue(movable.Rect.Y - limiter.Rect.Y < movable.Rect.Height); - } - - [TestMethod] - public void MergeZones() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - Assert.AreEqual(3, zones.Count); - Assert.AreEqual(2, thumbs.Count); - - Move(zones[0], thumbs[0].Rect.X + thumbs[0].Rect.Width + 10, true, true, -(zones[0].Rect.Height / 2) + 10); - - AppiumWebElement mergeButton = gridEditor.FindElementByName("Merge zones"); - Assert.IsNotNull(mergeButton, "Cannot merge: no merge button"); - new Actions(session).Click(mergeButton).Perform(); - - Assert.AreEqual(2, gridEditor.FindElementsByClassName("GridZone").Count); - Assert.AreEqual(1, gridEditor.FindElementsByClassName("Thumb").Count); - } - - [TestMethod] - public void MoveAfterMerge() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - WindowsElement gridEditor = session.FindElementByClassName("GridEditor"); - Assert.IsNotNull(gridEditor); - - ReadOnlyCollection thumbs = gridEditor.FindElementsByClassName("Thumb"); - - //create new zones - new Actions(session).MoveToElement(thumbs[0]).Click().MoveByOffset(-(thumbs[0].Rect.X / 2), 0) - .KeyDown(OpenQA.Selenium.Keys.Shift).Click().KeyUp(OpenQA.Selenium.Keys.Shift) - .Perform(); - thumbs = gridEditor.FindElementsByClassName("Thumb"); - - //merge zones - ReadOnlyCollection zones = gridEditor.FindElementsByClassName("GridZone"); - Move(zones[0], thumbs[0].Rect.X + thumbs[0].Rect.Width + 10, true, true, -(zones[0].Rect.Height / 2) + 10); - AppiumWebElement mergeButton = gridEditor.FindElementByName("Merge zones"); - Assert.IsNotNull(mergeButton, "Cannot merge: no merge button"); - new Actions(session).Click(mergeButton).Perform(); - - //move thumb - thumbs = gridEditor.FindElementsByClassName("Thumb"); - AppiumWebElement thumb = thumbs[0]; - Move(thumb, 0, false, true); - Assert.IsTrue(thumb.Rect.Left <= moveStep); - Assert.IsTrue(thumb.Rect.Right > 0); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - - ResetSettings(); - - if (!isPowerToysLaunched) - { - LaunchPowerToys(); - } - Assert.IsTrue(OpenEditor()); - OpenTemplates(); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseEditor(); - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - - } - - [TestCleanup] - public void TestCleanup() - { - AppiumWebElement cancelButton = creatorWindow.FindElementByName("Cancel"); - Assert.IsNotNull(cancelButton); - new Actions(session).MoveToElement(cancelButton).Click().Perform(); - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorOpeningTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorOpeningTests.cs deleted file mode 100644 index dd762301e9..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorOpeningTests.cs +++ /dev/null @@ -1,300 +0,0 @@ -using System.IO.Abstractions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorOpeningTests : FancyZonesEditor - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - private static readonly IDirectory Directory = FileSystem.Directory; - void RemoveSettingsFile() - { - File.Delete(_zoneSettingsPath); - File.Delete(_appHistoryPath); - } - - void RemoveSettingsFolder() - { - Directory.Delete(_settingsFolderPath, true); - } - - void CreateEmptySettingsFile() - { - string zoneSettings = ""; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = ""; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void CreateDefaultSettingsFile() - { - string zoneSettings = "{\"devices\":[],\"custom-zone-sets\":[]}"; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = "{\"app-zone-history\":[]}"; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void CreateValidSettingsFile() - { - string zoneSettings = "{\"devices\":[{\"device-id\":\"DELA026#5&10a58c63&0&UID16777488_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{D13ABB6D-7721-4176-9647-C8C0836D99CC}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}],\"custom-zone-sets\":[]}"; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = "{\"app-zone-history\":[{\"app-path\":\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\Extensions\\TestPlatform\\testhost.exe\",\"zone-index\":3,\"device-id\":\"DELA026#5&10a58c63&0&UID16777488_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"zoneset-uuid\":\"{D13ABB6D-7721-4176-9647-C8C0836D99CC}\"}]}"; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void CreateValidSettingsFileWithUtf8() - { - string zoneSettings = "{\"devices\":[{\"device-id\":\"DELA026#5&10a58c63&0&UID16777488_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{D13ABB6D-7721-4176-9647-C8C0836D99CC}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}],\"custom-zone-sets\":[]}"; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = "{\"app-zone-history\":[{\"app-path\":\"C:\\Program Files (x86)\\йцукен\\testhost.exe\",\"zone-index\":3,\"device-id\":\"DELA026#5&10a58c63&0&UID16777488_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"zoneset-uuid\":\"{D13ABB6D-7721-4176-9647-C8C0836D99CC}\"}]}"; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void CreateInvalidSettingsFile() - { - string zoneSettings = "{\"app-zone-history\":[{\"app-path\":\"C:\\Program Files (x86)\\Microsoft Visual Studio\\testhost.exe\",\"zone-index\":3,\"device-id\":\"wrong-device-id\",\"zoneset-uuid\":\"{D13ABB6D-invalid-uuid-C8C0836D99CC}\"}],\"devices\":[{\"device-id\":\"DELA026#5&10a58c63&0&UID16777488_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{D13ABB6D-7721-4176-9647-C8C0836D99CC}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}],\"custom-zone-sets\":[]}"; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = ""; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void CreateCroppedSettingsFile() - { - string zoneSettings = "{\"devices\":[],\"custom-zone-sets\":[{\"uuid\":\"{8BEC7183-C90E-4D41-AD1C-1AC2BC4760BA}\",\"name\":\""; - File.WriteAllText(_zoneSettingsPath, zoneSettings); - - string appHistory = "{\"app-zone-history\":[]}"; - File.WriteAllText(_appHistoryPath, appHistory); - } - - void TestEditorOpened(bool errorExpected = false) - { - WindowsElement errorMessage = null; - try - { - errorMessage = session.FindElementByName("FancyZones Editor Exception Handler"); - if (errorMessage != null) - { - errorMessage.FindElementByName("OK").Click(); - } - } - catch (OpenQA.Selenium.WebDriverException) - { - //no error message, it's ok - } - - editorWindow = session.FindElementByName("FancyZones Editor"); - Assert.IsNotNull(editorWindow); - - if (!errorExpected) - { - Assert.IsNull(errorMessage); - } - else - { - Assert.IsNotNull(errorMessage); - } - } - - void OpenEditorBySettingsButton() - { - OpenSettings(); - OpenFancyZonesSettings(); - settingsWindow.FindElementByName("Launch zones editor").Click(); - } - - void OpenEditorByHotkey() - { - new Actions(session).KeyDown(OpenQA.Selenium.Keys.Command).SendKeys("`").KeyUp(OpenQA.Selenium.Keys.Command).Perform(); - } - - [TestMethod] - public void OpenEditorBySettingsButtonNoSettings() - { - RemoveSettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorBySettingsButtonNoSettingsFolder() - { - /* - if (isPowerToysLaunched) - { - ExitPowerToys(); - } - RemoveSettingsFolder(); - LaunchPowerToys(); - */ - - RemoveSettingsFolder(); - OpenEditorBySettingsButton(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorBySettingsButtonEmptySettings() - { - CreateEmptySettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorBySettingsButtonDefaultSettings() - { - CreateDefaultSettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorBySettingsButtonValidSettings() - { - CreateValidSettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorBySettingsButtonValidUtf8Settings() - { - CreateValidSettingsFileWithUtf8(); - OpenEditorBySettingsButton(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorBySettingsButtonInvalidSettings() - { - CreateInvalidSettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorBySettingsButtonCroppedSettings() - { - CreateCroppedSettingsFile(); - OpenEditorBySettingsButton(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorByHotkeyNoSettings() - { - RemoveSettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorByHotkeyNoSettingsFolder() - { - /* - if (isPowerToysLaunched) - { - ExitPowerToys(); - } - RemoveSettingsFolder(); - LaunchPowerToys(); - */ - RemoveSettingsFolder(); - OpenEditorByHotkey(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorByHotkeyEmptySettings() - { - CreateEmptySettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorByHotkeyDefaultSettings() - { - CreateDefaultSettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorByHotkeyValidSettings() - { - CreateValidSettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorByHotkeyValidUtf8Settings() - { - CreateValidSettingsFileWithUtf8(); - OpenEditorByHotkey(); - TestEditorOpened(); - } - - [TestMethod] - public void OpenEditorByHotkeyInvalidSettings() - { - CreateInvalidSettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(true); - } - - [TestMethod] - public void OpenEditorByHotkeyCroppedSettings() - { - CreateCroppedSettingsFile(); - OpenEditorByHotkey(); - TestEditorOpened(true); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - - ResetDefaultFancyZonesSettings(true); - } - - [ClassCleanup] - public static void ClassCleanup() - { - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - - } - - [TestCleanup] - public void TestCleanup() - { - CloseEditor(); - - if (!Directory.Exists(_settingsFolderPath)) - { - Directory.CreateDirectory(_settingsFolderPath); - } - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorSettingsTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorSettingsTests.cs deleted file mode 100644 index ca4c807469..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorSettingsTests.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.IO.Abstractions; -//using System.IO; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium; -using OpenQA.Selenium.Appium; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorSettingsTests : FancyZonesEditor - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - - private const string editorZoneCount = "editor-zone-count"; - private const string editorShowSpacing = "editor-show-spacing"; - private const string editorSpacing = "editor-spacing"; - - [TestMethod] - public void ZoneCount() - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement minusButton = editorWindow.FindElementByAccessibilityId("decrementZones"); - AppiumWebElement zoneCount = editorWindow.FindElementByAccessibilityId("zoneCount"); - - int editorZoneCountValue; - Assert.IsTrue(Int32.TryParse(zoneCount.Text, out editorZoneCountValue)); - - for (int i = editorZoneCountValue - 1, j = 0; i > -5; --i, ++j) - { - minusButton.Click(); - - Assert.IsTrue(Int32.TryParse(zoneCount.Text, out editorZoneCountValue)); - Assert.AreEqual(Math.Max(i, 1), editorZoneCountValue); - - if (j == 0 || i == -4) - { - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - WaitSeconds(1); - Assert.AreEqual(editorZoneCountValue, GetEditZonesSetting(editorZoneCount)); - Assert.IsTrue(OpenEditor()); - - minusButton = editorWindow.FindElementByAccessibilityId("decrementZones"); - zoneCount = editorWindow.FindElementByAccessibilityId("zoneCount"); - } - } - - AppiumWebElement plusButton = editorWindow.FindElementByAccessibilityId("incrementZones"); - - for (int i = 2; i < 45; ++i) - { - plusButton.Click(); - - Assert.IsTrue(Int32.TryParse(zoneCount.Text, out editorZoneCountValue)); - Assert.AreEqual(Math.Min(i, 40), editorZoneCountValue); - } - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - WaitSeconds(1); - Assert.AreEqual(editorZoneCountValue, GetEditZonesSetting(editorZoneCount)); - } - - [TestMethod] - public void ShowSpacingTest() - { - for (int i = 0; i < 2; ++i) - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement spaceAroundSetting = editorWindow.FindElementByAccessibilityId("spaceAroundSetting"); - bool spaceAroundSettingValue = spaceAroundSetting.Selected; - spaceAroundSetting.Click(); - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - WaitSeconds(1); - - Assert.AreNotEqual(spaceAroundSettingValue, GetEditZonesSetting(editorShowSpacing)); - } - } - - [TestMethod] - public void SpacingTestsValid() - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement spaceAroundSetting = editorWindow.FindElementByAccessibilityId("spaceAroundSetting"); - bool editorShowSpacingValue = spaceAroundSetting.Selected; - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - string[] validValues = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - - foreach (string editorSpacingValue in validValues) - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement paddingValue = editorWindow.FindElementByAccessibilityId("paddingValue"); - ClearText(paddingValue); - paddingValue.SendKeys(editorSpacingValue); - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - WaitSeconds(1); - - Assert.AreEqual(editorShowSpacingValue, GetEditZonesSetting(editorShowSpacing)); - Assert.AreEqual(editorSpacingValue, GetEditZonesSetting(editorSpacing)); - } - } - - [TestMethod] - public void SpacingTestsInvalid() - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement spaceAroundSetting = editorWindow.FindElementByAccessibilityId("spaceAroundSetting"); - bool editorShowSpacingValue = spaceAroundSetting.Selected; - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - string[] invalidValues = { "!", "/", "<", "?", "D", "Z", "]", "m", "}", "1.5", "2,5" }; - - string editorSpacingValue = GetEditZonesSetting(editorSpacing); - - foreach (string value in invalidValues) - { - Assert.IsTrue(OpenEditor()); - - AppiumWebElement paddingValue = editorWindow.FindElementByAccessibilityId("paddingValue"); - ClearText(paddingValue); - paddingValue.SendKeys(value); - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - Assert.AreEqual(editorShowSpacingValue, GetEditZonesSetting(editorShowSpacing)); - Assert.AreEqual(editorSpacingValue, GetEditZonesSetting(editorSpacing)); - } - } - - [TestMethod] - public void SpacingTestLargeValue() - { - Assert.IsTrue(OpenEditor()); - editorWindow.FindElementByName("Grid").Click(); - - AppiumWebElement paddingValue = editorWindow.FindElementByAccessibilityId("paddingValue"); - ClearText(paddingValue); - paddingValue.SendKeys("1000"); - - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - editorWindow = null; - - try - { - Assert.IsTrue(OpenEditor()); - } - catch { } - - Assert.AreNotEqual(editorWindow, null, "Editor Zones Window is not starting after setting large padding value"); - } - - private T GetEditZonesSetting(string value) - { - JObject zoneSettings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - T result = zoneSettings["devices"][0][value].ToObject(); - return result; - } - - private void ClearText(AppiumWebElement windowsElement) - { - windowsElement.SendKeys(Keys.Home); - windowsElement.SendKeys(Keys.Control + Keys.Delete); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - ResetSettings(); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseSettings(); - ResetDefaultFancyZonesSettings(false); - ResetDefaultZoneSettings(false); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - } - - [TestCleanup] - public void TestCleanup() - { - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesApplyTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesApplyTests.cs deleted file mode 100644 index ace3aa3fc3..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesApplyTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.IO.Abstractions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorTemplatesApplyTests : FancyZonesEditor - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - - private void ApplyLayout(string tabName) - { - editorWindow.FindElementByName(tabName).Click(); - editorWindow.FindElementByAccessibilityId("ApplyTemplateButton").Click(); - - try - { - Assert.IsNull(session.FindElementByName("FancyZones Editor")); - } - catch (OpenQA.Selenium.WebDriverException) - { - //editor was closed as expected - } - } - - private void CheckSettingsLayout(string expectedLayout) - { - JObject settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual(expectedLayout, settings["devices"][0]["active-zoneset"]["type"]); - } - - [TestMethod] - public void ApplyFocus() - { - ApplyLayout("Focus"); - CheckSettingsLayout("focus"); - } - - [TestMethod] - public void ApplyColumns() - { - ApplyLayout("Columns"); - CheckSettingsLayout("columns"); - } - - [TestMethod] - public void ApplyRows() - { - ApplyLayout("Rows"); - CheckSettingsLayout("rows"); - } - - [TestMethod] - public void ApplyGrid() - { - ApplyLayout("Grid"); - CheckSettingsLayout("grid"); - } - - [TestMethod] - public void ApplyPriorityGrid() - { - ApplyLayout("Priority Grid"); - CheckSettingsLayout("priority-grid"); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - - ResetDefaultFancyZonesSettings(true); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseSettings(); - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - Assert.IsTrue(OpenEditor()); - OpenTemplates(); - } - - [TestCleanup] - public void TestCleanup() - { - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesEditTests.cs b/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesEditTests.cs deleted file mode 100644 index 6d1b922bb5..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/EditorTemplatesEditTests.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System.IO.Abstractions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [TestClass] - public class FancyZonesEditorTemplatesEditTests : FancyZonesEditor - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - private void ChangeLayout() - { - new Actions(session).MoveToElement(creatorWindow.FindElementByAccessibilityId("PART_TitleBar")).MoveByOffset(0, -50).Click().Perform(); - } - - private void Cancel(AppiumWebElement creatorWindow) - { - AppiumWebElement cancelButton = creatorWindow.FindElementByName("Cancel"); - Assert.IsNotNull(cancelButton); - new Actions(session).MoveToElement(cancelButton).Click().Perform(); - } - - private void CancelTest(AppiumWebElement creatorWindow) - { - Cancel(creatorWindow); - WaitSeconds(1); - - Assert.AreEqual(_defaultZoneSettings, File.ReadAllText(_zoneSettingsPath), "Settings were changed"); - } - - private void SaveTest() - { - new Actions(session).MoveToElement(creatorWindow.FindElementByName("Save and apply")).Click().Perform(); - WaitSeconds(1); - - JObject settings = JObject.Parse(File.ReadAllText(_zoneSettingsPath)); - Assert.AreEqual("Custom Layout 1", settings["custom-zone-sets"][0]["name"]); - Assert.AreEqual(settings["custom-zone-sets"][0]["uuid"], settings["devices"][0]["active-zoneset"]["uuid"]); - } - - [TestMethod] - public void EditFocusCancel() - { - OpenCreatorWindow("Focus", "EditTemplateButton"); - ZoneCountTest(3, 0); - - creatorWindow.FindElementByAccessibilityId("newZoneButton").Click(); - ZoneCountTest(4, 0); - - CancelTest(creatorWindow); - } - - [TestMethod] - public void EditColumnsCancel() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - CancelTest(creatorWindow); - } - - [TestMethod] - public void EditRowsCancel() - { - OpenCreatorWindow("Rows", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - CancelTest(creatorWindow); - } - - [TestMethod] - public void EditGridCancel() - { - OpenCreatorWindow("Grid", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - CancelTest(creatorWindow); - } - - [TestMethod] - public void EditPriorityGridCancel() - { - OpenCreatorWindow("Priority Grid", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - CancelTest(creatorWindow); - } - - [TestMethod] - public void EditFocusSave() - { - OpenCreatorWindow("Focus", "EditTemplateButton"); - ZoneCountTest(3, 0); - - creatorWindow.FindElementByAccessibilityId("newZoneButton").Click(); - ZoneCountTest(4, 0); - - SaveTest(); - } - - [TestMethod] - public void EditColumnsSave() - { - OpenCreatorWindow("Columns", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - SaveTest(); - } - - [TestMethod] - public void EditRowsSave() - { - OpenCreatorWindow("Rows", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - SaveTest(); - } - - [TestMethod] - public void EditGridSave() - { - OpenCreatorWindow("Grid", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - SaveTest(); - } - - [TestMethod] - public void EditPriorityGridSave() - { - OpenCreatorWindow("Priority Grid", "EditTemplateButton"); - ZoneCountTest(0, 3); - - ChangeLayout(); - ZoneCountTest(0, 4); - - SaveTest(); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, true, false, false, false, false, false, false); - - ResetDefaultFancyZonesSettings(false); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseSettings(); - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - ResetDefaultZoneSettings(true); - Assert.IsTrue(OpenEditor()); - OpenTemplates(); - } - - [TestCleanup] - public void TestCleanup() - { - //Close editor - try - { - if (editorWindow != null) - { - editorWindow.SendKeys(OpenQA.Selenium.Keys.Alt + OpenQA.Selenium.Keys.F4); - } - } - catch (OpenQA.Selenium.WebDriverException) - { - //editor was already closed - } - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/FancyZonesEditor.cs b/src/tests/win-app-driver/FancyZonesTests/FancyZonesEditor.cs deleted file mode 100644 index eaaa1dd19c..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/FancyZonesEditor.cs +++ /dev/null @@ -1,106 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; -using System; - -namespace PowerToysTests -{ - public class FancyZonesEditor : PowerToysSession - { - protected static WindowsElement editorWindow; - protected static AppiumWebElement creatorWindow; - - protected static void ResetSettings() - { - ResetDefaultFancyZonesSettings(false); - ResetDefaultZoneSettings(true); - } - - protected static bool OpenEditor() - { - try - { - new Actions(session).KeyDown(OpenQA.Selenium.Keys.Command).SendKeys("`").KeyUp(OpenQA.Selenium.Keys.Command).Perform(); - - //editorWindow = WaitElementByXPath("//Window[@Name=\"FancyZones Editor\"]"); - editorWindow = session.FindElementByName("FancyZones Editor"); - Assert.IsNotNull(editorWindow, "Couldn't find editor window"); - - return true; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - - return false; - } - - protected static void CloseEditor() - { - try - { - if (editorWindow != null) - { - editorWindow.SendKeys(OpenQA.Selenium.Keys.Alt + OpenQA.Selenium.Keys.F4); - } - } - catch (OpenQA.Selenium.WebDriverException) - { - //editor has been already closed - } - } - - protected static void OpenCustomLayouts() - { - try - { - WindowsElement customsTab = session.FindElementByName("Custom"); - customsTab.Click(); - string isSelected = customsTab.GetAttribute("SelectionItem.IsSelected"); - Assert.AreEqual("True", isSelected, "Custom tab cannot be opened"); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - protected static void OpenTemplates() - { - try - { - WindowsElement templatesTab = session.FindElementByName("Templates"); - templatesTab.Click(); - string isSelected = templatesTab.GetAttribute("SelectionItem.IsSelected"); - Assert.AreEqual("True", isSelected, "Templates tab cannot be opened"); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - protected static void OpenCreatorWindow(string tabName, string buttonId = "EditCustomButton") - { - try - { - editorWindow.FindElementByName(tabName).Click(); - editorWindow.FindElementByAccessibilityId(buttonId).Click(); - creatorWindow = editorWindow.FindElementByXPath("//Window"); - Assert.IsNotNull(creatorWindow, "Creator window didn't open"); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - protected void ZoneCountTest(int canvasZoneCount, int gridZoneCount) - { - Assert.AreEqual(canvasZoneCount, session.FindElementsByClassName("CanvasZone").Count); - Assert.AreEqual(gridZoneCount, session.FindElementsByClassName("GridZone").Count); - } - } -} \ No newline at end of file diff --git a/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs b/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs deleted file mode 100644 index 2c8ea49139..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/FancyZonesSettingsTests.cs +++ /dev/null @@ -1,776 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO.Abstractions; -using System.Linq; -using System.Windows.Forms; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [Ignore] - [TestClass] - public class FancyZonesSettingsTests : PowerToysSession - { - private static readonly IFileSystem FileSystem = new FileSystem(); - private static readonly IFile File = FileSystem.File; - - - private JObject _initialSettingsJson; - - private static WindowsElement _saveButton; - private static Actions _scrollUp; - - private const int _expectedTogglesCount = 9; - - private static void Init() - { - OpenSettings(); - OpenFancyZonesSettings(); - - _saveButton = session.FindElementByName("Save"); - Assert.IsNotNull(_saveButton); - - _scrollUp = new Actions(session).MoveToElement(_saveButton).MoveByOffset(0, _saveButton.Rect.Height).ContextClick() - .SendKeys(OpenQA.Selenium.Keys.Home); - Assert.IsNotNull(_scrollUp); - } - - private JObject GetProperties() - { - try - { - JObject settings = JObject.Parse(File.ReadAllText(_fancyZonesSettingsPath)); - return settings["properties"].ToObject(); - } - catch (Newtonsoft.Json.JsonReaderException) - { - return new JObject(); - } - } - - private T GetPropertyValue(string propertyName) - { - JObject properties = GetProperties(); - return properties[propertyName].ToObject()["value"].Value(); - } - - private T GetPropertyValue(JObject properties, string propertyName) - { - return properties[propertyName].ToObject()["value"].Value(); - } - - private void ScrollDown(int count) - { - Actions scroll = new Actions(session); - scroll.MoveToElement(_saveButton).MoveByOffset(0, _saveButton.Rect.Height).ContextClick(); - for (int i = 0; i < count; i++) - { - scroll.SendKeys(OpenQA.Selenium.Keys.PageDown); - } - - scroll.Perform(); - } - - private void ScrollUp() - { - _scrollUp.Perform(); - } - - private void SaveChanges() - { - string isEnabled = _saveButton.GetAttribute("IsEnabled"); - Assert.AreEqual("True", isEnabled); - - _saveButton.Click(); - - isEnabled = _saveButton.GetAttribute("IsEnabled"); - Assert.AreEqual("False", isEnabled); - } - - private void SaveAndCheckOpacitySettings(WindowsElement editor, int expected) - { - Assert.AreEqual(expected.ToString() + "\r\n", editor.Text); - - SaveChanges(); - WaitSeconds(1); - - int value = GetPropertyValue("fancyzones_highlight_opacity"); - Assert.AreEqual(expected, value); - } - - private void SetOpacity(WindowsElement editor, string key) - { - editor.Click(); //activate - editor.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); //clear previous value - editor.SendKeys(key); - editor.SendKeys(OpenQA.Selenium.Keys.Enter); //confirm changes - } - - private void TestRgbInput(string name) - { - WindowsElement colorInput = session.FindElementByXPath("//Edit[@Name=\"" + name + "\"]"); - Assert.IsNotNull(colorInput); - - colorInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - colorInput.SendKeys("0"); - colorInput.SendKeys(OpenQA.Selenium.Keys.Enter); - Assert.AreEqual("0\r\n", colorInput.Text); - - string invalidSymbols = "qwertyuiopasdfghjklzxcvbnm,./';][{}:`~!@#$%^&*()_-+=\"\'\\"; - foreach (char symbol in invalidSymbols) - { - colorInput.SendKeys(symbol.ToString() + OpenQA.Selenium.Keys.Enter); - Assert.AreEqual("0\r\n", colorInput.Text); - } - - string validSymbols = "0123456789"; - foreach (char symbol in validSymbols) - { - colorInput.SendKeys(symbol.ToString() + OpenQA.Selenium.Keys.Enter); - Assert.AreEqual(symbol.ToString() + "\r\n", colorInput.Text); - colorInput.SendKeys(OpenQA.Selenium.Keys.Backspace); - } - - //print zero first - colorInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - colorInput.SendKeys("0"); - colorInput.SendKeys("1"); - Assert.AreEqual("1\r\n", colorInput.Text); - - //too many symbols - colorInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - colorInput.SendKeys("1"); - colorInput.SendKeys("2"); - colorInput.SendKeys("3"); - colorInput.SendKeys("4"); - Assert.AreEqual("123\r\n", colorInput.Text); - - //too big value - colorInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - colorInput.SendKeys("555"); - - Actions action = new Actions(session); //reset focus from input - action.MoveToElement(colorInput).MoveByOffset(0, colorInput.Rect.Height).Click().Perform(); - - Assert.AreEqual("255\r\n", colorInput.Text); - } - - private void ClearInput(WindowsElement input) - { - input.Click(); - input.SendKeys(OpenQA.Selenium.Keys.Control + "a"); - input.SendKeys(OpenQA.Selenium.Keys.Backspace); - } - - private void TestHotkey(WindowsElement input, int modifierKeysState, string key, string keyString) - { - BitArray b = new BitArray(new int[] { modifierKeysState }); - int[] flags = b.Cast().Select(bit => bit ? 1 : 0).ToArray(); - - Actions action = new Actions(session).MoveToElement(input).Click(); - string expectedText = ""; - if (flags[0] == 1) - { - action.KeyDown(OpenQA.Selenium.Keys.Command); - expectedText += "Win + "; - } - if (flags[1] == 1) - { - action.KeyDown(OpenQA.Selenium.Keys.Control); - expectedText += "Ctrl + "; - } - if (flags[2] == 1) - { - action.KeyDown(OpenQA.Selenium.Keys.Alt); - expectedText += "Alt + "; - } - if (flags[3] == 1) - { - action.KeyDown(OpenQA.Selenium.Keys.Shift); - expectedText += "Shift + "; - } - - expectedText += keyString + "\r\n"; - - action.SendKeys(key + key); - action.MoveByOffset(0, (input.Rect.Height / 2) + 10).ContextClick(); - if (flags[0] == 1) - { - action.KeyUp(OpenQA.Selenium.Keys.Command); - } - if (flags[1] == 1) - { - action.KeyUp(OpenQA.Selenium.Keys.Control); - } - if (flags[2] == 1) - { - action.KeyUp(OpenQA.Selenium.Keys.Alt); - } - if (flags[3] == 1) - { - action.KeyUp(OpenQA.Selenium.Keys.Shift); - } - action.Perform(); - - SaveChanges(); - WaitSeconds(1); - - //Assert.AreEqual(expectedText, input.Text); - - JObject props = GetProperties(); - JObject hotkey = props["fancyzones_editor_hotkey"].ToObject()["value"].ToObject(); - Assert.AreEqual(flags[0] == 1, hotkey.Value("win")); - Assert.AreEqual(flags[1] == 1, hotkey.Value("ctrl")); - Assert.AreEqual(flags[2] == 1, hotkey.Value("alt")); - Assert.AreEqual(flags[3] == 1, hotkey.Value("shift")); - //Assert.AreEqual(keyString, hotkey.Value("key")); - } - - private void TestColorSliders(WindowsElement saturationAndBrightness, WindowsElement hue, WindowsElement hex, WindowsElement red, WindowsElement green, WindowsElement blue, string propertyName) - { - System.Drawing.Rectangle satRect = saturationAndBrightness.Rect; - System.Drawing.Rectangle hueRect = hue.Rect; - - //black on the bottom - new Actions(session).MoveToElement(saturationAndBrightness).ClickAndHold().MoveByOffset(0, satRect.Height).Release().Perform(); - WaitSeconds(1); - - Assert.AreEqual("0\r\n", red.Text); - Assert.AreEqual("0\r\n", green.Text); - Assert.AreEqual("0\r\n", blue.Text); - Assert.AreEqual("000000\r\n", hex.Text); - - SaveChanges(); - WaitSeconds(1); - Assert.AreEqual("#000000", GetPropertyValue(propertyName)); - - //white in left corner - new Actions(session).MoveToElement(saturationAndBrightness).ClickAndHold().MoveByOffset(-(satRect.Width / 2), -(satRect.Height / 2)).Release().Perform(); - Assert.AreEqual("255\r\n", red.Text); - Assert.AreEqual("255\r\n", green.Text); - Assert.AreEqual("255\r\n", blue.Text); - Assert.AreEqual("ffffff\r\n", hex.Text); - - SaveChanges(); - WaitSeconds(1); - Assert.AreEqual("#ffffff", GetPropertyValue(propertyName)); - - //color in right corner - new Actions(session).MoveToElement(saturationAndBrightness).ClickAndHold().MoveByOffset((satRect.Width / 2), -(satRect.Height / 2)).Release() - .MoveToElement(hue).ClickAndHold().MoveByOffset(-(hueRect.Width / 2), 0).Release().Perform(); - Assert.AreEqual("255\r\n", red.Text); - Assert.AreEqual("0\r\n", green.Text); - Assert.AreEqual("0\r\n", blue.Text); - Assert.AreEqual("ff0000\r\n", hex.Text); - - SaveChanges(); - WaitSeconds(1); - Assert.AreEqual("#ff0000", GetPropertyValue(propertyName)); - } - - [TestMethod] - public void FancyZonesSettingsOpen() - { - WindowsElement fzTitle = session.FindElementByName("FancyZones Settings"); - Assert.IsNotNull(fzTitle); - } - - /* - * click each toggle, - * save changes, - * check if settings are changed after clicking save button - */ - [TestMethod] - public void TogglesSingleClickSaveButtonTest() - { - List toggles = session.FindElementsByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]").ToList(); - Assert.AreEqual(_expectedTogglesCount, toggles.Count); - - List toggleValues = new List(); - foreach (WindowsElement toggle in toggles) - { - Assert.IsNotNull(toggle); - - bool isOn = toggle.GetAttribute("Toggle.ToggleState") == "1"; - toggleValues.Add(isOn); - - toggle.Click(); - - SaveChanges(); - } - - WaitSeconds(1); - - //check saved settings - JObject savedProps = GetProperties(); - Assert.AreNotEqual(toggleValues[0], GetPropertyValue(savedProps, "fancyzones_shiftDrag")); - Assert.AreNotEqual(toggleValues[1], GetPropertyValue(savedProps, "fancyzones_mouseSwitch")); - Assert.AreNotEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_overrideSnapHotkeys")); - Assert.AreNotEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_moveWindowAcrossMonitors")); - Assert.AreNotEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_moveWindowsBasedOnPosition")); - Assert.AreNotEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); - Assert.AreNotEqual(toggleValues[6], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); - Assert.AreNotEqual(toggleValues[7], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); - Assert.AreNotEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_restoreSize")); - Assert.AreNotEqual(toggleValues[9], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); - Assert.AreNotEqual(toggleValues[10], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); - Assert.AreNotEqual(toggleValues[11], GetPropertyValue(savedProps, "fancyzones_multi_monitor_mode")); - Assert.AreNotEqual(toggleValues[12], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); - } - - /* - * click each toggle twice, - * save changes, - * check if settings are unchanged after clicking save button - */ - [TestMethod] - public void TogglesDoubleClickSave() - { - List toggles = session.FindElementsByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]").ToList(); - Assert.AreEqual(_expectedTogglesCount, toggles.Count); - - List toggleValues = new List(); - foreach (WindowsElement toggle in toggles) - { - Assert.IsNotNull(toggle); - - bool isOn = toggle.GetAttribute("Toggle.ToggleState") == "1"; - toggleValues.Add(isOn); - - toggle.Click(); - toggle.Click(); - } - - SaveChanges(); - WaitSeconds(1); - - JObject savedProps = GetProperties(); - Assert.AreEqual(toggleValues[0], GetPropertyValue(savedProps, "fancyzones_shiftDrag")); - Assert.AreEqual(toggleValues[1], GetPropertyValue(savedProps, "fancyzones_mouseSwitch")); - Assert.AreEqual(toggleValues[2], GetPropertyValue(savedProps, "fancyzones_overrideSnapHotkeys")); - Assert.AreEqual(toggleValues[3], GetPropertyValue(savedProps, "fancyzones_moveWindowAcrossMonitors")); - Assert.AreEqual(toggleValues[4], GetPropertyValue(savedProps, "fancyzones_moveWindowsBasedOnPosition")); - Assert.AreEqual(toggleValues[5], GetPropertyValue(savedProps, "fancyzones_displayChange_moveWindows")); - Assert.AreEqual(toggleValues[6], GetPropertyValue(savedProps, "fancyzones_zoneSetChange_moveWindows")); - Assert.AreEqual(toggleValues[7], GetPropertyValue(savedProps, "fancyzones_appLastZone_moveWindows")); - Assert.AreEqual(toggleValues[8], GetPropertyValue(savedProps, "fancyzones_restoreSize")); - Assert.AreEqual(toggleValues[9], GetPropertyValue(savedProps, "use_cursorpos_editor_startupscreen")); - Assert.AreEqual(toggleValues[10], GetPropertyValue(savedProps, "fancyzones_show_on_all_monitors")); - Assert.AreEqual(toggleValues[11], GetPropertyValue(savedProps, "fancyzones_span_zones_across_monitors")); - Assert.AreEqual(toggleValues[12], GetPropertyValue(savedProps, "fancyzones_makeDraggedWindowTransparent")); - } - - [TestMethod] - public void HighlightOpacitySetValue() - { - WindowsElement editor = session.FindElementByName("Zone opacity (%)"); - Assert.IsNotNull(editor); - - SetOpacity(editor, "50"); - SaveAndCheckOpacitySettings(editor, 50); - - SetOpacity(editor, "-50"); - SaveAndCheckOpacitySettings(editor, 0); - - SetOpacity(editor, "200"); - SaveAndCheckOpacitySettings(editor, 100); - - //for invalid input values previously saved value expected - SetOpacity(editor, "asdf"); - SaveAndCheckOpacitySettings(editor, 100); - - SetOpacity(editor, "*"); - SaveAndCheckOpacitySettings(editor, 100); - - SetOpacity(editor, OpenQA.Selenium.Keys.Return); - SaveAndCheckOpacitySettings(editor, 100); - - Clipboard.SetText("Hello, clipboard"); - SetOpacity(editor, OpenQA.Selenium.Keys.Control + "v"); - SaveAndCheckOpacitySettings(editor, 100); - } - - [TestMethod] - public void HighlightOpacityIncreaseValue() - { - WindowsElement editor = session.FindElementByName("Zone opacity (%)"); - Assert.IsNotNull(editor); - - SetOpacity(editor, "99"); - SaveAndCheckOpacitySettings(editor, 99); - - System.Drawing.Rectangle editorRect = editor.Rect; - - Actions action = new Actions(session); - action.MoveToElement(editor).MoveByOffset(editorRect.Width / 2 + 10, -editorRect.Height / 4).Perform(); - WaitSeconds(1); - - action.Click().Perform(); - Assert.AreEqual("100\r\n", editor.Text); - SaveAndCheckOpacitySettings(editor, 100); - - action.Click().Perform(); - Assert.AreEqual("100\r\n", editor.Text); - SaveAndCheckOpacitySettings(editor, 100); - } - - [TestMethod] - public void HighlightOpacityDecreaseValue() - { - - WindowsElement editor = session.FindElementByName("Zone opacity (%)"); - Assert.IsNotNull(editor); - - SetOpacity(editor, "1"); - SaveAndCheckOpacitySettings(editor, 1); - - System.Drawing.Rectangle editorRect = editor.Rect; - - Actions action = new Actions(session); - action.MoveToElement(editor).MoveByOffset(editorRect.Width / 2 + 10, editorRect.Height / 4).Perform(); - WaitSeconds(1); - - action.Click().Perform(); - Assert.AreEqual("0\r\n", editor.Text); - SaveAndCheckOpacitySettings(editor, 0); - - action.Click().Perform(); - Assert.AreEqual("0\r\n", editor.Text); - SaveAndCheckOpacitySettings(editor, 0); - } - - [TestMethod] - public void HighlightOpacityClearValueButton() - { - ScrollDown(3); - WindowsElement editor = session.FindElementByName("Zone opacity (%)"); - Assert.IsNotNull(editor); - - editor.Click(); //activate - AppiumWebElement clearButton = editor.FindElementByName("Clear value"); - Assert.IsNotNull(clearButton); - - /*element is not pointer- or keyboard interactable.*/ - Actions action = new Actions(session); - action.MoveToElement(clearButton).Click().Perform(); - - Assert.AreEqual("\r\n", editor.Text); - } - - [TestMethod] - public void HighlightColorSlidersTest() - { - ScrollDown(4); - - ReadOnlyCollection saturationAndBrightness = session.FindElementsByName("Saturation and brightness"); - ReadOnlyCollection hue = session.FindElementsByName("Hue"); - ReadOnlyCollection hex = session.FindElementsByXPath("//Edit[@Name=\"Hex\"]"); - ReadOnlyCollection red = session.FindElementsByXPath("//Edit[@Name=\"Red\"]"); - ReadOnlyCollection green = session.FindElementsByXPath("//Edit[@Name=\"Green\"]"); - ReadOnlyCollection blue = session.FindElementsByXPath("//Edit[@Name=\"Blue\"]"); - - TestColorSliders(saturationAndBrightness[2], hue[2], hex[2], red[2], green[2], blue[2], "fancyzones_zoneBorderColor"); - - new Actions(session).MoveToElement(saturationAndBrightness[2]).MoveByOffset(saturationAndBrightness[2].Rect.Width / 2 + 10, 0) - .Click().SendKeys(OpenQA.Selenium.Keys.PageUp).Perform(); - TestColorSliders(saturationAndBrightness[1], hue[1], hex[1], red[1], green[1], blue[1], "fancyzones_zoneColor"); - - new Actions(session).MoveToElement(saturationAndBrightness[1]).MoveByOffset(saturationAndBrightness[1].Rect.Width / 2 + 10, 0) - .Click().SendKeys(OpenQA.Selenium.Keys.PageDown + OpenQA.Selenium.Keys.PageDown).SendKeys(OpenQA.Selenium.Keys.PageUp + OpenQA.Selenium.Keys.PageUp).Perform(); - TestColorSliders(saturationAndBrightness[0], hue[0], hex[0], red[0], green[0], blue[0], "fancyzones_zoneHighlightColor"); - } - - [TestMethod] - public void HighlightColorTest() - { - ScrollDown(2); - - WindowsElement saturationAndBrightness = session.FindElementByName("Saturation and brightness"); - WindowsElement hue = session.FindElementByName("Hue"); - WindowsElement hex = session.FindElementByXPath("//Edit[@Name=\"Hex\"]"); - - Assert.IsNotNull(saturationAndBrightness); - Assert.IsNotNull(hue); - Assert.IsNotNull(hex); - - hex.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - hex.SendKeys("63c99a"); - new Actions(session).MoveToElement(hex).MoveByOffset(0, hex.Rect.Height).Click().Perform(); - - Assert.AreEqual("Saturation 51 brightness 79", saturationAndBrightness.Text); - Assert.AreEqual("152", hue.Text); - - SaveChanges(); - WaitSeconds(1); - Assert.AreEqual("#63c99a", GetPropertyValue("fancyzones_zoneHighlightColor")); - } - - [TestMethod] - public void HighlightRGBInputsTest() - { - ScrollDown(2); - - TestRgbInput("Red"); - TestRgbInput("Green"); - TestRgbInput("Blue"); - } - - [TestMethod] - public void HighlightHexInputTest() - { - ScrollDown(2); - - WindowsElement hexInput = session.FindElementByXPath("//Edit[@Name=\"Hex\"]"); - Assert.IsNotNull(hexInput); - - hexInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - - string invalidSymbols = "qwrtyuiopsghjklzxvnm,./';][{}:`~!#@$%^&*()_-+=\"\'\\"; - foreach (char symbol in invalidSymbols) - { - hexInput.SendKeys(symbol.ToString()); - Assert.AreEqual("", hexInput.Text.Trim()); - } - - string validSymbols = "0123456789abcdef"; - foreach (char symbol in validSymbols) - { - hexInput.SendKeys(symbol.ToString()); - Assert.AreEqual(symbol.ToString(), hexInput.Text.Trim()); - hexInput.SendKeys(OpenQA.Selenium.Keys.Backspace); - } - - //too many symbols - hexInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - hexInput.SendKeys("000000"); - hexInput.SendKeys("1"); - Assert.AreEqual("000000\r\n", hexInput.Text); - - //short string - hexInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - hexInput.SendKeys("000"); - new Actions(session).MoveToElement(hexInput).MoveByOffset(0, hexInput.Rect.Height).Click().Perform(); - Assert.AreEqual("000000\r\n", hexInput.Text); - - hexInput.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Backspace); - hexInput.SendKeys("1234"); - new Actions(session).MoveToElement(hexInput).MoveByOffset(0, hexInput.Rect.Height).Click().Perform(); - Assert.AreEqual("112233\r\n", hexInput.Text); - } - - [TestMethod] - public void ExcludeApps() - { - WindowsElement input = session.FindElementByXPath("//Edit[contains(@Name, \"exclude\")]"); - Assert.IsNotNull(input); - ClearInput(input); - - string inputValue; - - //valid - inputValue = "Notepad\nChrome"; - input.SendKeys(inputValue); - SaveChanges(); - ClearInput(input); - WaitSeconds(1); - Assert.AreEqual(inputValue, GetPropertyValue("fancyzones_excluded_apps")); - - //invalid - inputValue = "Notepad Chrome"; - input.SendKeys(inputValue); - SaveChanges(); - ClearInput(input); - WaitSeconds(1); - Assert.AreEqual(inputValue, GetPropertyValue("fancyzones_excluded_apps")); - - inputValue = "Notepad,Chrome"; - input.SendKeys(inputValue); - SaveChanges(); - ClearInput(input); - WaitSeconds(1); - Assert.AreEqual(inputValue, GetPropertyValue("fancyzones_excluded_apps")); - - inputValue = "Note*"; - input.SendKeys(inputValue); - SaveChanges(); - ClearInput(input); - WaitSeconds(1); - Assert.AreEqual(inputValue, GetPropertyValue("fancyzones_excluded_apps")); - - inputValue = "Кириллица"; - input.SendKeys(inputValue); - SaveChanges(); - ClearInput(input); - WaitSeconds(1); - Assert.AreEqual(inputValue, GetPropertyValue("fancyzones_excluded_apps")); - } - - [TestMethod] - public void ExitDialogSave() - { - WindowsElement toggle = session.FindElementByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]"); - Assert.IsNotNull(toggle); - - bool initialToggleValue = toggle.GetAttribute("Toggle.ToggleState") == "1"; - - toggle.Click(); - CloseSettings(); - WindowsElement exitDialog = session.FindElementByName("Changes not saved"); - Assert.IsNotNull(exitDialog); - - exitDialog.FindElementByName("Save").Click(); - - //check if window still opened - WindowsElement powerToysWindow = session.FindElementByXPath("//Window[@Name=\"PowerToys Settings\"]"); - Assert.IsNotNull(powerToysWindow); - - //check settings change - JObject savedProps = GetProperties(); - - Assert.AreNotEqual(initialToggleValue, GetPropertyValue(savedProps, "fancyzones_shiftDrag")); - - //return initial app state - toggle.Click(); - } - - [TestMethod] - public void ExitDialogExit() - { - WindowsElement toggle = session.FindElementByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]"); - Assert.IsNotNull(toggle); - - bool initialToggleValue = toggle.GetAttribute("Toggle.ToggleState") == "1"; - - toggle.Click(); - CloseSettings(); - - WindowsElement exitDialog = session.FindElementByName("Changes not saved"); - Assert.IsNotNull(exitDialog); - - exitDialog.FindElementByName("Exit").Click(); - - //check if window still opened - try - { - WindowsElement powerToysWindow = session.FindElementByXPath("//Window[@Name=\"PowerToys Settings\"]"); - Assert.IsNull(powerToysWindow); - } - catch (OpenQA.Selenium.WebDriverException) - { - //window is no longer available, which is expected - } - - //return initial app state - Init(); - - //check settings change - JObject savedProps = GetProperties(); - Assert.AreEqual(initialToggleValue, GetPropertyValue(savedProps, "fancyzones_shiftDrag")); - } - - [TestMethod] - public void ExitDialogCancel() - { - WindowsElement toggle = session.FindElementByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]"); - Assert.IsNotNull(toggle); - - toggle.Click(); - CloseSettings(); - WindowsElement exitDialog = session.FindElementByName("Changes not saved"); - Assert.IsNotNull(exitDialog); - - exitDialog.FindElementByName("Cancel").Click(); - - //check if window still opened - WindowsElement powerToysWindow = session.FindElementByXPath("//Window[@Name=\"PowerToys Settings\"]"); - Assert.IsNotNull(powerToysWindow); - - //check settings change - JObject savedProps = GetProperties(); - JObject initialProps = _initialSettingsJson["properties"].ToObject(); - Assert.AreEqual(GetPropertyValue(initialProps, "fancyzones_shiftDrag"), GetPropertyValue(savedProps, "fancyzones_shiftDrag")); - - //return initial app state - toggle.Click(); - SaveChanges(); - } - - [TestMethod] - public void ConfigureHotkey() - { - WindowsElement input = session.FindElementByXPath("//Edit[contains(@Name, \"hotkey\")]"); - Assert.IsNotNull(input); - - for (int i = 0; i < 16; i++) - { - TestHotkey(input, i, OpenQA.Selenium.Keys.End, "End"); - } - } - - [TestMethod] - public void ConfigureLocalSymbolHotkey() - { - WindowsElement input = session.FindElementByXPath("//Edit[contains(@Name, \"hotkey\")]"); - Assert.IsNotNull(input); - TestHotkey(input, 0, "ё", "Ё"); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - - Init(); - } - - [ClassCleanup] - public static void ClassCleanup() - { - CloseSettings(); - - try - { - WindowsElement exitDialogButton = session.FindElementByName("Exit"); - if (exitDialogButton != null) - { - exitDialogButton.Click(); - } - } - catch (OpenQA.Selenium.WebDriverException) - { - //element couldn't be located - } - - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - if (session == null) - return; - - try - { - _initialSettingsJson = JObject.Parse(_initialFancyZonesSettings); - } - catch (Newtonsoft.Json.JsonReaderException) - { - //empty settings - } - } - - [TestCleanup] - public void TestCleanup() - { - ScrollUp(); - } - } -} diff --git a/src/tests/win-app-driver/FancyZonesTests/README.md b/src/tests/win-app-driver/FancyZonesTests/README.md deleted file mode 100644 index 57ac0514e4..0000000000 --- a/src/tests/win-app-driver/FancyZonesTests/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# FancyZones Test Plan - -## Settings - - [x] Test if settings are saved in file properly - -## Editor - - [x] Open editor by clicking button from settings - - [x] without settings file - - [x] without settings folder - - [x] with valid settings file - - [x] with valid settings file contained cyrillic characters - - [x] with invalid settings file - - [x] with cropped file - - [x] Open editor by hotkey - - [x] without settings file - - [x] without settings folder - - [x] with valid settings file - - [x] with valid settings file contained cyrillic characters - - [x] with invalid settings file - - [x] with cropped file - - [ ] Increase/decrease zone count, check min and max possible values - - [ ] Test if settings are saved in file properly - - [ ] `Show spacing` checked/unchecked - - [ ] `Space around zone` saved correctly - - [ ] `Space around zone` possible input values - - [ ] Edit templates, check settings files - - [ ] Create new custom layout - - [ ] empty - - [ ] one zone - - [ ] fullscreen - - [ ] not fullscreen - - [ ] many zones - - [ ] overlapping - - [ ] non-overlapping - - [ ] utf-16 layout name - - [ ] empty layout name - - [ ] special characters in layout name - - [ ] Remove custom layout - - [ ] Edit selected layout - -### Usage diff --git a/src/tests/win-app-driver/PowerToysSession.cs b/src/tests/win-app-driver/PowerToysSession.cs deleted file mode 100644 index 479507e07f..0000000000 --- a/src/tests/win-app-driver/PowerToysSession.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using System.IO.Abstractions; -using System.Threading; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using OpenQA.Selenium; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - public class PowerToysSession - { - 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; - - protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723"; - protected const string AppPath = "C:\\Program Files\\PowerToys\\PowerToys.exe"; - - protected static WindowsDriver session; - protected static bool isPowerToysLaunched = false; - - protected static WindowsElement trayButton; - protected static WindowsElement settingsWindow; - - protected static string _commonSettingsFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys"); - protected static string _settingsFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\FancyZones"); - protected static string _fancyZonesSettingsPath = _settingsFolderPath + "\\settings.json"; - protected static string _zoneSettingsPath = _settingsFolderPath + "\\zones-settings.json"; - protected static string _appHistoryPath = _settingsFolderPath + "\\app-zone-history.json"; - protected static string _commonSettingsPath = _commonSettingsFolderPath + "\\settings.json"; - - protected static string _initialFancyZonesSettings = ""; - protected static string _initialZoneSettings = ""; - protected static string _initialAppHistorySettings = ""; - protected static string _initialCommonSettings = ""; - - protected const string _defaultFancyZonesSettings = "{\"version\":\"1.0\",\"name\":\"FancyZones\",\"properties\":{\"fancyzones_shiftDrag\":{\"value\":true},\"fancyzones_mouseSwitch\":{\"value\":false},\"fancyzones_overrideSnapHotkeys\":{\"value\":false},\"fancyzones_moveWindowAcrossMonitors\":{\"value\":false},\"fancyzones_zoneSetChange_flashZones\":{\"value\":false},\"fancyzones_displayChange_moveWindows\":{\"value\":false},\"fancyzones_zoneSetChange_moveWindows\":{\"value\":false},\"fancyzones_appLastZone_moveWindows\":{\"value\":false},\"use_cursorpos_editor_startupscreen\":{\"value\":true},\"fancyzones_zoneHighlightColor\":{\"value\":\"#0078D7\"},\"fancyzones_highlight_opacity\":{\"value\":90},\"fancyzones_editor_hotkey\":{\"value\":{\"win\":true,\"ctrl\":false,\"alt\":false,\"shift\":false,\"code\":192,\"key\":\"`\"}},\"fancyzones_excluded_apps\":{\"value\":\"\"}}}"; - protected const string _defaultZoneSettings = "{\"devices\":[],\"custom-zone-sets\":[]}"; - - - public static void Setup(TestContext context) - { - if (session == null) - { - ReadUserSettings(); //read settings before running tests to restore them after - - // Create a new Desktop session to use PowerToys. - AppiumOptions appiumOptions = new AppiumOptions(); - appiumOptions.PlatformName = "Windows"; - appiumOptions.AddAdditionalCapability("app", "Root"); - try - { - session = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), appiumOptions); - session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1); - - trayButton = session.FindElementByAccessibilityId("1502"); - - isPowerToysLaunched = CheckPowerToysLaunched(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - } - - public static void TearDown() - { - RestoreUserSettings(); //restore initial settings files - - if (session != null) - { - trayButton = null; - settingsWindow = null; - - session.Quit(); - session = null; - } - } - - public static void WaitSeconds(double seconds) - { - Thread.Sleep(TimeSpan.FromSeconds(seconds)); - } - - public static void OpenSettings() - { - trayButton.Click(); - - try - { - PowerToysTrayButton().Click(); - settingsWindow = session.FindElementByName("PowerToys Settings"); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - - trayButton.Click(); //close - Assert.IsNotNull(settingsWindow); - } - - public static void OpenFancyZonesSettings() - { - try - { - AppiumWebElement fzNavigationButton = settingsWindow.FindElementByName("FancyZones"); - Assert.IsNotNull(fzNavigationButton); - - fzNavigationButton.Click(); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - public static void CloseSettings() - { - try - { - WindowsElement settings = session.FindElementByName("PowerToys Settings"); - if (settings != null) - { - settings.Click(); - settings.FindElementByName("Close").Click(); - //settings.SendKeys(Keys.Alt + Keys.F4); - } - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - - protected static AppiumWebElement PowerToysTrayButton() - { - WindowsElement notificationOverflow = session.FindElementByName("Notification Overflow"); - AppiumWebElement overflowArea = notificationOverflow.FindElementByName("Overflow Notification Area"); - AppiumWebElement powerToys = overflowArea.FindElementByXPath("//Button[contains(@Name, \"PowerToys\")]"); - return powerToys; - } - - private static bool CheckPowerToysLaunched() - { - bool isLaunched = false; - trayButton.Click(); - - try - { - AppiumWebElement pt = PowerToysTrayButton(); - isLaunched = (pt != null); - } - catch (OpenQA.Selenium.WebDriverException) - { - //PowerToys not found - } - - trayButton.Click(); //close - return isLaunched; - } - - public static void LaunchPowerToys() - { - AppiumOptions opts = new AppiumOptions(); - opts.AddAdditionalCapability("app", AppPath); - - try - { - WindowsDriver driver = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), opts); - Assert.IsNotNull(driver); - driver.LaunchApp(); - } - catch (WebDriverException) - { - //exception is expected since WinApDriver tries to find main app window - } - - isPowerToysLaunched = true; - } - - public static void ExitPowerToys() - { - trayButton.Click(); - - try - { - AppiumWebElement pt = PowerToysTrayButton(); - Assert.IsNotNull(pt, "Could not exit PowerToys"); - - new Actions(session).MoveToElement(pt).ContextClick().Perform(); - session.FindElementByAccessibilityId("40001").Click(); - //WaitElementByXPath("//MenuItem[@Name=\"Exit\"]").Click(); - - isPowerToysLaunched = false; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - - trayButton.Click(); //close tray - } - - public static void EnableModules(bool colorPicker, bool fancyZones, bool fileExplorer, bool imageResizer, bool keyboardManager, bool powerRename, bool powerRun, bool shortcutGuide, bool relaunch = false) - { - JObject json = JObject.Parse(_initialCommonSettings); - JObject enabled = new JObject(); - enabled["ColorPicker"] = colorPicker; - enabled["FancyZones"] = fancyZones; - enabled["File Explorer"] = fileExplorer; - enabled["Image Resizer"] = imageResizer; - enabled["Keyboard Manager"] = keyboardManager; - enabled["PowerRename"] = powerRename; - enabled["PowerToys Run"] = powerRun; - enabled["Shortcut Guide"] = shortcutGuide; - - json["enabled"] = enabled; - - ResetSettings(_commonSettingsFolderPath, _commonSettingsPath, json.ToString(), relaunch); - } - - public static void ResetDefaultFancyZonesSettings(bool relaunch) - { - ResetSettings(_settingsFolderPath, _fancyZonesSettingsPath, _defaultFancyZonesSettings, relaunch); - } - - public static void ResetDefaultZoneSettings(bool relaunch) - { - ResetSettings(_settingsFolderPath, _zoneSettingsPath, _defaultZoneSettings, relaunch); - } - - private static void ResetSettings(string folder, string filePath, string data, bool relaunch) - { - if (!Directory.Exists(folder)) - { - Directory.CreateDirectory(folder); - } - File.WriteAllText(filePath, data); - - ExitPowerToys(); - if (relaunch) - { - LaunchPowerToys(); - } - } - - private static void ReadUserSettings() - { - try - { - if (_initialCommonSettings.Length == 0) - { - _initialCommonSettings = File.ReadAllText(_commonSettingsPath); - } - } - catch (Exception) - { } - - try - { - if (_initialFancyZonesSettings.Length == 0) - { - _initialFancyZonesSettings = File.ReadAllText(_fancyZonesSettingsPath); - } - } - catch (Exception) - { } - - try - { - if (_initialZoneSettings.Length == 0) - { - _initialZoneSettings = File.ReadAllText(_zoneSettingsPath); - } - } - catch (Exception) - { } - - try - { - if (_initialAppHistorySettings.Length == 0) - { - _initialAppHistorySettings = File.ReadAllText(_appHistoryPath); - } - } - catch (Exception) - { } - } - - private static void RestoreUserSettings() - { - if (_initialCommonSettings.Length > 0) - { - File.WriteAllText(_commonSettingsPath, _initialCommonSettings); - } - else - { - File.Delete(_commonSettingsPath); - } - - if (_initialFancyZonesSettings.Length > 0) - { - File.WriteAllText(_fancyZonesSettingsPath, _initialFancyZonesSettings); - } - else - { - File.Delete(_fancyZonesSettingsPath); - } - - if (_initialZoneSettings.Length > 0) - { - File.WriteAllText(_zoneSettingsPath, _initialZoneSettings); - } - else - { - File.Delete(_zoneSettingsPath); - } - - if (_initialAppHistorySettings.Length > 0) - { - File.WriteAllText(_appHistoryPath, _initialAppHistorySettings); - } - else - { - File.Delete(_appHistoryPath); - } - } - } -} diff --git a/src/tests/win-app-driver/PowerToysTrayTests.cs b/src/tests/win-app-driver/PowerToysTrayTests.cs deleted file mode 100644 index a55739cabd..0000000000 --- a/src/tests/win-app-driver/PowerToysTrayTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [TestClass] - public class PowerToysTrayTests : PowerToysSession - { - private bool isSettingsOpened; - private bool isTrayOpened; - - [TestMethod] - public void SettingsOpen() - { - OpenSettings(); - - //check settings window opened - WindowsElement settingsWindow = session.FindElementByName("PowerToys Settings"); - Assert.IsNotNull(settingsWindow); - - isSettingsOpened = true; - } - - [TestMethod] - public void SettingsOpenWithContextMenu() - { - //open tray - trayButton.Click(); - WaitSeconds(1); - isTrayOpened = true; - - //open PowerToys context menu - AppiumWebElement pt = PowerToysTrayButton(); - Assert.IsNotNull(pt); - - new Actions(session).MoveToElement(pt).ContextClick().Perform(); - - //open settings - session.FindElementByXPath("//MenuItem[@Name=\"Settings\"]").Click(); - - //check settings window opened - WindowsElement settingsWindow = session.FindElementByName("PowerToys Settings"); - Assert.IsNotNull(settingsWindow); - - isSettingsOpened = true; - } - - [TestMethod] - public void PowerToysExit() - { - //open PowerToys context menu - trayButton.Click(); - isTrayOpened = true; - WaitSeconds(1); - - AppiumWebElement powerToys = PowerToysTrayButton(); - Assert.IsNotNull(powerToys); - - new Actions(session).MoveToElement(powerToys).ContextClick().Perform(); - - //exit - session.FindElementByAccessibilityId("40001").Click(); - - //check PowerToys exited - powerToys = null; - try - { - powerToys = PowerToysTrayButton(); - } - catch (OpenQA.Selenium.WebDriverException) - { - //expected, PowerToys shouldn't be here - } - - LaunchPowerToys(); - Assert.IsNull(powerToys); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - - if (!isPowerToysLaunched) - { - LaunchPowerToys(); - } - } - - [ClassCleanup] - public static void ClassCleanup() - { - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - isSettingsOpened = false; - isTrayOpened = false; - } - - [TestCleanup] - public void TestCleanup() - { - if (isSettingsOpened) - { - CloseSettings(); - } - - if (isTrayOpened) - { - trayButton.Click(); - } - } - } -} diff --git a/src/tests/win-app-driver/README.md b/src/tests/win-app-driver/README.md deleted file mode 100644 index dfa5d882f5..0000000000 --- a/src/tests/win-app-driver/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# PowerToys Tests - -The PowerToys tests are implemented using Appium and use the [Windows Application Driver](https://github.com/microsoft/WinAppDriver) as an Appium compatible server for Windows applications. - -## Prerequisites - - Install the latest stable version of Windows Application Driver in the test machine: [v1.1 Release](https://github.com/microsoft/WinAppDriver/releases/tag/v1.1) - - Install the ".Net desktop development" components in Visual Studio 2019. It should have support for `C#` and `.Net Framework 4.7.2`. - - Install [PowerToys](https://github.com/microsoft/PowerToys/releases/) - - In Windows 10 Settings, turn on `Developer Mode` (open the Windows 10 Settings and search "Developer settings"). - -If you have `PowerToys` installed, it can be launched automatically. Otherwise, if you are testing a local build, you should start `PowerToys` before running the tests. - -### Preparing the test machine - - Start `PowerToys` if necessary (see the Prerequisites). - - Run `WinAppDriver.exe` in Administrator mode, on the test machine. By default it's installed in `C:\Program Files (x86)\Windows Application Driver\` - - **Note:** notifications or other application windows, that are shown above the PowerToys settings window or tray icon, can disrupt the testing process. - -When testing on a remote machine, a Firewall exceptions must be added and the IP and port must be passed when starting "Windows Application Driver". Here's how to do it from the [Windows Application Driver FAQ](https://github.com/microsoft/WinAppDriver/wiki/Frequently-Asked-Questions#running-on-a-remote-machine): - -#### Running on a Remote Machine - -Windows Application Driver can run remotely on any Windows 10 machine with `WinAppDriver.exe` installed and running. This *test machine* can then serve any JSON wire protocol commands coming from the *test runner* remotely through the network. Below are the steps to the one-time setup for the *test machine* to receive inbound requests: - -1. On the *test machine* you want to run the test application on, open up **Windows Firewall with Advanced Security** - - Select **Inbound Rules** -> **New Rule...** - - **Rule Type** -> **Port** - - Select **TCP** - - Choose specific local port (4723 is WinAppDriver standard) - - **Action** -> **Allow the connection** - - **Profile** -> select all - - **Name** -> optional, choose name for rule (e.g. WinAppDriver remote). - - Below command when run in admin command prompt gives same result - ```shell - netsh advfirewall firewall add rule name="WinAppDriver remote" dir=in action=allow protocol=TCP localport=4723 - ``` - -2. Run `ipconfig.exe` to determine your machine's local IP address - > **Note**: Setting `*` as the IP address command line option will cause it to bind to all bound IP addresses on the machine -3. Run `WinAppDriver.exe 10.X.X.10 4723/wd/hub` as **administrator** with command line arguments as seen above specifying local IP and port -4. On the *test runner* machine where the runner and scripts are, update the test script to point to the IP of the remote *test machine* - -### Starting the tests on the Development Machine - - Open `PowerToys.sln` in Visual Studio. - - Build the `PowerToysTests` project. - - Select `Test > Windows > Test Explorer`. - - Select `Test > Run > All` tests in the menu bar. - -> Once the project is successfully built, you can use the **TestExplorer** to pick and choose the test scenario(s) to run - -> If Visual Studio fail to discover and run the test scenarios: -> 1. Select **Tools** > **Options...** > **Test** -> 2. Under *Active Solution*, uncheck *For improved performance, only use test adapters in test assembly folder or as specified in runsettings file* - -If a remote test machine is being used, the IP of the test machine must be used to replace the `WindowsApplicationDriverUrl` value in [PowerToysSession.cs](PowerToysSession.cs). - -### Extra tools and information - -For tests creation you will need a tool that enables you select any UI element and view the element's accessibility data. For this purpose you could use [AccessibilityInsights](https://accessibilityinsights.io/docs/windows/overview) or [Inspect](https://learn.microsoft.com/windows/win32/winauto/inspect-objects?redirectedfrom=MSDN). - -* `inspect.exe` you can find installed at `C:\Program Files (x86)\Windows Kits\10\bin\\\inspect.exe` -* `AccessibilityInsights` you can download [here](https://aka.ms/accessibilityinsights-windows/download) - -##### How to use Inspect -Open Inspect, find element you need to investigate (by clicking on element or finding it in a tree) and in the right part of inspector window you will see info about this element. - -Examples for searching elements with values of `Name`, `AutomationId` and `ControlType`: -``` -//use FindElementByAccessibilityId with AutomationId value -session.FindElementByAccessibilityId("40001"); -session.FindElementByAccessibilityId("decrementZones"); - -session.FindElementByName("PowerToys Settings"); - -//with XPath you can search elements with more specific information -session.FindElementByXPath("//Pane[@Name=\"PowerToys Settings\"]"); -session.FindElementByXPath("//Edit[contains(@Name, \"hotkey\")]"); -session.FindElementByXPath("//Pane[@Name=\"PowerToys Settings\"]/*[@LocalizedControlType=\"toggleswitch\"]"); -``` - ->One more thing to notice: close helper tools while running tests. Overlapping windows can affect test results. diff --git a/src/tests/win-app-driver/TestShortcutGuideHelper.cs b/src/tests/win-app-driver/TestShortcutGuideHelper.cs deleted file mode 100644 index 17067e93f0..0000000000 --- a/src/tests/win-app-driver/TestShortcutGuideHelper.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Appium.Windows; -using OpenQA.Selenium.Interactions; - -namespace PowerToysTests -{ - [TestClass] - public class TestShortcutGuideHelper : PowerToysSession - { - // Try to manage Press/Release of Windows Key here, - // since Keyboard.PressKey seems to release the key if pressed - // and Keyboard.ReleaseKey seems to press the key if not pressed. - private bool isWinKeyPressed; - - private void PressWinKey() - { - if (!isWinKeyPressed) - { - new Actions(session).KeyDown(OpenQA.Selenium.Keys.Command).Perform(); - isWinKeyPressed = true; - } - } - - private void ReleaseWinKey() - { - if (isWinKeyPressed) - { - new Actions(session).KeyUp(OpenQA.Selenium.Keys.Command).Perform(); - isWinKeyPressed = false; - } - } - - [TestMethod] - public void AppearsOnWinKeyPress() - { - PressWinKey(); - WaitSeconds(3); - - try - { - WindowsElement shortcutHelperWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Pane[@ClassName=\"PToyD2DPopup\"]"); - Assert.IsNotNull(shortcutHelperWindow); - } - catch(OpenQA.Selenium.WebDriverException) - { - Assert.Fail("Shortcut Guide not found"); - } - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException), - "The Shortcut Guide UI was still found after releasing the key.")] - public void DisappearsOnWinKeyRelease() - { - PressWinKey(); - WaitSeconds(2); - WindowsElement shortcutHelperWindow; - try - { - shortcutHelperWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Pane[@ClassName=\"PToyD2DPopup\"]"); - Assert.IsNotNull(shortcutHelperWindow); - } - catch (InvalidOperationException) - { - // Not the exception we wanted to catch here. - Assert.Fail("Shortcut Guide not found"); - } - - ReleaseWinKey(); - shortcutHelperWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Pane[@ClassName=\"PToyD2DPopup\"]"); - Assert.IsNull(shortcutHelperWindow); - } - - [TestMethod] - public void DoesNotBlockStartMenuOnShortPress() - { - PressWinKey(); - WaitSeconds(0.4); - // FindElementByClassName will be faster than using with XPath. - WindowsElement shortcutHelperWindow = session.FindElementByClassName("PToyD2DPopup"); - Assert.IsNotNull(shortcutHelperWindow); - ReleaseWinKey(); - WindowsElement startMenuWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Window[@Name=\"Start\"]"); - } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException), - "The Start Menu was found after releasing the key on a long press.")] - public void DoesNotSpawnStartMenuOnLongPress() - { - PressWinKey(); - WaitSeconds(2); - try - { - // FindElementByClassName will be faster than using with XPath. - WindowsElement shortcutHelperWindow = session.FindElementByClassName("PToyD2DPopup"); - Assert.IsNotNull(shortcutHelperWindow); - } - catch (InvalidOperationException) - { - // Not the exception we wanted to catch here. - Assert.Fail("Shortcut Guide not found"); - } - ReleaseWinKey(); - WindowsElement startMenuWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Window[@Name=\"Start\"]"); - } - - [ClassInitialize] - public static void ClassInitialize(TestContext context) - { - Setup(context); - Assert.IsNotNull(session); - EnableModules(false, false, false, false, false, false, false, true); - - if (!isPowerToysLaunched) - { - LaunchPowerToys(); - } - } - - [ClassCleanup] - public static void ClassCleanup() - { - ExitPowerToys(); - TearDown(); - } - - [TestInitialize] - public void TestInitialize() - { - isWinKeyPressed = false; - - // If the start menu is open, close it. - WindowsElement startMenuWindow = null; - try - { - startMenuWindow = session.FindElementByXPath("/Pane[@ClassName=\"#32769\"]/Window[@Name=\"Start\"]"); - } - catch (Exception) - { - //Start menu not found, as expected. - } - if (startMenuWindow != null) - { - string startMenuWindowHandle = (int.Parse(startMenuWindow.GetAttribute("NativeWindowHandle"))).ToString("x"); - // Create session for controlling the Start Menu. - AppiumOptions appiumOptions = new AppiumOptions(); - appiumOptions.PlatformName = "Windows"; - appiumOptions.AddAdditionalCapability("appTopLevelWindow", startMenuWindowHandle); - WindowsDriver startMenuSession = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), appiumOptions); - if (startMenuSession != null) - { - new Actions(session).SendKeys(OpenQA.Selenium.Keys.Escape + OpenQA.Selenium.Keys.Escape).Perform(); - startMenuSession.Quit(); - } - } - } - [TestCleanup] - public void TestCleanup() - { - // Release Windows Key in case it's being pressed by some of the tests - ReleaseWinKey(); - } - } -} diff --git a/src/tests/win-app-driver/win-app-driver.csproj b/src/tests/win-app-driver/win-app-driver.csproj deleted file mode 100644 index 5694111928..0000000000 --- a/src/tests/win-app-driver/win-app-driver.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netcoreapp3.1 - PowerToysTests - false - true - - - - - - - - - - - - - -