Skip to main content

sova_testing/
sqlite.rs

1//! Tempfile SQLite database for integration tests.
2
3use sova_db::DbHandle;
4use sea_orm::{Database, DatabaseConnection};
5use sea_orm_migration::MigratorTrait;
6use tempfile::TempDir;
7
8/// Isolated sqlite file + URL. Keeps [`TempDir`] alive for the test duration.
9pub struct SqliteTestDb {
10    _dir: TempDir,
11    url: String,
12}
13
14impl SqliteTestDb {
15    /// Create an empty sqlite file and set `DATABASE_URL`.
16    pub fn create() -> Self {
17        let dir = tempfile::tempdir().expect("tempdir");
18        let path = dir.path().join("test.db");
19        let url = format!("sqlite://{}?mode=rwc", path.display());
20        // SAFETY: test-only; integration tests own the process env for DB URL.
21        std::env::set_var("DATABASE_URL", &url);
22        Self { _dir: dir, url }
23    }
24
25    /// Create + apply all migrations from `M` (see [`apply_migrations`]).
26    pub async fn migrate<M: MigratorTrait>() -> Self {
27        let db = Self::create();
28        apply_migrations::<M>(&db.url).await;
29        db
30    }
31
32    pub fn url(&self) -> &str {
33        &self.url
34    }
35
36    /// Fresh connection (e.g. after TestClient owns the App pool).
37    pub async fn connect(&self) -> DatabaseConnection {
38        Database::connect(&self.url)
39            .await
40            .expect("sqlite reconnect")
41    }
42
43    /// [`DbHandle`] over a new connection.
44    pub async fn handle(&self) -> DbHandle {
45        DbHandle::Conn(self.connect().await)
46    }
47}
48
49/// Run each migration's `up` without sea-orm's version tracker.
50///
51/// Sova packs several migrations per `migration.rs`; `DeriveMigrationName` uses
52/// `file!()` stem, so `MigratorTrait::up` would collide on `seaql_migrations.version`.
53pub async fn apply_migrations<M: MigratorTrait>(url: &str) {
54    use sea_orm_migration::SchemaManager;
55    let conn = Database::connect(url).await.expect("sqlite connect");
56    let schema = SchemaManager::new(&conn);
57    for m in M::migrations() {
58        m.up(&schema).await.expect("migrate up");
59    }
60}