Skip to content

Commit

Permalink
chore: add python ui tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-yangy committed Oct 28, 2024
1 parent 87ca95a commit 32cd2eb
Show file tree
Hide file tree
Showing 14 changed files with 808 additions and 42 deletions.
23 changes: 9 additions & 14 deletions .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,19 @@ jobs:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
ALTSERVER_HOST: 54.66.58.33
ALTSERVER_PORT: 13000
with:
targetPlatform: StandaloneOSX
projectPath: sample
buildMethod: MacBuilder.BuildForAltTester
customParameters: -logFile logFile.log -quit -batchmode
- name: Upload artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: Build-StandaloneOSX
path: sample/Builds/MacOS
test:
name: Run UI tests on AltTester 🧪
runs-on: macos-latest
runs-on: self-hosted
needs: build
steps:
- uses: actions/checkout@v3
Expand All @@ -54,21 +51,19 @@ jobs:
- uses: actions/download-artifact@v4
with:
name: Build-StandaloneOSX
- name: Open application
run: |
export RUN_IN_BROWSERSTACK="false"
export ALTSERVER_HOST="54.66.58.33"
export ALTSERVER_PORT=13000
chmod -R 755 SampleApp.app
open SampleApp.app
- uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install dependencies
run: pip install -r "sample/Tests/requirements.txt"
- name: Run UI tests
env:
UNITY_APP_PATH: ${{ github.workspace }}/SampleApp.app
UNITY_APP_NAME: SampleApp
MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }}
working-directory: sample/Tests
run: |
export ALTSERVER_HOST="54.66.58.33"
export ALTSERVER_PORT=13000
pytest -s -v sample/Tests/test.py
chmod -R 755 ${{ github.workspace }}/SampleApp.app
chmod +x test_mac.sh
./test_mac.sh
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@ sample/AltTester.log
sample/mono_crash*

# Vuplex
sample/Assets/Vuplex*
sample/Assets/Vuplex*

__pycache__/
*.pyc
.pytest_cache/
3 changes: 2 additions & 1 deletion sample/Tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ google_auth_oauthlib==1.2.0
protobuf==5.27.2
selenium==4.22.0
pytest==8.2.2
requests==2.32.3
requests==2.32.3
mailslurp-client==15.19.22
69 changes: 69 additions & 0 deletions sample/Tests/src/device_code_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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
from fetch_otp import EMAIL, fetch_code

# brew install chromedriver

def main():
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 Gmail")
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()

if __name__ == "__main__":
main()
68 changes: 68 additions & 0 deletions sample/Tests/src/device_code_login_windows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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
from gmail_fetch_otp import fetch_gmail_code

EMAIL = '[email protected]'

# Add chrome.exe to environment variable
# Download chrome driver and add to environment variable

def main():
print("Connect to Chrome")
# Set up Chrome options to connect to the existing Chrome instance
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "localhost:9222")
# Connect to the existing Chrome instance
driver = webdriver.Chrome(options=chrome_options)

print("Waiting for new window...")
WebDriverWait(driver, 60).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 Gmail...")
code = fetch_gmail_code()
if code:
print(f"Successfully fetched OTP: {code}")
else:
print("Failed to fetch OTP from Gmail")
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()

if __name__ == "__main__":
main()
37 changes: 37 additions & 0 deletions sample/Tests/src/device_code_logout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

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

def main():
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, 60).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)

driver.quit()

if __name__ == "__main__":
main()
33 changes: 33 additions & 0 deletions sample/Tests/src/device_code_logout_windows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

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

def main():
print("Connect to Chrome")
# Set up Chrome options to connect to the existing Chrome instance
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "localhost:9222")
# Connect to the existing Chrome instance
driver = webdriver.Chrome(options=chrome_options)

print("Waiting for new window...")
WebDriverWait(driver, 60).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)

driver.quit()

if __name__ == "__main__":
main()
30 changes: 30 additions & 0 deletions sample/Tests/src/fetch_otp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os
import mailslurp_client
from mailslurp_client.api import InboxControllerApi, WaitForControllerApi
import re

INBOX_ID = "33f17f82-274b-4269-9ce6-c620e89fcd8d"
EMAIL = "[email protected]"

def get_mailslurp_client():
configuration = mailslurp_client.Configuration()
configuration.api_key['x-api-key'] = os.getenv('MAILSLURP_API_KEY')
api_client = mailslurp_client.ApiClient(configuration)
waitfor_controller = WaitForControllerApi(api_client)
return waitfor_controller

def extract_otp_from_email(email_body):
# Pattern to match 6-digit code in Passport emails
pattern = r'<h1[^>]*>(\d{6})</h1>'
match = re.search(pattern, email_body)
if match:
return match.group(1)
return None

def fetch_code():
waitfor_controller = get_mailslurp_client()
email = waitfor_controller.wait_for_latest_email(inbox_id=INBOX_ID, timeout=30000, unread_only=True)
if email:
otp = extract_otp_from_email(email.body)
return otp
return None
26 changes: 0 additions & 26 deletions sample/Tests/test.py

This file was deleted.

Loading

0 comments on commit 32cd2eb

Please sign in to comment.