Files
justin 9f8dd960f4 Test auth flows and switch core tests to session auth
New auth suite covers registration, login (incl. wrong-password), email verification, password reset (old sessions + old password rejected), logout revocation, and no-enumeration on reset. Core tenancy tests now authenticate via real sessions. A capturing mailer makes email flows assertable. 13 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
2026-06-06 10:51:51 -04:00

74 lines
2.5 KiB
Python

"""End-to-end coverage of the core data model through the API: tenancy, the
privacy seam, and real session auth."""
from tests.conftest import auth, register
async def test_tree_and_person_flow(client):
token = await register(client, "keeper@example.com")
resp = await client.post(
"/api/v1/trees",
json={"name": "Smith Family", "visibility": "private"},
headers=auth(token),
)
assert resp.status_code == 201, resp.text
tree = resp.json()
assert tree["visibility"] == "private"
tree_id = tree["id"]
resp = await client.get("/api/v1/trees", headers=auth(token))
assert resp.status_code == 200
assert len(resp.json()) == 1
resp = await client.post(
f"/api/v1/trees/{tree_id}/persons",
json={"given": "John", "surname": "Smith"},
headers=auth(token),
)
assert resp.status_code == 201, resp.text
person = resp.json()
assert person["primary_name"] == "John Smith"
assert person["tree_id"] == tree_id
resp = await client.get(f"/api/v1/trees/{tree_id}/persons", headers=auth(token))
assert resp.status_code == 200
assert len(resp.json()) == 1
async def test_private_tree_isolated_from_other_users(client):
owner = await register(client, "owner@example.com")
other = await register(client, "stranger@example.com")
resp = await client.post(
"/api/v1/trees", json={"name": "Private", "visibility": "private"}, headers=auth(owner)
)
tree_id = resp.json()["id"]
resp = await client.get(f"/api/v1/trees/{tree_id}", headers=auth(other))
assert resp.status_code == 403
resp = await client.get(f"/api/v1/trees/{tree_id}/persons", headers=auth(other))
assert resp.status_code == 403
async def test_public_tree_viewable_but_not_editable_by_non_member(client):
owner = await register(client, "owner2@example.com")
viewer = await register(client, "viewer2@example.com")
resp = await client.post(
"/api/v1/trees", json={"name": "Public", "visibility": "public"}, headers=auth(owner)
)
tree_id = resp.json()["id"]
resp = await client.get(f"/api/v1/trees/{tree_id}", headers=auth(viewer))
assert resp.status_code == 200
resp = await client.post(
f"/api/v1/trees/{tree_id}/persons", json={"given": "Nope"}, headers=auth(viewer)
)
assert resp.status_code == 403
async def test_auth_required_without_token(client):
resp = await client.get("/api/v1/trees")
assert resp.status_code == 401