Coderabbit fixes:

- Mac
- Flask debug
- Threaded flask
- propagate token in GET requests
- enhance spec docs
- normalize MAC x2
- mcp disablement redundant private attribute
- run all tests imports
This commit is contained in:
Adam Outler
2026-01-19 00:03:27 +00:00
parent ecea1d1fbd
commit bb0c0e1c74
13 changed files with 326 additions and 55 deletions

View File

@@ -5,15 +5,8 @@ Runs all page-specific UI tests and provides summary
"""
import sys
# Import all test modules
from .test_helpers import test_ui_dashboard
from .test_helpers import test_ui_devices
from .test_helpers import test_ui_network
from .test_helpers import test_ui_maintenance
from .test_helpers import test_ui_multi_edit
from .test_helpers import test_ui_notifications
from .test_helpers import test_ui_settings
from .test_helpers import test_ui_plugins
import os
import pytest
def main():
@@ -22,22 +15,28 @@ def main():
print("NetAlertX UI Test Suite")
print("=" * 70)
# Get directory of this script
base_dir = os.path.dirname(os.path.abspath(__file__))
test_modules = [
("Dashboard", test_ui_dashboard),
("Devices", test_ui_devices),
("Network", test_ui_network),
("Maintenance", test_ui_maintenance),
("Multi-Edit", test_ui_multi_edit),
("Notifications", test_ui_notifications),
("Settings", test_ui_settings),
("Plugins", test_ui_plugins),
("Dashboard", "test_ui_dashboard.py"),
("Devices", "test_ui_devices.py"),
("Network", "test_ui_network.py"),
("Maintenance", "test_ui_maintenance.py"),
("Multi-Edit", "test_ui_multi_edit.py"),
("Notifications", "test_ui_notifications.py"),
("Settings", "test_ui_settings.py"),
("Plugins", "test_ui_plugins.py"),
]
results = {}
for name, module in test_modules:
for name, filename in test_modules:
try:
result = module.run_tests()
print(f"\nRunning {name} tests...")
file_path = os.path.join(base_dir, filename)
# Run pytest
result = pytest.main([file_path, "-v"])
results[name] = result == 0
except Exception as e:
print(f"\n{name} tests failed with exception: {e}")

View File

@@ -82,13 +82,21 @@ def test_add_device_with_generated_mac_ip(driver, api_token):
wait_for_page_load(driver, timeout=10)
# --- Click "Add Device" ---
add_buttons = driver.find_elements(By.CSS_SELECTOR, "button#btnAddDevice, button[onclick*='addDevice'], a[href*='deviceDetails.php?mac='], .btn-add-device")
if not add_buttons:
# Wait for the "New Device" link specifically to ensure it's loaded
add_selector = "a[href*='deviceDetails.php?mac=new'], button#btnAddDevice, .btn-add-device"
try:
add_button = wait_for_element_by_css(driver, add_selector, timeout=10)
except Exception:
# Fallback to broader search if specific selector fails
add_buttons = driver.find_elements(By.XPATH, "//button[contains(text(),'Add') or contains(text(),'New')] | //a[contains(text(),'Add') or contains(text(),'New')]")
if not add_buttons:
assert True, "Add device button not found, skipping test"
return
add_buttons[0].click()
if add_buttons:
add_button = add_buttons[0]
else:
assert True, "Add device button not found, skipping test"
return
# Use JavaScript click to bypass any transparent overlays from the chart
driver.execute_script("arguments[0].click();", add_button)
# Wait for the device form to appear (use the NEWDEV_devMac field as indicator)
wait_for_element_by_css(driver, "#NEWDEV_devMac", timeout=10)

View File

@@ -6,6 +6,7 @@ Tests CSV export/import, delete operations, database tools
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from .test_helpers import BASE_URL, api_get, wait_for_page_load # noqa: E402
@@ -30,7 +31,10 @@ def test_export_csv_button_works(driver):
import os
import glob
driver.get(f"{BASE_URL}/maintenance.php")
# Use 127.0.0.1 instead of localhost to avoid IPv6 resolution issues in the browser
# which can lead to "Failed to fetch" if the server is only listening on IPv4.
target_url = f"{BASE_URL}/maintenance.php".replace("localhost", "127.0.0.1")
driver.get(target_url)
wait_for_page_load(driver, timeout=10)
# Clear any existing downloads
@@ -38,13 +42,22 @@ def test_export_csv_button_works(driver):
for f in glob.glob(f"{download_dir}/*.csv"):
os.remove(f)
# Ensure the Backup/Restore tab is active so the button is in a clickable state
try:
tab = WebDriverWait(driver, 5).until(
EC.element_to_be_clickable((By.ID, "tab_BackupRestore_id"))
)
tab.click()
except Exception:
pass
# Find the export button
export_btns = driver.find_elements(By.ID, "btnExportCSV")
try:
export_btn = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "btnExportCSV"))
)
if len(export_btns) > 0:
export_btn = export_btns[0]
# Click it (JavaScript click works even if CSS hides it)
# Click it (JavaScript click works even if CSS hides it or if it's overlapped)
driver.execute_script("arguments[0].click();", export_btn)
# Wait for download to complete (up to 10 seconds)
@@ -70,9 +83,15 @@ def test_export_csv_button_works(driver):
# Download via blob/JavaScript - can't verify file in headless mode
# Just verify button click didn't cause errors
assert "error" not in driver.page_source.lower(), "Button click should not cause errors"
else:
# Button doesn't exist on this page
assert True, "Export button not found on this page"
except Exception as e:
# Check for alerts that might be blocking page_source access
try:
alert = driver.switch_to.alert
alert_text = alert.text
alert.accept()
assert False, f"Alert present: {alert_text}"
except Exception:
raise e
def test_import_section_present(driver):