Create TestContext for setting up and tearing down the database after each test
This commit is contained in:
parent
1fa7c7e177
commit
ba77fb80aa
81
tests/common/bakery_chain/baker.rs
Normal file
81
tests/common/bakery_chain/baker.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"baker"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub bakery_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
BakeryId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Bakery,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(None).def(),
|
||||
Self::BakeryId => ColumnType::Integer.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Bakery => Entity::belongs_to(super::bakery::Entity)
|
||||
.from(Column::BakeryId)
|
||||
.to(super::bakery::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::bakery::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Bakery.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
super::cakes_bakers::Relation::Cake.def()
|
||||
}
|
||||
|
||||
fn via() -> Option<RelationDef> {
|
||||
Some(super::cakes_bakers::Relation::Baker.def().rev())
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
84
tests/common/bakery_chain/bakery.rs
Normal file
84
tests/common/bakery_chain/bakery.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"bakery"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub profit_margin: f64,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
ProfitMargin,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Baker,
|
||||
Order,
|
||||
Cake,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(None).def(),
|
||||
Self::ProfitMargin => ColumnType::Float.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Baker => Entity::has_many(super::baker::Entity).into(),
|
||||
Self::Order => Entity::has_many(super::order::Entity).into(),
|
||||
Self::Cake => Entity::has_many(super::cake::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::baker::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Baker.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::order::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Order.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Cake.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
1
tests/common/bakery_chain/bakery_chain_erd.drawio
Normal file
1
tests/common/bakery_chain/bakery_chain_erd.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2021-06-30T11:15:47.471Z" agent="5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.6.13 Chrome/89.0.4389.128 Electron/12.0.7 Safari/537.36" etag="CL5AmeQl6dz-rdIIukNg" version="14.6.13" type="device"><diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1">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</diagram></mxfile>
|
BIN
tests/common/bakery_chain/bakery_chain_erd.jpg
Normal file
BIN
tests/common/bakery_chain/bakery_chain_erd.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
96
tests/common/bakery_chain/cake.rs
Normal file
96
tests/common/bakery_chain/cake.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use rust_decimal::prelude::*;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"cake"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub price: Decimal,
|
||||
pub bakery_id: Option<i32>,
|
||||
pub gluten_free: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
Price,
|
||||
BakeryId,
|
||||
GlutenFree,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Bakery,
|
||||
Lineitem,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(None).def(),
|
||||
Self::Price => ColumnType::Decimal(Some((19, 4))).def(),
|
||||
Self::BakeryId => ColumnType::Integer.def(),
|
||||
Self::GlutenFree => ColumnType::Boolean.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Bakery => Entity::belongs_to(super::bakery::Entity)
|
||||
.from(Column::BakeryId)
|
||||
.to(super::bakery::Column::Id)
|
||||
.into(),
|
||||
Self::Lineitem => Entity::has_many(super::lineitem::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::bakery::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Bakery.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::baker::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
super::cakes_bakers::Relation::Baker.def()
|
||||
}
|
||||
|
||||
fn via() -> Option<RelationDef> {
|
||||
Some(super::cakes_bakers::Relation::Cake.def().rev())
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::lineitem::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Lineitem.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
68
tests/common/bakery_chain/cakes_bakers.rs
Normal file
68
tests/common/bakery_chain/cakes_bakers.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"cakes_bakers"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub cake_id: i32,
|
||||
pub baker_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
CakeId,
|
||||
BakerId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
CakeId,
|
||||
BakerId,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Cake,
|
||||
Baker,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::CakeId => ColumnType::Integer.def(),
|
||||
Self::BakerId => ColumnType::Integer.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||
.from(Column::CakeId)
|
||||
.to(super::cake::Column::Id)
|
||||
.into(),
|
||||
Self::Baker => Entity::belongs_to(super::baker::Entity)
|
||||
.from(Column::BakerId)
|
||||
.to(super::baker::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
68
tests/common/bakery_chain/customer.rs
Normal file
68
tests/common/bakery_chain/customer.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"customer"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub notes: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Name,
|
||||
Notes,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Order,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Name => ColumnType::String(None).def(),
|
||||
Self::Notes => ColumnType::Text.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Order => Entity::has_many(super::order::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::order::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Order.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
89
tests/common/bakery_chain/lineitem.rs
Normal file
89
tests/common/bakery_chain/lineitem.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use rust_decimal::prelude::*;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"lineitem"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub price: Decimal,
|
||||
pub quantity: i32,
|
||||
pub order_id: Option<i32>,
|
||||
pub cake_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Price,
|
||||
Quantity,
|
||||
OrderId,
|
||||
CakeId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Order,
|
||||
Cake,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Price => ColumnType::Money(Some((19, 4))).def(),
|
||||
Self::Quantity => ColumnType::Integer.def(),
|
||||
Self::OrderId => ColumnType::Integer.def(),
|
||||
Self::CakeId => ColumnType::Integer.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Order => Entity::belongs_to(super::order::Entity)
|
||||
.from(Column::OrderId)
|
||||
.to(super::order::Column::Id)
|
||||
.into(),
|
||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||
.from(Column::CakeId)
|
||||
.to(super::cake::Column::Id)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::order::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Order.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::cake::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Cake.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
15
tests/common/bakery_chain/mod.rs
Normal file
15
tests/common/bakery_chain/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
pub mod baker;
|
||||
pub mod bakery;
|
||||
pub mod cake;
|
||||
pub mod cakes_bakers;
|
||||
pub mod customer;
|
||||
pub mod lineitem;
|
||||
pub mod order;
|
||||
|
||||
pub use super::baker::Entity as Baker;
|
||||
pub use super::bakery::Entity as Bakery;
|
||||
pub use super::cake::Entity as Cake;
|
||||
pub use super::cakes_bakers::Entity as CakesBakers;
|
||||
pub use super::customer::Entity as Customer;
|
||||
pub use super::lineitem::Entity as Lineitem;
|
||||
pub use super::order::Entity as Order;
|
97
tests/common/bakery_chain/order.rs
Normal file
97
tests/common/bakery_chain/order.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use rust_decimal::prelude::*;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn table_name(&self) -> &str {
|
||||
"order"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub id: i32,
|
||||
pub total: Decimal,
|
||||
pub bakery_id: Option<i32>,
|
||||
pub customer_id: Option<i32>,
|
||||
pub placed_at: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
Id,
|
||||
Total,
|
||||
BakeryId,
|
||||
CustomerId,
|
||||
PlacedAt,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
Id,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation {
|
||||
Bakery,
|
||||
Customer,
|
||||
Lineitem,
|
||||
}
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::Id => ColumnType::Integer.def(),
|
||||
Self::Total => ColumnType::Decimal(Some((19, 4))).def(),
|
||||
Self::BakeryId => ColumnType::Integer.def(),
|
||||
Self::CustomerId => ColumnType::Integer.def(),
|
||||
Self::PlacedAt => ColumnType::DateTime.def(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef {
|
||||
match self {
|
||||
Self::Bakery => Entity::belongs_to(super::bakery::Entity)
|
||||
.from(Column::BakeryId)
|
||||
.to(super::bakery::Column::Id)
|
||||
.into(),
|
||||
Self::Customer => Entity::belongs_to(super::customer::Entity)
|
||||
.from(Column::CustomerId)
|
||||
.to(super::customer::Column::Id)
|
||||
.into(),
|
||||
Self::Lineitem => Entity::has_many(super::lineitem::Entity).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::bakery::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Bakery.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::customer::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Customer.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl Related<super::lineitem::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Lineitem.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
50
tests/common/mod.rs
Normal file
50
tests/common/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
pub mod schema;
|
||||
use sea_orm::{Database, DatabaseConnection};
|
||||
pub mod bakery_chain;
|
||||
pub use bakery_chain::*;
|
||||
|
||||
macro_rules! function {
|
||||
() => {{
|
||||
fn f() {}
|
||||
fn type_name_of<T>(_: T) -> &'static str {
|
||||
std::any::type_name::<T>()
|
||||
}
|
||||
let name = type_name_of(f);
|
||||
&name[..name.len() - 3]
|
||||
}};
|
||||
}
|
||||
|
||||
pub struct TestContext {
|
||||
base_url: String,
|
||||
db_name: String,
|
||||
pub db_conn: DatabaseConnection,
|
||||
}
|
||||
|
||||
impl TestContext {
|
||||
pub async fn new(base_url: &str, db_name: &str) -> Self {
|
||||
let db_conn = Database::connect("sqlite::memory:").await.unwrap();
|
||||
Self::setup_schema(&db_conn).await;
|
||||
|
||||
Self {
|
||||
base_url: base_url.to_string(),
|
||||
db_name: db_name.to_string(),
|
||||
db_conn,
|
||||
}
|
||||
}
|
||||
|
||||
async fn setup_schema(db: &DatabaseConnection) {
|
||||
assert!(schema::create_bakery_table(db).await.is_ok());
|
||||
assert!(schema::create_baker_table(db).await.is_ok());
|
||||
assert!(schema::create_customer_table(db).await.is_ok());
|
||||
assert!(schema::create_order_table(db).await.is_ok());
|
||||
assert!(schema::create_lineitem_table(db).await.is_ok());
|
||||
assert!(schema::create_cake_table(db).await.is_ok());
|
||||
assert!(schema::create_cakes_bakers_table(db).await.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestContext {
|
||||
fn drop(&mut self) {
|
||||
println!("dropping context");
|
||||
}
|
||||
}
|
211
tests/common/schema.rs
Normal file
211
tests/common/schema.rs
Normal file
@ -0,0 +1,211 @@
|
||||
use sea_orm::{error::*, sea_query, DbConn, ExecResult};
|
||||
use sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Index, TableCreateStatement};
|
||||
|
||||
pub use super::bakery_chain::*;
|
||||
|
||||
async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result<ExecResult, DbErr> {
|
||||
let builder = db.get_schema_builder_backend();
|
||||
db.execute(builder.build(stmt)).await
|
||||
}
|
||||
|
||||
pub async fn create_bakery_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(bakery::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(bakery::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(bakery::Column::Name).string())
|
||||
.col(ColumnDef::new(bakery::Column::ProfitMargin).float())
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_baker_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(baker::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(baker::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(baker::Column::Name).string())
|
||||
.col(ColumnDef::new(baker::Column::BakeryId).integer())
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_baker_bakery")
|
||||
.from(baker::Entity, baker::Column::BakeryId)
|
||||
.to(bakery::Entity, bakery::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_customer_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(customer::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(customer::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(customer::Column::Name).string())
|
||||
.col(ColumnDef::new(customer::Column::Notes).text())
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_order_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(order::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(order::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(order::Column::Total).float())
|
||||
.col(ColumnDef::new(order::Column::BakeryId).integer().not_null())
|
||||
.col(
|
||||
ColumnDef::new(order::Column::CustomerId)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(order::Column::PlacedAt)
|
||||
.date_time()
|
||||
.not_null(),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_order_bakery")
|
||||
.from(order::Entity, order::Column::BakeryId)
|
||||
.to(bakery::Entity, bakery::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_order_customer")
|
||||
.from(order::Entity, order::Column::CustomerId)
|
||||
.to(customer::Entity, customer::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_lineitem_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(lineitem::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(lineitem::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(lineitem::Column::Price).decimal())
|
||||
.col(ColumnDef::new(lineitem::Column::Quantity).integer())
|
||||
.col(
|
||||
ColumnDef::new(lineitem::Column::OrderId)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(lineitem::Column::CakeId)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_lineitem_order")
|
||||
.from(lineitem::Entity, lineitem::Column::OrderId)
|
||||
.to(order::Entity, order::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_lineitem_cake")
|
||||
.from(lineitem::Entity, lineitem::Column::CakeId)
|
||||
.to(cake::Entity, cake::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_cakes_bakers_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(cakes_bakers::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(cakes_bakers::Column::CakeId)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(cakes_bakers::Column::BakerId)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.primary_key(
|
||||
Index::create()
|
||||
.col(cakes_bakers::Column::CakeId)
|
||||
.col(cakes_bakers::Column::BakerId),
|
||||
)
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
||||
|
||||
pub async fn create_cake_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
let stmt = sea_query::Table::create()
|
||||
.table(cake::Entity)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(cake::Column::Id)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(cake::Column::Name).string())
|
||||
.col(ColumnDef::new(cake::Column::Price).float())
|
||||
.col(ColumnDef::new(cake::Column::BakeryId).integer().not_null())
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_cake_bakery")
|
||||
.from(cake::Entity, cake::Column::BakeryId)
|
||||
.to(bakery::Entity, bakery::Column::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.col(ColumnDef::new(cake::Column::GlutenFree).boolean())
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
}
|
37
tests/relational_tests.rs
Normal file
37
tests/relational_tests.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use sea_orm::{entity::*, InsertResult};
|
||||
|
||||
pub mod bakery_chain;
|
||||
pub use bakery_chain::*;
|
||||
|
||||
pub mod common;
|
||||
pub use common::TestContext;
|
||||
|
||||
#[async_std::test]
|
||||
// cargo test --test realtional_tests -- --nocapture
|
||||
async fn main() {
|
||||
test_left_join().await;
|
||||
}
|
||||
|
||||
pub async fn test_left_join() {
|
||||
let ctx = TestContext::new("test", "test").await;
|
||||
|
||||
let seaside_bakery = bakery::ActiveModel {
|
||||
name: Set("SeaSide Bakery".to_owned()),
|
||||
profit_margin: Set(10.4),
|
||||
..Default::default()
|
||||
};
|
||||
let res: InsertResult = Bakery::insert(seaside_bakery)
|
||||
.exec(&ctx.db_conn)
|
||||
.await
|
||||
.expect("could not insert bakery");
|
||||
|
||||
let bakery: Option<bakery::Model> = Bakery::find_by_id(res.last_insert_id)
|
||||
.one(&ctx.db_conn)
|
||||
.await
|
||||
.expect("could not find bakery");
|
||||
|
||||
assert!(bakery.is_some());
|
||||
let bakery_model = bakery.unwrap();
|
||||
assert_eq!(bakery_model.name, "SeaSide Bakery");
|
||||
assert_eq!(bakery_model.profit_margin, 10.4);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user