calculator.127local.net/tests/conftest.py
2025-09-01 20:08:03 -07:00

129 lines
4.1 KiB
Python

import contextlib, http.server, os, socket, threading, time
import pytest
import pathlib
import sys
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
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 driver():
"""Set up Chrome driver with options"""
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
yield driver
driver.quit()
@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