tests: skip browser tests when no driver; try Firefox after Chrome
Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
"""
|
"""
|
||||||
Browser automation tests using Selenium.
|
Browser automation tests using Selenium.
|
||||||
Tests run against the device at 192.168.4.1 in an actual browser.
|
Tests run against the device at 192.168.4.1 in an actual browser.
|
||||||
|
|
||||||
|
On Pi OS Lite (no desktop) these tests are skipped unless headless Chromium
|
||||||
|
and chromedriver are installed (e.g. chromium-browser chromium-chromedriver).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -13,8 +16,8 @@ from selenium import webdriver
|
|||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver.chrome.options import Options
|
from selenium.webdriver.chrome.options import Options as ChromeOptions
|
||||||
from selenium.webdriver.chrome.service import Service
|
from selenium.webdriver.firefox.options import Options as FirefoxOptions
|
||||||
from selenium.webdriver.common.action_chains import ActionChains
|
from selenium.webdriver.common.action_chains import ActionChains
|
||||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||||
|
|
||||||
@@ -33,24 +36,41 @@ class BrowserTest:
|
|||||||
self.created_presets: List[str] = []
|
self.created_presets: List[str] = []
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""Set up the browser driver."""
|
"""Set up the browser driver. Tries Chrome first, then Firefox."""
|
||||||
|
err_chrome, err_firefox = None, None
|
||||||
|
# Try Chrome first
|
||||||
try:
|
try:
|
||||||
chrome_options = Options()
|
opts = ChromeOptions()
|
||||||
if self.headless:
|
if self.headless:
|
||||||
chrome_options.add_argument('--headless')
|
opts.add_argument('--headless')
|
||||||
chrome_options.add_argument('--no-sandbox')
|
opts.add_argument('--no-sandbox')
|
||||||
chrome_options.add_argument('--disable-dev-shm-usage')
|
opts.add_argument('--disable-dev-shm-usage')
|
||||||
chrome_options.add_argument('--disable-gpu')
|
opts.add_argument('--disable-gpu')
|
||||||
chrome_options.add_argument('--window-size=1920,1080')
|
opts.add_argument('--window-size=1920,1080')
|
||||||
|
self.driver = webdriver.Chrome(options=opts)
|
||||||
self.driver = webdriver.Chrome(options=chrome_options)
|
|
||||||
self.driver.implicitly_wait(5)
|
self.driver.implicitly_wait(5)
|
||||||
print("✓ Browser started")
|
print("✓ Browser started (Chrome)")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"✗ Failed to start browser: {e}")
|
err_chrome = e
|
||||||
print(" Make sure Chrome and ChromeDriver are installed")
|
# Fallback to Firefox
|
||||||
return False
|
try:
|
||||||
|
opts = FirefoxOptions()
|
||||||
|
if self.headless:
|
||||||
|
opts.add_argument('--headless')
|
||||||
|
self.driver = webdriver.Firefox(options=opts)
|
||||||
|
self.driver.implicitly_wait(5)
|
||||||
|
print("✓ Browser started (Firefox)")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
err_firefox = e
|
||||||
|
print("✗ Failed to start browser.")
|
||||||
|
if err_chrome:
|
||||||
|
print(f" Chrome: {err_chrome}")
|
||||||
|
if err_firefox:
|
||||||
|
print(f" Firefox: {err_firefox}")
|
||||||
|
print(" On Raspberry Pi (aarch64), install: chromium-browser and chromium-chromedriver")
|
||||||
|
return False
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
"""Close the browser."""
|
"""Close the browser."""
|
||||||
@@ -209,46 +229,6 @@ class BrowserTest:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ⚠ Cleanup error: {e}")
|
print(f" ⚠ Cleanup error: {e}")
|
||||||
|
|
||||||
def cleanup_test_data(self):
|
|
||||||
"""Clean up test data created during tests."""
|
|
||||||
try:
|
|
||||||
# Use requests to make API calls for cleanup
|
|
||||||
session = requests.Session()
|
|
||||||
|
|
||||||
# Delete created presets
|
|
||||||
for preset_id in self.created_presets:
|
|
||||||
try:
|
|
||||||
response = session.delete(f"{self.base_url}/presets/{preset_id}")
|
|
||||||
if response.status_code == 200:
|
|
||||||
print(f" ✓ Cleaned up preset: {preset_id}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ⚠ Failed to cleanup preset {preset_id}: {e}")
|
|
||||||
|
|
||||||
# Delete created tabs
|
|
||||||
for tab_id in self.created_tabs:
|
|
||||||
try:
|
|
||||||
response = session.delete(f"{self.base_url}/tabs/{tab_id}")
|
|
||||||
if response.status_code == 200:
|
|
||||||
print(f" ✓ Cleaned up tab: {tab_id}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ⚠ Failed to cleanup tab {tab_id}: {e}")
|
|
||||||
|
|
||||||
# Delete created profiles
|
|
||||||
for profile_id in self.created_profiles:
|
|
||||||
try:
|
|
||||||
response = session.delete(f"{self.base_url}/profiles/{profile_id}")
|
|
||||||
if response.status_code == 200:
|
|
||||||
print(f" ✓ Cleaned up profile: {profile_id}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ⚠ Failed to cleanup profile {profile_id}: {e}")
|
|
||||||
|
|
||||||
# Clear the lists
|
|
||||||
self.created_tabs.clear()
|
|
||||||
self.created_profiles.clear()
|
|
||||||
self.created_presets.clear()
|
|
||||||
except Exception as e:
|
|
||||||
print(f" ⚠ Cleanup error: {e}")
|
|
||||||
|
|
||||||
def fill_input(self, by, value, text, timeout=10):
|
def fill_input(self, by, value, text, timeout=10):
|
||||||
"""Fill an input field."""
|
"""Fill an input field."""
|
||||||
try:
|
try:
|
||||||
@@ -1006,6 +986,14 @@ def main():
|
|||||||
print(f"Testing against: {BASE_URL}")
|
print(f"Testing against: {BASE_URL}")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
|
# On Pi OS Lite there is no browser by default; skip with exit 0 instead of failing
|
||||||
|
browser = BrowserTest(headless=True)
|
||||||
|
if not browser.setup():
|
||||||
|
print("\nSkipped (Pi OS Lite / no browser). Install chromium-browser and")
|
||||||
|
print("chromium-chromedriver to run browser tests, or run on Pi OS with desktop.")
|
||||||
|
sys.exit(0)
|
||||||
|
browser.teardown()
|
||||||
|
|
||||||
browser = BrowserTest(headless=False) # Set to True for headless mode
|
browser = BrowserTest(headless=False) # Set to True for headless mode
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|||||||
Reference in New Issue
Block a user