-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#203 Create initial Playwright tests
- Loading branch information
Showing
16 changed files
with
560 additions
and
21 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,9 @@ coverage/ | |
cypress/videos/ | ||
cypress/screenshots/ | ||
|
||
# Playwright | ||
test-results/ | ||
|
||
# Data files | ||
*.db | ||
*.db-journal |
This file contains 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
This file contains 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
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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
Empty file.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
""" | ||
Setup and global fixtures for E2E tests. | ||
Called automatically by Pytest before running tests. | ||
""" | ||
|
||
from typing import Any | ||
from collections.abc import Generator | ||
import pytest | ||
from paramdb import ParamDB | ||
from tests.e2e.helpers import setup_db_and_start_server, clear, reset | ||
|
||
|
||
@pytest.fixture(name="db_name", scope="session") | ||
def fixture_db_name() -> str: | ||
"""Database file name.""" | ||
return "param.db" | ||
|
||
|
||
@pytest.fixture(name="db_path", scope="session") | ||
def fixture_db_path( | ||
tmp_path_factory: pytest.TempPathFactory, base_url: str, db_name: str | ||
) -> Generator[str, None, None]: | ||
""" | ||
Path to the ParamDB database. The ParamView server for the database is also started | ||
and cleaned up by this fixture. | ||
""" | ||
db_path = str(tmp_path_factory.mktemp("db") / db_name) | ||
stop_server = setup_db_and_start_server(db_path, base_url) | ||
yield db_path | ||
stop_server() | ||
|
||
|
||
@pytest.fixture(name="db") | ||
def fixture_db(db_path: str) -> ParamDB[Any]: | ||
"""ParamDB database.""" | ||
return ParamDB[Any](db_path) | ||
|
||
|
||
@pytest.fixture(name="_clear_db") | ||
def fixture_clear_db(db: ParamDB[Any]) -> None: | ||
"""Clears the database.""" | ||
clear(db) | ||
|
||
|
||
@pytest.fixture(name="_reset_db") | ||
def fixture_reset_db(db: ParamDB[Any]) -> None: | ||
"""Resets the database.""" | ||
reset(db) | ||
|
||
|
||
@pytest.fixture(name="_reset_single_db") | ||
def fixture_reset_single_db(db: ParamDB[Any]) -> None: | ||
"""Resets the database to have a single commit.""" | ||
reset(db, num_commits=1) | ||
|
||
|
||
@pytest.fixture(name="_reset_long_db") | ||
def fixture_reset_long_db(db: ParamDB[Any]) -> None: | ||
"""Resets the database to have 100 commits.""" | ||
reset(db, num_commits=100) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
"""Helper functions for E2E tests.""" | ||
|
||
from __future__ import annotations | ||
from typing import Any | ||
from collections.abc import Callable | ||
import time | ||
import signal | ||
import subprocess | ||
from datetime import datetime, timedelta, timezone | ||
import requests # type: ignore | ||
from sqlalchemy import delete | ||
from freezegun import freeze_time | ||
import astropy.units as u # type: ignore | ||
from paramdb import ParamDB, Param, Struct, ParamList, ParamDict | ||
from paramdb._database import _Snapshot | ||
|
||
|
||
_SERVER_POLLING_WAIT = 0.1 | ||
_SERVER_POLLING_MAX_RETRIES = int(5 / _SERVER_POLLING_WAIT) | ||
_SERVER_REQUEST_TIMEOUT = 1.0 | ||
_START_DATE = datetime(2023, 1, 1, tzinfo=timezone.utc).astimezone() | ||
|
||
|
||
class _CustomParam(Param): | ||
int: int | ||
str: str | ||
|
||
|
||
class _CustomStruct(Struct): | ||
int: int | ||
str: str | ||
param: _CustomParam | ||
|
||
|
||
def get_date(commit_id: int) -> datetime: | ||
"""Get the date corresponding to the given commit ID.""" | ||
return _START_DATE + timedelta(days=commit_id - 1) | ||
|
||
|
||
def clear(db: ParamDB[Any]) -> None: | ||
"""Clear the database.""" | ||
with db._Session.begin() as session: # pylint: disable=no-member,protected-access | ||
session.execute(delete(_Snapshot)) # Clear all commits | ||
|
||
|
||
def commit( | ||
db: ParamDB[Any], message: str | None = None, data: Any | None = None | ||
) -> None: | ||
"""Make a commit with the given message.""" | ||
num_commits = db.num_commits | ||
commit_id = num_commits + 1 | ||
message = f"Commit {commit_id}" if message is None else message | ||
data = ParamDict(commit_id=commit_id, b=2, c=3) if data is None else data | ||
with freeze_time(get_date(num_commits + 1)): | ||
db.commit(message, data) | ||
|
||
|
||
def reset(db: ParamDB[Any], num_commits: int = 3) -> None: | ||
"""Clear the database and make some initial commits.""" | ||
clear(db) | ||
initial_data = ParamDict( | ||
{ | ||
"commit_id": 1, | ||
"int": 123, | ||
"float": 1.2345, | ||
"bool": True, | ||
"str": "test", | ||
"None": None, | ||
"datetime": get_date(1), | ||
"Quantity": 1.2345 * u.m, | ||
"list": [123, "test"], | ||
"dict": {"int": 123, "str": "test"}, | ||
"paramList": ParamList([123, "test"]), | ||
"paramDict": ParamDict(int=123, str="test"), | ||
"struct": _CustomStruct( | ||
int=123, str="test", param=_CustomParam(int=123, str="test") | ||
), | ||
"param": _CustomParam(int=123, str="test"), | ||
} | ||
) | ||
commit(db, "Initial commit", initial_data) | ||
for _ in range(2, num_commits + 1): | ||
commit(db) | ||
|
||
|
||
def setup_db_and_start_server(db_path: str, base_url: str) -> Callable[[], None]: | ||
""" | ||
Set up the database, start the server, wait for the server to be up, and return a | ||
function to stop the server. | ||
""" | ||
# Verify that the base url is available | ||
try: | ||
requests.get(base_url, timeout=_SERVER_REQUEST_TIMEOUT) | ||
raise RuntimeError(f"{base_url} is already in use.") | ||
except requests.ConnectionError: | ||
time.sleep(_SERVER_POLLING_WAIT) | ||
|
||
reset(ParamDB(db_path)) | ||
|
||
# pylint: disable=consider-using-with | ||
server_process = subprocess.Popen(["paramview", db_path, "--no-open"]) | ||
|
||
# Wait for server to be up | ||
for _ in range(_SERVER_POLLING_MAX_RETRIES): | ||
try: | ||
requests.get(base_url, timeout=_SERVER_REQUEST_TIMEOUT) | ||
break | ||
except requests.ConnectionError: | ||
time.sleep(_SERVER_POLLING_WAIT) | ||
|
||
def stop_server() -> None: | ||
server_process.send_signal(signal.SIGINT) | ||
|
||
return stop_server | ||
|
||
|
||
def load_classes_from_db(db: ParamDB[Any]) -> None: | ||
""" | ||
Load the last commit as Python classes. This helps to test that objects are | ||
formatted properly, in particular datetime and Quantity objects. | ||
""" | ||
db.load() |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"""Tests for the page title.""" | ||
|
||
from playwright.sync_api import Page, expect | ||
|
||
|
||
def test_title_is_db_name(_reset_db: None, page: Page, db_name: str) -> None: | ||
"""Page title is the database file name.""" | ||
page.goto("/") | ||
expect(page).to_have_title(db_name) | ||
|
||
|
||
def test_title_is_error(_clear_db: None, page: Page) -> None: | ||
"""Page title is "Error" if an error has occurred.""" | ||
page.goto("/") | ||
expect(page).to_have_title("Error") |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
"""Tests for parameter editing.""" | ||
|
||
from playwright.sync_api import Page, expect | ||
|
||
|
||
def test_displays_inputs(_reset_single_db: None, page: Page) -> None: | ||
"""Displays correct input for each parameter type.""" | ||
page.goto("/") | ||
page.get_by_test_id("edit-button").click() | ||
expect( | ||
page.get_by_test_id("parameter-list-item-int") | ||
.get_by_test_id("leaf-input") | ||
.get_by_role("textbox") | ||
).to_have_value("123") |
Empty file.
This file contains 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
File renamed without changes.
File renamed without changes.
This file contains 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
File renamed without changes.