test(browser): fixture, env host and pacing, safer colour inputs
Made-with: Cursor
This commit is contained in:
@@ -1,22 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Browser automation tests using Selenium.
|
||||
Tests run against the device at 192.168.4.1 in an actual browser.
|
||||
Tests run against the device in an actual browser. Target host defaults to
|
||||
``192.168.4.1``; override with ``LED_CONTROLLER_DEVICE_IP`` (IP or hostname,
|
||||
or a full ``http://`` / ``https://`` base URL).
|
||||
|
||||
Fixed delays between UI steps use ``LED_CONTROLLER_BROWSER_SLEEP_SCALE``
|
||||
(default ``0.5``, i.e. half the nominal pause). Set to ``1`` for the old pacing,
|
||||
or ``0`` to skip fixed sleeps (may flake). Driver implicit wait defaults to
|
||||
``2`` seconds; override with ``LED_CONTROLLER_BROWSER_IMPLICIT_WAIT``.
|
||||
|
||||
On Pi OS Lite (no desktop) these tests are skipped unless headless Chromium
|
||||
and chromedriver are installed (e.g. chromium-browser chromium-chromedriver).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
if os.environ.get("LED_CONTROLLER_RUN_BROWSER_TESTS") != "1":
|
||||
# pytest catches Skipped; plain `python tests/test_browser.py` does not.
|
||||
if __name__ == "__main__":
|
||||
print(
|
||||
"Browser tests are disabled by default. "
|
||||
"Set LED_CONTROLLER_RUN_BROWSER_TESTS=1 to run.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
raise SystemExit(0)
|
||||
pytest.skip(
|
||||
"Legacy device browser automation script; enable explicitly to run.",
|
||||
allow_module_level=True,
|
||||
)
|
||||
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
from typing import Optional, List
|
||||
@@ -28,10 +43,46 @@ from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.chrome.options import Options as ChromeOptions
|
||||
from selenium.webdriver.firefox.options import Options as FirefoxOptions
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
from selenium.common.exceptions import (
|
||||
TimeoutException,
|
||||
NoSuchElementException,
|
||||
ElementNotInteractableException,
|
||||
)
|
||||
|
||||
_DEFAULT_DEVICE_HOST = "192.168.4.1"
|
||||
|
||||
|
||||
def _device_base_url() -> str:
|
||||
raw = os.environ.get("LED_CONTROLLER_DEVICE_IP", _DEFAULT_DEVICE_HOST).strip()
|
||||
if not raw:
|
||||
raw = _DEFAULT_DEVICE_HOST
|
||||
if raw.startswith(("http://", "https://")):
|
||||
return raw.rstrip("/")
|
||||
return f"http://{raw}"
|
||||
|
||||
|
||||
# Base URL for the device
|
||||
BASE_URL = "http://192.168.4.1"
|
||||
BASE_URL = _device_base_url()
|
||||
|
||||
|
||||
def _browser_sleep(seconds: float) -> None:
|
||||
"""Scale fixed UI pauses via LED_CONTROLLER_BROWSER_SLEEP_SCALE (default 0.5)."""
|
||||
try:
|
||||
scale = float(os.environ.get("LED_CONTROLLER_BROWSER_SLEEP_SCALE", "0.5"))
|
||||
except ValueError:
|
||||
scale = 0.5
|
||||
if scale <= 0:
|
||||
return
|
||||
time.sleep(max(0.0, float(seconds)) * scale)
|
||||
|
||||
|
||||
def _implicit_wait_s() -> int:
|
||||
try:
|
||||
v = float(os.environ.get("LED_CONTROLLER_BROWSER_IMPLICIT_WAIT", "2"))
|
||||
except ValueError:
|
||||
v = 2.0
|
||||
return int(max(0, min(60, round(v))))
|
||||
|
||||
|
||||
class BrowserTest:
|
||||
"""Browser automation test class."""
|
||||
@@ -57,7 +108,7 @@ class BrowserTest:
|
||||
opts.add_argument('--disable-gpu')
|
||||
opts.add_argument('--window-size=1920,1080')
|
||||
self.driver = webdriver.Chrome(options=opts)
|
||||
self.driver.implicitly_wait(5)
|
||||
self.driver.implicitly_wait(_implicit_wait_s())
|
||||
print("✓ Browser started (Chrome)")
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -68,7 +119,7 @@ class BrowserTest:
|
||||
if self.headless:
|
||||
opts.add_argument('--headless')
|
||||
self.driver = webdriver.Firefox(options=opts)
|
||||
self.driver.implicitly_wait(5)
|
||||
self.driver.implicitly_wait(_implicit_wait_s())
|
||||
print("✓ Browser started (Firefox)")
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -92,7 +143,7 @@ class BrowserTest:
|
||||
url = f"{self.base_url}{path}"
|
||||
try:
|
||||
self.driver.get(url)
|
||||
time.sleep(1) # Wait for page load
|
||||
_browser_sleep(1) # Wait for page load
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Failed to navigate to {url}: {e}")
|
||||
@@ -108,11 +159,18 @@ class BrowserTest:
|
||||
except TimeoutException:
|
||||
return None
|
||||
|
||||
def _scroll_into_view(self, element) -> None:
|
||||
self.driver.execute_script(
|
||||
"arguments[0].scrollIntoView({block: 'center', inline: 'nearest'});",
|
||||
element,
|
||||
)
|
||||
|
||||
def click_element(self, by, value, timeout=10, use_js=False):
|
||||
"""Click an element."""
|
||||
try:
|
||||
element = self.wait_for_element(by, value, timeout)
|
||||
if element:
|
||||
self._scroll_into_view(element)
|
||||
if use_js:
|
||||
# Use JavaScript click for elements that might be intercepted
|
||||
self.driver.execute_script("arguments[0].click();", element)
|
||||
@@ -122,7 +180,7 @@ class BrowserTest:
|
||||
element.click()
|
||||
except Exception:
|
||||
self.driver.execute_script("arguments[0].click();", element)
|
||||
time.sleep(0.5) # Wait for action
|
||||
_browser_sleep(0.5) # Wait for action
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
@@ -137,7 +195,7 @@ class BrowserTest:
|
||||
alert.accept()
|
||||
else:
|
||||
alert.dismiss()
|
||||
time.sleep(0.3)
|
||||
_browser_sleep(0.3)
|
||||
return True
|
||||
except TimeoutException:
|
||||
return False
|
||||
@@ -243,8 +301,34 @@ class BrowserTest:
|
||||
try:
|
||||
element = self.wait_for_element(by, value, timeout)
|
||||
if element:
|
||||
self._scroll_into_view(element)
|
||||
# Chrome often reports <input type="color"> as not interactable for clear/send_keys.
|
||||
if (element.get_attribute("type") or "").lower() == "color":
|
||||
hex_v = text.strip()
|
||||
if hex_v and not hex_v.startswith("#"):
|
||||
hex_v = "#" + hex_v
|
||||
self.driver.execute_script(
|
||||
"""
|
||||
var el = arguments[0], v = arguments[1];
|
||||
el.value = v;
|
||||
el.dispatchEvent(new Event('input', {bubbles: true}));
|
||||
el.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
""",
|
||||
element,
|
||||
hex_v,
|
||||
)
|
||||
return True
|
||||
element.clear()
|
||||
try:
|
||||
element.send_keys(text)
|
||||
except ElementNotInteractableException:
|
||||
self.driver.execute_script(
|
||||
"arguments[0].value = arguments[1];"
|
||||
"arguments[0].dispatchEvent(new Event('input', {bubbles: true}));"
|
||||
"arguments[0].dispatchEvent(new Event('change', {bubbles: true}));",
|
||||
element,
|
||||
text,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
@@ -273,7 +357,7 @@ class BrowserTest:
|
||||
try:
|
||||
actions = ActionChains(self.driver)
|
||||
actions.drag_and_drop(source_element, target_element).perform()
|
||||
time.sleep(0.5) # Wait for drop to complete
|
||||
_browser_sleep(0.5) # Wait for drop to complete
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Drag and drop failed: {e}")
|
||||
@@ -284,12 +368,18 @@ class BrowserTest:
|
||||
try:
|
||||
actions = ActionChains(self.driver)
|
||||
actions.drag_and_drop_by_offset(element, x_offset, y_offset).perform()
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Drag and drop by offset failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def browser() -> BrowserTest:
|
||||
return BrowserTest()
|
||||
|
||||
|
||||
def test_browser_connection(browser: BrowserTest) -> bool:
|
||||
"""Test basic browser connection."""
|
||||
print("Testing browser connection...")
|
||||
@@ -333,7 +423,7 @@ def test_zones_ui(browser: BrowserTest) -> bool:
|
||||
if browser.click_element(By.ID, 'zones-btn'):
|
||||
print("✓ Clicked Zones button")
|
||||
# Wait for modal to appear
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
modal = browser.wait_for_element(By.ID, 'zones-modal')
|
||||
if modal and 'active' in modal.get_attribute('class'):
|
||||
print("✓ Zones modal opened")
|
||||
@@ -353,7 +443,7 @@ def test_zones_ui(browser: BrowserTest) -> bool:
|
||||
# Click create button
|
||||
if browser.click_element(By.ID, 'create-zone-btn'):
|
||||
print(" ✓ Clicked create button")
|
||||
time.sleep(1) # Wait for creation
|
||||
_browser_sleep(1) # Wait for creation
|
||||
# Check if zone appears in list and extract ID
|
||||
tabs_list = browser.wait_for_element(By.ID, 'zones-list-modal')
|
||||
if tabs_list:
|
||||
@@ -386,9 +476,9 @@ def test_zones_ui(browser: BrowserTest) -> bool:
|
||||
try:
|
||||
# First, close and reopen modal to refresh
|
||||
browser.click_element(By.ID, 'zones-close-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
browser.click_element(By.ID, 'zones-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Right-click the row corresponding to 'Browser Test Zone'
|
||||
try:
|
||||
@@ -402,7 +492,7 @@ def test_zones_ui(browser: BrowserTest) -> bool:
|
||||
if tab_row:
|
||||
actions = ActionChains(browser.driver)
|
||||
actions.context_click(tab_row).perform()
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Check if edit modal opened
|
||||
edit_modal = browser.wait_for_element(By.ID, 'edit-zone-modal')
|
||||
@@ -415,7 +505,7 @@ def test_zones_ui(browser: BrowserTest) -> bool:
|
||||
edit_form = browser.wait_for_element(By.ID, 'edit-zone-form')
|
||||
if edit_form:
|
||||
browser.driver.execute_script("arguments[0].submit();", edit_form)
|
||||
time.sleep(1) # Wait for update
|
||||
_browser_sleep(1) # Wait for update
|
||||
print("✓ Submitted edit form")
|
||||
passed += 1
|
||||
else:
|
||||
@@ -476,7 +566,7 @@ def test_profiles_ui(browser: BrowserTest) -> bool:
|
||||
total += 1
|
||||
if browser.click_element(By.ID, 'profiles-btn'):
|
||||
print("✓ Clicked Profiles button")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
modal = browser.wait_for_element(By.ID, 'profiles-modal')
|
||||
if modal:
|
||||
print("✓ Profiles modal opened")
|
||||
@@ -491,7 +581,7 @@ def test_profiles_ui(browser: BrowserTest) -> bool:
|
||||
print(" ✓ Filled profile name")
|
||||
if browser.click_element(By.ID, 'create-profile-btn'):
|
||||
print(" ✓ Clicked create button")
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
# Check if profile appears
|
||||
profiles_list = browser.wait_for_element(By.ID, 'profiles-list')
|
||||
if profiles_list and 'Browser Test Profile' in profiles_list.text:
|
||||
@@ -535,7 +625,7 @@ def test_mobile_tab_presets_two_columns():
|
||||
first_tab = bt.wait_for_element(By.CSS_SELECTOR, '.zone-button', timeout=10)
|
||||
assert first_tab is not None, "No zone buttons found"
|
||||
first_tab.click()
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
|
||||
container = bt.wait_for_element(By.ID, 'presets-list-zone', timeout=10)
|
||||
assert container is not None, "presets-list-zone not found"
|
||||
@@ -577,7 +667,7 @@ def test_presets_ui(browser: BrowserTest) -> bool:
|
||||
total += 1
|
||||
if browser.click_element(By.ID, 'presets-btn'):
|
||||
print("✓ Clicked Presets button")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
modal = browser.wait_for_element(By.ID, 'presets-modal')
|
||||
if modal:
|
||||
print("✓ Presets modal opened")
|
||||
@@ -590,7 +680,7 @@ def test_presets_ui(browser: BrowserTest) -> bool:
|
||||
try:
|
||||
if browser.click_element(By.ID, 'preset-add-btn'):
|
||||
print(" ✓ Clicked Add Preset button")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
editor_modal = browser.wait_for_element(By.ID, 'preset-editor-modal')
|
||||
if editor_modal:
|
||||
print("✓ Preset editor modal opened")
|
||||
@@ -628,7 +718,7 @@ def test_presets_ui(browser: BrowserTest) -> bool:
|
||||
# Save preset
|
||||
if browser.click_element(By.ID, 'preset-save-btn'):
|
||||
print(" ✓ Clicked save button")
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
# Check if preset appears in list
|
||||
presets_list = browser.wait_for_element(By.ID, 'presets-list')
|
||||
if presets_list and 'Browser Test Preset' in presets_list.text:
|
||||
@@ -645,7 +735,7 @@ def test_presets_ui(browser: BrowserTest) -> bool:
|
||||
|
||||
# Close editor modal
|
||||
browser.click_element(By.ID, 'preset-editor-close-btn', use_js=True)
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
# Close presets modal
|
||||
browser.click_element(By.ID, 'presets-close-btn', use_js=True)
|
||||
|
||||
@@ -683,7 +773,7 @@ def test_color_palette_ui(browser: BrowserTest) -> bool:
|
||||
total += 1
|
||||
if browser.click_element(By.ID, 'color-palette-btn'):
|
||||
print("✓ Clicked Color Palette button")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
modal = browser.wait_for_element(By.ID, 'color-palette-modal')
|
||||
if modal:
|
||||
print("✓ Color palette modal opened")
|
||||
@@ -703,7 +793,7 @@ def test_color_palette_ui(browser: BrowserTest) -> bool:
|
||||
# Click add color button
|
||||
if browser.click_element(By.ID, 'palette-add-color-btn'):
|
||||
print(" ✓ Clicked Add Color button")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
# Handle alert if color already exists
|
||||
browser.handle_alert(accept=True, timeout=1)
|
||||
# Check if color appears in palette
|
||||
@@ -735,7 +825,7 @@ def test_color_palette_ui(browser: BrowserTest) -> bool:
|
||||
target = color_swatches[1]
|
||||
if browser.drag_and_drop(source, target):
|
||||
print("✓ Dragged color to reorder")
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
passed += 1
|
||||
else:
|
||||
print("✗ Drag and drop failed")
|
||||
@@ -781,7 +871,7 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
# Test 2: Open zones modal and create/select a zone
|
||||
total += 1
|
||||
browser.click_element(By.ID, 'zones-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Check if we have zones, if not create one
|
||||
tabs_list = browser.wait_for_element(By.ID, 'zones-list-modal')
|
||||
@@ -789,13 +879,13 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
# Create a zone
|
||||
browser.fill_input(By.ID, 'new-zone-name', 'Drag Test Zone')
|
||||
browser.click_element(By.ID, 'create-zone-btn')
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
|
||||
# Select first zone (or the one we just created)
|
||||
select_buttons = browser.driver.find_elements(By.XPATH, "//button[contains(text(), 'Select')]")
|
||||
if select_buttons:
|
||||
select_buttons[0].click()
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
print("✓ Selected a zone")
|
||||
passed += 1
|
||||
else:
|
||||
@@ -805,42 +895,42 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
return False
|
||||
|
||||
browser.click_element(By.ID, 'zones-close-btn', use_js=True)
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Test 3: Open presets modal and create presets
|
||||
total += 1
|
||||
browser.click_element(By.ID, 'presets-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Create first preset
|
||||
browser.click_element(By.ID, 'preset-add-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
browser.fill_input(By.ID, 'preset-name-input', 'Preset 1')
|
||||
browser.fill_input(By.ID, 'preset-new-color', '#ff0000')
|
||||
browser.click_element(By.ID, 'preset-add-color-btn')
|
||||
browser.click_element(By.ID, 'preset-save-btn')
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
|
||||
# Create second preset
|
||||
browser.click_element(By.ID, 'preset-add-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
browser.fill_input(By.ID, 'preset-name-input', 'Preset 2')
|
||||
browser.fill_input(By.ID, 'preset-new-color', '#00ff00')
|
||||
browser.click_element(By.ID, 'preset-add-color-btn')
|
||||
browser.click_element(By.ID, 'preset-save-btn')
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
|
||||
# Create third preset
|
||||
browser.click_element(By.ID, 'preset-add-btn')
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
browser.fill_input(By.ID, 'preset-name-input', 'Preset 3')
|
||||
browser.fill_input(By.ID, 'preset-new-color', '#0000ff')
|
||||
browser.click_element(By.ID, 'preset-add-color-btn')
|
||||
browser.click_element(By.ID, 'preset-save-btn')
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
|
||||
browser.click_element(By.ID, 'presets-close-btn', use_js=True)
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
print("✓ Created 3 presets for drag test")
|
||||
passed += 1
|
||||
@@ -858,24 +948,24 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
"if (window.tabsManager && window.tabsManager.openEditTabModal) { window.tabsManager.openEditTabModal(arguments[0], null); }",
|
||||
zone_id
|
||||
)
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
list_el = browser.wait_for_element(By.ID, 'edit-zone-presets-list', timeout=5)
|
||||
if list_el:
|
||||
select_buttons = browser.driver.find_elements(By.XPATH, "//div[@id='edit-zone-presets-list']//button[text()='Add']")
|
||||
if len(select_buttons) >= 2:
|
||||
browser.driver.execute_script("arguments[0].click();", select_buttons[0])
|
||||
time.sleep(1.5)
|
||||
_browser_sleep(1.5)
|
||||
browser.handle_alert(accept=True, timeout=1)
|
||||
select_buttons = browser.driver.find_elements(By.XPATH, "//div[@id='edit-zone-presets-list']//button[text()='Add']")
|
||||
if len(select_buttons) >= 1:
|
||||
browser.driver.execute_script("arguments[0].click();", select_buttons[0])
|
||||
time.sleep(1.5)
|
||||
_browser_sleep(1.5)
|
||||
browser.handle_alert(accept=True, timeout=1)
|
||||
print(" ✓ Added 2 presets to zone")
|
||||
passed += 1
|
||||
elif len(select_buttons) == 1:
|
||||
browser.driver.execute_script("arguments[0].click();", select_buttons[0])
|
||||
time.sleep(1.5)
|
||||
_browser_sleep(1.5)
|
||||
browser.handle_alert(accept=True, timeout=1)
|
||||
print(" ✓ Added 1 preset to zone")
|
||||
passed += 1
|
||||
@@ -894,16 +984,16 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
# Wait for presets to load in the zone
|
||||
presets_list_tab = browser.wait_for_element(By.ID, 'presets-list-zone', timeout=5)
|
||||
if presets_list_tab:
|
||||
time.sleep(1) # Wait for presets to render
|
||||
_browser_sleep(1) # Wait for presets to render
|
||||
|
||||
# Reordering is only available in Edit mode (tiles get .draggable-preset)
|
||||
mode_toggle = browser.wait_for_element(By.CSS_SELECTOR, '.ui-mode-toggle', timeout=5)
|
||||
if mode_toggle and mode_toggle.get_attribute('aria-pressed') == 'false':
|
||||
mode_toggle.click()
|
||||
time.sleep(0.5)
|
||||
_browser_sleep(0.5)
|
||||
|
||||
# Find draggable preset elements - wait a bit more for rendering
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
draggable_presets = browser.driver.find_elements(By.CSS_SELECTOR, '#presets-list-zone .draggable-preset')
|
||||
if len(draggable_presets) >= 2:
|
||||
print(f" ✓ Found {len(draggable_presets)} draggable presets")
|
||||
@@ -919,7 +1009,7 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
# Use ActionChains for drag and drop
|
||||
actions = ActionChains(browser.driver)
|
||||
actions.click_and_hold(source).move_to_element(target).release().perform()
|
||||
time.sleep(1) # Wait for reorder to complete
|
||||
_browser_sleep(1) # Wait for reorder to complete
|
||||
|
||||
# Check if order changed
|
||||
draggable_presets_after = browser.driver.find_elements(By.CSS_SELECTOR, '#presets-list-zone .draggable-preset')
|
||||
@@ -945,18 +1035,18 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
"if (window.tabsManager && window.tabsManager.openEditTabModal) { window.tabsManager.openEditTabModal(arguments[0], null); }",
|
||||
zone_id
|
||||
)
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
select_buttons = browser.driver.find_elements(By.XPATH, "//div[@id='edit-zone-presets-list']//button[text()='Add']")
|
||||
if select_buttons:
|
||||
print(" Attempting to add another preset...")
|
||||
browser.driver.execute_script("arguments[0].click();", select_buttons[0])
|
||||
time.sleep(1.5)
|
||||
_browser_sleep(1.5)
|
||||
browser.handle_alert(accept=True, timeout=1)
|
||||
try:
|
||||
browser.driver.execute_script("document.getElementById('edit-zone-modal').classList.remove('active');")
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
draggable_presets = browser.driver.find_elements(By.CSS_SELECTOR, '#presets-list-zone .draggable-preset')
|
||||
if len(draggable_presets) >= 2:
|
||||
print(" ✓ Added another preset, now testing drag...")
|
||||
@@ -964,7 +1054,7 @@ def test_preset_drag_and_drop(browser: BrowserTest) -> bool:
|
||||
target = draggable_presets[1]
|
||||
actions = ActionChains(browser.driver)
|
||||
actions.click_and_hold(source).move_to_element(target).release().perform()
|
||||
time.sleep(1)
|
||||
_browser_sleep(1)
|
||||
print("✓ Performed drag and drop")
|
||||
passed += 1
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user