Backend tests run on SQLite by default (78 passed, 1 skipped); no Postgres needed

- conftest: default SHONAR_TEST_DATABASE_URL is a temp SQLite file, matching
  the bundled-lite engine; set the env var to a PG URL to exercise that path
- models.py: add sqlite_where to the two partial unique indexes — without it
  SQLite built a FULL unique index on recording_id (WHERE not carried over),
  wrongly blocking a second export asset per recording
- test_m9: pass UUID objects (not str) to direct ORM inserts/gets; SQLite's
  GUID bind processor rejects strings (asyncpg tolerated them)

Verified: pytest -q = 78 passed, 1 skipped; ruff check clean
This commit is contained in:
avi 2026-09-14 20:59:49 -05:00
commit a94609c07b
3 changed files with 35 additions and 9 deletions

View file

@ -7,6 +7,7 @@ via SHONAR_TEST_DATABASE_URL) — both paths share the endpoint contract.
from __future__ import annotations
import io
import uuid
import zipfile
from tests.test_recordings import auth, user_tokens, wav_bytes
@ -44,7 +45,15 @@ async def add_transcript(rec_id: str, text: str, segments=None):
from shonar.db.session import session_factory
async with session_factory()() as s:
s.add(Transcript(recording_id=rec_id, text=text, segments=segments, provider="test"))
# UUID object (not str): SQLite's GUID bind processor requires it.
s.add(
Transcript(
recording_id=uuid.UUID(rec_id) if isinstance(rec_id, str) else rec_id,
text=text,
segments=segments,
provider="test",
)
)
await s.commit()
@ -53,7 +62,13 @@ async def add_summary(rec_id: str, content: dict):
from shonar.db.session import session_factory
async with session_factory()() as s:
s.add(Summary(recording_id=rec_id, content=content, provider="test"))
s.add(
Summary(
recording_id=uuid.UUID(rec_id) if isinstance(rec_id, str) else rec_id,
content=content,
provider="test",
)
)
await s.commit()
@ -241,7 +256,7 @@ async def test_retention_sweep_purges_expired(client):
r = await client.delete(f"/api/v1/recordings/{rid}", headers=h)
assert r.status_code == 204
async with session_factory()() as s:
rec = await s.get(Recording, rid)
rec = await s.get(Recording, uuid.UUID(rid))
rec.deleted_at = utcnow() - timedelta(days=31)
# remember the storage key before the row vanishes
from shonar.db.models import Asset
@ -260,7 +275,7 @@ async def test_retention_sweep_purges_expired(client):
assert purged["files"] >= 1
async with session_factory()() as s:
assert await s.get(Recording, rid) is None
assert await s.get(Recording, uuid.UUID(rid)) is None
from shonar.storage import get_storage
assert not await get_storage().exists(storage_key) # file gone too
@ -271,7 +286,7 @@ async def test_retention_sweep_purges_expired(client):
purged = await retention.sweep_deleted()
assert purged["recordings"] == 0
async with session_factory()() as s:
assert await s.get(Recording, rid2) is not None
assert await s.get(Recording, uuid.UUID(rid2)) is not None
async def test_retention_sweep_account(client):
@ -292,7 +307,7 @@ async def test_retention_sweep_account(client):
purged = await retention.sweep_deleted()
assert purged["users"] == 1
async with session_factory()() as s:
assert await s.get(Recording, rid) is None # cascade
assert await s.get(Recording, uuid.UUID(rid)) is None # cascade
assert await s.scalar(select_user("m9r2@example.com")) is None