aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/bootstrap/test_new_instance.py90
-rw-r--r--tests/conftest.py1
-rw-r--r--tests/integration/test_browse.py90
-rw-r--r--tests/playwright/conftest.py11
-rw-r--r--tests/playwright/test_basic.py27
-rw-r--r--tests/playwright/test_profiles.py2
-rw-r--r--tests/playwright/test_share.py3
-rw-r--r--tests/playwright/test_tileproxy.py4
8 files changed, 192 insertions, 36 deletions
diff --git a/tests/bootstrap/test_new_instance.py b/tests/bootstrap/test_new_instance.py
index dc3076e..05076f4 100644
--- a/tests/bootstrap/test_new_instance.py
+++ b/tests/bootstrap/test_new_instance.py
@@ -2,6 +2,7 @@
script, as described in the documentation.
"""
+import configparser
import contextlib
import logging
import os
@@ -10,6 +11,8 @@ import subprocess
import venv
from pathlib import Path
+import sqlalchemy
+
LOGGER = logging.getLogger(__name__)
REPO_BASE = Path(__file__).parent.parent.parent
@@ -51,31 +54,66 @@ def create_config(config_name: Path):
Path("data").mkdir()
+def cleanup_database(config_name: Path):
+ """Connects to the database and ensures everything is reset.
+
+ :param config_name: Path to the config file.
+ """
+ if not config_name.exists():
+ return
+
+ parser = configparser.ConfigParser()
+ parser["DEFAULT"]["here"] = str(config_name.parent)
+ parser.read(config_name)
+
+ db_url = parser["app:main"]["sqlalchemy.url"]
+ engine = sqlalchemy.create_engine(db_url)
+
+ match engine.name:
+ case "sqlite":
+ pass
+ case "postgresql":
+ with engine.connect() as connection:
+ connection.execute(sqlalchemy.text("DROP SCHEMA public CASCADE;"))
+ connection.execute(sqlalchemy.text("CREATE SCHEMA public;"))
+ connection.commit()
+
+
def test_setup_via_fietsupdate(tmpdir):
with chdir(tmpdir):
- # We create a new temporary virtual environment with a fresh install, just
- # to be sure there's as little interference as possible.
- LOGGER.info("Installing Fietsboek into clean env")
- binaries_path = install_fietsboek(tmpdir / "venv")
-
- LOGGER.info("Creating a test configuration")
- create_config(Path("testing.ini"))
-
- # Try to run the migrations
- subprocess.check_call(
- [binaries_path / "fietsupdate", "update", "-c", "testing.ini", "-f"]
- )
-
- # Also try to add an administrator
- subprocess.check_call([
- binaries_path / "fietsctl",
- "user",
- "add",
- "-c", "testing.ini",
- "--email", "foobar@example.com",
- "--name", "Foo Bar",
- "--password", "raboof",
- "--admin",
- ])
-
- assert True
+ try:
+ # We create a new temporary virtual environment with a fresh install, just
+ # to be sure there's as little interference as possible.
+ LOGGER.info("Installing Fietsboek into clean env")
+ binaries_path = install_fietsboek(tmpdir / "venv")
+
+ LOGGER.info("Installing additional SQL engines")
+ subprocess.check_call(
+ [binaries_path / "pip", "install", "psycopg2"]
+ )
+
+ LOGGER.info("Creating a test configuration")
+ create_config(Path("testing.ini"))
+
+ # Try to run the migrations
+ subprocess.check_call(
+ [binaries_path / "fietsupdate", "update", "-c", "testing.ini", "-f"]
+ )
+
+ # Also try to add an administrator
+ subprocess.check_call([
+ binaries_path / "fietsctl",
+ "user",
+ "add",
+ "-c", "testing.ini",
+ "--email", "foobar@example.com",
+ "--name", "Foo Bar",
+ "--password", "raboof",
+ "--admin",
+ ])
+
+ assert True
+ finally:
+ # Clean up the database. This is important with anything but SQLite, as
+ # the tables would otherwise persist and interfere with the other tests.
+ cleanup_database(Path("testing.ini"))
diff --git a/tests/conftest.py b/tests/conftest.py
index cd74b0b..652d443 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -52,6 +52,7 @@ def dbengine(app_settings, ini_file):
yield engine
+ engine.dispose()
Base.metadata.drop_all(bind=engine)
alembic.command.stamp(alembic_cfg, None, purge=True)
diff --git a/tests/integration/test_browse.py b/tests/integration/test_browse.py
index 875821d..83218cc 100644
--- a/tests/integration/test_browse.py
+++ b/tests/integration/test_browse.py
@@ -22,6 +22,7 @@ def added_tracks(tm, dbsession, owner, data_manager):
tm.abort()
tracks = []
+ track_ids = []
with tm:
track = models.Track(
owner=owner,
@@ -37,6 +38,7 @@ def added_tracks(tm, dbsession, owner, data_manager):
dbsession.flush()
data_manager.initialize(track.id).compress_gpx(load_gpx_asset("MyTourbook_1.gpx.gz"))
tracks.append(track)
+ track_ids.append(track.id)
track = models.Track(
owner=owner,
@@ -52,12 +54,62 @@ def added_tracks(tm, dbsession, owner, data_manager):
dbsession.flush()
data_manager.initialize(track.id).compress_gpx(load_gpx_asset("Teasi_1.gpx.gz"))
tracks.append(track)
+ track_ids.append(track.id)
tm.begin()
tm.doom()
try:
- yield tracks
+ yield track_ids
+ finally:
+ tm.abort()
+ with tm:
+ for track in tracks:
+ dbsession.delete(track)
+ tm.begin()
+ tm.doom()
+
+
+@contextmanager
+def a_lot_of_tracks(tm, dbsession, owner, data_manager):
+ """Adds some tracks to the database session.
+
+ This function should be used as a context manager and it ensures that the
+ added tracks are deleted again after the test, to make a clean slate for
+ the next test.
+ """
+ # The normal transaction is "doomed", so we need to abort it, start a fresh
+ # one, and then explicitely commit it, otherwise we will not persist the
+ # objects to the database.
+ tm.abort()
+
+ gpx_data = load_gpx_asset("MyTourbook_1.gpx.gz")
+
+ tracks = []
+ track_ids = []
+ with tm:
+ for index in range(50):
+ track = models.Track(
+ owner=owner,
+ title=f"Traxi {index}",
+ visibility=Visibility.PUBLIC,
+ description="One of many",
+ badges=[],
+ link_secret="foobar",
+ tagged_people=[],
+ )
+ track.date = datetime(2022 - index, 3, 14, 9, 26, 59)
+ dbsession.add(track)
+ dbsession.flush()
+ data_manager.initialize(track.id).compress_gpx(gpx_data)
+ tracks.append(track)
+ track_ids.append(track.id)
+
+ tm.begin()
+ tm.doom()
+
+ try:
+ yield track_ids
finally:
tm.abort()
with tm:
@@ -78,15 +130,43 @@ def test_browse(testapp, dbsession, route_path, logged_in, tm, data_manager):
assert "Barfoo" in browse.text
+def test_browse_paged(testapp, dbsession, route_path, logged_in, tm, data_manager):
+ # pylint: disable=too-many-positional-arguments
+ with a_lot_of_tracks(tm, dbsession, logged_in, data_manager):
+ page_1 = testapp.get(route_path("browse", _query=[("page", 1)]))
+ assert "Traxi 0" in page_1.text
+ assert "Traxi 10" in page_1.text
+ assert "Traxi 20" not in page_1.text
+ assert "Traxi 30" not in page_1.text
+ assert "Traxi 40" not in page_1.text
+
+ page_2 = testapp.get(route_path("browse", _query=[("page", 2)]))
+ assert "Traxi 0" not in page_2.text
+ assert "Traxi 10" not in page_2.text
+ assert "Traxi 20" in page_2.text
+ assert "Traxi 30" in page_2.text
+ assert "Traxi 40" not in page_2.text
+
+ page_3 = testapp.get(route_path("browse", _query=[("page", 3)]))
+ assert "Traxi 0" not in page_3.text
+ assert "Traxi 10" not in page_3.text
+ assert "Traxi 20" not in page_3.text
+ assert "Traxi 30" not in page_3.text
+ assert "Traxi 40" in page_3.text
+
+
def test_archive(testapp, dbsession, route_path, logged_in, tm, data_manager):
# pylint: disable=too-many-positional-arguments
- with added_tracks(tm, dbsession, logged_in, data_manager):
+ with added_tracks(tm, dbsession, logged_in, data_manager) as tracks:
archive = testapp.get(
- route_path('track-archive', _query=[("track_id[]", "1"), ("track_id[]", "2")])
+ route_path(
+ 'track-archive',
+ _query=[("track_id[]", tracks[0]), ("track_id[]", tracks[1])],
+ )
)
result = io.BytesIO(archive.body)
with zipfile.ZipFile(result, 'r') as zipped:
assert len(zipped.namelist()) == 2
- assert "track_1.gpx" in zipped.namelist()
- assert "track_2.gpx" in zipped.namelist()
+ assert f"track_{tracks[0]}.gpx" in zipped.namelist()
+ assert f"track_{tracks[1]}.gpx" in zipped.namelist()
diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py
index 4e7f5a4..adf5ef3 100644
--- a/tests/playwright/conftest.py
+++ b/tests/playwright/conftest.py
@@ -7,10 +7,12 @@ from wsgiref import simple_server
from pyramid.authentication import AuthTktCookieHelper
from pyramid.testing import DummyRequest
+import fietsboek.config
from testutils import load_gpx_asset
from fietsboek import models, util, actions
from fietsboek.models.track import Visibility, TrackType
from fietsboek.config import Config
+from fietsboek.views.tileproxy import TileRequester
import pytest
@@ -55,7 +57,11 @@ def dbaccess(app):
through and the running WSGI app cannot read them.
"""
session_factory = app.registry["dbsession_factory"]
- return session_factory()
+ factory = session_factory()
+
+ yield factory
+
+ factory.close()
class Helper:
@@ -112,11 +118,14 @@ class Helper:
"""
if user is None:
user = self.john_doe()
+ config = fietsboek.config.parse(self.app_settings)
with self.dbaccess:
user = self.dbaccess.merge(user)
track = actions.add_track(
self.dbaccess,
self.data_manager,
+ TileRequester(None),
+ config.public_tile_layers()[0],
owner=user,
title="Another awesome track",
visibility=Visibility.PRIVATE,
diff --git a/tests/playwright/test_basic.py b/tests/playwright/test_basic.py
index 231962e..3ae0f58 100644
--- a/tests/playwright/test_basic.py
+++ b/tests/playwright/test_basic.py
@@ -101,6 +101,33 @@ def test_edit(page: Page, playwright_helper, dbaccess):
assert track.description == "Not so descriptive anymore"
+def test_edit_change_gpx(page: Page, playwright_helper, tmp_path, dbaccess):
+ playwright_helper.login()
+ track_id = playwright_helper.add_track().id
+
+ track = dbaccess.execute(select(models.Track).filter_by(id=track_id)).scalar_one()
+ old_cache = track.cache.length, track.cache.uphill, track.cache.downhill
+
+ page.goto(f"/track/{track_id}")
+ page.locator(".btn", has_text="Edit").click()
+
+ gpx_data = load_gpx_asset("Synthetic_BRouter_1.gpx.gz")
+ gpx_path = tmp_path / "NewGPX.gpx"
+ with open(gpx_path, "wb") as gpx_fobj:
+ gpx_fobj.write(gpx_data)
+
+ page.get_by_label("New file for this track").set_input_files(gpx_path)
+ page.locator(".btn", has_text="Save").click()
+
+ track = dbaccess.execute(select(models.Track).filter_by(id=track_id)).scalar_one()
+ new_cache = track.cache
+ dbaccess.refresh(new_cache)
+
+ assert old_cache[0] != new_cache.length
+ assert old_cache[1] != new_cache.uphill
+ assert old_cache[2] != new_cache.downhill
+
+
def test_browse(page: Page, playwright_helper, dbaccess):
playwright_helper.login()
track = playwright_helper.add_track()
diff --git a/tests/playwright/test_profiles.py b/tests/playwright/test_profiles.py
index 7e5fb3c..ffbaab0 100644
--- a/tests/playwright/test_profiles.py
+++ b/tests/playwright/test_profiles.py
@@ -5,7 +5,7 @@ def test_forbidden(page: Page, playwright_helper):
john = playwright_helper.john_doe()
with page.expect_response(lambda resp: resp.status == 403):
- page.goto(f"/user/{john.id}")
+ page.goto(f"/user/{john.id}/")
def test_profile(page: Page, playwright_helper):
diff --git a/tests/playwright/test_share.py b/tests/playwright/test_share.py
index de288a0..dcba899 100644
--- a/tests/playwright/test_share.py
+++ b/tests/playwright/test_share.py
@@ -29,7 +29,8 @@ def test_view_wrong_link(page: Page, playwright_helper, dbaccess):
with page.expect_response(lambda resp: resp.status == 403):
page.goto(f"/track/{track.id}?secret=foobar")
- assert "Forbidden" in page.content()
+ assert "No entry" in page.content()
+ assert "not allowed to access" in page.content()
def test_change_link(page: Page, playwright_helper, dbaccess):
diff --git a/tests/playwright/test_tileproxy.py b/tests/playwright/test_tileproxy.py
index d4d3389..2a2bdc0 100644
--- a/tests/playwright/test_tileproxy.py
+++ b/tests/playwright/test_tileproxy.py
@@ -14,7 +14,7 @@ def test_tileproxy(page: Page, playwright_helper, caplog):
# If we're too fast, the log entry might not be there yet, wait 2 more
# seconds
- if "Skipping tile proxy request for testing URL" not in caplog.messages:
+ if "Skipping tile request for testing URL" not in caplog.messages:
time.sleep(2)
- assert "Skipping tile proxy request for testing URL" in caplog.messages
+ assert "Skipping tile request for testing URL" in caplog.messages