import pytest from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.options import Options import time from selenium.webdriver.common.keys import Keys @pytest.fixture(scope="function") def driver(): """Create a new browser instance for each test""" chrome_options = Options() chrome_options.add_argument("--headless") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--disable-gpu") driver = webdriver.Chrome(options=chrome_options) driver.implicitly_wait(10) yield driver driver.quit() # calculator_page fixture is now defined in conftest.py class TestCalculatorNavigation: """Test calculator navigation and basic functionality""" def test_debug_page_content(self, driver): """Debug test to see what's actually on the page""" driver.get("http://localhost:8008") # Wait for basic page structure WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "sidenav")) ) # Print page title and basic info print(f"\nPage title: {driver.title}") print(f"Current URL: {driver.current_url}") # Check if sidenav has any content sidenav = driver.find_element(By.CLASS_NAME, "sidenav") print(f"Sidenav HTML: {sidenav.get_attribute('innerHTML')}") # Check for JavaScript errors in console logs = driver.get_log('browser') if logs: print(f"\nBrowser console logs:") for log in logs: print(f" {log['level']}: {log['message']}") # Check if app.js loaded try: app_js = driver.find_element(By.XPATH, "//script[@src='/js/app.js']") print(f"App.js script tag found: {app_js.get_attribute('outerHTML')}") except: print("App.js script tag NOT found!") # Wait a bit longer and check again time.sleep(3) sidenav_after_wait = driver.find_element(By.CLASS_NAME, "sidenav") print(f"Sidenav HTML after 3s wait: {sidenav_after_wait.get_attribute('innerHTML')}") # This test should always pass for debugging assert True def test_page_loads(self, calculator_page): """Test that the calculator page loads correctly""" assert "calculator.127local.net" in calculator_page.title assert calculator_page.find_element(By.CLASS_NAME, "sidenav") assert calculator_page.find_element(By.CLASS_NAME, "content") def test_calculator_list(self, calculator_page): """Test that all calculators are listed in navigation""" nav_items = calculator_page.find_elements(By.CSS_SELECTOR, ".sidenav a") calculator_names = [item.text for item in nav_items] expected_calculators = [ "Interest (Simple & Compound)", "Bandwidth", "NMEA", "RAID", "Currency Converter" ] for expected in expected_calculators: assert expected in calculator_names, f"Calculator {expected} not found in navigation" class TestInterestCalculator: """Test the Interest calculator functionality""" def test_interest_calculator_loads(self, calculator_page): """Test that interest calculator loads and displays correctly""" # Click on interest calculator interest_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Interest')]") interest_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "principal")) ) # Check that all inputs are present assert calculator_page.find_element(By.NAME, "principal") assert calculator_page.find_element(By.NAME, "rate") assert calculator_page.find_element(By.NAME, "compound") assert calculator_page.find_element(By.NAME, "years") assert calculator_page.find_element(By.NAME, "contrib") assert calculator_page.find_element(By.NAME, "contribFreq") def test_simple_interest_calculation(self, calculator_page): """Test simple interest calculation""" # Load interest calculator interest_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Interest')]") interest_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "principal")) ) # Set values for simple interest principal_input = calculator_page.find_element(By.NAME, "principal") rate_input = calculator_page.find_element(By.NAME, "rate") years_input = calculator_page.find_element(By.NAME, "years") compound_select = calculator_page.find_element(By.NAME, "compound") principal_input.clear() principal_input.send_keys("1000") rate_input.clear() rate_input.send_keys("5") years_input.clear() years_input.send_keys("3") # Select simple interest (no compounding) # Click on the Select Lite button to open dropdown compound_button = calculator_page.find_element(By.CSS_SELECTOR, '[name="compound"] + .select-lite__button') compound_button.click() # Wait for dropdown to appear and select Simple option simple_option = WebDriverWait(calculator_page, 10).until( EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'select-lite__option') and contains(text(), 'Simple')]")) ) simple_option.click() # Wait for calculation time.sleep(1) # Check result result = calculator_page.find_element(By.CLASS_NAME, "result") assert "Future value:" in result.text assert "1,150.00" in result.text # 1000 + (1000 * 0.05 * 3) def test_compound_interest_calculation(self, calculator_page): """Test compound interest calculation""" # Load interest calculator interest_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Interest')]") interest_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "principal")) ) # Set values for compound interest principal_input = calculator_page.find_element(By.NAME, "principal") rate_input = calculator_page.find_element(By.NAME, "rate") years_input = calculator_page.find_element(By.NAME, "years") principal_input.clear() principal_input.send_keys("1000") rate_input.clear() rate_input.send_keys("5") years_input.clear() years_input.send_keys("3") # Wait for calculation time.sleep(1) # Check result (should be higher than simple interest) result = calculator_page.find_element(By.CLASS_NAME, "result") assert "Future value:" in result.text # Compound interest should be > 1150 (simple interest result) assert "1,150.00" not in result.text or "1,157.63" in result.text class TestCurrencyConverter: """Test the Currency Converter functionality""" def test_currency_converter_loads(self, calculator_page): """Test that currency converter loads and displays correctly""" # Click on currency converter currency_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Currency Converter')]") currency_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "amount")) ) # Check that all inputs are present assert calculator_page.find_element(By.NAME, "amount") assert calculator_page.find_element(By.NAME, "from") assert calculator_page.find_element(By.NAME, "to") def test_currency_conversion_same_currency(self, calculator_page): """Test conversion when from and to currencies are the same""" # Load currency converter currency_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Currency Converter')]") currency_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "amount")) ) # Debug: verify we're on the currency converter print(f"Current URL: {calculator_page.current_url}") print(f"Page title: {calculator_page.title}") # Check for currency converter specific elements try: from_select = calculator_page.find_element(By.NAME, "from") to_select = calculator_page.find_element(By.NAME, "to") print(f"From select value: {from_select.get_attribute('value')}") print(f"To select value: {to_select.get_attribute('value')}") except Exception as e: print(f"Error finding currency elements: {e}") # Set amount amount_input = calculator_page.find_element(By.NAME, "amount") amount_input.clear() amount_input.send_keys("100") # Trigger calculation by changing the amount amount_input.send_keys(Keys.TAB) # Wait for calculation to complete WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "result")) ) # Wait a bit more for the currency converter to fully load and replace the old result time.sleep(1) # Find all result elements and get the one that's actually visible/contains currency content result_elements = calculator_page.find_elements(By.CLASS_NAME, "result") # Look for the result element that contains currency-related content currency_result = None for elem in result_elements: html = elem.get_attribute('innerHTML') if 'USD' in html or 'EUR' in html or 'Currency' in html or 'conversion' in html.lower(): currency_result = elem break if not currency_result: # If no currency result found, use the last result element (most recent) currency_result = result_elements[-1] # Check result assert "100 USD" in currency_result.text or "100 EUR" in currency_result.text def test_currency_conversion_different_currencies(self, calculator_page): """Test conversion between different currencies""" # Load currency converter currency_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Currency Converter')]") currency_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "amount")) ) # Set amount amount_input = calculator_page.find_element(By.NAME, "amount") amount_input.clear() amount_input.send_keys("100") # Trigger calculation by changing the amount amount_input.send_keys(Keys.TAB) # Wait for calculation and API response WebDriverWait(calculator_page, 15).until( EC.presence_of_element_located((By.CLASS_NAME, "result")) ) # Wait a bit more for the currency converter to fully load and replace the old result time.sleep(1) # Find all result elements and get the one that's actually visible/contains currency content result_elements = calculator_page.find_elements(By.CLASS_NAME, "result") # Look for the result element that contains currency-related content currency_result = None for elem in result_elements: html = elem.get_attribute('innerHTML') if 'USD' in html or 'EUR' in html or 'Currency' in html or 'conversion' in html.lower(): currency_result = elem break if not currency_result: # If no currency result found, use the last result element (most recent) currency_result = result_elements[-1] # Check that some result is displayed assert currency_result.text.strip() != "" # Check for either conversion result or static rates message assert any(text in currency_result.text for text in ["USD", "EUR", "Static rates", "Live rates"]) class TestBandwidthCalculator: """Test the Bandwidth calculator functionality""" def test_bandwidth_calculator_loads(self, calculator_page): """Test that bandwidth calculator loads""" bandwidth_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Bandwidth')]") bandwidth_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "result")) ) # Check that result area is present assert calculator_page.find_element(By.CLASS_NAME, "result") class TestNMEACalculator: """Test the NMEA calculator functionality""" def test_nmea_calculator_loads(self, calculator_page): """Test that NMEA calculator loads""" nmea_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'NMEA')]") nmea_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "result")) ) # Check that result area is present assert calculator_page.find_element(By.CLASS_NAME, "result") class TestRAIDCalculator: """Test the RAID calculator functionality""" def test_raid_calculator_loads(self, calculator_page): """Test that RAID calculator loads""" raid_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'RAID')]") raid_btn.click() # Wait for calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "result")) ) # Check that result area is present assert calculator_page.find_element(By.CLASS_NAME, "result") class TestCalculatorResponsiveness: """Test calculator responsiveness and UI behavior""" def test_theme_toggle(self, calculator_page): """Test that theme toggle button works""" theme_btn = calculator_page.find_element(By.ID, "themeToggle") initial_text = theme_btn.text # Click theme toggle theme_btn.click() # Wait for theme change time.sleep(1) # Check that text changed assert theme_btn.text != initial_text def test_calculator_switching(self, calculator_page): """Test switching between different calculators""" # Start with interest calculator interest_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Interest')]") interest_btn.click() # Wait for interest calculator to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "principal")) ) # Switch to currency converter currency_btn = calculator_page.find_element(By.XPATH, "//a[contains(text(), 'Currency Converter')]") currency_btn.click() # Wait for currency converter to load WebDriverWait(calculator_page, 10).until( EC.presence_of_element_located((By.NAME, "amount")) ) # Verify we're on currency converter assert calculator_page.find_element(By.NAME, "amount") assert calculator_page.find_element(By.NAME, "from") assert calculator_page.find_element(By.NAME, "to")