aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2026-01-09 17:15:36 +0100
committerDaniel Schadt <kingdread@gmx.de>2026-01-09 17:15:36 +0100
commitadab3f162ddc642f5fe4fad39d0eeda543c1d2db (patch)
tree05400ea0b73e69974f24d00f949a627a4a2d7b3e
parent735d8278e95cb1ac1237992bb93ae6187be4923a (diff)
downloadfietsboek-adab3f162ddc642f5fe4fad39d0eeda543c1d2db.tar.gz
fietsboek-adab3f162ddc642f5fe4fad39d0eeda543c1d2db.tar.bz2
fietsboek-adab3f162ddc642f5fe4fad39d0eeda543c1d2db.zip
have a general populate() to fill some data in
Especially with all the "list" commands, we now see that we always have to put some data into the instance. This is cumbersome, especially as we get to the track commands. Therefore, I added a method to put some data into the instance -- that also helps to ensure that we properly cascade things if we delete a user, for example. Currently, this method only adds two users and two tracks, but I plan to also add comments and friendship associations. Further, we can think about re-writing the playwright tests to use this population as well, instead of the playwright_helper one.
-rw-r--r--tests/assets/picture01.jpgbin0 -> 58545 bytes
-rw-r--r--tests/assets/picture02.jpgbin0 -> 52997 bytes
-rw-r--r--tests/cli/test_fietsctl.py87
-rw-r--r--tests/testutils.py126
4 files changed, 153 insertions, 60 deletions
diff --git a/tests/assets/picture01.jpg b/tests/assets/picture01.jpg
new file mode 100644
index 0000000..cdd6d1b
--- /dev/null
+++ b/tests/assets/picture01.jpg
Binary files differ
diff --git a/tests/assets/picture02.jpg b/tests/assets/picture02.jpg
new file mode 100644
index 0000000..3e38495
--- /dev/null
+++ b/tests/assets/picture02.jpg
Binary files differ
diff --git a/tests/cli/test_fietsctl.py b/tests/cli/test_fietsctl.py
index e1994b6..6e19f21 100644
--- a/tests/cli/test_fietsctl.py
+++ b/tests/cli/test_fietsctl.py
@@ -10,6 +10,7 @@ from sqlalchemy.orm import Session
from fietsboek import models
from .conftest import fietsctl_results # pylint: disable=relative-beyond-top-level
+from ..testutils import populate # pylint: disable=relative-beyond-top-level
class CliChecker:
@@ -119,99 +120,65 @@ def test_user_add(fietsctl, dbsession):
assert user.is_verified
-def test_user_list(fietsctl, dbengine):
- with Session(dbengine) as session:
- user = models.User(name="Shauna", email="vayne@lge.com")
- user.set_password("vayne")
- user.roll_session_secret()
- session.add(user)
-
- user = models.User(name="Berri", email="tx@ar.rak", is_admin=True, is_verified=True)
- user.set_password("txarrak")
- user.roll_session_secret()
- session.add(user)
-
- session.commit()
+def test_user_list(fietsctl, dbengine, data_manager):
+ populate(dbengine, data_manager)
res = fietsctl(["user", "list"])
assert res.successful()
- assert res.has_line("vayne@lge\\.com .* Shauna")
- assert res.has_line("av.*tx@ar\\.rak .* Berri")
+ assert res.has_line("av.*jon\\.snow@nw\\.org.*Jon")
+ assert res.has_line("v.*davos@seaworth\\.com.*Davos")
-def test_user_del(fietsctl, dbengine):
- with Session(dbengine) as session:
- user = models.User(name="Shaun", email="murphy@tg.doc", is_verified=True)
- user.set_password("murphy")
- user.roll_session_secret()
- session.add(user)
-
- user = models.User(name="Aaron", email="gl@ss.man", is_verified=True)
- user.set_password("glassman")
- user.roll_session_secret()
- session.add(user)
+def test_user_del(fietsctl, dbengine, data_manager):
+ populate(dbengine, data_manager)
- session.commit()
-
- res = fietsctl(["user", "del", "-f", "--email", "murphy@tg.doc"])
+ res = fietsctl(["user", "del", "-f", "--email", "jon.snow@nw.org"])
assert res.successful()
with dbengine.connect() as conn:
- qry = select(models.User).filter_by(email="gl@ss.man")
+ qry = select(models.User).filter_by(email="davos@seaworth.com")
row = conn.execute(qry).scalar_one_or_none()
assert row
- qry = select(models.User).filter_by(email="murphy@tg.doc")
+ qry = select(models.User).filter_by(email="jon.snow@nw.org")
row = conn.execute(qry).scalar_one_or_none()
assert row is None
- res = fietsctl(["user", "del", "-f", "--email", "gl@ss.man"])
+ res = fietsctl(["user", "del", "-f", "--email", "davos@seaworth.com"])
assert res.successful()
with dbengine.connect() as conn:
- qry = select(models.User).filter_by(email="gl@ss.man")
+ qry = select(models.User).filter_by(email="davos@seaworth.com")
row = conn.execute(qry).scalar_one_or_none()
assert row is None
-def test_user_passwd(fietsctl, dbengine):
- with Session(dbengine) as session:
- user = models.User(name="john", email="dori@n", is_verified=True)
- user.set_password("dorian")
- user.roll_session_secret()
- session.add(user)
- session.commit()
- user_id = user.id
-
- res = fietsctl(["user", "passwd", "--email", "dori@n", "--password", "DORIAN"])
+def test_user_passwd(fietsctl, dbengine, data_manager):
+ ids = populate(dbengine, data_manager)
+
+ res = fietsctl(["user", "passwd", "--email", "jon.snow@nw.org", "--password", "Ghost"])
assert res.successful()
with Session(dbengine) as session:
- user = session.get(models.User, user_id)
- user.check_password("DORIAN")
+ user = session.get(models.User, ids.jon)
+ user.check_password("Ghost")
with pytest.raises(models.user.PasswordMismatch):
- user.check_password("dorian")
+ user.check_password("ygritte")
-def test_user_modify(fietsctl, dbengine):
- with Session(dbengine) as session:
- user = models.User(name="stephen", email="str@n.ge")
- user.set_password("strange")
- user.roll_session_secret()
- session.add(user)
- session.commit()
- user_id = user.id
+def test_user_modify(fietsctl, dbengine, data_manager):
+ ids = populate(dbengine, data_manager)
res = fietsctl([
"user", "modify",
- "--email", "str@n.ge",
+ "--email", "davos@seaworth.com",
"--admin",
- "--verified",
- "--set-email", "not-str@n.ge",
+ "--no-verified",
+ "--set-email", "ser.davos@seaworth.com",
])
assert res.successful()
with Session(dbengine) as session:
- user: models.User = session.get(models.User, user_id)
- assert user.is_verified
+ user: models.User = session.get(models.User, ids.davos)
+ assert not user.is_verified
assert user.is_admin
- assert user.email == "not-str@n.ge"
+ assert user.email == "ser.davos@seaworth.com"
diff --git a/tests/testutils.py b/tests/testutils.py
index 810bdf7..9db3673 100644
--- a/tests/testutils.py
+++ b/tests/testutils.py
@@ -1,8 +1,34 @@
"""Various utility functions for testing."""
+import datetime
import gzip
+import io
from pathlib import Path
+from typing import NamedTuple
from playwright.sync_api import Page
+from sqlalchemy import Engine
+from sqlalchemy.orm import Session
+
+from fietsboek import convert, models, util
+from fietsboek.data import DataManager
+
+
+class PopulationIds(NamedTuple):
+ """Collection of database IDs that :func:`populate` returns."""
+ jon: int
+ davos: int
+
+
+def load_test_asset(filename: str) -> bytes:
+ """Load a test asset.
+
+ Unlike :func:`load_gpx_asset`, this function does not do gzip decompression.
+
+ :param filkename: Name of the asset to load.
+ :return: The content of the file as bytes.
+ """
+ asset_dir = Path(__file__).parent / "assets"
+ return (asset_dir / filename).read_bytes()
def load_gpx_asset(filename: str) -> bytes:
@@ -36,3 +62,103 @@ def extract_and_upload(page: Page, filename: str, tmp_path: Path):
page.get_by_label("GPX file").set_input_files(gpx_path)
page.locator(".bi-upload").click()
+
+
+def populate(dbengine: Engine, data_manager: DataManager) -> PopulationIds:
+ """Populates the database and data directory with some test data."""
+ user_ids = []
+ with Session(dbengine) as session:
+ user = models.User(name="Jon", email="jon.snow@nw.org", is_verified=True, is_admin=True)
+ user.set_password("ygritte")
+ user.roll_session_secret()
+ session.add(user)
+ session.flush()
+ user_ids.append(user.id)
+
+ user = models.User(name="Davos", email="davos@seaworth.com", is_verified=True)
+ user.set_password("123456")
+ user.roll_session_secret()
+ session.add(user)
+ session.flush()
+ user_ids.append(user.id)
+
+ session.commit()
+
+ for user_id in user_ids:
+ data_manager.initialize_user(user_id)
+
+ # First track for Jon:
+
+ gpx_data = load_gpx_asset("Teasi_1.gpx.gz")
+ track = convert.smart_convert(gpx_data)
+ path = track.path()
+ track.points = []
+ track.owner_id = user_ids[0]
+ track.title = "Trip around Winterfell"
+ track.visibility = models.track.Visibility.PUBLIC
+ track.type = models.track.TrackType.ORGANIC
+ track.description = "I took my sister for a quick trip around Winterfell"
+ track.badges = []
+ track.link_secret = util.random_link_secret()
+ track.tagged_people = []
+ track.date = datetime.datetime(1984, 1, 2, 10, 11, tzinfo=datetime.UTC)
+ track.transformers = []
+ track.sync_tags({"westeros"})
+
+ with Session(dbengine) as session:
+ session.add(track)
+ session.flush()
+
+ assert track.id is not None
+ manager = data_manager.initialize(track.id)
+ manager.compress_backup(gpx_data)
+
+ track.fast_set_path(path)
+ track.ensure_cache(path)
+ session.add(track.cache)
+
+ image_name = manager.add_image(io.BytesIO(load_test_asset("picture01.jpg")), "PIC001.jpg")
+ image_meta = models.ImageMetadata(track=track, image_name=image_name)
+ image_meta.description = "Beautiful sight out of the Hunter's Gate"
+ session.add(image_meta)
+
+ image_name = manager.add_image(io.BytesIO(load_test_asset("picture02.jpg")), "PIC002.jpg")
+ image_meta = models.ImageMetadata(track=track, image_name=image_name)
+ image_meta.description = "Our steel wire horses ready to gallop"
+ session.add(image_meta)
+
+ session.commit()
+
+ # Second track for Jon:
+
+ gpx_data = load_gpx_asset("MyTourbook_1.gpx.gz")
+ track = convert.smart_convert(gpx_data)
+ path = track.path()
+ track.points = []
+ track.owner_id = user_ids[0]
+ track.title = "Road to Riverrun"
+ track.visibility = models.track.Visibility.PUBLIC
+ track.type = models.track.TrackType.ORGANIC
+ track.description = "Got a wedding to attend!"
+ track.badges = []
+ track.link_secret = util.random_link_secret()
+ track.tagged_people = []
+ track.date = datetime.datetime(1985, 8, 5, 16, 41, tzinfo=datetime.UTC)
+ track.transformers = []
+ track.sync_tags({"westeros"})
+
+ with Session(dbengine) as session:
+ session.add(track)
+ session.flush()
+
+ assert track.id is not None
+ manager = data_manager.initialize(track.id)
+ manager.compress_backup(gpx_data)
+
+ track.fast_set_path(path)
+ track.ensure_cache(path)
+ session.add(track.cache)
+
+ session.commit()
+
+ return PopulationIds(jon=user_ids[0], davos=user_ids[1])