From c0c8e764a8819ba10066beb4ca829488ceed4e9d Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 22 Dec 2022 18:40:26 +0100 Subject: reorder playwright helper structure To add more playwright tests and to cut down on the duplicated code, the helper methods have been put into a small class. This way, we don't have to add 100 pytest fixtures. --- tests/playwright/conftest.py | 86 ++++++++++++++++++++++++++++++++++++ tests/playwright/test_basic.py | 98 ++++++++---------------------------------- 2 files changed, 104 insertions(+), 80 deletions(-) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index dedaf22..1130df2 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -1,7 +1,17 @@ +import datetime import socket import threading +from typing import Optional from wsgiref import simple_server +from pyramid.authentication import AuthTktCookieHelper +from pyramid.testing import DummyRequest + +from testutils import load_gpx_asset +from fietsboek import models +from fietsboek.models.track import Visibility, TrackType +from fietsboek.config import Config + import pytest @@ -46,3 +56,79 @@ def dbaccess(app): """ session_factory = app.registry["dbsession_factory"] return session_factory() + + +class Helper: + """Helper to insert objects for testing into the database and similar.""" + + def __init__(self, dbaccess, app_settings, page, data_manager): + self.dbaccess = dbaccess + self.app_settings = app_settings + self.page = page + self.data_manager = data_manager + self._johnny = None + + def john_doe(self) -> models.User: + """Provides a test user (John Doe). + + This fixture either returns the existing John or creates a new one. + """ + if self._johnny: + return self._johnny + + with self.dbaccess: + user = models.User(name="John Doe", email="john@doe.com", is_verified=True) + user.set_password("password") + self.dbaccess.add(user) + self.dbaccess.commit() + self.dbaccess.refresh(user, ["id"]) + self.dbaccess.expunge(user) + self._johnny = user + return user + + def login(self, user: Optional[models.User] = None): + """Logs the given user in by setting the auth cookie.""" + if user is None: + user = self.john_doe() + config = Config.construct(session_key=self.app_settings["session_key"]) + secret = config.derive_secret("auth-cookie") + helper = AuthTktCookieHelper(secret) + headers = helper.remember(DummyRequest(), str(user.id)) + for _, header_val in headers: + cookie = header_val.split(";")[0] + name, value = cookie.split("=", 1) + self.page.context.add_cookies( + [ + {"name": name, "value": value, "domain": "localhost", "path": "/"}, + ] + ) + + def add_track( + self, user: Optional[models.User] = None, track_name: str = "Teasi_1.gpx.gz" + ) -> models.Track: + """Add a track to the given user. + + If the user is None, John Doe is used. + """ + if user is None: + user = self.john_doe() + with self.dbaccess: + user = self.dbaccess.merge(user) + track = models.Track( + title="Another awesome track", + visibility=Visibility.PRIVATE, + description="Another description", + ) + track.date = datetime.datetime.now(datetime.timezone.utc) + user.tracks.append(track) + self.dbaccess.flush() + self.dbaccess.refresh(track, ["id"]) + self.dbaccess.expunge(track) + self.data_manager.initialize(track.id).compress_gpx(load_gpx_asset(track_name)) + self.dbaccess.commit() + return track + + +@pytest.fixture +def playwright_helper(dbaccess, app_settings, page, data_manager): + return Helper(dbaccess, app_settings, page, data_manager) diff --git a/tests/playwright/test_basic.py b/tests/playwright/test_basic.py index cde682e..a2e6030 100644 --- a/tests/playwright/test_basic.py +++ b/tests/playwright/test_basic.py @@ -1,45 +1,12 @@ import datetime import pytest -from pyramid.authentication import AuthTktCookieHelper -from pyramid.testing import DummyRequest from playwright.sync_api import Page, expect from sqlalchemy import select from testutils import load_gpx_asset from fietsboek import models -from fietsboek.models.track import Visibility, TrackType -from fietsboek.config import Config - - -@pytest.fixture -def john_doe(dbaccess): - """Provides a test user (John Doe). - - This fixture either returns the existing John or creates a new one. - """ - with dbaccess: - user = models.User(name="John Doe", email="john@doe.com", is_verified=True) - user.set_password("password") - dbaccess.add(user) - dbaccess.commit() - dbaccess.refresh(user, ["id"]) - dbaccess.expunge(user) - return user - - -def do_login(settings: dict, page: Page, user: models.User): - """Logs the given user in by setting the auth cookie.""" - config = Config.construct(session_key=settings["session_key"]) - secret = config.derive_secret("auth-cookie") - helper = AuthTktCookieHelper(secret) - headers = helper.remember(DummyRequest(), str(user.id)) - for _, header_val in headers: - cookie = header_val.split(";")[0] - name, value = cookie.split("=", 1) - page.context.add_cookies([ - {"name": name, "value": value, "domain": "localhost", "path": "/"}, - ]) +from fietsboek.models.track import Visibility def test_homepage(page: Page): @@ -60,7 +27,8 @@ def test_login_failed(page: Page): expect(page.locator(".alert")).to_have_text("Invalid login credentials") -def test_login_success(page: Page, john_doe): +def test_login_success(page: Page, playwright_helper): + playwright_helper.john_doe() page.goto("/") page.get_by_role("button", name="User").click() @@ -73,8 +41,9 @@ def test_login_success(page: Page, john_doe): expect(page.locator(".alert")).to_have_text("You are now logged in") -def test_upload(page: Page, john_doe, app_settings, tmp_path, dbaccess): - do_login(app_settings, page, john_doe) +def test_upload(page: Page, playwright_helper, tmp_path, dbaccess): + playwright_helper.login() + page.goto("/") page.get_by_text("Upload").click() @@ -111,21 +80,9 @@ def test_upload(page: Page, john_doe, app_settings, tmp_path, dbaccess): assert track.description == "Beschreibung der tollen Tour" -def test_edit(page: Page, john_doe, app_settings, dbaccess, data_manager): - do_login(app_settings, page, john_doe) - with dbaccess: - john_doe = dbaccess.merge(john_doe) - track = models.Track( - title="Another awesome track", - visibility=Visibility.PRIVATE, - description="Another description", - ) - track.date = datetime.datetime.now(datetime.timezone.utc) - john_doe.tracks.append(track) - dbaccess.flush() - track_id = track.id - data_manager.initialize(track_id).compress_gpx(load_gpx_asset("Teasi_1.gpx.gz")) - dbaccess.commit() +def test_edit(page: Page, playwright_helper, dbaccess): + playwright_helper.login() + track_id = playwright_helper.add_track().id page.goto(f"/track/{track_id}") page.locator(".btn", has_text="Edit").click() @@ -151,20 +108,13 @@ def test_edit(page: Page, john_doe, app_settings, dbaccess, data_manager): assert track.description == "Not so descriptive anymore" -def test_browse(page: Page, john_doe, app_settings, dbaccess, data_manager): - do_login(app_settings, page, john_doe) +def test_browse(page: Page, playwright_helper, dbaccess): + playwright_helper.login() + track = playwright_helper.add_track() + with dbaccess: - john_doe = dbaccess.merge(john_doe) - track = models.Track( - title="We're looking for this track", - visibility=Visibility.PRIVATE, - description="Another description", - type=TrackType.ORGANIC, - ) - track.date = datetime.datetime.now(datetime.timezone.utc) - john_doe.tracks.append(track) - dbaccess.flush() - data_manager.initialize(track.id).compress_gpx(load_gpx_asset("Teasi_1.gpx.gz")) + track = dbaccess.merge(track) + track.title = "We're looking for this track" dbaccess.commit() page.goto("/") @@ -185,21 +135,9 @@ def test_browse(page: Page, john_doe, app_settings, dbaccess, data_manager): expect(page.locator(".card-header", has_text="We're looking for this track")).to_be_visible() -def test_delete(page: Page, john_doe, app_settings, dbaccess, data_manager): - do_login(app_settings, page, john_doe) - with dbaccess: - john_doe = dbaccess.merge(john_doe) - track = models.Track( - title="Another awesome track", - visibility=Visibility.PRIVATE, - description="Another description", - ) - track.date = datetime.datetime.now(datetime.timezone.utc) - john_doe.tracks.append(track) - dbaccess.flush() - track_id = track.id - data_manager.initialize(track_id).compress_gpx(load_gpx_asset("Teasi_1.gpx.gz")) - dbaccess.commit() +def test_delete(page: Page, playwright_helper, dbaccess, data_manager): + playwright_helper.login() + track_id = playwright_helper.add_track().id page.goto(f"/track/{track_id}") page.locator("#deleteLink", has_text="Delete").click() -- cgit v1.2.3