-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #344 from immutable/feature/dx-3421-android-browse…
…rstack [DX-3421] android UI test on CI (BrowserStack)
- Loading branch information
Showing
4 changed files
with
167 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# ============================= | ||
# Set BrowserStack Credentials | ||
# ============================= | ||
# Add your BrowserStack userName and acccessKey here or set BROWSERSTACK_USERNAME and | ||
# BROWSERSTACK_ACCESS_KEY as env variables | ||
#userName: BROWSERSTACK_USERNAME | ||
#accessKey: BROWSERSTACK_ACCESS_KEY | ||
|
||
# ====================== | ||
# BrowserStack Reporting | ||
# ====================== | ||
# The following capabilities are used to set up reporting on BrowserStack: | ||
# Set 'projectName' to the name of your project. Example, Marketing Website | ||
projectName: Unity Sample App | ||
# Set `buildName` as the name of the job / testsuite being run | ||
buildName: browserstack build | ||
# `buildIdentifier` is a unique id to differentiate every execution that gets appended to | ||
# buildName. Choose your buildIdentifier format from the available expressions: | ||
# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution | ||
# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 | ||
# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests | ||
buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} | ||
framework: pytest | ||
source: pytest-browserstack:sample-sdk:v1.0 | ||
|
||
# Set `app` to define the app that is to be used for testing. | ||
# It can either take the id of any uploaded app or the path of the app directly. | ||
#app: ./WikipediaSample.apk | ||
app: ./SampleApp.apk #For running local tests | ||
|
||
# ======================================= | ||
# Platforms (Browsers / Devices to test) | ||
# ======================================= | ||
# Platforms object contains all the browser / device combinations you want to test on. | ||
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) | ||
|
||
platforms: | ||
# - deviceName: Samsung Galaxy S22 Ultra | ||
# osVersion: 12.0 | ||
# platformName: android | ||
# - deviceName: Samsung Galaxy S21 | ||
# osVersion: 11.0 | ||
# platformName: android | ||
- deviceName: Google Pixel 6 Pro | ||
osVersion: 12.0 | ||
platformName: android | ||
|
||
# ======================= | ||
# Parallels per Platform | ||
# ======================= | ||
# The number of parallel threads to be used for each platform set. | ||
# BrowserStack's SDK runner will select the best strategy based on the configured value | ||
# | ||
# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack | ||
# | ||
# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack | ||
parallelsPerPlatform: 1 | ||
|
||
# ========================================== | ||
# BrowserStack Local | ||
# (For localhost, staging/private websites) | ||
# ========================================== | ||
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet | ||
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction | ||
browserstackLocal: true # <boolean> (Default false) | ||
browserStackLocalOptions: | ||
#Options to be passed to BrowserStack local in-case of advanced configurations | ||
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local. | ||
forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. | ||
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections | ||
|
||
# =================== | ||
# Debugging features | ||
# =================== | ||
debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran | ||
networkLogs: false # <boolean> Set to true to enable HAR logs capturing | ||
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors) | ||
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) | ||
acceptInsecureCerts: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import sys | ||
import time | ||
import unittest | ||
from pathlib import Path | ||
|
||
from appium import webdriver | ||
from appium.options.android import UiAutomator2Options | ||
from appium.webdriver.common.appiumby import AppiumBy | ||
from appium.webdriver.webdriver import WebDriver | ||
from selenium.webdriver.support.ui import WebDriverWait | ||
from selenium.webdriver.support import expected_conditions as EC | ||
|
||
from alttester import AltDriver, AltReversePortForwarding, By | ||
|
||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'src')) | ||
from fetch_otp import EMAIL, fetch_code | ||
|
||
# To run this test on an actual Android device: appium --base-path /wd/hub --allow-insecure chromedriver_autodownload | ||
class TestBase(unittest.TestCase): | ||
altdriver = None | ||
appium_driver = None | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
options = UiAutomator2Options() | ||
options.auto_web_view = True | ||
options.ensure_webviews_have_pages = True | ||
options.native_web_screenshot = True | ||
options.new_command_timeout = 3600 | ||
|
||
cls.appium_driver = webdriver.Remote('https://hub-cloud.browserstack.com/wd/hub/', options=options) | ||
|
||
time.sleep(10) | ||
cls.altdriver = AltDriver() | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
print("\nEnding") | ||
cls.altdriver.stop() | ||
cls.appium_driver.quit() | ||
|
||
def test_1_pkce_login(self): | ||
# Select use PKCE auth | ||
self.altdriver.find_object(By.NAME, "PKCE").tap() | ||
|
||
# Wait for unauthenticated screen | ||
self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") | ||
|
||
# Login | ||
loginBtn = self.altdriver.wait_for_object(By.NAME, "LoginBtn") | ||
loginBtn.tap() | ||
|
||
driver = self.appium_driver | ||
|
||
# Wait for the Chrome Custom Tabs context to appear | ||
WebDriverWait(driver, 30).until(lambda d: 'WEBVIEW_chrome' in d.contexts) | ||
driver.switch_to.context("WEBVIEW_chrome") | ||
|
||
email_field = driver.find_element(by=AppiumBy.XPATH, value="//input[@name=\"address\"]") | ||
email_field.send_keys(EMAIL) | ||
submit_button = driver.find_element(by=AppiumBy.XPATH, value="//form/div/div/div[2]/button") | ||
submit_button.click() | ||
|
||
time.sleep(10) # Wait for OTP | ||
|
||
code = fetch_code() | ||
if code: | ||
print(f"Successfully fetched OTP: {code}") | ||
else: | ||
print("Failed to fetch OTP from email") | ||
|
||
otp_field = driver.find_element(by=AppiumBy.XPATH, value="//div[@id=\"passwordless_container\"]/div[1]/input") | ||
otp_field.send_keys(code) | ||
|
||
# Wait for authenticated screen | ||
self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") |