import contextlib, http.server, os, socket, threading, time import pytest import pathlib import sys import requests from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By ROOT = os.path.dirname(os.path.abspath(__file__)) DOCROOT = os.path.abspath(os.path.join(ROOT, '..', 'public')) class SpaHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): if self.path == '/' or self.path.split('?',1)[0].split('#',1)[0] == '/': return http.server.SimpleHTTPRequestHandler.do_GET(self) try: return http.server.SimpleHTTPRequestHandler.do_GET(self) except Exception: pass self.path = '/index.html' return http.server.SimpleHTTPRequestHandler.do_GET(self) @contextlib.contextmanager def static_server(): os.chdir(DOCROOT) httpd = None with socket.socket() as s: s.bind(('127.0.0.1', 0)) host, port = s.getsockname() handler = SpaHandler httpd = http.server.ThreadingHTTPServer(('127.0.0.1', port), handler) t = threading.Thread(target=httpd.serve_forever, daemon=True) t.start() try: yield f"http://127.0.0.1:{port}" finally: httpd.shutdown() t.join() @pytest.fixture(scope="session") def base_url(): with static_server() as url: yield url @pytest.fixture(scope="session") def dev_server(): """Start the local development server for testing using the same logic as dev_server.py""" # Check if server is already running try: response = requests.get("http://localhost:8008", timeout=1) if response.status_code == 200: print("Development server already running on port 8008") yield "http://localhost:8008" return except: pass # Use the same server logic as dev_server.py print("Starting development server...") # Import the handler class from dev_server sys.path.append(os.path.dirname(DOCROOT)) from dev_server import SPAHandler # Create and start server os.chdir(DOCROOT) # serve from /public httpd = http.server.ThreadingHTTPServer(('127.0.0.1', 8008), SPAHandler) t = threading.Thread(target=httpd.serve_forever, daemon=True) t.start() # Wait for server to start max_wait = 30 for i in range(max_wait): try: response = requests.get("http://localhost:8008", timeout=1) if response.status_code == 200: print(f"Development server started successfully after {i+1} seconds") break except: if i == max_wait - 1: print("Failed to start development server") httpd.shutdown() raise time.sleep(1) try: yield "http://localhost:8008" finally: print("Stopping development server...") httpd.shutdown() t.join() print("Development server stopped") @pytest.fixture(scope="function") def calculator_page(driver, dev_server): """Navigate to the calculator page using the development server""" driver.get(f"{dev_server}") # Wait for the page to load and JavaScript to populate navigation WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "sidenav")) ) # Wait for JavaScript to populate the navigation with calculator links WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//a[contains(text(), 'Interest')]")) ) return driver