teecup/tests/conftest.py

121 lines
4.6 KiB
Python
Raw Normal View History

"""
Delt testoppsett for backend-integrasjonstestene.
Kjøres ALLTID mot en scratch-database (se scripts/run_backend_tests.sh) --
aldri mot ekte teecup_db. Poolen initialiseres per test (funksjonsscope,
ikke sesjonsscope) for å unngå event loop-fallgruver med pytest-asyncio --
en full pool-oppstart tar millisekunder og suiten er liten nok til at det
ikke koster noe i praksis.
Hjelpefunksjonene under (create_user, create_org, ...) setter kun de
kolonnene testene faktisk trenger å kontrollere, med fornuftige defaults
for resten -- se \\d-utskrift av schema for hvilke felt som er NOT NULL.
"""
import uuid
import pytest_asyncio
from app import db as app_db
def new_id() -> str:
return str(uuid.uuid4())
@pytest_asyncio.fixture
async def pool():
await app_db.init_pool()
yield
await app_db.close_pool()
async def create_user(**overrides) -> str:
"""Egen tilkobling, samme begrunnelse som create_org -- app_user har
ingen RLS (ikke org-scopet), det er trygt/enkelt å ikke kreve en
ferdig-åpnet `conn` fra kalleren."""
user_id = overrides.get("id", new_id())
display_name = overrides.get("display_name", f"Testbruker {user_id[:8]}")
birth_date = overrides.get("birth_date")
email = overrides.get("email", f"{user_id}@pytest.invalid")
async with app_db.plain_connection() as conn:
await conn.execute(
"""
INSERT INTO app_user (id, display_name, birth_date, email)
VALUES ($1, $2, $3, $4)
""",
user_id, display_name, birth_date, email,
)
return user_id
async def create_org(**overrides) -> str:
"""Egen tilkobling (ikke `conn`-parameter som de andre hjelperne) --
speiler den ekte selvrefererende RLS-bootstrappen i
routers/organizations.py::create_organization: `app.current_org`
være satt til organisasjonens EGEN, ennå-ikke-eksisterende id FØR
innsettingen, ellers avviser org_self-policyen den (teecup_app er
NOSUPERUSER/NOBYPASSRLS, akkurat som i produksjon)."""
org_id = overrides.get("id", new_id())
name = overrides.get("name", f"Testklubb {org_id[:8]}")
async with app_db.org_connection(org_id) as conn:
await conn.execute("INSERT INTO organization (id, name) VALUES ($1, $2)", org_id, name)
return org_id
async def add_membership(organization_id: str, user_id: str, role: str = "member") -> None:
"""organization_membership er org-scopet (RLS), samme begrunnelse som
create_org over -- skrives med riktig app.current_org satt."""
async with app_db.org_connection(organization_id) as conn:
await conn.execute(
"INSERT INTO organization_membership (organization_id, user_id, role) VALUES ($1, $2, $3)",
organization_id, user_id, role,
)
async def create_round(conn, owner_user_id: str, **overrides) -> str:
round_id = overrides.get("id", new_id())
# course_source='teeoff' krever KUN teeoff_facility_slug/teeoff_course_id
# (fritekst, ingen FK mot en ekte teeoff-bane) -- enklere for et testfixtur
# enn 'custom', som (round_check-constrainten) også krever en ekte rad i
# personal_course.
await conn.execute(
"""
INSERT INTO round (id, owner_user_id, course_source, teeoff_facility_slug,
teeoff_course_id, course_name_snapshot, tee_name_snapshot, played_at)
VALUES ($1, $2, 'teeoff', 'test-facility', 'test-course', 'Testbanen', 'Gul', CURRENT_DATE)
""",
round_id, owner_user_id,
)
return round_id
async def create_participant(conn, round_id: str, **overrides) -> str:
participant_id = overrides.get("id", new_id())
user_id = overrides.get("user_id")
is_owner = overrides.get("is_owner", True)
course_handicap_snapshot = overrides.get("course_handicap_snapshot")
await conn.execute(
"""
INSERT INTO round_participant (id, round_id, user_id, is_owner, gender,
tee_name_snapshot, course_handicap_snapshot)
VALUES ($1, $2, $3, $4, 'x', 'Gul', $5)
""",
participant_id, round_id, user_id, is_owner, course_handicap_snapshot,
)
return participant_id
async def create_hole(conn, participant_id: str, hole_number: int, par: int = 4,
stroke_index: int = 9, **overrides) -> str:
hole_id = overrides.get("id", new_id())
version = overrides.get("version", 1)
await conn.execute(
"""
INSERT INTO round_hole (id, round_participant_id, hole_number, par, stroke_index, version)
VALUES ($1, $2, $3, $4, $5, $6)
""",
hole_id, participant_id, hole_number, par, stroke_index, version,
)
return hole_id