from pathlib import Path import unittest PROJECT_ROOT = Path(__file__).resolve().parents[1] UP_PATH = PROJECT_ROOT / "database" / "014_booking_current_source_batch.sql" DOWN_PATH = PROJECT_ROOT / "database" / "014_booking_current_source_batch.down.sql" class BookingCurrentSourceMigrationTests(unittest.TestCase): def test_forward_migration_adds_guarded_singleton_and_filters_view(self) -> None: sql = UP_PATH.read_text(encoding="utf-8") for required in ( "current_database() <> 'booking_test'", "ARR migrations 008 through 013 must be applied first", "CREATE TABLE booking.current_source_batch", "singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton)", "current_source_batch_acceptance_guard", "batch.batch_status = 'accepted'", "FROM booking.current_source_batch AS active_source", "source.source_batch_id = active_source.source_batch_id", "historical batches remain immutable but inactive", ): with self.subTest(required=required): self.assertIn(required, sql) self.assertIn("ORDER BY", sql) self.assertIn("LIMIT 1", sql) def test_rollback_refuses_after_excel_history_exists(self) -> None: sql = DOWN_PATH.read_text(encoding="utf-8") self.assertIn("source_kind = 'booking_excel'", sql) self.assertIn("refusing rollback: Booking Excel source history exists", sql) self.assertIn("multiple accepted Booking source batches exist", sql) self.assertIn("DROP TABLE booking.current_source_batch", sql) if __name__ == "__main__": unittest.main(verbosity=2)