// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. //! Shared test scaffolding: a temp data directory with a SQLite database and a //! matching config file, so command handlers run end-to-end with no external //! services. #![allow(clippy::unwrap_used, clippy::expect_used)] use std::path::Path; use store::{NewUser, Store}; use tempfile::TempDir; /// A throwaway environment for a CLI command test. pub(crate) struct Env { _dir: TempDir, config_path: std::path::PathBuf, db_url: String, } /// Build a temp data dir with a config pointing at a fresh SQLite database. pub(crate) fn env() -> Env { let dir = tempfile::tempdir().unwrap(); let repos = dir.path().join("repos"); let db = dir.path().join("fabrica.db"); let db_url = format!("sqlite://{}", db.display()); let config_path = dir.path().join("fabrica.toml"); let toml = format!( "[storage]\ndata_dir = {:?}\nrepo_dir = {:?}\n\n[database]\nurl = {:?}\n", dir.path().display(), repos.display(), db_url, ); std::fs::write(&config_path, toml).unwrap(); Env { _dir: dir, config_path, db_url, } } impl Env { /// The `--config` path the handlers accept. The `Option` is intrinsic to the /// handler signature, not incidental. #[allow(clippy::unnecessary_wraps)] pub(crate) fn path(&self) -> Option<&Path> { Some(self.config_path.as_path()) } /// A store connected to the same database the handlers use. pub(crate) async fn store(&self) -> Store { Store::connect(&self.db_url, 1).await.unwrap() } /// Create a user directly and return its id, for tests that need one to exist. pub(crate) async fn make_user(&self, name: &str) -> String { let store = self.store().await; store.migrate().await.unwrap(); store .create_user(NewUser { username: name.to_string(), email: format!("{name}@example.com"), display_name: None, password_hash: None, is_admin: false, must_change_password: false, }) .await .unwrap() .id } }