Merge pull request #60 from SeaQL/ss/test_suite_refactor

Test suite refactor
This commit is contained in:
Chris Tsang 2021-08-07 18:21:59 +08:00 committed by GitHub
commit 1c73ab0759
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 341 additions and 185 deletions

View File

@ -47,6 +47,8 @@ jobs:
sqlite: sqlite:
name: SQLite name: SQLite
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env:
DATABASE_URL: "sqlite::memory:"
strategy: strategy:
matrix: matrix:
# runtime: [async-std-native-tls, async-std-rustls, actix-native-tls, actix-rustls, tokio-native-tls, tokio-rustls] # runtime: [async-std-native-tls, async-std-rustls, actix-native-tls, actix-rustls, tokio-native-tls, tokio-rustls]
@ -79,6 +81,8 @@ jobs:
mysql: mysql:
name: MySQL name: MySQL
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env:
DATABASE_URL: "mysql://root:@localhost"
strategy: strategy:
matrix: matrix:
# version: [8.0, 5.7, 5.6] # version: [8.0, 5.7, 5.6]
@ -130,6 +134,8 @@ jobs:
mariadb: mariadb:
name: MariaDB name: MariaDB
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env:
DATABASE_URL: "mysql://root:@localhost"
strategy: strategy:
matrix: matrix:
# version: [10.6, 10.5, 10.4, 10.3, 10.2] # version: [10.6, 10.5, 10.4, 10.3, 10.2]
@ -181,6 +187,8 @@ jobs:
postgres: postgres:
name: Postgres name: Postgres
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env:
DATABASE_URL: "postgres://root:root@localhost"
strategy: strategy:
matrix: matrix:
# version: [13.3, 12.7, 11.12, 10.17, 9.6.22] # version: [13.3, 12.7, 11.12, 10.17, 9.6.22]

View File

@ -39,7 +39,7 @@ impl std::fmt::Debug for DatabaseConnection {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
Self::SqlxMySqlPoolConnection(_) => "SqlxMySqlPoolConnection", Self::SqlxMySqlPoolConnection(_) => "SqlxMySqlPoolConnection",
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
Self::SqlxPostgresPoolConnection(_) => "SqlxMySqlPoolConnection", Self::SqlxPostgresPoolConnection(_) => "SqlxPostgresPoolConnection",
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
Self::SqlxSqlitePoolConnection(_) => "SqlxSqlitePoolConnection", Self::SqlxSqlitePoolConnection(_) => "SqlxSqlitePoolConnection",
#[cfg(feature = "mock")] #[cfg(feature = "mock")]

View File

@ -63,7 +63,13 @@ where
Some(res) => res, Some(res) => res,
None => return Ok(0), None => return Ok(0),
}; };
let num_items = result.try_get::<i32>("", "num_items")? as usize; let num_items = match self.db {
#[cfg(feature = "sqlx-postgres")]
DatabaseConnection::SqlxPostgresPoolConnection(_) => {
result.try_get::<i64>("", "num_items")? as usize
}
_ => result.try_get::<i32>("", "num_items")? as usize,
};
Ok(num_items) Ok(num_items)
} }

View File

@ -1,4 +1,4 @@
use crate::DbErr; use crate::{debug_print, DbErr};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use serde_json::Value as Json; use serde_json::Value as Json;
use std::fmt; use std::fmt;
@ -90,31 +90,28 @@ macro_rules! try_getable_all {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
QueryResultRow::SqlxPostgres(row) => { QueryResultRow::SqlxPostgres(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(row) => { QueryResultRow::SqlxSqlite(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
QueryResultRow::Mock(row) => match row.try_get(column.as_str()) { QueryResultRow::Mock(row) => match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
}, },
} }
} }
@ -157,10 +154,8 @@ macro_rules! try_getable_unsigned {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
QueryResultRow::SqlxPostgres(_) => { QueryResultRow::SqlxPostgres(_) => {
@ -169,15 +164,16 @@ macro_rules! try_getable_unsigned {
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(row) => { QueryResultRow::SqlxSqlite(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
QueryResultRow::Mock(row) => match row.try_get(column.as_str()) { QueryResultRow::Mock(row) => match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
}, },
} }
} }
@ -218,10 +214,8 @@ macro_rules! try_getable_mysql {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { row.try_get::<Option<$type>, _>(column.as_str())
Ok(v) => Ok(Some(v)), .map_err(crate::sqlx_error_to_query_err)
Err(_) => Ok(None),
}
} }
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
QueryResultRow::SqlxPostgres(_) => { QueryResultRow::SqlxPostgres(_) => {
@ -234,7 +228,10 @@ macro_rules! try_getable_mysql {
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
QueryResultRow::Mock(row) => match row.try_get(column.as_str()) { QueryResultRow::Mock(row) => match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
}, },
} }
} }
@ -309,7 +306,10 @@ impl TryGetable for Option<Decimal> {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
} }
} }
#[cfg(feature = "sqlx-postgres")] #[cfg(feature = "sqlx-postgres")]
@ -317,7 +317,10 @@ impl TryGetable for Option<Decimal> {
use sqlx::Row; use sqlx::Row;
match row.try_get(column.as_str()) { match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
} }
} }
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
@ -325,13 +328,19 @@ impl TryGetable for Option<Decimal> {
let result: Result<Decimal, _> = TryGetable::try_get(res, pre, col); let result: Result<Decimal, _> = TryGetable::try_get(res, pre, col);
match result { match result {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
} }
} }
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
QueryResultRow::Mock(row) => match row.try_get(column.as_str()) { QueryResultRow::Mock(row) => match row.try_get(column.as_str()) {
Ok(v) => Ok(Some(v)), Ok(v) => Ok(Some(v)),
Err(_) => Ok(None), Err(e) => {
debug_print!("{:#?}", e.to_string());
Ok(None)
}
}, },
} }
} }

View File

@ -5,16 +5,20 @@ pub use common::{bakery_chain::*, setup::*, TestContext};
mod crud; mod crud;
// cargo test --test bakery_chain_tests -- --nocapture // Run the test locally:
#[async_std::test] // DATABASE_URL="mysql://root:@localhost" cargo test --features sqlx-mysql,runtime-async-std --test bakery_chain_tests
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
async fn main() { async fn main() {
let base_url = "mysql://root:@localhost"; let ctx = TestContext::new("bakery_chain_schema_crud_tests").await;
let db_name = "bakery_chain_schema_crud_tests"; create_entities(&ctx.db).await;
ctx.delete().await;
let db: DatabaseConnection = common::setup::setup(base_url, db_name).await;
create_entities(&db).await;
common::setup::tear_down(base_url, db_name).await;
} }
async fn create_entities(db: &DatabaseConnection) { async fn create_entities(db: &DatabaseConnection) {

View File

@ -1,20 +1,23 @@
use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, DbBackend, DbConn, Statement}; #[allow(unused_imports)]
use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, Database, DbConn};
mod setup; // DATABASE_URL="sqlite::memory:" cargo test --features sqlx-sqlit,runtime-async-std --test basic
// cargo test --test basic -- --nocapture
#[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-actix", actix_rt::test)] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
async fn main() { async fn main() {
let db: DbConn = setup::setup().await; use std::env;
let base_url = env::var("DATABASE_URL").expect("Enviroment variable 'DATABASE_URL' not set");
let db: DbConn = Database::connect(&base_url).await.unwrap();
setup_schema(&db).await; setup_schema(&db).await;
crud_cake(&db).await.unwrap(); crud_cake(&db).await.unwrap();
} }
#[cfg(feature = "sqlx-sqlite")]
async fn setup_schema(db: &DbConn) { async fn setup_schema(db: &DbConn) {
use sea_query::*; use sea_query::*;
@ -28,14 +31,14 @@ async fn setup_schema(db: &DbConn) {
.primary_key(), .primary_key(),
) )
.col(ColumnDef::new(cake::Column::Name).string()) .col(ColumnDef::new(cake::Column::Name).string())
.build(SqliteQueryBuilder); .to_owned();
let result = db let builder = db.get_database_backend();
.execute(Statement::from_string(DbBackend::Sqlite, stmt)) let result = db.execute(builder.build(&stmt)).await;
.await;
println!("Create table cake: {:?}", result); println!("Create table cake: {:?}", result);
} }
#[cfg(feature = "sqlx-sqlite")]
async fn crud_cake(db: &DbConn) -> Result<(), DbErr> { async fn crud_cake(db: &DbConn) -> Result<(), DbErr> {
let apple = cake::ActiveModel { let apple = cake::ActiveModel {
name: Set("Apple Pie".to_owned()), name: Set("Apple Pie".to_owned()),

View File

@ -15,8 +15,8 @@ pub struct Model {
pub id: i32, pub id: i32,
pub price: Decimal, pub price: Decimal,
pub quantity: i32, pub quantity: i32,
pub order_id: Option<i32>, pub order_id: i32,
pub cake_id: Option<i32>, pub cake_id: i32,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
@ -51,7 +51,7 @@ impl ColumnTrait for Column {
fn def(&self) -> ColumnDef { fn def(&self) -> ColumnDef {
match self { match self {
Self::Id => ColumnType::Integer.def(), Self::Id => ColumnType::Integer.def(),
Self::Price => ColumnType::Money(Some((19, 4))).def(), Self::Price => ColumnType::Decimal(Some((19, 4))).def(),
Self::Quantity => ColumnType::Integer.def(), Self::Quantity => ColumnType::Integer.def(),
Self::OrderId => ColumnType::Integer.def(), Self::OrderId => ColumnType::Integer.def(),
Self::CakeId => ColumnType::Integer.def(), Self::CakeId => ColumnType::Integer.def(),

View File

@ -15,8 +15,8 @@ impl EntityName for Entity {
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub total: Decimal, pub total: Decimal,
pub bakery_id: Option<i32>, pub bakery_id: i32,
pub customer_id: Option<i32>, pub customer_id: i32,
pub placed_at: NaiveDateTime, pub placed_at: NaiveDateTime,
} }

View File

@ -2,6 +2,7 @@ pub mod setup;
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
pub mod bakery_chain; pub mod bakery_chain;
pub use bakery_chain::*; pub use bakery_chain::*;
use std::env;
pub struct TestContext { pub struct TestContext {
base_url: String, base_url: String,
@ -10,12 +11,14 @@ pub struct TestContext {
} }
impl TestContext { impl TestContext {
pub async fn new(base_url: &str, db_name: &str) -> Self { pub async fn new(test_name: &str) -> Self {
let db: DatabaseConnection = setup::setup(base_url, db_name).await; let base_url =
env::var("DATABASE_URL").expect("Enviroment variable 'DATABASE_URL' not set");
let db: DatabaseConnection = setup::setup(&base_url, test_name).await;
Self { Self {
base_url: base_url.to_string(), base_url: base_url,
db_name: db_name.to_string(), db_name: test_name.to_string(),
db, db,
} }
} }

View File

@ -3,24 +3,47 @@ pub mod schema;
pub use schema::*; pub use schema::*;
pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection { pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
let url = format!("{}/mysql", base_url); let db = if cfg!(feature = "sqlx-mysql") {
let db = Database::connect(&url).await.unwrap(); let url = format!("{}/mysql", base_url);
let _drop_db_result = db let db = Database::connect(&url).await.unwrap();
.execute(Statement::from_string( let _drop_db_result = db
DatabaseBackend::MySql, .execute(Statement::from_string(
format!("DROP DATABASE IF EXISTS `{}`;", db_name), DatabaseBackend::MySql,
)) format!("DROP DATABASE IF EXISTS `{}`;", db_name),
.await; ))
.await;
let _create_db_result = db let _create_db_result = db
.execute(Statement::from_string( .execute(Statement::from_string(
DatabaseBackend::MySql, DatabaseBackend::MySql,
format!("CREATE DATABASE `{}`;", db_name), format!("CREATE DATABASE `{}`;", db_name),
)) ))
.await; .await;
let url = format!("{}/{}", base_url, db_name); let url = format!("{}/{}", base_url, db_name);
let db = Database::connect(&url).await.unwrap(); Database::connect(&url).await.unwrap()
} else if cfg!(feature = "sqlx-postgres") {
let url = format!("{}/postgres", base_url);
let db = Database::connect(&url).await.unwrap();
let _drop_db_result = db
.execute(Statement::from_string(
DatabaseBackend::Postgres,
format!("DROP DATABASE IF EXISTS \"{}\";", db_name),
))
.await;
let _create_db_result = db
.execute(Statement::from_string(
DatabaseBackend::Postgres,
format!("CREATE DATABASE \"{}\";", db_name),
))
.await;
let url = format!("{}/{}", base_url, db_name);
Database::connect(&url).await.unwrap()
} else {
Database::connect(base_url).await.unwrap()
};
assert!(schema::create_bakery_table(&db).await.is_ok()); assert!(schema::create_bakery_table(&db).await.is_ok());
assert!(schema::create_baker_table(&db).await.is_ok()); assert!(schema::create_baker_table(&db).await.is_ok());
@ -33,12 +56,24 @@ pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
} }
pub async fn tear_down(base_url: &str, db_name: &str) { pub async fn tear_down(base_url: &str, db_name: &str) {
let url = format!("{}/mysql", base_url); if cfg!(feature = "sqlx-mysql") {
let db = Database::connect(&url).await.unwrap(); let url = format!("{}/mysql", base_url);
let _drop_db_result = db let db = Database::connect(&url).await.unwrap();
.execute(Statement::from_string( let _ = db
DatabaseBackend::MySql, .execute(Statement::from_string(
format!("DROP DATABASE IF EXISTS `{}`;", db_name), DatabaseBackend::MySql,
)) format!("DROP DATABASE IF EXISTS \"{}\";", db_name),
.await; ))
.await;
} else if cfg!(feature = "sqlx-postgres") {
let url = format!("{}/postgres", base_url);
let db = Database::connect(&url).await.unwrap();
let _ = db
.execute(Statement::from_string(
DatabaseBackend::Postgres,
format!("DROP DATABASE IF EXISTS \"{}\";", db_name),
))
.await;
} else {
};
} }

View File

@ -70,8 +70,8 @@ pub async fn test_create_lineitem(db: &DbConn) {
// Order // Order
let order_1 = order::ActiveModel { let order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery_insert_res.last_insert_id as i32)), bakery_id: Set(bakery_insert_res.last_insert_id as i32),
customer_id: Set(Some(customer_insert_res.last_insert_id as i32)), customer_id: Set(customer_insert_res.last_insert_id as i32),
total: Set(dec!(7.55)), total: Set(dec!(7.55)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
..Default::default() ..Default::default()
@ -83,8 +83,8 @@ pub async fn test_create_lineitem(db: &DbConn) {
// Lineitem // Lineitem
let lineitem_1 = lineitem::ActiveModel { let lineitem_1 = lineitem::ActiveModel {
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)), cake_id: Set(cake_insert_res.last_insert_id as i32),
order_id: Set(Some(order_insert_res.last_insert_id as i32)), order_id: Set(order_insert_res.last_insert_id as i32),
price: Set(dec!(7.55)), price: Set(dec!(7.55)),
quantity: Set(1), quantity: Set(1),
..Default::default() ..Default::default()
@ -102,9 +102,10 @@ pub async fn test_create_lineitem(db: &DbConn) {
assert!(lineitem.is_some()); assert!(lineitem.is_some());
let lineitem_model = lineitem.unwrap(); let lineitem_model = lineitem.unwrap();
assert_eq!(lineitem_model.price, dec!(7.55)); assert_eq!(lineitem_model.price, dec!(7.55));
let cake: Option<cake::Model> = Cake::find_by_id(lineitem_model.cake_id) let cake: Option<cake::Model> = Cake::find_by_id(lineitem_model.cake_id as u64)
.one(db) .one(db)
.await .await
.expect("could not find cake"); .expect("could not find cake");
@ -119,7 +120,7 @@ pub async fn test_create_lineitem(db: &DbConn) {
let order_model = order.unwrap(); let order_model = order.unwrap();
assert_eq!( assert_eq!(
order_model.customer_id.unwrap(), order_model.customer_id,
customer_insert_res.last_insert_id as i32 customer_insert_res.last_insert_id as i32
); );
} }

View File

@ -70,8 +70,8 @@ pub async fn test_create_order(db: &DbConn) {
// Order // Order
let order_1 = order::ActiveModel { let order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery_insert_res.last_insert_id as i32)), bakery_id: Set(bakery_insert_res.last_insert_id as i32),
customer_id: Set(Some(customer_insert_res.last_insert_id as i32)), customer_id: Set(customer_insert_res.last_insert_id as i32),
total: Set(dec!(15.10)), total: Set(dec!(15.10)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
..Default::default() ..Default::default()
@ -83,8 +83,8 @@ pub async fn test_create_order(db: &DbConn) {
// Lineitem // Lineitem
let lineitem_1 = lineitem::ActiveModel { let lineitem_1 = lineitem::ActiveModel {
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)), cake_id: Set(cake_insert_res.last_insert_id as i32),
order_id: Set(Some(order_insert_res.last_insert_id as i32)), order_id: Set(order_insert_res.last_insert_id as i32),
price: Set(dec!(7.55)), price: Set(dec!(7.55)),
quantity: Set(2), quantity: Set(2),
..Default::default() ..Default::default()
@ -94,7 +94,7 @@ pub async fn test_create_order(db: &DbConn) {
.await .await
.expect("could not insert lineitem"); .expect("could not insert lineitem");
let order: Option<order::Model> = Order::find_by_id(order_insert_res.last_insert_id) let order: Option<order::Model> = Order::find_by_id(order_insert_res.last_insert_id as i32)
.one(db) .one(db)
.await .await
.expect("could not find order"); .expect("could not find order");
@ -103,7 +103,7 @@ pub async fn test_create_order(db: &DbConn) {
let order_model = order.unwrap(); let order_model = order.unwrap();
assert_eq!(order_model.total, dec!(15.10)); assert_eq!(order_model.total, dec!(15.10));
let customer: Option<customer::Model> = Customer::find_by_id(order_model.customer_id) let customer: Option<customer::Model> = Customer::find_by_id(order_model.customer_id as u64)
.one(db) .one(db)
.await .await
.expect("could not find customer"); .expect("could not find customer");
@ -111,7 +111,7 @@ pub async fn test_create_order(db: &DbConn) {
let customer_model = customer.unwrap(); let customer_model = customer.unwrap();
assert_eq!(customer_model.name, "Kate"); assert_eq!(customer_model.name, "Kate");
let bakery: Option<bakery::Model> = Bakery::find_by_id(order_model.bakery_id) let bakery: Option<bakery::Model> = Bakery::find_by_id(order_model.bakery_id as i64)
.one(db) .one(db)
.await .await
.expect("could not find bakery"); .expect("could not find bakery");

View File

@ -130,10 +130,11 @@ pub async fn test_update_deleted_customer(db: &DbConn) {
assert_eq!(Customer::find().count(db).await.unwrap(), init_n_customers); assert_eq!(Customer::find().count(db).await.unwrap(), init_n_customers);
let customer: Option<customer::Model> = Customer::find_by_id(customer_id.clone().unwrap()) let customer: Option<customer::Model> =
.one(db) Customer::find_by_id(customer_id.clone().unwrap() as i64)
.await .one(db)
.expect("could not find customer"); .await
.expect("could not find customer");
assert_eq!(customer, None); assert_eq!(customer, None);
} }

View File

@ -1,14 +1,21 @@
// cargo test --test query_tests -- --nocapture
use sea_orm::entity::*; use sea_orm::entity::*;
use sea_orm::QueryFilter; use sea_orm::QueryFilter;
pub mod common; pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext}; pub use common::{bakery_chain::*, setup::*, TestContext};
#[async_std::test] // Run the test locally:
#[cfg(feature = "sqlx-mysql")] // DATABASE_URL="mysql://root:@localhost" cargo test --features sqlx-mysql,runtime-async-std --test query_tests
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_one_with_no_result() { pub async fn find_one_with_no_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_one_with_no_result").await; let ctx = TestContext::new("find_one_with_no_result").await;
let bakery = Bakery::find().one(&ctx.db).await.unwrap(); let bakery = Bakery::find().one(&ctx.db).await.unwrap();
assert_eq!(bakery, None); assert_eq!(bakery, None);
@ -16,10 +23,16 @@ pub async fn find_one_with_no_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_one_with_result() { pub async fn find_one_with_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_one_with_result").await; let ctx = TestContext::new("find_one_with_result").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -37,10 +50,16 @@ pub async fn find_one_with_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_by_id_with_no_result() { pub async fn find_by_id_with_no_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_by_id_with_no_result").await; let ctx = TestContext::new("find_by_id_with_no_result").await;
let bakery = Bakery::find_by_id(999).one(&ctx.db).await.unwrap(); let bakery = Bakery::find_by_id(999).one(&ctx.db).await.unwrap();
assert_eq!(bakery, None); assert_eq!(bakery, None);
@ -48,10 +67,16 @@ pub async fn find_by_id_with_no_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_by_id_with_result() { pub async fn find_by_id_with_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_by_id_with_result").await; let ctx = TestContext::new("find_by_id_with_result").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -73,10 +98,16 @@ pub async fn find_by_id_with_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_all_with_no_result() { pub async fn find_all_with_no_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_all_with_no_result").await; let ctx = TestContext::new("find_all_with_no_result").await;
let bakeries = Bakery::find().all(&ctx.db).await.unwrap(); let bakeries = Bakery::find().all(&ctx.db).await.unwrap();
assert_eq!(bakeries.len(), 0); assert_eq!(bakeries.len(), 0);
@ -84,10 +115,16 @@ pub async fn find_all_with_no_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_all_with_result() { pub async fn find_all_with_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_all_with_result").await; let ctx = TestContext::new("find_all_with_result").await;
let _ = bakery::ActiveModel { let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -114,10 +151,16 @@ pub async fn find_all_with_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_all_filter_no_result() { pub async fn find_all_filter_no_result() {
let ctx = TestContext::new("mysql://root:@localhost", "find_all_filter_no_result").await; let ctx = TestContext::new("find_all_filter_no_result").await;
let _ = bakery::ActiveModel { let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -148,10 +191,16 @@ pub async fn find_all_filter_no_result() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn find_all_filter_with_results() { pub async fn find_all_filter_with_results() {
let ctx = TestContext::new("mysql://root:@localhost", "find_all_filter_with_results").await; let ctx = TestContext::new("find_all_filter_with_results").await;
let _ = bakery::ActiveModel { let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -172,7 +221,7 @@ pub async fn find_all_filter_with_results() {
.expect("could not insert bakery"); .expect("could not insert bakery");
let bakeries = Bakery::find() let bakeries = Bakery::find()
.filter(bakery::Column::Name.contains("bakery")) .filter(bakery::Column::Name.contains("Bakery"))
.all(&ctx.db) .all(&ctx.db)
.await .await
.unwrap(); .unwrap();

View File

@ -1,5 +1,3 @@
// cargo test --test realtional_tests -- --nocapture
use chrono::offset::Utc; use chrono::offset::Utc;
use rust_decimal::prelude::*; use rust_decimal::prelude::*;
use rust_decimal_macros::dec; use rust_decimal_macros::dec;
@ -8,10 +6,18 @@ use sea_orm::{entity::*, query::*, FromQueryResult};
pub mod common; pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext}; pub use common::{bakery_chain::*, setup::*, TestContext};
#[async_std::test] // Run the test locally:
#[cfg(feature = "sqlx-mysql")] // DATABASE_URL="mysql://root:@localhost" cargo test --features sqlx-mysql,runtime-async-std --test relational_tests
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn left_join() { pub async fn left_join() {
let ctx = TestContext::new("mysql://root:@localhost", "test_left_join").await; let ctx = TestContext::new("test_left_join").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -85,10 +91,12 @@ pub async fn left_join() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
pub async fn right_join() { pub async fn right_join() {
let ctx = TestContext::new("mysql://root:@localhost", "test_right_join").await; let ctx = TestContext::new("test_right_join").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -116,8 +124,8 @@ pub async fn right_join() {
.expect("could not insert customer"); .expect("could not insert customer");
let _order = order::ActiveModel { let _order = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(15.10)), total: Set(dec!(15.10)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -166,10 +174,16 @@ pub async fn right_join() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn inner_join() { pub async fn inner_join() {
let ctx = TestContext::new("mysql://root:@localhost", "test_inner_join").await; let ctx = TestContext::new("test_inner_join").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -197,8 +211,8 @@ pub async fn inner_join() {
.expect("could not insert customer"); .expect("could not insert customer");
let kate_order_1 = order::ActiveModel { let kate_order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(15.10)), total: Set(dec!(15.10)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -209,8 +223,8 @@ pub async fn inner_join() {
.expect("could not insert order"); .expect("could not insert order");
let kate_order_2 = order::ActiveModel { let kate_order_2 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(100.00)), total: Set(dec!(100.00)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -251,10 +265,16 @@ pub async fn inner_join() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn group_by() { pub async fn group_by() {
let ctx = TestContext::new("mysql://root:@localhost", "test_group_by").await; let ctx = TestContext::new("test_group_by").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -274,8 +294,8 @@ pub async fn group_by() {
.expect("could not insert customer"); .expect("could not insert customer");
let kate_order_1 = order::ActiveModel { let kate_order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(99.95)), total: Set(dec!(99.95)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -286,8 +306,8 @@ pub async fn group_by() {
.expect("could not insert order"); .expect("could not insert order");
let kate_order_2 = order::ActiveModel { let kate_order_2 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(200.00)), total: Set(dec!(200.00)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -300,7 +320,7 @@ pub async fn group_by() {
#[derive(Debug, FromQueryResult)] #[derive(Debug, FromQueryResult)]
struct SelectResult { struct SelectResult {
name: String, name: String,
number_orders: Option<i32>, number_orders: Option<i64>,
total_spent: Option<Decimal>, total_spent: Option<Decimal>,
min_spent: Option<Decimal>, min_spent: Option<Decimal>,
max_spent: Option<Decimal>, max_spent: Option<Decimal>,
@ -351,11 +371,17 @@ pub async fn group_by() {
ctx.delete().await; ctx.delete().await;
} }
#[async_std::test] #[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg(feature = "sqlx-mysql")] #[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
pub async fn having() { pub async fn having() {
// customers with orders with total equal to $90 // customers with orders with total equal to $90
let ctx = TestContext::new("mysql://root:@localhost", "test_having").await; let ctx = TestContext::new("test_having").await;
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -375,8 +401,8 @@ pub async fn having() {
.expect("could not insert customer"); .expect("could not insert customer");
let kate_order_1 = order::ActiveModel { let kate_order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(100.00)), total: Set(dec!(100.00)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -387,8 +413,8 @@ pub async fn having() {
.expect("could not insert order"); .expect("could not insert order");
let _kate_order_2 = order::ActiveModel { let _kate_order_2 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(12.00)), total: Set(dec!(12.00)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -407,8 +433,8 @@ pub async fn having() {
.expect("could not insert customer"); .expect("could not insert customer");
let _bob_order_1 = order::ActiveModel { let _bob_order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_bob.id.clone().unwrap())), customer_id: Set(customer_bob.id.clone().unwrap()),
total: Set(dec!(50.0)), total: Set(dec!(50.0)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -419,8 +445,8 @@ pub async fn having() {
.expect("could not insert order"); .expect("could not insert order");
let _bob_order_2 = order::ActiveModel { let _bob_order_2 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_bob.id.clone().unwrap())), customer_id: Set(customer_bob.id.clone().unwrap()),
total: Set(dec!(50.0)), total: Set(dec!(50.0)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),

View File

@ -7,10 +7,14 @@ use uuid::Uuid;
pub mod common; pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext}; pub use common::{bakery_chain::*, setup::*, TestContext};
#[async_std::test] // Run the test locally:
#[cfg(feature = "sqlx-mysql")] // DATABASE_URL="mysql://root:@localhost" cargo test --features sqlx-mysql,runtime-async-std --test sequential_op_tests
#[cfg_attr(feature = "runtime-async-std", async_std::test)]
#[cfg_attr(feature = "runtime-actix", actix_rt::test)]
#[cfg_attr(feature = "runtime-tokio", tokio::test)]
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
pub async fn test_multiple_operations() { pub async fn test_multiple_operations() {
let ctx = TestContext::new("mysql://root:@localhost", "multiple_sequential_operations").await; let ctx = TestContext::new("multiple_sequential_operations").await;
init_setup(&ctx.db).await; init_setup(&ctx.db).await;
let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap(); let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap();
@ -21,8 +25,11 @@ pub async fn test_multiple_operations() {
let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap(); let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap();
assert_eq!(baker_least_sales.name, "Baker 1"); assert_eq!(baker_least_sales.name, "Baker 1");
ctx.delete().await;
} }
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
async fn init_setup(db: &DatabaseConnection) { async fn init_setup(db: &DatabaseConnection) {
let bakery = bakery::ActiveModel { let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),
@ -87,8 +94,8 @@ async fn init_setup(db: &DatabaseConnection) {
.expect("could not insert customer"); .expect("could not insert customer");
let kate_order_1 = order::ActiveModel { let kate_order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery.id.clone().unwrap())), bakery_id: Set(bakery.id.clone().unwrap()),
customer_id: Set(Some(customer_kate.id.clone().unwrap())), customer_id: Set(customer_kate.id.clone().unwrap()),
total: Set(dec!(99.95)), total: Set(dec!(99.95)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -99,10 +106,10 @@ async fn init_setup(db: &DatabaseConnection) {
.expect("could not insert order"); .expect("could not insert order");
let _lineitem = lineitem::ActiveModel { let _lineitem = lineitem::ActiveModel {
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)), cake_id: Set(cake_insert_res.last_insert_id as i32),
price: Set(dec!(10.00)), price: Set(dec!(10.00)),
quantity: Set(12), quantity: Set(12),
order_id: Set(Some(kate_order_1.id.clone().unwrap())), order_id: Set(kate_order_1.id.clone().unwrap()),
..Default::default() ..Default::default()
} }
.save(db) .save(db)
@ -110,10 +117,10 @@ async fn init_setup(db: &DatabaseConnection) {
.expect("could not insert order"); .expect("could not insert order");
let _lineitem2 = lineitem::ActiveModel { let _lineitem2 = lineitem::ActiveModel {
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)), cake_id: Set(cake_insert_res.last_insert_id as i32),
price: Set(dec!(50.00)), price: Set(dec!(50.00)),
quantity: Set(2), quantity: Set(2),
order_id: Set(Some(kate_order_1.id.clone().unwrap())), order_id: Set(kate_order_1.id.clone().unwrap()),
..Default::default() ..Default::default()
} }
.save(db) .save(db)
@ -121,11 +128,17 @@ async fn init_setup(db: &DatabaseConnection) {
.expect("could not insert order"); .expect("could not insert order");
} }
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
async fn find_baker_least_sales(db: &DatabaseConnection) -> Option<baker::Model> { async fn find_baker_least_sales(db: &DatabaseConnection) -> Option<baker::Model> {
#[cfg(feature = "sqlx-postgres")]
type Type = i64;
#[cfg(not(feature = "sqlx-postgres"))]
type Type = Decimal;
#[derive(Debug, FromQueryResult)] #[derive(Debug, FromQueryResult)]
struct SelectResult { struct SelectResult {
id: i32, id: i32,
cakes_sold_opt: Option<Decimal>, cakes_sold_opt: Option<Type>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -166,18 +179,19 @@ async fn find_baker_least_sales(db: &DatabaseConnection) -> Option<baker::Model>
.into_iter() .into_iter()
.map(|b| LeastSalesBakerResult { .map(|b| LeastSalesBakerResult {
id: b.id.clone(), id: b.id.clone(),
cakes_sold: b.cakes_sold_opt.unwrap_or(dec!(0)), cakes_sold: b.cakes_sold_opt.unwrap_or_default().into(),
}) })
.collect(); .collect();
results.sort_by(|a, b| b.cakes_sold.cmp(&a.cakes_sold)); results.sort_by(|a, b| b.cakes_sold.cmp(&a.cakes_sold));
Baker::find_by_id(results.last().unwrap().id) Baker::find_by_id(results.last().unwrap().id as i64)
.one(db) .one(db)
.await .await
.unwrap() .unwrap()
} }
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
async fn create_cake(db: &DatabaseConnection, baker: baker::Model) -> Option<cake::Model> { async fn create_cake(db: &DatabaseConnection, baker: baker::Model) -> Option<cake::Model> {
let new_cake = cake::ActiveModel { let new_cake = cake::ActiveModel {
name: Set("New Cake".to_owned()), name: Set("New Cake".to_owned()),
@ -210,6 +224,7 @@ async fn create_cake(db: &DatabaseConnection, baker: baker::Model) -> Option<cak
.unwrap() .unwrap()
} }
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
async fn create_order(db: &DatabaseConnection, cake: cake::Model) { async fn create_order(db: &DatabaseConnection, cake: cake::Model) {
let another_customer = customer::ActiveModel { let another_customer = customer::ActiveModel {
name: Set("John".to_owned()), name: Set("John".to_owned()),
@ -220,8 +235,8 @@ async fn create_order(db: &DatabaseConnection, cake: cake::Model) {
.expect("could not insert customer"); .expect("could not insert customer");
let order = order::ActiveModel { let order = order::ActiveModel {
bakery_id: Set(Some(cake.bakery_id.unwrap())), bakery_id: Set(cake.bakery_id.unwrap()),
customer_id: Set(Some(another_customer.id.clone().unwrap())), customer_id: Set(another_customer.id.clone().unwrap()),
total: Set(dec!(200.00)), total: Set(dec!(200.00)),
placed_at: Set(Utc::now().naive_utc()), placed_at: Set(Utc::now().naive_utc()),
@ -232,10 +247,10 @@ async fn create_order(db: &DatabaseConnection, cake: cake::Model) {
.expect("could not insert order"); .expect("could not insert order");
let _lineitem = lineitem::ActiveModel { let _lineitem = lineitem::ActiveModel {
cake_id: Set(Some(cake.id)), cake_id: Set(cake.id),
price: Set(dec!(10.00)), price: Set(dec!(10.00)),
quantity: Set(300), quantity: Set(300),
order_id: Set(Some(order.id.clone().unwrap())), order_id: Set(order.id.clone().unwrap()),
..Default::default() ..Default::default()
} }
.save(db) .save(db)
@ -243,6 +258,7 @@ async fn create_order(db: &DatabaseConnection, cake: cake::Model) {
.expect("could not insert order"); .expect("could not insert order");
} }
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
pub async fn test_delete_bakery(db: &DatabaseConnection) { pub async fn test_delete_bakery(db: &DatabaseConnection) {
let initial_bakeries = Bakery::find().all(db).await.unwrap().len(); let initial_bakeries = Bakery::find().all(db).await.unwrap().len();

View File

@ -1,5 +0,0 @@
use sea_orm::{Database, DatabaseConnection};
pub async fn setup() -> DatabaseConnection {
Database::connect("sqlite::memory:").await.unwrap()
}