mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
test(BRIDGE-247): Automate Bridge 0% update rollout
This commit is contained in:
57
tests/e2e/ui_tests/windows_os/Tests/ZeroPercentUpdateTest.cs
Normal file
57
tests/e2e/ui_tests/windows_os/Tests/ZeroPercentUpdateTest.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using ProtonMailBridge.UI.Tests.Results;
|
||||
using ProtonMailBridge.UI.Tests.TestsHelper;
|
||||
using ProtonMailBridge.UI.Tests.Windows;
|
||||
|
||||
namespace ProtonMailBridge.UI.Tests.Tests
|
||||
{
|
||||
public class ZeroPercentUpdateTest : TestSession
|
||||
{
|
||||
private readonly LoginWindow _loginWindow = new();
|
||||
private readonly SettingsMenuWindow _settingsMenuWindow = new();
|
||||
private readonly HelpMenuWindow _helpMenuWindow = new();
|
||||
private readonly ZeroPercentUpdateWindow _zeroPercentWindow = new();
|
||||
|
||||
[SetUp]
|
||||
public void TestInitialize()
|
||||
{
|
||||
LaunchApp();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Category("ZeroPercentUpdateRollout")]
|
||||
public void EnableBetaAccessVerifyBetaIsEnabledVerifyNotificationAndRestartBridge()
|
||||
{
|
||||
_zeroPercentWindow.ClickStartSetupButton();
|
||||
_zeroPercentWindow.CLickCancelButton();
|
||||
_helpMenuWindow.ClickHelpButton();
|
||||
_zeroPercentWindow.SaveCurrentVersionAndTagNumber();
|
||||
Thread.Sleep(2000);
|
||||
ClientCleanup();
|
||||
_zeroPercentWindow.editTheVault();
|
||||
LaunchApp();
|
||||
_loginWindow.SignIn(TestUserData.GetPaidUser());
|
||||
_settingsMenuWindow.ClickSettingsButton();
|
||||
_zeroPercentWindow.VerifyBetaAccessIsEnabled();
|
||||
_zeroPercentWindow.RestartBridgeNotification();
|
||||
_helpMenuWindow.ClickHelpButton();
|
||||
Thread.Sleep(2000);
|
||||
_zeroPercentWindow.VerifyVersionAndTagNumberOnRelaunch();
|
||||
}
|
||||
|
||||
|
||||
[TearDown]
|
||||
public void TestCleanup()
|
||||
{
|
||||
ClientCleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
261
tests/e2e/ui_tests/windows_os/Windows/ZeroPercentUpdateWindow.cs
Normal file
261
tests/e2e/ui_tests/windows_os/Windows/ZeroPercentUpdateWindow.cs
Normal file
@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using ProtonMailBridge.UI.Tests.TestsHelper;
|
||||
using FlaUI.Core.Definitions;
|
||||
using FlaUI.Core.AutomationElements;
|
||||
using FlaUI.Core.Input;
|
||||
// using System.Windows.Forms;
|
||||
|
||||
namespace ProtonMailBridge.UI.Tests.Windows
|
||||
{
|
||||
public class ZeroPercentUpdateWindow : UIActions
|
||||
{
|
||||
|
||||
private TextBox BridgeUpdateIsReady => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Text).And(cf.ByName("Bridge update is ready"))).AsTextBox();
|
||||
private Button StartSetupButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Start setup"))).AsButton();
|
||||
private Button CancelButton => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Cancel"))).AsButton();
|
||||
|
||||
private TextBox VersionBuildNumberTextBox => Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Pane)).FindAllDescendants(cf => cf.ByControlType(ControlType.Text))[13].AsTextBox();
|
||||
|
||||
public void editTheVault()
|
||||
{
|
||||
try
|
||||
{
|
||||
string executablePath = Environment.GetEnvironmentVariable("UI_TEST_VAULT_EDITOR_EXE_PATH");
|
||||
|
||||
if (string.IsNullOrEmpty(executablePath))
|
||||
{
|
||||
Console.WriteLine("Executable path is not set in the environment variables.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(executablePath))
|
||||
{
|
||||
Console.WriteLine($"Executable not found at path: {executablePath}");
|
||||
return;
|
||||
}
|
||||
string readArgument = "read";
|
||||
string writeArgument = "write";
|
||||
string vaultJson;
|
||||
|
||||
// start the read process
|
||||
ProcessStartInfo readProcessInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executablePath,
|
||||
Arguments = readArgument,
|
||||
RedirectStandardOutput = true, // Capture the output
|
||||
UseShellExecute = false, // Required to redirect output
|
||||
CreateNoWindow = true // Optional: Run without showing a console window
|
||||
};
|
||||
|
||||
//read the output
|
||||
using (Process readProcess = Process.Start(readProcessInfo))
|
||||
{
|
||||
if (readProcess == null)
|
||||
{
|
||||
Assert.Fail("Failed to start the read process.");
|
||||
return;
|
||||
}
|
||||
|
||||
string output = readProcess.StandardOutput.ReadToEnd();
|
||||
readProcess.WaitForExit();
|
||||
|
||||
// Write the output to a file
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
vaultJson = Path.Combine(desktopPath, "vault.json");
|
||||
File.WriteAllText(vaultJson, output);
|
||||
|
||||
Console.WriteLine($"Vault data has been written to: {vaultJson}");
|
||||
}
|
||||
|
||||
//update the json file, UpdateChannel to early and UpdateRollout to 0
|
||||
string jsonContent = File.ReadAllText(vaultJson);
|
||||
JsonNode json = JsonNode.Parse(jsonContent);
|
||||
|
||||
if (json == null)
|
||||
{
|
||||
Assert.Fail("Can not parse the vault.json file");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var settingsNode = json["Settings"];
|
||||
|
||||
settingsNode["UpdateChannel"] = "early";
|
||||
settingsNode["UpdateRollout"] = 0;
|
||||
// must use UnsafeRelaxedJsonEscaping for the serialization of the + character in the timestamp
|
||||
File.WriteAllText(vaultJson, json.ToJsonString(new JsonSerializerOptions { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }));
|
||||
}
|
||||
|
||||
// read the new content from the json file
|
||||
jsonContent = File.ReadAllText(vaultJson);
|
||||
// start the write process
|
||||
Process writeProcess = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executablePath,
|
||||
Arguments = writeArgument,
|
||||
RedirectStandardInput = true, // Pass input via standard input
|
||||
RedirectStandardOutput = true, // Capture standard output
|
||||
RedirectStandardError = true, // Capture error output
|
||||
UseShellExecute = false, // Required for redirection
|
||||
CreateNoWindow = true // Run without showing a window
|
||||
}
|
||||
};
|
||||
|
||||
writeProcess.Start();
|
||||
|
||||
// pass the json file content to the process
|
||||
using (StreamWriter writer = writeProcess.StandardInput)
|
||||
{
|
||||
if (writer.BaseStream.CanWrite)
|
||||
{
|
||||
writer.Write(jsonContent);
|
||||
}
|
||||
}
|
||||
|
||||
// read the output and errors
|
||||
string writeOutput = writeProcess.StandardOutput.ReadToEnd();
|
||||
string error = writeProcess.StandardError.ReadToEnd();
|
||||
|
||||
writeProcess.WaitForExit();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(writeOutput))
|
||||
{
|
||||
Console.WriteLine("Output from write process:");
|
||||
Console.WriteLine(writeOutput);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
Console.WriteLine("Error from write process:");
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
|
||||
// Check exit code for success/failure
|
||||
if (writeProcess.ExitCode != 0)
|
||||
{
|
||||
Assert.Fail("Write process exited with error code: " + writeProcess.ExitCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Fail(ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ZeroPercentUpdateWindow VerifyBetaAccessIsEnabled()
|
||||
{
|
||||
CheckBox BetaAccess = Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.CheckBox).And(cf.ByName("Beta access toggle"))).AsCheckBox();
|
||||
Assert.That(BetaAccess.IsToggled, Is.True);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ZeroPercentUpdateWindow RestartBridgeNotification()
|
||||
{
|
||||
WaitUntilElementIsVisible(() => BridgeUpdateIsReady, 60);
|
||||
Assert.That(BridgeUpdateIsReady.IsAvailable, Is.True);
|
||||
Button RestartBridge = Window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Button).And(cf.ByName("Restart Bridge"))).AsButton();
|
||||
RestartBridge.Click();
|
||||
Thread.Sleep(5000);
|
||||
LaunchApp();
|
||||
Window.Focus();
|
||||
Thread.Sleep(5000);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static int[] PreviousVersionNumbers = null;
|
||||
private static string PreviousTagNumber = null;
|
||||
|
||||
private int[] GetVersionNumbers()
|
||||
{
|
||||
string text = VersionBuildNumberTextBox.Name;
|
||||
|
||||
string versionString = text.Substring(text.IndexOf("v") + 1).Split(' ')[0];
|
||||
return Array.ConvertAll(versionString.Split('.'), int.Parse);
|
||||
}
|
||||
private string GetTagNumber()
|
||||
{
|
||||
string text = VersionBuildNumberTextBox.Name;
|
||||
return text.Substring(text.IndexOf("(br-") + 4).Split(')')[0];
|
||||
}
|
||||
public void SaveCurrentVersionAndTagNumber()
|
||||
{
|
||||
PreviousVersionNumbers = GetVersionNumbers();
|
||||
PreviousTagNumber = GetTagNumber();
|
||||
}
|
||||
public void VerifyVersionAndTagNumberOnRelaunch()
|
||||
{
|
||||
int[] newVersionNumbers = GetVersionNumbers();
|
||||
string newTagNumber = GetTagNumber();
|
||||
|
||||
if (PreviousVersionNumbers == null || PreviousTagNumber == null)
|
||||
{
|
||||
throw new Exception("Previous version or tag number is not set.");
|
||||
}
|
||||
|
||||
bool isVersionGreater = false;
|
||||
for (int i = 0; i < PreviousVersionNumbers.Length; i++)
|
||||
{
|
||||
if (newVersionNumbers[i] > PreviousVersionNumbers[i])
|
||||
{
|
||||
isVersionGreater = true;
|
||||
break;
|
||||
}
|
||||
else if (newVersionNumbers[i] < PreviousVersionNumbers[i])
|
||||
{
|
||||
throw new Exception($"Current version {string.Join('.', newVersionNumbers)} is not greater than previous version {string.Join('.', PreviousVersionNumbers)}.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVersionGreater)
|
||||
{
|
||||
throw new Exception($"Current version {string.Join('.', newVersionNumbers)} is not greater than previous version {string.Join('.', PreviousVersionNumbers)}.");
|
||||
}
|
||||
|
||||
if (newTagNumber == PreviousTagNumber)
|
||||
{
|
||||
throw new Exception($"Current tag number (br-{newTagNumber}) is the same as the previous tag number (br-{PreviousTagNumber}).");
|
||||
}
|
||||
}
|
||||
|
||||
public ZeroPercentUpdateWindow ClickStartSetupButton()
|
||||
{
|
||||
StartSetupButton.Click();
|
||||
return this;
|
||||
}
|
||||
public ZeroPercentUpdateWindow CLickCancelButton()
|
||||
{
|
||||
CancelButton.Click();
|
||||
return this;
|
||||
}
|
||||
private void WaitUntilElementIsVisible(Func<AutomationElement> findElementFunc, int numOfSeconds)
|
||||
{
|
||||
TimeSpan timeout = TimeSpan.FromSeconds(numOfSeconds);
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
|
||||
|
||||
while (stopwatch.Elapsed < timeout)
|
||||
{
|
||||
//if element is visible the processing is completed
|
||||
var element = findElementFunc();
|
||||
if (element != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Wait.UntilInputIsProcessed();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user