mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2026-02-04 00:08:33 +00:00
test(BRIDGE-136): Download Bridge
This commit is contained in:
committed by
Gordana Zafirova
parent
cf9b35163a
commit
fd709b0d08
34
ci/test.yml
34
ci/test.yml
@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
stage: test
|
stage: test
|
||||||
extends:
|
extends:
|
||||||
@ -33,8 +31,6 @@ lint-bug-report-preview:
|
|||||||
paths:
|
paths:
|
||||||
- coverage/**
|
- coverage/**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test-linux:
|
test-linux:
|
||||||
extends:
|
extends:
|
||||||
- .image-linux-test
|
- .image-linux-test
|
||||||
@ -93,7 +89,6 @@ test-integration-race:
|
|||||||
paths:
|
paths:
|
||||||
- integration-race-job.log
|
- integration-race-job.log
|
||||||
|
|
||||||
|
|
||||||
test-integration-nightly:
|
test-integration-nightly:
|
||||||
extends:
|
extends:
|
||||||
- test-integration
|
- test-integration
|
||||||
@ -131,12 +126,38 @@ test-coverage:
|
|||||||
paths:
|
paths:
|
||||||
- coverage*
|
- coverage*
|
||||||
- coverage/**
|
- coverage/**
|
||||||
when: 'always'
|
when: "always"
|
||||||
reports:
|
reports:
|
||||||
coverage_report:
|
coverage_report:
|
||||||
coverage_format: cobertura
|
coverage_format: cobertura
|
||||||
path: coverage.xml
|
path: coverage.xml
|
||||||
|
|
||||||
|
test-e2e-ui:
|
||||||
|
stage: test
|
||||||
|
extends:
|
||||||
|
- .rules-branch-and-MR-manual
|
||||||
|
tags:
|
||||||
|
- inbox-virt-windows-ui-v1
|
||||||
|
variables:
|
||||||
|
REQUIRES_GRAPHICAL_CONSOLE: true
|
||||||
|
before_script:
|
||||||
|
- echo "Downloading dotnet dependencies"
|
||||||
|
- cd ./tests/e2e/ui_tests/windows_os/
|
||||||
|
- dotnet restore ./ProtonMailBridge.UI.Tests.csproj
|
||||||
|
- dotnet list package
|
||||||
|
script:
|
||||||
|
- pwsh $CI_PROJECT_DIR/tests/e2e/ui_tests/windows_os/InstallerScripts/Get-BridgeInstaller.ps1
|
||||||
|
- no_grpc_proxy=127.0.0.1 dotnet test ./ProtonMailBridge.UI.Tests.csproj -- NUnit.Where="cat != TemporarilyExcluded"
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
- cp /c/users/gitlab-runner/AppData/Roaming/protonmail/bridge-v3/logs/* $CI_PROJECT_DIR/tests/e2e/ui_tests/windows_os/Results/artifacts/Logs/
|
||||||
|
- pwsh $CI_PROJECT_DIR/tests/e2e/ui_tests/windows_os/InstallerScripts/Remove-Bridge.ps1
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- tests/e2e/ui_tests/windows_os/Results/artifacts/*
|
||||||
|
when: always
|
||||||
|
|
||||||
go-vuln-check:
|
go-vuln-check:
|
||||||
extends:
|
extends:
|
||||||
- .image-linux-test
|
- .image-linux-test
|
||||||
@ -150,4 +171,3 @@ go-vuln-check:
|
|||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
- vulns*
|
- vulns*
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
# Download the Bridge installer, and install it
|
||||||
|
|
||||||
|
# Set variables with Bridge's download link and the download path
|
||||||
|
# to be used later on
|
||||||
|
$bridgeDownloadURL = $env:BRIDGE_DOWNLOAD_URL
|
||||||
|
$bridgeDownloadPath = "$env:CI_PROJECT_DIR/tests/e2e/ui_tests/windows_os/InstallerScripts/Bridge-Installer.exe"
|
||||||
|
|
||||||
|
# Write the download link of Bridge to use it if manual re-tests are needed
|
||||||
|
Write-Output $bridgeDownloadURL
|
||||||
|
|
||||||
|
# Download the Bridge-Installer.exe file
|
||||||
|
Invoke-WebRequest -Uri $bridgeDownloadURL -OutFile $bridgeDownloadPath
|
||||||
|
|
||||||
|
if (Test-Path -Path $bridgeDownloadPath) {
|
||||||
|
Write-Output "Bridge Installer downloaded."
|
||||||
|
$file = Get-Item $bridgeDownloadPath | Select-Object Name, Length
|
||||||
|
$size = $file.Length
|
||||||
|
$sizeMB = "{0:N2}" -f ($size / 1MB)
|
||||||
|
Write-Output "File size in MB: $sizeMB"
|
||||||
|
} else {
|
||||||
|
Write-Output "Bridge installer NOT DOWNLOADED"
|
||||||
|
}
|
||||||
|
# Install the downloaded Bridge-Installer.exe file
|
||||||
|
# The installer is passive, meaning no user interaction is needed
|
||||||
|
# If the user does not have admin rights, it will still show the UAC prompt
|
||||||
|
# where a user needs to click on "Yes",
|
||||||
|
# but this will be not needed since the image in the pipeline will be an
|
||||||
|
# Admin account
|
||||||
|
|
||||||
|
# Argument list for passive install
|
||||||
|
# $argList = "/passive INSTALLSHORTCUT=yes INSTALLDESKTOPSHORTCUT=yes"
|
||||||
|
|
||||||
|
# Install Bridge
|
||||||
|
$process = Start-Process -Wait -ArgumentList "/passive INSTALLSHORTCUT=yes INSTALLDESKTOPSHORTCUT=yes" -PassThru -FilePath $bridgeDownloadPath
|
||||||
|
|
||||||
|
# Check exit code of the installation process to confirm installation
|
||||||
|
if ($process.ExitCode -eq "0") {
|
||||||
|
Write-Output "Bridge installed successfully"
|
||||||
|
} else {
|
||||||
|
Write-Error "Bridge not installed successfully!"
|
||||||
|
Write-Error "Installer Exit Code: $($process.ExitCode)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delete the installer after installation to clean up the space
|
||||||
|
Remove-Item -Path $bridgeDownloadPath
|
||||||
156
tests/e2e/ui_tests/windows_os/InstallerScripts/Remove-Bridge.ps1
Normal file
156
tests/e2e/ui_tests/windows_os/InstallerScripts/Remove-Bridge.ps1
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<#
|
||||||
|
PowerShell script for uninstalling Bridge
|
||||||
|
And removing all other files (vault, cache, updates, etc)
|
||||||
|
#>
|
||||||
|
|
||||||
|
|
||||||
|
# Define variables with path to Bridge files (vault, cache, startup entry etc)
|
||||||
|
$RoamProtonmail = "$env:APPDATA\protonmail"
|
||||||
|
$RoamProtonAG = "$env:APPDATA\Proton AG"
|
||||||
|
$LocalProtonmail = "$env:LOCALAPPDATA\protonmail"
|
||||||
|
$LocalProtonAG = "$env:LOCALAPPDATA\Proton AG"
|
||||||
|
$StartUpProtonBridge = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\Proton Mail Bridge.lnk"
|
||||||
|
|
||||||
|
function Uninstall-PMBridge {
|
||||||
|
# Uninstalling REBRANDED version of Bridge
|
||||||
|
# Find the UninstallSTring in the registry (64bit & 32bit)
|
||||||
|
# Use the UninstallString with `msiexec.exe` to uninstall Bridge
|
||||||
|
|
||||||
|
$registry64 = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "Proton Mail Bridge" } | Select-Object UninstallString
|
||||||
|
|
||||||
|
if ($registry64) {
|
||||||
|
$registry64 = $registry64 | Select-Object -Last 1
|
||||||
|
$registry64 = $registry64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
|
||||||
|
$registry64 = $registry64.Trim()
|
||||||
|
Start-Process "msiexec.exe" -arg "/X $registry64 /passive" -Wait
|
||||||
|
}
|
||||||
|
|
||||||
|
$registry32 = Get-ChildItem "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "Proton Mail Bridge" } | Select-Object UninstallString
|
||||||
|
|
||||||
|
if ($registry32) {
|
||||||
|
$registry32 = $registry32 | Select-Object -Last 1
|
||||||
|
$registry32 = $registry32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
|
||||||
|
$registry32 = $registry32.Trim()
|
||||||
|
Start-Process "msiexec.exe" -arg "/X $registry32 /passive" -Wait
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Uninstalling PRE-REBRANDED version of Bridge
|
||||||
|
# Find the UninstallSTring in the registry (64bit & 32bit)
|
||||||
|
# Use the UninstallString with `msiexec.exe` to uninstall Bridge
|
||||||
|
|
||||||
|
$preRebrandRegistry64 = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "ProtonMail Bridge" } | Select-Object UninstallString
|
||||||
|
|
||||||
|
if ($preRebrandRegistry64) {
|
||||||
|
$preRebrandRegistry64 = $preRebrandRegistry64 | Select-Object -Last 1
|
||||||
|
$preRebrandRegistry64 = $preRebrandRegistry64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
|
||||||
|
$preRebrandRegistry64 = $preRebrandRegistry64.Trim()
|
||||||
|
Start-Process "msiexec.exe" -arg "/X $preRebrandRegistry64 /passive" -Wait
|
||||||
|
}
|
||||||
|
|
||||||
|
$preRebrandRegistry32 = Get-ChildItem "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "ProtonMail Bridge" } | Select-Object UninstallString
|
||||||
|
|
||||||
|
if ($preRebrandRegistry32) {
|
||||||
|
$preRebrandRegistry32 = $preRebrandRegistry32 | Select-Object -Last 1
|
||||||
|
$preRebrandRegistry32 = $preRebrandRegistry32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
|
||||||
|
$preRebrandRegistry32 = $preRebrandRegistry32.Trim()
|
||||||
|
Start-Process "msiexec.exe" -arg "/X $preRebrandRegistry32 /passive" -Wait
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Stop-PMBridge {
|
||||||
|
# Stop the `bridge` process to completely quit Bridge
|
||||||
|
|
||||||
|
$bridge = Get-Process "bridge" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($bridge){
|
||||||
|
|
||||||
|
$bridge | Stop-Process -Force
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Remove-PMBridgeResources {
|
||||||
|
# Delete all the Bridge resource folders
|
||||||
|
# They should be deleted with uninstalling Bridge
|
||||||
|
# But to just make sure do this again
|
||||||
|
|
||||||
|
Remove-Item $RoamProtonmail -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item $RoamProtonAG -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item $LocalProtonmail -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item $LocalProtonAG -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item $StartUpProtonBridge -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Find-PMBridgeResources {
|
||||||
|
# Search and check if the Bridge resource folders
|
||||||
|
# Are deleted
|
||||||
|
# Write to Output the result
|
||||||
|
|
||||||
|
$FolderExists = $false
|
||||||
|
|
||||||
|
if ( Test-Path -Path $RoamProtonmail ){
|
||||||
|
Write-Host "`r`n'$RoamProtonmail' is not deleted!" -ForegroundColor Red
|
||||||
|
$FolderExists = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Test-Path -Path $RoamProtonAG ) {
|
||||||
|
Write-Host "`r`n'$RoamProtonAG' is not deleted!" -ForegroundColor Red
|
||||||
|
$FolderExists = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Test-Path -Path $LocalProtonmail ) {
|
||||||
|
Write-Host "`r`n'$LocalProtonmail' is not deleted!" -ForegroundColor Red
|
||||||
|
$FolderExists = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Test-Path -Path $LocalProtonAG ) {
|
||||||
|
Write-Host "`r`n'$LocalProtonAG' is not deleted!" -ForegroundColor Red
|
||||||
|
$FolderExists = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Test-Path -Path $StartUpProtonBridge ) {
|
||||||
|
Write-Host "`r`n'$StartUpProtonBridge' is not deleted!" -ForegroundColor Red
|
||||||
|
$FolderExists = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $FolderExists ) {
|
||||||
|
Write-Host "`r`nSome directories were not deleted properly!`r`n" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
Write-Host "`r`nAll Bridge resource folders deleted!`r`n" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Remove-PMBridgeCredentials {
|
||||||
|
# Delete the entries in the credential manager
|
||||||
|
|
||||||
|
$CredentialsData = @((cmdkey /listall | Where-Object{$_ -like "*LegacyGeneric:target=protonmail*"}).replace("Target: ",""))
|
||||||
|
|
||||||
|
for($i =0; $i -le ($CredentialsData.Count -1); $i++){
|
||||||
|
[string]$DeleteData = $CredentialsData[$i].trim()
|
||||||
|
cmdkey /delete:$DeleteData
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Invoke-BridgeFunctions {
|
||||||
|
Stop-PMBridge
|
||||||
|
Uninstall-PMBridge
|
||||||
|
Remove-PMBridgeResources
|
||||||
|
Find-PMBridgeResources
|
||||||
|
Remove-PMBridgeCredentials
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Invoke-BridgeFunctions
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<#
|
||||||
|
PowerShell script for removing Bridge credentials from
|
||||||
|
Microsoft Credentials manager
|
||||||
|
#>
|
||||||
|
|
||||||
|
$Bridge = Get-Process "bridge" -ErrorAction SilentlyContinue
|
||||||
|
$CredentialsData = @((cmdkey /listall | Where-Object{$_ -like "*LegacyGeneric:target=protonmail*"}).replace("Target: ",""))
|
||||||
|
|
||||||
|
|
||||||
|
function Remove-BridgeCredentials {
|
||||||
|
# Delete the entries in the credential manager
|
||||||
|
|
||||||
|
for($i=0; $i -le ($CredentialsData.Count -1); $i++){
|
||||||
|
[string]$DeleteData = $CredentialsData[$i].trim()
|
||||||
|
cmdkey /delete:$DeleteData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stop-PMBridge {
|
||||||
|
# Stop the `bridge` process to completely quit Bridge
|
||||||
|
|
||||||
|
if ($Bridge){
|
||||||
|
|
||||||
|
$Bridge | Stop-Process -Force
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Functions{
|
||||||
|
Stop-PMBridge
|
||||||
|
Remove-BridgeCredentials
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-Functions
|
||||||
@ -18,14 +18,17 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="FlaUI.Core" Version="4.0.0" />
|
<PackageReference Include="FlaUI.Core" Version="4.0.0" />
|
||||||
<PackageReference Include="FlaUI.UIA3" Version="4.0.0" />
|
<PackageReference Include="FlaUI.UIA3" Version="4.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.1" />
|
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.4.6" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit" Version="4.3.0" />
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="4.4.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="8.0.8" />
|
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
|
||||||
|
<PackageReference Include="System.Management" Version="9.0.0" />
|
||||||
|
<PackageReference Include="System.Management.Automation" Version="7.4.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -16,42 +16,44 @@ namespace ProtonMailBridge.UI.Tests.Results
|
|||||||
private Button OkToAcknowledgeAccountAlreadySignedIn => NotificationWindow.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("OK"))).AsButton();
|
private Button OkToAcknowledgeAccountAlreadySignedIn => NotificationWindow.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("OK"))).AsButton();
|
||||||
private AutomationElement[] TextFields => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Text));
|
private AutomationElement[] TextFields => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Text));
|
||||||
private TextBox SynchronizingField => TextFields[4].AsTextBox();
|
private TextBox SynchronizingField => TextFields[4].AsTextBox();
|
||||||
private TextBox AccountDisabledErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("failed to create new API client: 422 POST https://mail-api.proton.me/auth/v4: This account has been suspended due to a potential policy violation. If you believe this is in error, please contact us at https://proton.me/support/appeal-abuse (Code=10003, Status=422)"))).AsTextBox();
|
private TextBox AccountDisabledErrorText => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Text)).FirstOrDefault(e =>!string.IsNullOrEmpty(e.Name) && e.Name.IndexOf("This account has been suspended due to a potential policy violation.", StringComparison.OrdinalIgnoreCase) >= 0)?.AsTextBox();
|
||||||
private TextBox AccountDelinquentErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("failed to create new API client: 422 POST https://mail-api.proton.me/auth/v4: Use of this client requires permissions not available to your account (Code=2011, Status=422)"))).AsTextBox();
|
|
||||||
private TextBox IncorrectLoginCredentialsErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Incorrect login credentials"))).AsTextBox();
|
private TextBox IncorrectLoginCredentialsErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Incorrect login credentials"))).AsTextBox();
|
||||||
private TextBox EnterEmailOrUsernameErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Enter email or username"))).AsTextBox();
|
private TextBox EnterEmailOrUsernameErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Enter email or username"))).AsTextBox();
|
||||||
private TextBox EnterPasswordErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Enter password"))).AsTextBox();
|
private TextBox EnterPasswordErrorText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Enter password"))).AsTextBox();
|
||||||
private TextBox ConnectedStateText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Connected"))).AsTextBox();
|
private TextBox ConnectedStateText => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Connected"))).AsTextBox();
|
||||||
private CheckBox SplitAddressesToggle => AccountView.FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("Split addresses toggle"))).AsCheckBox();
|
private CheckBox SplitAddressesToggle => AccountView.FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("Split addresses toggle"))).AsCheckBox();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public HomeResult CheckConnectedState()
|
public HomeResult CheckConnectedState()
|
||||||
{
|
{
|
||||||
Assert.That(ConnectedStateText.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => ConnectedStateText.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult CheckIfLoggedIn()
|
public HomeResult CheckIfLoggedIn()
|
||||||
{
|
{
|
||||||
Assert.That(SignOutButton.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => SignOutButton.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult CheckIfSynchronizingBarIsShown()
|
public HomeResult CheckIfSynchronizingBarIsShown()
|
||||||
{
|
{
|
||||||
Assert.That(SynchronizingField.IsAvailable && SynchronizingField.Name.StartsWith("Synchronizing"), Is.True);
|
RetryHelper.Eventually(() => SynchronizingField.IsAvailable && SynchronizingField.Name.StartsWith("Synchronizing"));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult CheckIfFreeAccountErrorIsDisplayed(string ErrorText)
|
public HomeResult CheckIfFreeAccountErrorIsDisplayed(string ErrorText)
|
||||||
{
|
{
|
||||||
Assert.That(FreeAccountErrorText.Name == ErrorText, Is.True);
|
RetryHelper.Eventually(() => FreeAccountErrorText.Name == ErrorText);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult CheckIfAccountIsSignedOut()
|
public HomeResult CheckIfAccountIsSignedOut()
|
||||||
{
|
{
|
||||||
Assert.That(SignedOutAccount.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => SignedOutAccount.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult CheckIfAccountAlreadySignedInIsDisplayed()
|
public HomeResult CheckIfAccountAlreadySignedInIsDisplayed()
|
||||||
{
|
{
|
||||||
Assert.That(AlreadySignedInText.IsAvailable, Is.True);
|
|
||||||
|
RetryHelper.Eventually(() => AlreadySignedInText.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HomeResult ClickOkToAcknowledgeAccountAlreadySignedIn ()
|
public HomeResult ClickOkToAcknowledgeAccountAlreadySignedIn ()
|
||||||
@ -67,32 +69,30 @@ namespace ProtonMailBridge.UI.Tests.Results
|
|||||||
}
|
}
|
||||||
|
|
||||||
public HomeResult CheckIfEnterUsernameAndEnterPasswordErrorMsgsAreDisplayed()
|
public HomeResult CheckIfEnterUsernameAndEnterPasswordErrorMsgsAreDisplayed()
|
||||||
{
|
{
|
||||||
Assert.That(EnterEmailOrUsernameErrorText.IsAvailable && EnterPasswordErrorText.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => EnterEmailOrUsernameErrorText.IsAvailable && EnterPasswordErrorText.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HomeResult CheckIfDsabledAccountErrorIsDisplayed()
|
public HomeResult CheckIfDsabledAccountErrorIsDisplayed()
|
||||||
{
|
{
|
||||||
Assert.That(AccountDisabledErrorText.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => AccountDisabledErrorText.IsAvailable);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HomeResult CheckIfDelinquentAccountErrorIsDisplayed()
|
|
||||||
{
|
|
||||||
Assert.That(AccountDelinquentErrorText.IsAvailable, Is.True);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HomeResult CheckIfNotificationTextIsShown()
|
public HomeResult CheckIfNotificationTextIsShown()
|
||||||
{
|
{
|
||||||
Assert.That(AlreadySignedInText.IsAvailable, Is.True);
|
RetryHelper.Eventually(() => AlreadySignedInText.IsAvailable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HomeResult CheckIfSplitAddressesIsDisabledByDefault()
|
public HomeResult CheckIfSplitAddressesIsDisabledByDefault()
|
||||||
{
|
{
|
||||||
Assert.That(SplitAddressesToggle.IsToggled, Is.False);
|
RetryHelper.Eventually(() =>
|
||||||
|
{
|
||||||
|
bool isNotToggled = SplitAddressesToggle.IsToggled == null || !(bool)SplitAddressesToggle.IsToggled;
|
||||||
|
return isNotToggled;
|
||||||
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
# This is a folder where all files that are needed for debugging purposes will be saved in regards to failing tests
|
||||||
@ -1,11 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Management.Automation;
|
||||||
|
using System.Management.Automation.Runspaces;
|
||||||
using FlaUI.Core.AutomationElements;
|
using FlaUI.Core.AutomationElements;
|
||||||
using FlaUI.Core;
|
using FlaUI.Core;
|
||||||
using FlaUI.UIA3;
|
using FlaUI.UIA3;
|
||||||
using ProtonMailBridge.UI.Tests.TestsHelper;
|
using ProtonMailBridge.UI.Tests.TestsHelper;
|
||||||
using FlaUI.Core.Input;
|
using FlaUI.Core.Input;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Drawing.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FlaUI.Core.Tools;
|
||||||
|
|
||||||
namespace ProtonMailBridge.UI.Tests
|
namespace ProtonMailBridge.UI.Tests
|
||||||
{
|
{
|
||||||
@ -17,13 +22,57 @@ namespace ProtonMailBridge.UI.Tests
|
|||||||
protected static Window Window;
|
protected static Window Window;
|
||||||
protected static Window ChromeWindow;
|
protected static Window ChromeWindow;
|
||||||
protected static Window FileExplorerWindow;
|
protected static Window FileExplorerWindow;
|
||||||
|
protected static Runspace? myRunSpace;
|
||||||
|
protected static string? bridgeDownloadURL;
|
||||||
|
protected static string downloadEnvVariable = "BRIDGE_DOWNLOAD_URL";
|
||||||
|
private static readonly DebugTests debugTests = new();
|
||||||
|
protected static string atlasEnvironment = "https://mail-api.proton.pink/";
|
||||||
|
|
||||||
|
|
||||||
protected static void ClientCleanup()
|
protected static void ClientCleanup()
|
||||||
{
|
{
|
||||||
App.Kill();
|
var outcome = TestContext.CurrentContext.Result.Outcome.Status;
|
||||||
App.Dispose();
|
if (outcome == NUnit.Framework.Interfaces.TestStatus.Failed)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
debugTests.TakeScreenshot();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
App.Kill();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
App.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
// Give some time to properly exit the app
|
// Give some time to properly exit the app
|
||||||
Thread.Sleep(10000);
|
Thread.Sleep(10000);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RemoveBridgeCredentials();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine($"Failed to remove Bridge credentials: {ex}");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void switchToFileExplorerWindow()
|
public static void switchToFileExplorerWindow()
|
||||||
@ -60,28 +109,117 @@ namespace ProtonMailBridge.UI.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cast the found element to a Window object
|
// Cast the found element to a Window object
|
||||||
ChromeWindow = _chromeWindow.AsWindow();
|
ChromeWindow = _chromeWindow.AsWindow();
|
||||||
|
|
||||||
// Focus on the Chrome window
|
// Focus on the Chrome window
|
||||||
ChromeWindow.Focus();
|
ChromeWindow.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void RefreshWindow(TimeSpan? timeout = null)
|
||||||
|
{
|
||||||
|
Window = null;
|
||||||
|
TimeSpan refreshTimeout = timeout ?? TestData.ThirtySecondsTimeout;
|
||||||
|
RetryResult<Window> retry = Retry.WhileNull(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Window = App.GetMainWindow(new UIA3Automation(), refreshTimeout);
|
||||||
|
}
|
||||||
|
catch (System.TimeoutException)
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
return Window;
|
||||||
|
},
|
||||||
|
refreshTimeout, TestData.RetryInterval);
|
||||||
|
|
||||||
|
if (!retry.Success)
|
||||||
|
{
|
||||||
|
Assert.Fail($"Failed to refresh window in {refreshTimeout.TotalSeconds} seconds.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void LaunchApp()
|
public static void LaunchApp()
|
||||||
{
|
{
|
||||||
|
TestContext.Out.WriteLine($"[RUNNING TEST] {TestContext.CurrentContext.Test.FullName}");
|
||||||
|
System.Environment.SetEnvironmentVariable("BRIDGE_HOST_URL", $"{atlasEnvironment}");
|
||||||
string appExecutable = TestData.AppExecutable;
|
string appExecutable = TestData.AppExecutable;
|
||||||
Application.Launch(appExecutable);
|
Application.Launch(appExecutable);
|
||||||
Wait.UntilInputIsProcessed(TestData.FiveSecondsTimeout);
|
Wait.UntilInputIsProcessed(TestData.FiveSecondsTimeout);
|
||||||
App = Application.Attach("bridge-gui.exe");
|
App = Application.Attach("bridge-gui.exe");
|
||||||
|
RefreshWindow(TestData.OneMinuteTimeout);
|
||||||
|
Window.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
try
|
private static RetryResult<bool> WaitUntilAppIsRunning()
|
||||||
|
{
|
||||||
|
RetryResult<bool> retry = Retry.WhileFalse(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
Process[] pname = Process.GetProcessesByName("Proton Mail Bridge");
|
||||||
|
return pname.Length > 0;
|
||||||
|
},
|
||||||
|
TimeSpan.FromSeconds(30), TestData.RetryInterval);
|
||||||
|
|
||||||
|
return retry;
|
||||||
|
}
|
||||||
|
public static void CreateRunSpace()
|
||||||
|
{
|
||||||
|
bridgeDownloadURL = Environment.GetEnvironmentVariable($"{downloadEnvVariable}");
|
||||||
|
myRunSpace = RunspaceFactory.CreateRunspace();
|
||||||
|
myRunSpace.Open();
|
||||||
|
Pipeline cmd = myRunSpace.CreatePipeline($"New-Item env:{downloadEnvVariable} -Value {bridgeDownloadURL} -Force");
|
||||||
|
cmd.Invoke();
|
||||||
|
cmd = myRunSpace.CreatePipeline(@"Set-Location $env:CI_PROJECT_DIR\tests\e2e\ui_tests\windows_os\InstallerScripts");
|
||||||
|
cmd.Invoke();
|
||||||
|
cmd = myRunSpace.CreatePipeline(@"Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser");
|
||||||
|
cmd.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<PSObject>? InstallBridge()
|
||||||
|
{
|
||||||
|
CreateRunSpace();
|
||||||
|
if (myRunSpace is not null)
|
||||||
{
|
{
|
||||||
Window = App.GetMainWindow(new UIA3Automation(), TestData.ThirtySecondsTimeout);
|
Pipeline cmd = myRunSpace.CreatePipeline("Get-Location");
|
||||||
|
cmd.Invoke();
|
||||||
|
cmd = myRunSpace.CreatePipeline(@".\Get-BridgeInstaller.ps1");
|
||||||
|
var objects = cmd.Invoke();
|
||||||
|
|
||||||
|
return objects;
|
||||||
}
|
}
|
||||||
catch (System.TimeoutException)
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<PSObject>? UninstallBridge()
|
||||||
|
{
|
||||||
|
CreateRunSpace();
|
||||||
|
if (myRunSpace is not null)
|
||||||
{
|
{
|
||||||
Assert.Fail("Failed to get window of application!");
|
Pipeline cmd = myRunSpace.CreatePipeline(@".\Remove-Bridge.ps1");
|
||||||
|
var objects = cmd.Invoke();
|
||||||
|
|
||||||
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<PSObject>? RemoveBridgeCredentials()
|
||||||
|
{
|
||||||
|
CreateRunSpace();
|
||||||
|
if (myRunSpace is not null)
|
||||||
|
{
|
||||||
|
Pipeline cmd = myRunSpace.CreatePipeline(@".\Remove-BridgeCredentials.ps1");
|
||||||
|
var objects = cmd.Invoke();
|
||||||
|
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_homeResult.CheckIfLoggedIn();
|
_homeResult.CheckIfLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
public void OpenGoToHelpTopics()
|
public void OpenGoToHelpTopics()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -46,7 +46,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_helpMenuWindow.ClickBackFromHelpMenu();
|
_helpMenuWindow.ClickBackFromHelpMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
public void CheckForUpdates()
|
public void CheckForUpdates()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -58,7 +58,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
Wait.UntilInputIsProcessed(TimeSpan.FromSeconds(1));
|
Wait.UntilInputIsProcessed(TimeSpan.FromSeconds(1));
|
||||||
_helpMenuWindow.ClickBackFromHelpMenu();
|
_helpMenuWindow.ClickBackFromHelpMenu();
|
||||||
}
|
}
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
public void OpenLogs()
|
public void OpenLogs()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -134,7 +134,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
[TearDown]
|
[TearDown]
|
||||||
public void TestCleanup()
|
public void TestCleanup()
|
||||||
{
|
{
|
||||||
_mainWindow.RemoveAccount();
|
_mainWindow.RemoveAccountTestCleanup();
|
||||||
ClientCleanup();
|
ClientCleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,25 +3,39 @@ using ProtonMailBridge.UI.Tests.TestsHelper;
|
|||||||
using ProtonMailBridge.UI.Tests.Windows;
|
using ProtonMailBridge.UI.Tests.Windows;
|
||||||
using ProtonMailBridge.UI.Tests.Results;
|
using ProtonMailBridge.UI.Tests.Results;
|
||||||
using FlaUI.Core.Input;
|
using FlaUI.Core.Input;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||||
|
|
||||||
namespace ProtonMailBridge.UI.Tests.Tests
|
namespace ProtonMailBridge.UI.Tests.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
[Category("LoginLogoutTests")]
|
||||||
public class LoginLogoutTests : TestSession
|
public class LoginLogoutTests : TestSession
|
||||||
{
|
{
|
||||||
private readonly LoginWindow _loginWindow = new();
|
private readonly LoginWindow _loginWindow = new();
|
||||||
private readonly HomeWindow _mainWindow = new();
|
private readonly HomeWindow _mainWindow = new();
|
||||||
private readonly HomeResult _homeResult = new();
|
private readonly HomeResult _homeResult = new();
|
||||||
private readonly string FreeAccountErrorText = "Bridge is exclusive to our mail paid plans. Upgrade your account to use Bridge.";
|
private readonly string FreeAccountErrorText = "Bridge is exclusive to our mail paid plans. Upgrade your account to use Bridge.";
|
||||||
|
private bool removeAccount = true;
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Category("NOOP")]
|
||||||
|
public void Noop()
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine("NoOP");
|
||||||
|
removeAccount = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Category("DebugTests")]
|
||||||
public void LoginAsFreeUser()
|
public void LoginAsFreeUser()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetFreeUser());
|
_loginWindow.SignIn(TestUserData.GetFreeUser());
|
||||||
_homeResult.CheckIfFreeAccountErrorIsDisplayed(FreeAccountErrorText);
|
_homeResult.CheckIfFreeAccountErrorIsDisplayed(FreeAccountErrorText);
|
||||||
|
removeAccount = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Category("DebugTests")]
|
||||||
public void LoginAsPaidUser()
|
public void LoginAsPaidUser()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -46,13 +60,8 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
[Test]
|
[Test]
|
||||||
public void AddAliasAddress()
|
public void AddAliasAddress()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
|
||||||
_homeResult.CheckIfLoggedIn();
|
|
||||||
_mainWindow.AddNewAccount();
|
|
||||||
_loginWindow.SignIn(TestUserData.GetAliasUser());
|
_loginWindow.SignIn(TestUserData.GetAliasUser());
|
||||||
_homeResult.CheckIfAccountAlreadySignedInIsDisplayed();
|
_homeResult.CheckIfLoggedIn();
|
||||||
_homeResult.ClickOkToAcknowledgeAccountAlreadySignedIn();
|
|
||||||
_loginWindow.ClickCancelToSignIn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -83,6 +92,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_loginWindow.SignIn(TestUserData.GetIncorrectCredentialsUser());
|
_loginWindow.SignIn(TestUserData.GetIncorrectCredentialsUser());
|
||||||
_homeResult.CheckIfIncorrectCredentialsErrorIsDisplayed();
|
_homeResult.CheckIfIncorrectCredentialsErrorIsDisplayed();
|
||||||
_loginWindow.ClickCancelToSignIn();
|
_loginWindow.ClickCancelToSignIn();
|
||||||
|
removeAccount = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, Order (1)]
|
[Test, Order (1)]
|
||||||
@ -91,8 +101,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_loginWindow.SignIn(TestUserData.GetEmptyCredentialsUser());
|
_loginWindow.SignIn(TestUserData.GetEmptyCredentialsUser());
|
||||||
_homeResult.CheckIfEnterUsernameAndEnterPasswordErrorMsgsAreDisplayed();
|
_homeResult.CheckIfEnterUsernameAndEnterPasswordErrorMsgsAreDisplayed();
|
||||||
_loginWindow.ClickCancelToSignIn();
|
_loginWindow.ClickCancelToSignIn();
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
removeAccount = false;
|
||||||
_homeResult.CheckIfLoggedIn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -114,14 +123,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_loginWindow.SignIn(TestUserData.GetDisabledUser());
|
_loginWindow.SignIn(TestUserData.GetDisabledUser());
|
||||||
_homeResult.CheckIfDsabledAccountErrorIsDisplayed();
|
_homeResult.CheckIfDsabledAccountErrorIsDisplayed();
|
||||||
_loginWindow.ClickCancelToSignIn();
|
_loginWindow.ClickCancelToSignIn();
|
||||||
}
|
removeAccount = false;
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void AddDeliquentAccount()
|
|
||||||
{
|
|
||||||
_loginWindow.SignIn(TestUserData.GetDeliquentUser());
|
|
||||||
_homeResult.CheckIfDelinquentAccountErrorIsDisplayed();
|
|
||||||
_loginWindow.ClickCancelToSignIn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -143,14 +145,18 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void TestInitialize()
|
public void TestInitialize()
|
||||||
{
|
{
|
||||||
LaunchApp();
|
LaunchApp();
|
||||||
|
Thread.Sleep(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public void TestCleanup()
|
public void TestCleanup()
|
||||||
{
|
{
|
||||||
_mainWindow.RemoveAccount();
|
if (removeAccount)
|
||||||
|
{
|
||||||
|
_mainWindow.RemoveAccountTestCleanup();
|
||||||
|
}
|
||||||
ClientCleanup();
|
ClientCleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ using FlaUI.UIA3;
|
|||||||
namespace ProtonMailBridge.UI.Tests.Tests
|
namespace ProtonMailBridge.UI.Tests.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
[Category("SettingsMenuTests")]
|
||||||
public class SettingsMenuTests : TestSession
|
public class SettingsMenuTests : TestSession
|
||||||
{
|
{
|
||||||
private readonly LoginWindow _loginWindow = new();
|
private readonly LoginWindow _loginWindow = new();
|
||||||
@ -175,7 +176,6 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_settingsMenuWindow.ClickSettingsButton();
|
_settingsMenuWindow.ClickSettingsButton();
|
||||||
_settingsMenuWindow.ExpandAdvancedSettings();
|
_settingsMenuWindow.ExpandAdvancedSettings();
|
||||||
Mouse.Scroll(-20);
|
Mouse.Scroll(-20);
|
||||||
//Thread.Sleep(3000);
|
|
||||||
_settingsMenuResults.CollectUsageDiagnosticsIsEnabledByDefault();
|
_settingsMenuResults.CollectUsageDiagnosticsIsEnabledByDefault();
|
||||||
Mouse.Scroll(20);
|
Mouse.Scroll(20);
|
||||||
_settingsMenuWindow.CollapseAdvancedSettings();
|
_settingsMenuWindow.CollapseAdvancedSettings();
|
||||||
@ -189,8 +189,10 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_settingsMenuWindow.ClickSettingsButton();
|
_settingsMenuWindow.ClickSettingsButton();
|
||||||
_settingsMenuWindow.ExpandAdvancedSettings();
|
_settingsMenuWindow.ExpandAdvancedSettings();
|
||||||
Mouse.Scroll(-20);
|
Mouse.Scroll(-20);
|
||||||
|
Thread.Sleep(5000);
|
||||||
_settingsMenuWindow.DisableAndEnableCollectUsageDiagnostics();
|
_settingsMenuWindow.DisableAndEnableCollectUsageDiagnostics();
|
||||||
Mouse.Scroll(20);
|
Mouse.Scroll(20);
|
||||||
|
Thread.Sleep(5000);
|
||||||
_settingsMenuWindow.CollapseAdvancedSettings();
|
_settingsMenuWindow.CollapseAdvancedSettings();
|
||||||
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
||||||
}
|
}
|
||||||
@ -270,7 +272,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
public void ChangeLocationSwitchBackToDefaultAndDeleteOldLocalCacheLocation()
|
public void ChangeLocationSwitchBackToDefaultAndDeleteOldLocalCacheLocation()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -284,7 +286,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
_settingsMenuWindow.ClickBackFromSettingsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
public void ExportTlsCertificatesVerifyExportAndDeleteTheExportFolder()
|
public void ExportTlsCertificatesVerifyExportAndDeleteTheExportFolder()
|
||||||
{
|
{
|
||||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||||
@ -325,7 +327,15 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
[TearDown]
|
[TearDown]
|
||||||
public void TestCleanup()
|
public void TestCleanup()
|
||||||
{
|
{
|
||||||
_mainWindow.RemoveAccount();
|
try
|
||||||
|
{
|
||||||
|
_mainWindow.RemoveAccountTestCleanup();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
TestContext.Out.WriteLine("Teardown error on test account cleanup: " + ex);
|
||||||
|
}
|
||||||
|
|
||||||
ClientCleanup();
|
ClientCleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
LaunchApp();
|
LaunchApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test, Category("TemporarilyExcluded")]
|
||||||
[Category("ZeroPercentUpdateRollout")]
|
|
||||||
public void EnableBetaAccessVerifyBetaIsEnabledVerifyNotificationAndRestartBridge()
|
public void EnableBetaAccessVerifyBetaIsEnabledVerifyNotificationAndRestartBridge()
|
||||||
{
|
{
|
||||||
_zeroPercentWindow.ClickStartSetupButton();
|
_zeroPercentWindow.ClickStartSetupButton();
|
||||||
@ -52,6 +51,7 @@ namespace ProtonMailBridge.UI.Tests.Tests
|
|||||||
public void TestCleanup()
|
public void TestCleanup()
|
||||||
{
|
{
|
||||||
ClientCleanup();
|
ClientCleanup();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
tests/e2e/ui_tests/windows_os/TestsHelper/DebugTests.cs
Normal file
24
tests/e2e/ui_tests/windows_os/TestsHelper/DebugTests.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using FlaUI.Core.Capturing;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ProtonMailBridge.UI.Tests.TestsHelper
|
||||||
|
{
|
||||||
|
internal class DebugTests
|
||||||
|
{
|
||||||
|
public void TakeScreenshot()
|
||||||
|
{
|
||||||
|
string testName = TestContext.CurrentContext.Test.Name;
|
||||||
|
string Timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
|
||||||
|
string ScreenshotName = "Screenshot_" + testName + "_" + Timestamp + ".png";
|
||||||
|
string Query = "%CI_PROJECT_DIR%\\tests\\e2e\\ui_tests\\windows_os\\Results\\artifacts\\Screenshots\\" + ScreenshotName;
|
||||||
|
string ScreenshotLocation = Environment.ExpandEnvironmentVariables(Query);
|
||||||
|
var ScreenshotFile = Capture.Screen();
|
||||||
|
ScreenshotFile.ToFile(ScreenshotLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
tests/e2e/ui_tests/windows_os/TestsHelper/RetryHelper.cs
Normal file
43
tests/e2e/ui_tests/windows_os/TestsHelper/RetryHelper.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ProtonMailBridge.UI.Tests.TestsHelper
|
||||||
|
{
|
||||||
|
public class RetryHelper
|
||||||
|
{
|
||||||
|
public static void Eventually(Func<bool> condition, int retries = 10, int delaySeconds = 5)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < retries; i++)
|
||||||
|
{
|
||||||
|
if (condition()) return;
|
||||||
|
|
||||||
|
Thread.Sleep(TimeSpan.FromSeconds(delaySeconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EventuallyAction(Action action, int retries = 20, int delaySeconds = 2)
|
||||||
|
{
|
||||||
|
Exception? lastException = null;
|
||||||
|
for (int i = 0; i < retries; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
return;
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
lastException = e;
|
||||||
|
Thread.Sleep(TimeSpan.FromSeconds(delaySeconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Eventually failed after retries", lastException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,60 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using FlaUI.Core.AutomationElements;
|
using FlaUI.Core.AutomationElements;
|
||||||
using FlaUI.Core.Definitions;
|
using FlaUI.Core.Definitions;
|
||||||
using FlaUI.Core.Input;
|
using FlaUI.Core.Input;
|
||||||
using FlaUI.Core.Tools;
|
using FlaUI.Core.Tools;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using ProtonMailBridge.UI.Tests.TestsHelper;
|
||||||
|
|
||||||
namespace ProtonMailBridge.UI.Tests
|
namespace ProtonMailBridge.UI.Tests
|
||||||
{
|
{
|
||||||
public class UIActions : TestSession
|
public class UIActions : TestSession
|
||||||
{
|
{
|
||||||
public AutomationElement AccountView => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane));
|
public AutomationElement AccountView => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane));
|
||||||
|
|
||||||
|
protected dynamic WaitUntilElementExistsByName(string name, TimeSpan time)
|
||||||
|
{
|
||||||
|
WaitForElement(() =>
|
||||||
|
{
|
||||||
|
RefreshWindow();
|
||||||
|
return Window.FindFirstDescendant(cf => cf.ByName(name)) != null;
|
||||||
|
}, time, name);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
protected AutomationElement ElementByName(string name, TimeSpan? timeout = null)
|
||||||
|
{
|
||||||
|
WaitUntilElementExistsByName(name, timeout ?? TestData.TenSecondsTimeout);
|
||||||
|
return Window.FindFirstDescendant(cf => cf.ByName(name));
|
||||||
|
}
|
||||||
|
private void WaitForElement(Func<bool> function, TimeSpan time, string selector, string customMessage = null)
|
||||||
|
{
|
||||||
|
RetryResult<bool> retry = Retry.WhileFalse(
|
||||||
|
() => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
App.WaitWhileBusy();
|
||||||
|
return function();
|
||||||
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
time, TestData.RetryInterval);
|
||||||
|
|
||||||
|
if (!retry.Success)
|
||||||
|
{
|
||||||
|
if(customMessage == null)
|
||||||
|
{
|
||||||
|
Assert.Fail($"Failed to get {selector} element within {time.TotalSeconds} seconds.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail(customMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
private Button LogsButton => HomeButtons[9].AsButton();
|
private Button LogsButton => HomeButtons[9].AsButton();
|
||||||
private Button ReportProblemButton => HomeButtons[10].AsButton();
|
private Button ReportProblemButton => HomeButtons[10].AsButton();
|
||||||
private Button ICannotFindEmailInClient => HomeButtons[7].AsButton();
|
private Button ICannotFindEmailInClient => HomeButtons[7].AsButton();
|
||||||
private TextBox DescriptionOnWhatHappened => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Edit)).AsTextBox();
|
private TextBox DescriptionOnWhatHappened => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane)).FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane)).FindFirstDescendant(cf => cf.ByControlType(ControlType.Edit)).AsTextBox();
|
||||||
private RadioButton MissingEmails => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.RadioButton).And(cf.ByName("Old emails are missing"))).AsRadioButton();
|
private RadioButton MissingEmails => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.RadioButton).And(cf.ByName("Old emails are missing"))).AsRadioButton();
|
||||||
private RadioButton FindEmails => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.RadioButton).And(cf.ByName("Yes"))).AsRadioButton();
|
private RadioButton FindEmails => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.RadioButton).And(cf.ByName("Yes"))).AsRadioButton();
|
||||||
private CheckBox VPNSoftware => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("VPN"))).AsCheckBox();
|
private CheckBox VPNSoftware => ReportProblemPane[0].FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("VPN"))).AsCheckBox();
|
||||||
|
|||||||
@ -11,6 +11,7 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
public class HomeWindow : UIActions
|
public class HomeWindow : UIActions
|
||||||
{
|
{
|
||||||
private AutomationElement[] AccountViewButtons => AccountView.FindAllChildren(cf => cf.ByControlType(ControlType.Button));
|
private AutomationElement[] AccountViewButtons => AccountView.FindAllChildren(cf => cf.ByControlType(ControlType.Button));
|
||||||
|
|
||||||
private AutomationElement[] HomeButtons => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Button));
|
private AutomationElement[] HomeButtons => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Button));
|
||||||
private Button AddNewAccountButton => HomeButtons[6].AsButton();
|
private Button AddNewAccountButton => HomeButtons[6].AsButton();
|
||||||
private Button RemoveAccountButton => AccountViewButtons[1].AsButton();
|
private Button RemoveAccountButton => AccountViewButtons[1].AsButton();
|
||||||
@ -21,14 +22,14 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
private CheckBox SplitAddressesToggle => AccountView.FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("Split addresses toggle"))).AsCheckBox();
|
private CheckBox SplitAddressesToggle => AccountView.FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("Split addresses toggle"))).AsCheckBox();
|
||||||
private Button EnableSplitAddressButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Enable split mode"))).AsButton();
|
private Button EnableSplitAddressButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Enable split mode"))).AsButton();
|
||||||
|
|
||||||
public HomeWindow RemoveAccount()
|
public HomeWindow RemoveAccountTestCleanup()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RemoveAccountButton.Click();
|
RemoveAccountButton.Click();
|
||||||
ConfirmRemoveAccountButton.Click();
|
ConfirmRemoveAccountButton.Click();
|
||||||
}
|
}
|
||||||
catch (System.NullReferenceException)
|
catch (System.IndexOutOfRangeException)
|
||||||
{
|
{
|
||||||
ClientCleanup();
|
ClientCleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using FlaUI.Core.Definitions;
|
|||||||
using ProtonMailBridge.UI.Tests.TestsHelper;
|
using ProtonMailBridge.UI.Tests.TestsHelper;
|
||||||
using ProtonMailBridge.UI.Tests.Results;
|
using ProtonMailBridge.UI.Tests.Results;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace ProtonMailBridge.UI.Tests.Windows
|
namespace ProtonMailBridge.UI.Tests.Windows
|
||||||
{
|
{
|
||||||
@ -11,7 +12,8 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
{
|
{
|
||||||
private AutomationElement[] InputFields => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Edit));
|
private AutomationElement[] InputFields => Window.FindAllDescendants(cf => cf.ByControlType(ControlType.Edit));
|
||||||
private TextBox UsernameInput => InputFields[0].AsTextBox();
|
private TextBox UsernameInput => InputFields[0].AsTextBox();
|
||||||
private TextBox PasswordInput => InputFields[1].AsTextBox();
|
private AutomationElement PasswordGroup => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Group).And(cf.ByName("Password")));
|
||||||
|
private TextBox PasswordInput => PasswordGroup.FindFirstDescendant(cf => cf.ByControlType(ControlType.Edit)).AsTextBox();
|
||||||
private Button SignInButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Sign in"))).AsButton();
|
private Button SignInButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Sign in"))).AsButton();
|
||||||
private Button SigningInButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Signing in"))).AsButton();
|
private Button SigningInButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Signing in"))).AsButton();
|
||||||
private Button StartSetupButton => Window.FindFirstDescendant(cf => cf.ByName("Start setup")).AsButton();
|
private Button StartSetupButton => Window.FindFirstDescendant(cf => cf.ByName("Start setup")).AsButton();
|
||||||
@ -20,11 +22,17 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
private Button UnlockButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Unlock"))).AsButton();
|
private Button UnlockButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Unlock"))).AsButton();
|
||||||
private Button CancelSignIn => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Cancel"))).AsButton();
|
private Button CancelSignIn => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Cancel"))).AsButton();
|
||||||
|
|
||||||
|
private Button UnlockingButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Unlocking"))).AsButton();
|
||||||
|
|
||||||
|
private static readonly int loginTimeout = 500;
|
||||||
|
|
||||||
public LoginWindow SignIn(TestUserData user)
|
public LoginWindow SignIn(TestUserData user)
|
||||||
{
|
{
|
||||||
ClickStartSetupButton();
|
ClickStartSetupButton();
|
||||||
|
|
||||||
|
TestContext.Out.WriteLine($"Trying to login with '{user.Username}':'{user.Password}'. Attempt {i}.");
|
||||||
EnterCredentials(user);
|
EnterCredentials(user);
|
||||||
WaitForAuthorizationToComplete(60);
|
WaitForAuthorizationToComplete(loginTimeout);
|
||||||
|
|
||||||
SetUpLater?.Click();
|
SetUpLater?.Click();
|
||||||
|
|
||||||
@ -33,11 +41,9 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public LoginWindow SignInMailbox(TestUserData user)
|
public LoginWindow SignInMailbox(TestUserData user)
|
||||||
{
|
{
|
||||||
ClickStartSetupButton();
|
SignIn(user);
|
||||||
EnterCredentials(user);
|
|
||||||
Wait.UntilInputIsProcessed(TestData.TenSecondsTimeout);
|
|
||||||
EnterMailboxPassword(user);
|
EnterMailboxPassword(user);
|
||||||
Wait.UntilInputIsProcessed(TestData.TenSecondsTimeout);
|
WaitForUnlockToComplete(loginTimeout);
|
||||||
|
|
||||||
SetUpLater?.Click();
|
SetUpLater?.Click();
|
||||||
|
|
||||||
@ -59,8 +65,14 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public LoginWindow EnterCredentials(TestUserData user)
|
public LoginWindow EnterCredentials(TestUserData user)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < InputFields.Length; i++)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"---------- {InputFields[i].Name} ----------");
|
||||||
|
}
|
||||||
|
|
||||||
UsernameInput.Text = user.Username;
|
UsernameInput.Text = user.Username;
|
||||||
PasswordInput.Text = user.Password;
|
PasswordInput.Text = user.Password;
|
||||||
|
TestContext.Out.WriteLine($"Trying to sign in with username '{user.Username}' and password '{user.Password}'");
|
||||||
SignInButton.Click();
|
SignInButton.Click();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -68,6 +80,7 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
public LoginWindow EnterMailboxPassword(TestUserData user)
|
public LoginWindow EnterMailboxPassword(TestUserData user)
|
||||||
{
|
{
|
||||||
MailboxPasswordInput.Text = user.MailboxPassword;
|
MailboxPasswordInput.Text = user.MailboxPassword;
|
||||||
|
TestContext.Out.WriteLine($"Entering mailbox password '{user.MailboxPassword}'");
|
||||||
UnlockButton.Click();
|
UnlockButton.Click();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -97,5 +110,25 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WaitForUnlockToComplete(int numOfSeconds)
|
||||||
|
{
|
||||||
|
TimeSpan timeout = TimeSpan.FromSeconds(numOfSeconds);
|
||||||
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
|
||||||
|
while (stopwatch.Elapsed < timeout)
|
||||||
|
{
|
||||||
|
//if Signing in button is not visible authorization process is finished
|
||||||
|
if (UnlockingButton == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wait.UntilInputIsProcessed();
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,7 +19,6 @@ using ProtonMailBridge.UI.Tests.TestsHelper;
|
|||||||
using Keyboard = FlaUI.Core.Input.Keyboard;
|
using Keyboard = FlaUI.Core.Input.Keyboard;
|
||||||
using Mouse = FlaUI.Core.Input.Mouse;
|
using Mouse = FlaUI.Core.Input.Mouse;
|
||||||
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
|
||||||
//using System.Windows.Forms;
|
|
||||||
using CheckBox = FlaUI.Core.AutomationElements.CheckBox;
|
using CheckBox = FlaUI.Core.AutomationElements.CheckBox;
|
||||||
using FlaUI.Core.Tools;
|
using FlaUI.Core.Tools;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -87,125 +86,127 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
private Button ResetButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Reset Bridge button"))).AsButton();
|
private Button ResetButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Reset Bridge button"))).AsButton();
|
||||||
private Button ResetAndRestartButtonInPopUp => NotificationWindow.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Reset and restart"))).AsButton();
|
private Button ResetAndRestartButtonInPopUp => NotificationWindow.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Reset and restart"))).AsButton();
|
||||||
private Button StartSetUpButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Start setup"))).AsButton();
|
private Button StartSetUpButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Start setup"))).AsButton();
|
||||||
|
|
||||||
public SettingsMenuWindow ClickSettingsButton()
|
public SettingsMenuWindow ClickSettingsButton()
|
||||||
{
|
{
|
||||||
SettingsButton.Click();
|
RetryHelper.EventuallyAction(() => SettingsButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow ClickBackFromSettingsMenu()
|
public SettingsMenuWindow ClickBackFromSettingsMenu()
|
||||||
{
|
{
|
||||||
BackToAccountViewButton.Click();
|
RetryHelper.EventuallyAction(() => BackToAccountViewButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow DisableAndEnableAutomaticUpdates()
|
public SettingsMenuWindow DisableAndEnableAutomaticUpdates()
|
||||||
{
|
{
|
||||||
AutomaticUpdates.Click();
|
RetryHelper.EventuallyAction(() => AutomaticUpdates.Click());
|
||||||
Assert.That(AutomaticUpdates.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(AutomaticUpdates.IsToggled, Is.False));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
AutomaticUpdates.Click();
|
RetryHelper.EventuallyAction(() => AutomaticUpdates.Click());
|
||||||
Assert.That(AutomaticUpdates.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(AutomaticUpdates.IsToggled, Is.True));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow DisableAndEnableOpenOnStartUp()
|
public SettingsMenuWindow DisableAndEnableOpenOnStartUp()
|
||||||
{
|
{
|
||||||
OpenOnStartUp.Click();
|
RetryHelper.EventuallyAction(() => OpenOnStartUp.Click());
|
||||||
Assert.That(OpenOnStartUp.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(OpenOnStartUp.IsToggled, Is.False));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
OpenOnStartUp.Click();
|
RetryHelper.EventuallyAction(() => OpenOnStartUp.Click());
|
||||||
Assert.That(OpenOnStartUp.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(OpenOnStartUp.IsToggled, Is.True));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow EnableAndDisableBetaAccess()
|
public SettingsMenuWindow EnableAndDisableBetaAccess()
|
||||||
{
|
{
|
||||||
BetaAccess.Click();
|
RetryHelper.EventuallyAction(() => BetaAccess.Click());
|
||||||
EnableBetaAccessButtonInPopUp.Click();
|
RetryHelper.EventuallyAction(() => EnableBetaAccessButtonInPopUp.Click());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
Assert.That(BetaAccess.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(BetaAccess.IsToggled, Is.True));
|
||||||
BetaAccess.Click();
|
RetryHelper.EventuallyAction(() => BetaAccess.Click());
|
||||||
Assert.That(BetaAccess.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(BetaAccess.IsToggled, Is.False));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow ExpandAdvancedSettings()
|
public SettingsMenuWindow ExpandAdvancedSettings()
|
||||||
{
|
{
|
||||||
AdvancedSettings.Click();
|
RetryHelper.EventuallyAction(() => AdvancedSettings.Click());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
Assert.That(AlternativeRouting != null && AlternativeRouting.IsAvailable, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(AlternativeRouting != null && AlternativeRouting.IsAvailable, Is.True));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow CollapseAdvancedSettings()
|
public SettingsMenuWindow CollapseAdvancedSettings()
|
||||||
{
|
{
|
||||||
AdvancedSettings.Click();
|
RetryHelper.EventuallyAction(() => AdvancedSettings.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow EnableAndDisableAlternativeRouting()
|
public SettingsMenuWindow EnableAndDisableAlternativeRouting()
|
||||||
{
|
{
|
||||||
AlternativeRouting.Click();
|
RetryHelper.EventuallyAction(() => AlternativeRouting.Click());
|
||||||
Assert.That(AlternativeRouting.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(AlternativeRouting.IsToggled, Is.True));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
AlternativeRouting.Click();
|
RetryHelper.EventuallyAction(() => AlternativeRouting.Click());
|
||||||
Assert.That(AlternativeRouting?.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(AlternativeRouting?.IsToggled, Is.False));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow CheckEnableAndDisableDarkMode()
|
public SettingsMenuWindow CheckEnableAndDisableDarkMode()
|
||||||
{
|
{
|
||||||
DarkMode.Click();
|
RetryHelper.EventuallyAction(() => DarkMode.Click());
|
||||||
Assert.That(DarkMode.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(DarkMode.IsToggled, Is.True));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
DarkMode.Click();
|
RetryHelper.EventuallyAction(() => DarkMode.Click());
|
||||||
Assert.That(DarkMode.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(DarkMode.IsToggled, Is.False));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow DisableAndEnableShowAllMail()
|
public SettingsMenuWindow DisableAndEnableShowAllMail()
|
||||||
{
|
{
|
||||||
ShowAllMail.Click();
|
RetryHelper.EventuallyAction(() => ShowAllMail.Click());
|
||||||
HideAllMailFolderInPopUp.Click();
|
RetryHelper.EventuallyAction(() => HideAllMailFolderInPopUp.Click());
|
||||||
Assert.That(ShowAllMail.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(ShowAllMail.IsToggled, Is.False));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
ShowAllMail.Click();
|
RetryHelper.EventuallyAction(() => ShowAllMail.Click());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
ShowAllMailFolderInPopUp.Click();
|
RetryHelper.EventuallyAction(() => ShowAllMailFolderInPopUp.Click());
|
||||||
Assert.That(ShowAllMail?.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(ShowAllMail?.IsToggled, Is.True));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow DisableAndEnableCollectUsageDiagnostics()
|
public SettingsMenuWindow DisableAndEnableCollectUsageDiagnostics()
|
||||||
{
|
{
|
||||||
CollectUsageDiagnostics.Click();
|
RetryHelper.EventuallyAction(() => CollectUsageDiagnostics.Click());
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
Assert.That(CollectUsageDiagnostics.IsToggled, Is.False);
|
RetryHelper.EventuallyAction(() => Assert.That(CollectUsageDiagnostics.IsToggled, Is.False));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
CollectUsageDiagnostics.Click();
|
RetryHelper.EventuallyAction(() => CollectUsageDiagnostics.Click());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
Assert.That(CollectUsageDiagnostics?.IsToggled, Is.True);
|
RetryHelper.EventuallyAction(() => Assert.That(CollectUsageDiagnostics?.IsToggled, Is.True));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow OpenChangeDefaultPorts()
|
public SettingsMenuWindow OpenChangeDefaultPorts()
|
||||||
{
|
{
|
||||||
ChangeDefaultPortsButton.Click();
|
RetryHelper.EventuallyAction(() => ChangeDefaultPortsButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SettingsMenuWindow CancelChangingDefaultPorts()
|
public SettingsMenuWindow CancelChangingDefaultPorts()
|
||||||
{
|
{
|
||||||
CancelDefaultPorts.Click();
|
RetryHelper.EventuallyAction(() => CancelDefaultPorts.Click());
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
private int GenerateUniqueRandomPort()
|
private int GenerateUniqueRandomPort()
|
||||||
{
|
{
|
||||||
return random.Next(MinPort, MaxPort +1);
|
return random.Next(MinPort, MaxPort + 1);
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow ChangeDefaultPorts()
|
public SettingsMenuWindow ChangeDefaultPorts()
|
||||||
{
|
{
|
||||||
ChangeDefaultPortsButton.Click();
|
RetryHelper.EventuallyAction(() => ChangeDefaultPortsButton.Click());
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
ImapPort.Click();
|
RetryHelper.EventuallyAction(() => ImapPort.Click());
|
||||||
int imapPort = GenerateUniqueRandomPort();
|
int imapPort = GenerateUniqueRandomPort();
|
||||||
int smtpPort;
|
int smtpPort;
|
||||||
|
|
||||||
@ -226,7 +227,8 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public SettingsMenuWindow SwitchBackToDefaultPorts()
|
public SettingsMenuWindow SwitchBackToDefaultPorts()
|
||||||
{
|
{
|
||||||
ChangeDefaultPortsButton.Click();
|
RetryHelper.EventuallyAction(() => ChangeDefaultPortsButton.Click());
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
ImapPort.Click();
|
ImapPort.Click();
|
||||||
ImapPort.Patterns.Value.Pattern.SetValue("");
|
ImapPort.Patterns.Value.Pattern.SetValue("");
|
||||||
@ -241,17 +243,18 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public SettingsMenuWindow OpenChangeConnectionMode()
|
public SettingsMenuWindow OpenChangeConnectionMode()
|
||||||
{
|
{
|
||||||
ChangeConnectionModeButton.Click();
|
RetryHelper.EventuallyAction(() => ChangeConnectionModeButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow CancelChangeConnectionMode()
|
public SettingsMenuWindow CancelChangeConnectionMode()
|
||||||
{
|
{
|
||||||
CancelChangeConnectionModeButton.Click();
|
RetryHelper.EventuallyAction(() => CancelChangeConnectionModeButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow ChangeConnectionMode()
|
public SettingsMenuWindow ChangeConnectionMode()
|
||||||
{
|
{
|
||||||
ImapSslMode.Click();
|
RetryHelper.EventuallyAction(() => ImapSslMode.Click());
|
||||||
|
|
||||||
SmtpSslMode.Click();
|
SmtpSslMode.Click();
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
SaveChangedConnectionMode.Click();
|
SaveChangedConnectionMode.Click();
|
||||||
@ -259,7 +262,8 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
}
|
}
|
||||||
public SettingsMenuWindow SwitchBackToDefaultConnectionMode()
|
public SettingsMenuWindow SwitchBackToDefaultConnectionMode()
|
||||||
{
|
{
|
||||||
ImapStarttlsMode.Click();
|
RetryHelper.EventuallyAction(() => ImapStarttlsMode.Click());
|
||||||
|
|
||||||
SmtpStarttlsMode.Click();
|
SmtpStarttlsMode.Click();
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
SaveChangedConnectionMode.Click();
|
SaveChangedConnectionMode.Click();
|
||||||
@ -268,7 +272,7 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public SettingsMenuWindow ConfigureLocalCache()
|
public SettingsMenuWindow ConfigureLocalCache()
|
||||||
{
|
{
|
||||||
ConfigureLocalCacheButton.Click();
|
RetryHelper.EventuallyAction(() => ConfigureLocalCacheButton.Click());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public SettingsMenuWindow CancelToConfigureLocalCache()
|
public SettingsMenuWindow CancelToConfigureLocalCache()
|
||||||
@ -319,14 +323,15 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
public SettingsMenuWindow ChangeAndSwitchBackLocalCacheLocation()
|
public SettingsMenuWindow ChangeAndSwitchBackLocalCacheLocation()
|
||||||
{
|
{
|
||||||
string? userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
|
string? userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE");
|
||||||
ChangeLocalCacheLocationButton.Click();
|
RetryHelper.EventuallyAction(() => ChangeLocalCacheLocationButton.Click());
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
FocusOnSelectCacheLocationWindow();
|
FocusOnSelectCacheLocationWindow();
|
||||||
ClickNewFolder.Click();
|
ClickNewFolder.Click();
|
||||||
Wait.UntilInputIsProcessed(TimeSpan.FromMilliseconds(2000));
|
Wait.UntilInputIsProcessed(TimeSpan.FromMilliseconds(2000));
|
||||||
Keyboard.TypeVirtualKeyCode(0x0D);
|
Keyboard.TypeVirtualKeyCode(0x0D);
|
||||||
AutomationElement pane = Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane));
|
AutomationElement pane = Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane));
|
||||||
AutomationElement pane2 = pane.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane).And(cf.ByName("Shell Folder View")));
|
AutomationElement pane2 = pane.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane).And(cf.ByName("Shell Folder View")));
|
||||||
AutomationElement list = pane2.FindFirstDescendant(cf => cf.ByControlType(ControlType.List).And(cf.ByName("Items View")));
|
AutomationElement list = pane2.FindFirstDescendant(cf => cf.ByControlType(ControlType.List).And(cf.ByName("Items View")));
|
||||||
AutomationElement listItem = list.FindFirstDescendant(cf => cf.ByControlType(ControlType.ListItem).And(cf.ByName("New folder")));
|
AutomationElement listItem = list.FindFirstDescendant(cf => cf.ByControlType(ControlType.ListItem).And(cf.ByName("New folder")));
|
||||||
TextBox folderName = listItem.FindFirstDescendant(cf => cf.ByControlType(ControlType.Edit)).AsTextBox();
|
TextBox folderName = listItem.FindFirstDescendant(cf => cf.ByControlType(ControlType.Edit)).AsTextBox();
|
||||||
@ -409,7 +414,8 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
}
|
}
|
||||||
public SettingsMenuWindow ExportAssertDeleteTLSCertificates()
|
public SettingsMenuWindow ExportAssertDeleteTLSCertificates()
|
||||||
{
|
{
|
||||||
ExportTLSCertificatesButton.Click();
|
RetryHelper.EventuallyAction(() => ExportTLSCertificatesButton.Click());
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
ClickNewFolder.Click();
|
ClickNewFolder.Click();
|
||||||
Wait.UntilInputIsProcessed(TimeSpan.FromMilliseconds(2000));
|
Wait.UntilInputIsProcessed(TimeSpan.FromMilliseconds(2000));
|
||||||
@ -472,7 +478,8 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
}
|
}
|
||||||
public SettingsMenuWindow VerifyRepairRestartsSync()
|
public SettingsMenuWindow VerifyRepairRestartsSync()
|
||||||
{
|
{
|
||||||
RepairBridgeButton.Click();
|
RetryHelper.EventuallyAction(() => RepairBridgeButton.Click());
|
||||||
|
|
||||||
RepairButtonInPopUp.Click();
|
RepairButtonInPopUp.Click();
|
||||||
bool syncRestarted = WaitForCondition(() =>
|
bool syncRestarted = WaitForCondition(() =>
|
||||||
{
|
{
|
||||||
@ -509,7 +516,7 @@ namespace ProtonMailBridge.UI.Tests.Windows
|
|||||||
|
|
||||||
public SettingsMenuWindow VerifyResetAndRestartBridge()
|
public SettingsMenuWindow VerifyResetAndRestartBridge()
|
||||||
{
|
{
|
||||||
ResetButton.Click();
|
RetryHelper.EventuallyAction(() => ResetButton.Click());
|
||||||
ResetAndRestartButtonInPopUp.Click();
|
ResetAndRestartButtonInPopUp.Click();
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
LaunchApp();
|
LaunchApp();
|
||||||
|
|||||||
Reference in New Issue
Block a user