Skip to content

Commit

Permalink
test(frontend): add basic Selenium testing
Browse files Browse the repository at this point in the history
So far, this just checks that the main pages (as listed in the navigation bar) do not 404, have a Django ProgrammingError page displayed, etc. The test uses the Chromium webdriver because it is more complex to set up one test to run with two different webdrivers in sequence. It also opts for emulating the common _desktop_ resolution of 1080p (future tests could check that the navbar expander, etc., work properly, but this is out of scope for test #1).
  • Loading branch information
Restioson committed Oct 18, 2024
1 parent 6d0d8fd commit b1c0813
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Dockerfile-dev
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RUN <<EOF
set -exo pipefail
apt-get update
apt-get -y upgrade
apt-get install -y --no-install-recommends libmagic1 gettext graphviz graphviz-dev
apt-get install -y --no-install-recommends libmagic1 gettext graphviz graphviz-dev chromium
pip install --upgrade pip
pip install -r requirements-dev.txt
EOF
Expand Down
64 changes: 64 additions & 0 deletions app/general/tests/test_frontend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium.common import TimeoutException
from selenium.webdriver.chrome.webdriver import WebDriver, Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait


# Wait timeout in seconds
WAIT_TIMEOUT = 5


class TestFrontend(StaticLiveServerTestCase):
@classmethod
def setUpClass(cls):
opts = Options()
opts.add_argument("--headless")
opts.add_argument("--no-sandbox")
opts.add_argument("--disable-dev-shm-usage")
opts.add_argument("--window-size=1920,1080")
cls.driver = WebDriver(opts)
cls.driver.implicitly_wait(WAIT_TIMEOUT)
super().setUpClass()

@classmethod
def tearDownClass(cls):
cls.driver.quit()
super().tearDownClass()

def test_no_404s(self):
# Sanity check in case we ever change the 404 title
self.driver.get(f"{self.live_server_url}/blabla404")
print(self.driver.title)
assert self.driver.title.startswith(
"Error"
), f"Actual title was {self.driver.title}. Page: {self.driver.page_source}"

# Check main page does not 404
self.driver.get(self.live_server_url)
self.assert_current_page_not_error()

# Check all nav items
for item in ["Search", "Institutions", "Projects", "Documents", "Languages", "Subjects"]:
self.check_nav_item(item)

def check_nav_item(self, link_text):
self.driver.find_element(By.PARTIAL_LINK_TEXT, link_text).click()

# We use 'in' to do a more permissive match (for instance 'Search' is usually '<search query> - Search'
try:
wait = WebDriverWait(self.driver, timeout=WAIT_TIMEOUT)
wait.until(lambda d: link_text in self.driver.title)
except TimeoutException:
assert link_text in self.driver.title, (
f"Expected title for page {link_text} to have {link_text};"
f" was {self.driver.title}"
)
self.assert_current_page_not_error()

def assert_current_page_not_error(self):
assert not self.driver.title.startswith("Error"), f"Actual title was {self.driver.title}"
assert not self.driver.title.startswith(
"ProgrammingError"
), f"Actual title was {self.driver.title}"
assert not self.driver.find_element(By.ID, "error-block").is_displayed()
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ django-debug-toolbar
django-extensions
faker
ruff
selenium==4.25.0

0 comments on commit b1c0813

Please sign in to comment.