/*
* Copyright (c) 2026 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see .
*/
using System;
using System.Threading;
using System.Collections.Generic;
using FlaUI.Core.Input;
using NUnit.Framework;
using ProtonVPN.UI.Tests.Enums;
using ProtonVPN.UI.Tests.UiTools;
using ProtonVPN.UI.Tests.TestsHelper;
namespace ProtonVPN.UI.Tests.Robots;
public class HomeRobot
{
protected Element EmptyIpAddress = Element.ByName("Your IP address").And(Element.ByName("-"));
protected Element EmptyCountry = Element.ByName("Country").And(Element.ByName("-"));
protected Element EmptyProvider = Element.ByName("Provider").And(Element.ByName("-"));
protected Element UnprotectedLabel = Element.ByName("Unprotected");
protected Element ConnectingLabel = Element.ByName("Connecting");
protected Element ProtectedLabel = Element.ByName("Protected");
protected Element CancelConnectionButton = Element.ByName("Cancel");
protected Element GetStartedButton = Element.ByName("Get started");
protected Element ConnectionDetailsProtocol = Element.ByAutomationId("ShowProtocolFlyoutButton");
protected Element ChangeProtocolButton = Element.ByAutomationId("ChangeProtocolFlyoutButton");
protected Element KebabMenuButton = Element.ByAutomationId("TitleBarMenuButton");
protected Element HelpButton = Element.ByAutomationId("HelpMenu");
protected Element KebabMenuSettingsItem = Element.ByAutomationId("KebabMenuSettingsItem");
protected Element KebabMenuExitItem = Element.ByAutomationId("KebabMenuExitItem");
protected Element ExitButton = Element.ByName("Exit");
protected Element MaximizeClientSizeButton = Element.ByAutomationId("Maximize");
protected Element RestoreClientSizeButton = Element.ByAutomationId("Restore");
protected Element CloseClientButton = Element.ByAutomationId("Close");
protected Element MinimizeClientButton = Element.ByAutomationId("Minimize");
protected Element ConnectionCardTitle = Element.ByAutomationId("ConnectionCardTitle");
protected Element ConnectionCardDescription = Element.ByAutomationId("ConnectionCardDescription");
protected Element ConnectionCardP2PTag = Element.ByAutomationId("ConnectionCardP2PTag");
protected Element ConnectionCardTorTag = Element.ByAutomationId("ConnectionCardTorTag");
protected Element ConnectionCardFreeConnectionsTagline = Element.ByAutomationId("ConnectionCardFreeConnectionsTagline");
protected Element ConnectionCardConnectButton = Element.ByAutomationId("ConnectionCardConnectButton");
protected Element ConnectionCardCancelButton = Element.ByAutomationId("ConnectionCardCancelButton");
protected Element ConnectionCardDisconnectButton = Element.ByAutomationId("ConnectionCardDisconnectButton");
protected Element ConnectionCardChangeServerButton = Element.ByAutomationId("ConnectionCardChangeServerButton");
protected Element ConnectionCardChangeServerTimeoutButton = Element.ByAutomationId("ConnectionCardChangeServerTimeoutButton");
protected Element ConnectionCardUpsellBanner = Element.ByAutomationId("ConnectionCardUpsellBanner");
protected Element NotTheCountryWantedLabel = Element.ByName("Not the country you wanted?");
protected Element UpgradeYourServerLabel = Element.ByName("Upgrade to choose any server.");
protected Element ServerChangesUpsellLabel = Element.ByName("Get unlimited server changes with VPN Plus.");
protected Element UpgradeButton = Element.ByName("Upgrade");
protected Element DefaultConnectionSelectorButton = Element.ByAutomationId("DefaultConnectionSelectorButton");
protected Element DefaultConnectionDropdown = Element.ByAutomationId("DefaultConnectionDropdown");
protected Element FastestCountryOption = Element.ByName("Fastest country");
protected Element RandomCountryOption = Element.ByName("Random country");
protected Element LastConnectionOption = Element.ByName("Last connection");
protected Element ProtectedLabelAdvancedKillSwitch = Element.ByName("Advanced kill switch activated");
protected Element ConnectionErrorPanel = Element.ByAutomationId("ConnectionErrorPanel");
protected Element WireGuardConnectionErrorPanelTitle => ConnectionErrorPanel.FindChild(Element.ByName("Connection failed"));
protected Element WireGuardConnectionErrorPanelDescription => ConnectionErrorPanel.FindChild(Element.ByName("Your device's WireGuard adapter is in use. Disconnect from any other VPN running on your device, then try again."));
protected Element ConnectionErrorPanelTryAgainButton => ConnectionErrorPanel.FindChild(Element.ByName("Try again"));
protected Element ConnectionErrorPanelCloseButton => ConnectionErrorPanel.FindChild(Element.ByName("Close"));
protected Element ShowIpFlyoutButton => Element.ByAutomationId("ShowIpFlyoutButton");
public HomeRobot DismissWelcomeModal()
{
Thread.Sleep(TestConstants.AnimationDelay);
GetStartedButton.ClickUntilElementDisappears();
Thread.Sleep(TestConstants.AnimationDelay);
return this;
}
public HomeRobot ClickOnConnectionCardTitle()
{
ConnectionCardTitle.Click();
return this;
}
public string? GetVpnServerIp()
{
return ShowIpFlyoutButton.GetAutomationElementName();
}
public HomeRobot ConnectViaConnectionCard(TimeSpan? retryIntervalOverload = null)
{
ConnectionCardConnectButton.Click(retryIntervalOverload);
return this;
}
public HomeRobot CancelConnection(TimeSpan? retryIntervalOverload = null)
{
ConnectionCardCancelButton.ClickUntilElementDisappears(retryIntervalOverload);
return this;
}
public HomeRobot Disconnect()
{
ConnectionCardDisconnectButton.Click();
return this;
}
public HomeRobot ClickOnProtocolConnectionDetails()
{
ConnectionDetailsProtocol.Click();
return this;
}
public HomeRobot ClickChangeProtocolButton()
{
ChangeProtocolButton.Click();
// Remove when VPNWIN-2599 is implemented.
Thread.Sleep(TestConstants.AnimationDelay);
return this;
}
public HomeRobot ExpandKebabMenuButton()
{
KebabMenuButton.Click();
// Remove when VPNWIN-2599 is implemented.
Thread.Sleep(TestConstants.AnimationDelay);
return this;
}
public HomeRobot ClickOnHelpButton()
{
HelpButton.DoubleClick();
return this;
}
public HomeRobot NavigateToSettingsViaKebabMenu()
{
KebabMenuSettingsItem.DoubleClick();
return this;
}
public HomeRobot ExitViaKebabMenu()
{
KebabMenuExitItem.DoubleClick();
return this;
}
public HomeRobot ExitViaKebabMenuWithConfirmation()
{
KebabMenuExitItem.DoubleClick();
ExitButton.Click();
return this;
}
public HomeRobot ChangeServer()
{
ConnectionCardChangeServerButton.Click();
return this;
}
public HomeRobot ClickLockedChangedServer()
{
ConnectionCardChangeServerTimeoutButton.Click();
return this;
}
public HomeRobot CloseClientViaCloseButton()
{
CloseClientButton.Click();
return this;
}
public HomeRobot MinimizeClientViaMinimizeButton()
{
MinimizeClientButton.Click();
return this;
}
public HomeRobot MaximizeClientSizeViaMaximizeButton()
{
MaximizeClientSizeButton.Click();
return this;
}
public HomeRobot RestoreClientSizeViaRestoreButton()
{
RestoreClientSizeButton.Click();
return this;
}
public HomeRobot SelectDefaultConnectionOption(VpnConnectionOption option)
{
DefaultConnectionSelectorButton.Click();
Thread.Sleep(TestConstants.AnimationDelay);
string optionName = option switch
{
VpnConnectionOption.Fastest => "Fastest country",
VpnConnectionOption.Random => "Random country",
VpnConnectionOption.Last => "Last connection",
_ => throw new NotImplementedException($"VpnConnectionOption '{option}' is not supported on the home page ComboBox."),
};
Element.ByName(optionName).Click();
Thread.Sleep(TestConstants.AnimationDelay);
return this;
}
public HomeRobot SelectDefaultConnectionCountry(string countryName, string? specificInfo = null)
{
DefaultConnectionSelectorButton.Click();
Thread.Sleep(TestConstants.AnimationDelay);
DefaultConnectionDropdown.SelectDropdownItem(countryName, specificInfo);
return this;
}
public HomeRobot CloseConnectionError()
{
ConnectionErrorPanelCloseButton.Click();
return this;
}
public class Verifications : HomeRobot
{
public Verifications IsLocationDetailsPanelEmpty()
{
EmptyIpAddress.WaitUntilDisplayed();
EmptyCountry.WaitUntilDisplayed();
EmptyProvider.WaitUntilDisplayed();
return this;
}
public Verifications AreLocationDetailsShown()
{
EmptyIpAddress.DoesNotExist();
EmptyCountry.DoesNotExist();
EmptyProvider.DoesNotExist();
return this;
}
public Verifications IsWelcomeModalDisplayed()
{
GetStartedButton.WaitUntilDisplayed(TestConstants.TwoMinutesTimeout);
return this;
}
public Verifications IsDisconnected(TimeSpan? timeout = null)
{
timeout ??= TestConstants.ThirtySecondsTimeout;
UnprotectedLabel.WaitUntilDisplayed(timeout);
ConnectionCardConnectButton.WaitUntilDisplayed(timeout);
return this;
}
public Verifications IsWireGuardErrorDisplayed()
{
WireGuardConnectionErrorPanelTitle.WaitUntilDisplayed(TestConstants.OneMinuteTimeout);
WireGuardConnectionErrorPanelDescription.WaitUntilDisplayed(TestConstants.ThirtySecondsTimeout);
ConnectionErrorPanelTryAgainButton.WaitUntilDisplayed(TestConstants.ThirtySecondsTimeout);
ConnectionErrorPanelCloseButton.WaitUntilDisplayed(TestConstants.ThirtySecondsTimeout);
return this;
}
public Verifications IsAdvancedKillSwitchActivated(bool isExpectedToBeActive = true)
{
if (isExpectedToBeActive)
{
ProtectedLabelAdvancedKillSwitch.WaitUntilDisplayed();
}
else
{
ProtectedLabelAdvancedKillSwitch.DoesNotExist();
}
ConnectionCardConnectButton.WaitUntilDisplayed();
return this;
}
public Verifications AssertAllVpnConnectionOptions()
{
DefaultConnectionSelectorButton.Click();
Thread.Sleep(TestConstants.AnimationDelay);
FastestCountryOption.WaitUntilDisplayed();
RandomCountryOption.WaitUntilDisplayed();
LastConnectionOption.WaitUntilDisplayed();
Mouse.Click();
return this;
}
public Verifications IsConnecting()
{
ConnectingLabel.WaitUntilDisplayed(TestConstants.OneMinuteTimeout, TestConstants.MoreFrequentRetryInterval);
return this;
}
public Verifications IsConnected()
{
ProtectedLabel.WaitUntilDisplayed(TestConstants.OneMinuteTimeout);
ConnectionCardDisconnectButton.WaitUntilDisplayed(TestConstants.ThirtySecondsTimeout);
return this;
}
public Verifications IsChangeServerNotLocked()
{
ConnectionCardConnectButton.DoesNotExist();
ConnectionCardChangeServerTimeoutButton.DoesNotExist();
ConnectionCardChangeServerButton.WaitUntilDisplayed();
return this;
}
public Verifications IsChangeServerLocked()
{
ConnectionCardChangeServerTimeoutButton.WaitUntilDisplayed();
return this;
}
public Verifications IsNotTheCountryWantedBannerDisplayed()
{
NotTheCountryWantedLabel.WaitUntilDisplayed();
UpgradeYourServerLabel.WaitUntilDisplayed();
return this;
}
public Verifications IsUnlimitedServersChangesUpsellDisplayed()
{
ServerChangesUpsellLabel.WaitUntilDisplayed();
UpgradeButton.WaitUntilDisplayed();
return this;
}
public Verifications IsConnectionCardFreeConnectionsTaglineDisplayed()
{
ConnectionCardFreeConnectionsTagline.WaitUntilDisplayed();
return this;
}
public Verifications IsP2PConnection()
{
ConnectionCardP2PTag.WaitUntilDisplayed();
return this;
}
public Verifications IsTorConnection()
{
ConnectionCardTorTag.WaitUntilDisplayed();
return this;
}
public Verifications ConnectionCardTitleEquals(string title)
{
ConnectionCardTitle.TextEquals(title);
return this;
}
public Verifications ConnectionCardDescriptionContainsOneOf(List countries)
{
ConnectionCardDescription.TextContainsOneOf(countries);
return this;
}
public Verifications ConnectionCardDescriptionContains(string description)
{
ConnectionCardDescription.TextContains(description);
return this;
}
public Verifications IsProtocolDisplayed(Protocol protocol)
{
switch (protocol)
{
case Protocol.WireGuardUdp:
ConnectionDetailsProtocol.TextEquals("WireGuard (UDP)");
break;
case Protocol.ProTunUdp:
ConnectionDetailsProtocol.TextEquals("Proton WireGuard (UDP)");
break;
case Protocol.OpenVpnUdp:
ConnectionDetailsProtocol.TextEquals("OpenVPN (UDP)");
break;
case Protocol.ProTunTcp:
ConnectionDetailsProtocol.TextEquals("Proton WireGuard (TCP)");
break;
case Protocol.ProTunTls:
ConnectionDetailsProtocol.TextEquals("Proton Stealth");
break;
case Protocol.WireGuardTcp:
ConnectionDetailsProtocol.TextEquals("WireGuard (TCP)");
break;
case Protocol.WireGuardTls:
ConnectionDetailsProtocol.TextEquals("Stealth");
break;
case Protocol.OpenVpnTcp:
ConnectionDetailsProtocol.TextEquals("OpenVPN (TCP)");
break;
}
return this;
}
public Verifications AssertVPNIpAndExternalIpMatch(string vpnIpAddress, string externalIpAddress)
{
Assert.That(vpnIpAddress.Equals(externalIpAddress), Is.True);
return this;
}
public Verifications AssertVpnConnectionEstablished(string ipAddressBefore, string ipAddressAfter)
{
Assert.That(ipAddressBefore.Equals(ipAddressAfter), Is.False,
$"User was not connected to VPN server. IP Address not connected: {ipAddressBefore}. " +
$"IP Address connected: {ipAddressAfter}");
return this;
}
public Verifications AssertVpnConnectionAfterKill(string ipAddressBeforeKill, string ipAddressAfterKill)
{
Assert.That(ipAddressBeforeKill.Equals(ipAddressAfterKill), Is.True,
$"VPN Connection was lost after app was killed. " +
$"IP Address before client was killed: {ipAddressBeforeKill}. " +
$"IP Address after client was killed: {ipAddressAfterKill}");
return this;
}
public Verifications AssertVpnConnectionAfterRestored(string ipAddressBeforeKill, string ipAddressAfterRestore)
{
Assert.That(ipAddressBeforeKill.Equals(ipAddressAfterRestore), Is.True,
$"VPN Connection was lost/reconnected after client was resumed. " +
$"IP Address before client was killed: {ipAddressBeforeKill}. " +
$"IP Address after client was restored: {ipAddressAfterRestore}");
return this;
}
}
public Verifications Verify => new();
}