forked from enviPath/enviPy
[Fix] Frontend Testing Fixtures (#249)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Co-authored-by: Liam Brydon <lbry121@aucklanduni.ac.nz> Reviewed-on: enviPath/enviPy#249
This commit is contained in:
69
tests/frontend/frontend_base.py
Normal file
69
tests/frontend/frontend_base.py
Normal file
@ -0,0 +1,69 @@
|
||||
import os
|
||||
|
||||
from django.conf import settings as s
|
||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||
from django.core.management import call_command
|
||||
from django.test import override_settings
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
|
||||
@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models", CELERY_TASK_ALWAYS_EAGER=True)
|
||||
class EnviPyStaticLiveServerTestCase(StaticLiveServerTestCase):
|
||||
fixtures = ["test_fixtures_incl_model.jsonl.gz"]
|
||||
|
||||
@staticmethod
|
||||
def repair_polymorphic_ctypes():
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from epdb.models import EPModel
|
||||
|
||||
for obj in EPModel.objects.filter(polymorphic_ctype__isnull=True):
|
||||
obj.polymorphic_ctype = ContentType.objects.get_for_model(obj.__class__)
|
||||
obj.save(update_fields=["polymorphic_ctype"])
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||||
super().setUpClass()
|
||||
|
||||
cls.playwright = sync_playwright().start()
|
||||
cls.browser = cls.playwright.chromium.launch()
|
||||
cls.username = "user0"
|
||||
cls.password = "SuperSafe"
|
||||
|
||||
def setUp(self):
|
||||
# DB gets flushed after each test and rolled back to initial fixture state.
|
||||
# Hence, we have to localize the urls per test.
|
||||
# The fixtures have "http://localhost:8000/" in all of the URLs
|
||||
# Use the custom mgmt command to adjust it to the current live_server_url
|
||||
call_command("localize_urls", old="http://localhost:8000/", new=f"{self.live_server_url}/")
|
||||
|
||||
# Fix broken polymorphic ctypes
|
||||
EnviPyStaticLiveServerTestCase.repair_polymorphic_ctypes()
|
||||
|
||||
s.SERVER_URL = self.live_server_url
|
||||
self.context = self.browser.new_context()
|
||||
self.page = self.context.new_page()
|
||||
|
||||
def tearDown(self):
|
||||
self.page.wait_for_load_state("networkidle")
|
||||
self.page.close()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.browser.close()
|
||||
cls.playwright.stop()
|
||||
super().tearDownClass()
|
||||
|
||||
def login(self):
|
||||
"""Sign in with the test user, 'user0'"""
|
||||
self.page.goto(self.live_server_url + "/login")
|
||||
self.page.get_by_role("textbox", name="Username").click()
|
||||
self.page.get_by_role("textbox", name="Username").fill(self.username)
|
||||
self.page.get_by_role("textbox", name="Password").click()
|
||||
self.page.get_by_role("textbox", name="Password").fill(self.password)
|
||||
|
||||
with self.page.expect_navigation():
|
||||
self.page.get_by_role("button", name="Sign In").click()
|
||||
|
||||
return self.page
|
||||
@ -1,108 +1,38 @@
|
||||
import os
|
||||
|
||||
from django.conf import settings as s
|
||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||
from django.test import tag
|
||||
from playwright.sync_api import expect, sync_playwright
|
||||
from playwright.sync_api import expect
|
||||
|
||||
from epdb.logic import UserManager
|
||||
from epdb.models import User, ExternalDatabase
|
||||
from .frontend_base import EnviPyStaticLiveServerTestCase
|
||||
|
||||
|
||||
class TestHomepage(StaticLiveServerTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||||
super().setUpClass()
|
||||
cls.playwright = sync_playwright().start()
|
||||
cls.browser = cls.playwright.chromium.launch()
|
||||
|
||||
def setUp(self):
|
||||
# Create test data
|
||||
s.SERVER_URL = self.live_server_url
|
||||
self.anonymous = UserManager.create_user(
|
||||
"anonymous",
|
||||
"anon@envipath.com",
|
||||
"SuperSafe",
|
||||
is_active=True,
|
||||
add_to_group=False,
|
||||
set_setting=False,
|
||||
)
|
||||
databases = [
|
||||
{
|
||||
"name": "PubChem Compound",
|
||||
"full_name": "PubChem Compound Database",
|
||||
"description": "Chemical database of small organic molecules",
|
||||
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/compound/{id}",
|
||||
},
|
||||
{
|
||||
"name": "PubChem Substance",
|
||||
"full_name": "PubChem Substance Database",
|
||||
"description": "Database of chemical substances",
|
||||
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/substance/{id}",
|
||||
},
|
||||
{
|
||||
"name": "ChEBI",
|
||||
"full_name": "Chemical Entities of Biological Interest",
|
||||
"description": "Dictionary of molecular entities",
|
||||
"base_url": "https://www.ebi.ac.uk/chebi",
|
||||
"url_pattern": "https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:{id}",
|
||||
},
|
||||
{
|
||||
"name": "RHEA",
|
||||
"full_name": "RHEA Reaction Database",
|
||||
"description": "Comprehensive resource of biochemical reactions",
|
||||
"base_url": "https://www.rhea-db.org",
|
||||
"url_pattern": "https://www.rhea-db.org/rhea/{id}",
|
||||
},
|
||||
{
|
||||
"name": "KEGG Reaction",
|
||||
"full_name": "KEGG Reaction Database",
|
||||
"description": "Database of biochemical reactions",
|
||||
"base_url": "https://www.genome.jp",
|
||||
"url_pattern": "https://www.genome.jp/entry/{id}",
|
||||
},
|
||||
{
|
||||
"name": "UniProt",
|
||||
"full_name": "MetaCyc Metabolic Pathway Database",
|
||||
"description": "UniProt is a freely accessible database of protein sequence and functional information",
|
||||
"base_url": "https://www.uniprot.org",
|
||||
"url_pattern": 'https://www.uniprot.org/uniprotkb?query="{id}"',
|
||||
},
|
||||
]
|
||||
|
||||
for db_info in databases:
|
||||
ExternalDatabase.objects.get_or_create(name=db_info["name"], defaults=db_info)
|
||||
self.username = "testuser"
|
||||
self.password = "password123"
|
||||
self.user = User.objects.create_user(username=self.username, password=self.password)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super().tearDownClass()
|
||||
cls.browser.close()
|
||||
cls.playwright.stop()
|
||||
class TestHomepage(EnviPyStaticLiveServerTestCase):
|
||||
@tag("frontend")
|
||||
def test_predict(self):
|
||||
page = self.login()
|
||||
page.get_by_role("textbox", name="canonical SMILES string").click()
|
||||
page.get_by_role("textbox", name="canonical SMILES string").fill("CCCN")
|
||||
page.get_by_role("button", name="Predict!").click()
|
||||
# Check that the pathway box is visible
|
||||
expect(page.locator("rect")).to_be_visible(timeout=10000)
|
||||
|
||||
@tag("frontend")
|
||||
def test_login(self):
|
||||
def test_advanced_predict(self):
|
||||
page = self.login()
|
||||
expect(page.locator("#loggedInButton")).to_be_visible()
|
||||
page.close()
|
||||
page.get_by_role("link", name="Advanced").click()
|
||||
# Check predict page opens correctly
|
||||
expect(page.get_by_role("heading", name="Predict a Pathway in")).to_be_visible()
|
||||
page.get_by_role("textbox", name="Name").click()
|
||||
page.get_by_role("textbox", name="Name").fill("Test Pathway")
|
||||
page.get_by_role("textbox", name="Description").click()
|
||||
page.get_by_role("textbox", name="Description").fill("Test Description")
|
||||
page.get_by_role("textbox", name="SMILES").click()
|
||||
page.get_by_role("textbox", name="SMILES").fill("OCCCN")
|
||||
page.locator("#predict-submit-button").click()
|
||||
# Check that the pathway box is visible
|
||||
expect(page.locator("rect")).to_be_visible(timeout=10000)
|
||||
|
||||
@tag("frontend")
|
||||
def test_go_home(self) -> None:
|
||||
page = self.login()
|
||||
page.get_by_role("link").first.click()
|
||||
# Check the homepage predict box is visible
|
||||
expect(page.get_by_text("SMILES Draw Predict! Caffeine")).to_be_visible()
|
||||
|
||||
def login(self):
|
||||
page = self.browser.new_page()
|
||||
page.goto(self.live_server_url + "/login/")
|
||||
page.get_by_role("textbox", name="Username").click()
|
||||
page.get_by_role("textbox", name="Username").fill(self.username)
|
||||
page.get_by_role("textbox", name="Password").click()
|
||||
page.get_by_role("textbox", name="Password").fill(self.password)
|
||||
page.get_by_role("button", name="Sign In").click()
|
||||
return page
|
||||
|
||||
51
tests/frontend/test_loginpage.py
Normal file
51
tests/frontend/test_loginpage.py
Normal file
@ -0,0 +1,51 @@
|
||||
from django.test import tag
|
||||
from playwright.sync_api import expect
|
||||
from django.conf import settings as s
|
||||
from .frontend_base import EnviPyStaticLiveServerTestCase
|
||||
|
||||
|
||||
class TestLoginPage(EnviPyStaticLiveServerTestCase):
|
||||
@tag("frontend")
|
||||
def test_register(self):
|
||||
page = self.page
|
||||
page.goto(self.live_server_url + "/login")
|
||||
page.get_by_text("Register", exact=True).click()
|
||||
page.get_by_role("textbox", name="Username").click()
|
||||
page.get_by_role("textbox", name="Username").fill("newuser")
|
||||
page.get_by_role("textbox", name="Email").click()
|
||||
page.get_by_role("textbox", name="Email").fill("newuser@new.com")
|
||||
page.get_by_role("textbox", name="Password", exact=True).click()
|
||||
page.get_by_role("textbox", name="Password", exact=True).fill("NewUser_1")
|
||||
page.get_by_role("textbox", name="Repeat Password").click()
|
||||
page.get_by_role("textbox", name="Repeat Password").fill("NewUser_1")
|
||||
page.get_by_role("button", name="Sign Up").click()
|
||||
|
||||
if s.ADMIN_APPROVAL_REQUIRED:
|
||||
expected_text = "Your account has been created! An admin will activate it soon!"
|
||||
else:
|
||||
expected_text = (
|
||||
"Account has been created! You'll receive a mail to activate your account shortly."
|
||||
)
|
||||
# Check for success text after Sign Up is clicked
|
||||
expect(page.get_by_text(expected_text)).to_be_visible(timeout=10000)
|
||||
|
||||
if s.ADMIN_APPROVAL_REQUIRED:
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
u = get_user_model().objects.get(username="newuser")
|
||||
u.is_active = True
|
||||
u.save()
|
||||
|
||||
page.get_by_role("textbox", name="Username").click()
|
||||
page.get_by_role("textbox", name="Username").fill("newuser")
|
||||
page.get_by_role("textbox", name="Password").click()
|
||||
page.get_by_role("textbox", name="Password").fill("NewUser_1")
|
||||
page.get_by_role("button", name="Sign In").click()
|
||||
# Check that the logged in button is visible indicating the user is logged in
|
||||
expect(page.locator("#loggedInButton")).to_be_visible(timeout=100000000)
|
||||
|
||||
@tag("frontend")
|
||||
def test_login(self):
|
||||
page = self.login()
|
||||
# Check that the logged in button is visible indicating the user is logged in
|
||||
expect(page.locator("#loggedInButton")).to_be_visible()
|
||||
69
tests/frontend/test_packagepage.py
Normal file
69
tests/frontend/test_packagepage.py
Normal file
@ -0,0 +1,69 @@
|
||||
import re
|
||||
from django.test import tag
|
||||
from playwright.sync_api import expect
|
||||
|
||||
from .frontend_base import EnviPyStaticLiveServerTestCase
|
||||
|
||||
|
||||
class TestPackagePage(EnviPyStaticLiveServerTestCase):
|
||||
@tag("frontend")
|
||||
def test_create_package(self):
|
||||
page = self.login()
|
||||
page = self.create_package(page)
|
||||
# Check the package name is correct
|
||||
expect(page.locator("h2")).to_contain_text("test package")
|
||||
|
||||
@tag("frontend")
|
||||
def test_package_permissions(self):
|
||||
page = self.login()
|
||||
page = self.create_package(page)
|
||||
page.get_by_role("button", name="Actions").click()
|
||||
page.get_by_role("button", name="Edit Permissions").click()
|
||||
# Add read and write permission to enviPath Users group
|
||||
page.locator("#select_grantee").select_option(label="enviPath Users")
|
||||
page.locator("#read_new").check()
|
||||
page.locator("#write_new").check()
|
||||
page.get_by_role("button", name="+", exact=True).click()
|
||||
page.get_by_role("button", name="Actions").click()
|
||||
page.get_by_role("button", name="Edit Permissions").click()
|
||||
# Check the permissions saved when re-opening the permissions box
|
||||
expect(page.get_by_text("enviPath Users")).to_be_visible()
|
||||
|
||||
@tag("frontend")
|
||||
def test_predict_in_package(self):
|
||||
page = self.login()
|
||||
page = self.create_package(page)
|
||||
pathway_button = page.get_by_role("link", name="Pathways")
|
||||
# Find number of current pathways by extracting it from pathway button
|
||||
num_pathways = int(re.search(r"Pathways \((\d+)\)", pathway_button.inner_text()).group(1))
|
||||
pathway_button.click()
|
||||
page.get_by_role("button", name="Actions").click()
|
||||
page.get_by_role("link", name="New Pathway").click()
|
||||
# Check that the predict page 'in [package_name]' text shows the current package
|
||||
expect(page.get_by_role("strong").get_by_text("test package")).to_be_visible()
|
||||
page.get_by_role("textbox", name="Name").click()
|
||||
page.get_by_role("textbox", name="Name").fill("Test Pathway")
|
||||
page.get_by_role("textbox", name="Description").click()
|
||||
page.get_by_role("textbox", name="Description").fill("Test description")
|
||||
page.get_by_role("textbox", name="SMILES").click()
|
||||
page.get_by_role("textbox", name="SMILES").fill("OCCCN")
|
||||
page.locator("#predict-submit-button").click()
|
||||
# Check a pathway is visible
|
||||
expect(page.locator("rect")).to_be_visible()
|
||||
page.get_by_role("link", name="test package").click()
|
||||
# Check that the package now has one more pathway than initially
|
||||
expect(page.locator("#docContent")).to_contain_text(f"Pathways ({num_pathways + 1})")
|
||||
|
||||
@staticmethod
|
||||
def create_package(page):
|
||||
"""Make a new empty package with name 'test package'"""
|
||||
page.get_by_role("button", name="Browse").click()
|
||||
page.get_by_role("link", name="Package", exact=True).click()
|
||||
page.get_by_role("button", name="Actions").click()
|
||||
page.get_by_role("button", name="New Package").click()
|
||||
page.get_by_role("textbox", name="Name").click()
|
||||
page.get_by_role("textbox", name="Name").fill("test package")
|
||||
page.get_by_role("textbox", name="Description").click()
|
||||
page.get_by_role("textbox", name="Description").fill("test description")
|
||||
page.get_by_role("button", name="Submit").click()
|
||||
return page
|
||||
Reference in New Issue
Block a user