- Add lib crate exposing modules for integration testing - Add dev-dependencies: tokio-test 0.4, tempfile - Refactor parse_csv_fields() as pure function for unit testing - Add field validation (minimum 16 fields required) - Fix repository last_insert_id using SELECT LAST_INSERT_ID() - Add 10 lib tests for CSV parsing and date formatting - Add 10 config tests for environment configuration - Add 7 import tests for CSV file parsing - Add 6 models tests for database structs - Add 12 repository tests for CRUD operations
123 lines
4.2 KiB
Rust
123 lines
4.2 KiB
Rust
//! Test database utilities.
|
|
//!
|
|
//! AI AGENT NOTE: These helpers manage the test database connection pool.
|
|
//! Uses rusty_petroleum_test database for all tests.
|
|
|
|
use sqlx::mysql::{MySqlPool, MySqlPoolOptions};
|
|
use std::time::Duration;
|
|
|
|
/// Creates a connection pool to the test database.
|
|
///
|
|
/// AI AGENT NOTE: Uses config.toml or config.test.toml for connection details.
|
|
/// The test database should be separate from dev/prod to avoid data conflicts.
|
|
pub async fn create_test_pool() -> MySqlPool {
|
|
let config = crate::config::Config::load(crate::config::Env::Test)
|
|
.expect("Failed to load test config");
|
|
|
|
MySqlPoolOptions::new()
|
|
.max_connections(1)
|
|
.acquire_timeout(Duration::from_secs(10))
|
|
.connect(&config.database.connection_url())
|
|
.await
|
|
.expect("Failed to connect to test database")
|
|
}
|
|
|
|
/// Resets the test database by dropping and recreating all tables.
|
|
///
|
|
/// AI AGENT NOTE: This is used before running tests to ensure a clean state.
|
|
/// It uses the `rusty_petroleum_test` database.
|
|
pub async fn reset_test_database() -> anyhow::Result<()> {
|
|
let config = crate::config::Config::load(crate::config::Env::Test)?;
|
|
let database_url = config.database.connection_url();
|
|
let base_url = database_url.trim_end_matches(config.env.database_name());
|
|
|
|
let setup_pool = MySqlPoolOptions::new()
|
|
.max_connections(1)
|
|
.connect(base_url)
|
|
.await?;
|
|
|
|
// Drop database if exists
|
|
sqlx::query(&format!("DROP DATABASE IF EXISTS {}", config.env.database_name()))
|
|
.execute(&setup_pool)
|
|
.await?;
|
|
|
|
// Create fresh database
|
|
sqlx::query(&format!("CREATE DATABASE {}", config.env.database_name()))
|
|
.execute(&setup_pool)
|
|
.await?;
|
|
|
|
drop(setup_pool);
|
|
|
|
// Now create tables
|
|
let pool = create_test_pool().await;
|
|
|
|
// Create customers table
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE customers (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
customer_number VARCHAR(50) NOT NULL UNIQUE,
|
|
card_report_group TINYINT UNSIGNED NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
INDEX idx_customer_number (customer_number)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
"#,
|
|
)
|
|
.execute(&pool)
|
|
.await?;
|
|
|
|
// Create cards table
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE cards (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
card_number VARCHAR(50) NOT NULL UNIQUE,
|
|
customer_id INT UNSIGNED NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
INDEX idx_card_number (card_number),
|
|
INDEX idx_customer_id (customer_id),
|
|
FOREIGN KEY (customer_id) REFERENCES customers(id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
"#,
|
|
)
|
|
.execute(&pool)
|
|
.await?;
|
|
|
|
// Create transactions table
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE transactions (
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
transaction_date DATETIME NOT NULL,
|
|
batch_number VARCHAR(20) NOT NULL,
|
|
amount DECIMAL(10,2) NOT NULL,
|
|
volume DECIMAL(10,3) NOT NULL,
|
|
price DECIMAL(8,4) NOT NULL,
|
|
quality_code INT NOT NULL,
|
|
quality_name VARCHAR(50) NOT NULL,
|
|
card_number VARCHAR(50) NOT NULL,
|
|
station VARCHAR(20) NOT NULL,
|
|
terminal VARCHAR(10) NOT NULL,
|
|
pump VARCHAR(10) NOT NULL,
|
|
receipt VARCHAR(20) NOT NULL,
|
|
control_number VARCHAR(20),
|
|
customer_id INT UNSIGNED NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
INDEX idx_transaction_date (transaction_date),
|
|
INDEX idx_batch_number (batch_number),
|
|
INDEX idx_customer_id (customer_id),
|
|
INDEX idx_card_number (card_number),
|
|
INDEX idx_station (station)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
"#,
|
|
)
|
|
.execute(&pool)
|
|
.await?;
|
|
|
|
drop(pool);
|
|
|
|
Ok(())
|
|
}
|