Created
May 9, 2025 15:38
-
-
Save DArmstrong87/83647b4f157089fb73c6cda2b854f73c to your computer and use it in GitHub Desktop.
Django Test with Selenium
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import time | |
| from unittest import skipIf | |
| from django.contrib.staticfiles.testing import StaticLiveServerTestCase | |
| from django.conf import settings | |
| from django.test.client import Client | |
| # Selenium imports | |
| from selenium import webdriver | |
| from selenium.webdriver.common.by import By | |
| from selenium.webdriver.support import expected_conditions as EC | |
| from selenium.webdriver.support.ui import Select, WebDriverWait | |
| from authentication.group_permissions import AuthGroups | |
| from .utils import create_user, IGNORED_BROWSER_ERRORS | |
| class FormSeleniumTestCase(StaticLiveServerTestCase): | |
| """ | |
| In order for this test to work in github actions, | |
| you must set up the workflow to add Chrome and the Chrome driver. | |
| Once you do that, you can remove the skipIf decorator. | |
| """ | |
| # Time to wait for elements to change after an action | |
| DELAY = 0 | |
| # Whether to show the browser | |
| SHOW_BROWSER = False | |
| def get_state(self) -> dict: | |
| """Return state from javascript""" | |
| return self.driver.execute_script(""" return state; """) | |
| def print_console_logs(self): | |
| """Print browser console logs""" | |
| logs = self.driver.get_log("browser") | |
| if logs: | |
| print("\n=== Browser Console Logs ===") | |
| for log in logs: | |
| print(f"[{log['level']}] {log['message']}") | |
| print("===========================\n") | |
| # Always print current state | |
| state = self.get_state() | |
| print("\n=== Current State ===") | |
| print(f"State: {state}") | |
| @skipIf(not settings.IS_LOCAL_DEV, "Test does not work in github actions") | |
| def setUp(self): | |
| # Use a unique port for this test run | |
| self.live_server_url = f"http://localhost:{self.server_thread.port}" | |
| user = create_user(AuthGroups.ADMIN.value) | |
| self.client = Client() | |
| self.client.force_login(user) | |
| chrome_options = webdriver.ChromeOptions() | |
| if not self.SHOW_BROWSER: | |
| chrome_options.add_argument("--headless") | |
| chrome_options.set_capability( | |
| "goog:loggingPrefs", {"browser": "ALL"} | |
| ) # Enable all browser logs | |
| self.driver = webdriver.Chrome(options=chrome_options) | |
| def print_available_elements(self): | |
| """Print all elements with IDs on the page""" | |
| print("\n=== Available Elements ===") | |
| elements = self.driver.find_elements(By.CSS_SELECTOR, "[id]") | |
| for element in elements: | |
| print(f"ID: {element.get_attribute('id')}") | |
| print("=========================\n") | |
| @skipIf(not settings.IS_LOCAL_DEV, "Test does not work in github actions") | |
| def test_elements(self): | |
| """ | |
| Tests state changes when selecting an element | |
| """ | |
| self.driver.get(self.live_server_url) | |
| cookie = self.client.cookies["sessionid"] | |
| self.driver.add_cookie( | |
| {"name": "sessionid", "value": cookie.value, "secure": False, "path": "/"} | |
| ) | |
| self.driver.refresh() | |
| self.driver.get(self.live_server_url + "/app/my-url") | |
| # Wait for an element that indicates the JavaScript file has loaded | |
| WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.ID, "submit-button"))) | |
| my_select_element = self.driver.find_element(By.ID, "mySelect") | |
| self.assertIsNotNone(my_select_element) | |
| my_select = Select(my_select_element) | |
| my_select.select_by_visible_text("Text shown on the select element") | |
| time.sleep(self.DELAY) | |
| self.print_console_logs() | |
| my_number_input= self.driver.find_element(By.ID, "myNumberInput") | |
| my_number_input.send_keys(3) | |
| time.sleep(self.DELAY) | |
| self.print_console_logs() | |
| # Check for uncaught errors in the logs | |
| # Fail test if errors found | |
| browser_log = self.driver.get_log("browser") | |
| for entry in browser_log: | |
| if entry.get("level") == "SEVERE": | |
| if ( | |
| any([err for err in IGNORED_BROWSER_ERRORS if err in entry.get("message")]) | |
| or "cloudflare" in entry.get("message").lower() | |
| ): | |
| print("Ignoring browser log:", entry.get("message")) | |
| else: | |
| self.fail(f"Console error: {entry.get('message')}") | |
| def tearDown(self): | |
| self.client.logout() | |
| self.driver.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment