PaperMate / tests /test_extensible_schema.py
Phuc-HugigFace's picture
feat(auth+db): session-aware nav, ownership fix, admin hardening, schema cleanup
73aafbd
Raw
History Blame
4.43 kB
from pathlib import Path
import unittest
class BaselineSchemaTests(unittest.TestCase):
def test_baseline_schema_defines_seven_tables(self):
migration_dir = Path(__file__).resolve().parents[1] / "supabase" / "migrations"
# Pin to the authoritative baseline file by name. Later additive
# migrations (e.g. auth/RBAC) sort after it, so migrations[-1] would
# otherwise point at the wrong file and break this assertion.
baseline = migration_dir / "20260616_baseline_schema.sql"
self.assertTrue(baseline.exists(), "Expected the baseline schema migration to exist")
sql = baseline.read_text(encoding="utf-8").lower()
expected_tables = [
"profiles",
"submissions",
"reviews",
"feedback",
"pipeline_steps",
"provider_calls",
"evidence_items",
]
for table in expected_tables:
self.assertIn(f"create table if not exists public.{table}", sql)
self.assertIn(f"alter table public.{table} enable row level security", sql)
# The usage rollup is a view, not a table.
self.assertIn("create or replace view public.submission_usage_summary", sql)
self.assertNotIn("create table if not exists public.submission_usage_summary", sql)
# Tables we deliberately dropped during consolidation.
for table in ("artifacts", "events", "pipeline_runs"):
self.assertIn(f"drop table if exists public.{table}", sql)
self.assertNotIn(f"create table if not exists public.{table}", sql)
# Identifier cleanup: single user-facing key, no vestigial submission_key.
self.assertIn("rename column secret_key to access_key", sql)
self.assertIn("drop column if exists submission_key", sql)
self.assertNotIn("submission_key text", sql)
# New columns required by the redesign.
self.assertIn("parsed_markdown_text", sql) # markdown text queryable in DB
self.assertIn("output_json", sql) # canonical per-step output
# output_summary was dropped (redundant with output_json — see
# 20260623_drop_unused_columns.sql); the baseline must no longer create it.
self.assertNotIn("output_summary", sql)
# All nine pipeline step names remain in the pipeline_steps CHECK.
for step_name in [
"pdf_to_markdown",
"extract_paper_title",
"extract_contributions",
"extract_research_topic",
"generate_search_queries",
"search_related_papers",
"fetch_paper_metadata",
"summarize_related_research",
"generate_review",
]:
self.assertIn(step_name, sql)
self.assertNotIn("conversation", sql)
class AuthRbacMigrationTests(unittest.TestCase):
def _sql(self):
path = (
Path(__file__).resolve().parents[1]
/ "supabase" / "migrations" / "20260620_auth_rbac.sql"
)
self.assertTrue(path.exists(), "Expected the auth/RBAC migration to exist")
return path.read_text(encoding="utf-8").lower()
def test_adds_rbac_and_auth_link_columns(self):
sql = self._sql()
self.assertIn("add column if not exists role text", sql)
self.assertIn("add column if not exists auth_user_id uuid", sql)
self.assertIn("add column if not exists is_active boolean", sql)
self.assertIn("references auth.users(id)", sql)
def test_creates_trigger_helpers_and_views(self):
sql = self._sql()
self.assertIn("function public.handle_new_user", sql)
self.assertIn("on auth.users", sql)
self.assertIn("function public.is_admin", sql)
self.assertIn("function public.current_profile_id", sql)
self.assertIn("create or replace view public.user_usage_summary", sql)
self.assertIn("create or replace view public.admin_overview", sql)
self.assertIn("create or replace view public.admin_cost_by_day", sql)
def test_is_additive_only_on_profiles(self):
# Must never drop/rename a profiles column — that would orphan the
# anonymous submissions FK (submissions.profile_id -> profiles.id).
sql = self._sql()
self.assertNotIn("drop column", sql)
self.assertNotIn("alter table public.profiles rename column", sql)