From 2fcb28dc523e850afc6ab099bf04d46c2ea5e0a7 Mon Sep 17 00:00:00 2001 From: Natalie Bunduwongse Date: Wed, 20 Nov 2024 13:10:59 +1300 Subject: [PATCH] test: simplify mac ui tests --- sample/Tests/src/fetch_otp.py | 2 +- sample/Tests/test/test_mac.py | 91 +++++++++++++++++++-- sample/Tests/test/test_mac_helpers.py | 110 +++++--------------------- sample/Tests/test/test_windows.py | 4 + 4 files changed, 106 insertions(+), 101 deletions(-) diff --git a/sample/Tests/src/fetch_otp.py b/sample/Tests/src/fetch_otp.py index 1a8459ba..1b406388 100644 --- a/sample/Tests/src/fetch_otp.py +++ b/sample/Tests/src/fetch_otp.py @@ -1,6 +1,6 @@ import os import mailslurp_client -from mailslurp_client.api import InboxControllerApi, WaitForControllerApi +from mailslurp_client.api import WaitForControllerApi import re INBOX_ID = "26b067b8-ef3a-4655-955a-19f157b35b6e" diff --git a/sample/Tests/test/test_mac.py b/sample/Tests/test/test_mac.py index f0da1806..6415ff1d 100644 --- a/sample/Tests/test/test_mac.py +++ b/sample/Tests/test/test_mac.py @@ -1,18 +1,31 @@ +import sys import time +from pathlib import Path + +from selenium import webdriver +from selenium.webdriver.chrome.service import Service +from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.by import By as SeleniumBy +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.keys import Keys from alttester import * from test import TestConfig, UnityTest -from test_mac_helpers import login, open_sample_app, bring_sample_app_to_foreground, stop_chrome, stop_sample_app +from test_mac_helpers import open_sample_app, bring_sample_app_to_foreground, stop_sample_app +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'src')) +from fetch_otp import fetch_code class MacTest(UnityTest): altdriver = None + seleniumdriver = None @classmethod def setUpClass(cls): - open_sample_app + open_sample_app() cls.altdriver = AltDriver() @classmethod @@ -20,6 +33,57 @@ def tearDownClass(cls): stop_sample_app() cls.altdriver.stop() + @classmethod + def setupChrome(cls): + print("Connect to Chrome") + chrome_options = Options() + chrome_options.add_argument('--remote-debugging-port=9222') + + # Initialise Chrome driver + cls.seleniumdriver = webdriver.Chrome(options=chrome_options) + + print("Open a window on Chrome") + cls.seleniumdriver.current_window_handle + + @classmethod + def login(cls): + print("Waiting for new window...") + WebDriverWait(cls.seleniumdriver, 30).until(EC.number_of_windows_to_be(2)) + + # Switch to the new window + all_windows = cls.seleniumdriver.window_handles + new_window = next(window for window in all_windows if window != cls.seleniumdriver.current_window_handle) + print("Switched to new window") + + # Wait for email input and enter email + email_field = WebDriverWait(cls.seleniumdriver, 60).until(EC.presence_of_element_located((SeleniumBy.ID, ':r1:'))) + print("Entering email...") + email_field.send_keys(TestConfig.EMAIL) + email_field.send_keys(Keys.RETURN) + + # Wait for OTP + print("Waiting for OTP...") + time.sleep(10) + print("Fetching OTP from MailSlurp...") + code = fetch_code() + + if not code: + cls.seleniumdriver.quit() + raise AssertionError("Failed to fetch OTP from MailSlurp") + + print(f"Successfully fetched OTP: {code}") + + # Find OTP input and enter the code + otp_field = WebDriverWait(cls.seleniumdriver, 60).until(EC.presence_of_element_located((SeleniumBy.CSS_SELECTOR, 'input[data-testid="passwordless_passcode__TextInput--0__input"]'))) + print("Entering OTP...") + otp_field.send_keys(code) + + # Wait for success page and confirm + success = WebDriverWait(cls.seleniumdriver, 60).until(EC.presence_of_element_located((SeleniumBy.CSS_SELECTOR, 'h1[data-testid="device_success_title"]'))) + print("Connected to Passport!") + + cls.seleniumdriver.quit() + def test_1_device_code_login(self): # Select use device code auth self.altdriver.find_object(By.NAME, "DeviceCodeAuth").tap() @@ -29,9 +93,12 @@ def test_1_device_code_login(self): # Login print("Logging in...") - login() + self.setupChrome() bring_sample_app_to_foreground() self.altdriver.wait_for_object(By.NAME, "LoginBtn").tap() + self.login() + bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") print("Logged in") @@ -116,23 +183,28 @@ def test_7_reconnect_device_code_connect_imx(self): # Logout print("Logging out...") + self.setupChrome() + bring_sample_app_to_foreground() self.altdriver.find_object(By.NAME, "LogoutBtn").tap() time.sleep(5) bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - stop_chrome() + self.seleniumdriver.quit() print("Logged out") - + # Connect IMX print("Logging in and connecting to IMX...") + self.setupChrome() + bring_sample_app_to_foreground() self.altdriver.wait_for_object(By.NAME, "ConnectBtn").tap() - login() + self.login() bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") print("Logged in and connected to IMX") - stop_chrome() # Get access token self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() @@ -145,10 +217,13 @@ def test_7_reconnect_device_code_connect_imx(self): # Logout print("Logging out...") + self.setupChrome() + bring_sample_app_to_foreground() self.altdriver.find_object(By.NAME, "LogoutBtn").tap() time.sleep(5) bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - stop_chrome() + self.seleniumdriver.quit() print("Logged out") \ No newline at end of file diff --git a/sample/Tests/test/test_mac_helpers.py b/sample/Tests/test/test_mac_helpers.py index 532edca7..cc9f513a 100644 --- a/sample/Tests/test/test_mac_helpers.py +++ b/sample/Tests/test/test_mac_helpers.py @@ -1,77 +1,5 @@ -import os -import sys import subprocess import time -from pathlib import Path - -from selenium import webdriver -from selenium.webdriver.chrome.service import Service -from selenium.webdriver.chrome.options import Options -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.common.keys import Keys -import time - -sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'src')) -from fetch_otp import EMAIL, fetch_code - -# brew install chromedriver - -def login(): - print("Connect to Chrome") - # Set up Chrome options to connect to the existing Chrome instance - chrome_options = Options() - chrome_options.add_argument('--remote-debugging-port=9222') - # Connect to the existing Chrome instance - driver = webdriver.Chrome(options=chrome_options) - - print("Open a window on Chrome") - # Get the original window handle - original_window = driver.current_window_handle - - print("Waiting for new window...") - WebDriverWait(driver, 30).until(EC.number_of_windows_to_be(2)) - - # Get all window handles - all_windows = driver.window_handles - - print("Find the new window") - new_window = [window for window in all_windows if window != driver.current_window_handle][0] - - print("Switch to the new window") - driver.switch_to.window(new_window) - - wait = WebDriverWait(driver, 60) - - print("Wait for email input...") - email_field = wait.until(EC.presence_of_element_located((By.ID, ':r1:'))) - print("Enter email") - email_field.send_keys(EMAIL) - email_field.send_keys(Keys.RETURN) - - # Wait for the OTP to arrive and page to load - print("Wait for OTP...") - time.sleep(10) - - print("Get OTP from Mailslurp...") - code = fetch_code() - if code: - print(f"Successfully fetched OTP: {code}") - else: - print("Failed to fetch OTP from MailSlurp") - driver.quit() - - print("Find OTP input...") - otp_field = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input[data-testid="passwordless_passcode__TextInput--0__input"]'))) - print("Enter OTP") - otp_field.send_keys(code) - - print("Wait for success page...") - success = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'h1[data-testid="device_success_title"]'))) - print("Connected to Passport!") - - driver.quit() def open_sample_app(): print("Opening Unity sample app...") @@ -81,31 +9,29 @@ def open_sample_app(): def stop_sample_app(): print("Stopping sample app...") - try: - # Get the PID of the sample app using ps, grep, and awk - cmd = f"ps aux | grep 'Sample.app' | grep -v grep | awk '{{print $2}}'" - pid = subprocess.check_output(cmd, shell=True, text=True).strip() - if pid: - # Terminate the process using the PID - subprocess.run(["kill", pid]) - print(f"Sample app (PID {pid}) has been terminated.") - else: - print("Sample app is not running.") - except subprocess.CalledProcessError: - print("Failed to find the sample app process.") + bash_script = """ + app_path="SampleApp.app" + echo "Closing sample app..." + PID=$(ps aux | grep "$app_path" | grep -v grep | awk '{print $2}') + if [ -n "$PID" ]; then + kill $PID + echo "Sample app (PID $PID) has been terminated." + else + echo "Sample app is not running." + fi + echo "Waiting for 5 seconds..." + sleep 5 + """ + + subprocess.run(bash_script, shell=True, check=True, text=True) time.sleep(5) print("Stopped sample app.") -def bring_sample_app_to_foreground(app_name): +def bring_sample_app_to_foreground(): print("Bringing Unity sample app to the foreground...") subprocess.run( - ['osascript', '-e', f'tell application "{app_name}" to activate'], + ['osascript', '-e', f'tell application "SampleApp" to activate'], check=True - ) - -def stop_chrome(): - print("Stopping Chrome all Chrome instances...") - subprocess.run(["pkill", "-f", "chrome"], check=True) - print("Stopped Chrome.") \ No newline at end of file + ) \ No newline at end of file diff --git a/sample/Tests/test/test_windows.py b/sample/Tests/test/test_windows.py index 93893017..de3a1819 100644 --- a/sample/Tests/test/test_windows.py +++ b/sample/Tests/test/test_windows.py @@ -31,6 +31,7 @@ def test_1_device_code_login(self): self.altdriver.wait_for_object(By.NAME, "LoginBtn").tap() login() bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") print("Logged in") @@ -112,6 +113,7 @@ def test_7_reconnect_device_code_connect_imx(self): self.altdriver.find_object(By.NAME, "LogoutBtn").tap() time.sleep(5) bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") stop_chrome() @@ -124,6 +126,7 @@ def test_7_reconnect_device_code_connect_imx(self): self.altdriver.wait_for_object(By.NAME, "ConnectBtn").tap() login() bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") print("Logged in and connected to IMX") @@ -145,6 +148,7 @@ def test_7_reconnect_device_code_connect_imx(self): self.altdriver.find_object(By.NAME, "LogoutBtn").tap() time.sleep(5) bring_sample_app_to_foreground() + # Wait for authenticated screen self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") stop_chrome()