Additional tests, macros for tests
This commit is contained in:
parent
cf464beb27
commit
a34f32dc15
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -1162,6 +1162,7 @@ dependencies = [
|
||||
"serde",
|
||||
"sqlx",
|
||||
"sqlx-core",
|
||||
"testx",
|
||||
"thiserror",
|
||||
"uuid 0.8.2",
|
||||
]
|
||||
@ -3830,6 +3831,10 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "testx"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
|
@ -4,6 +4,7 @@ members = [
|
||||
"shared/model",
|
||||
"shared/bus",
|
||||
"shared/config",
|
||||
"shared/testx",
|
||||
# actors
|
||||
"actors/account_manager",
|
||||
"actors/cart_manager",
|
||||
|
@ -30,3 +30,6 @@ rand = { version = "0.8.5", optional = true }
|
||||
itertools = { version = "0.10.3" }
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
testx = { path = "../../shared/testx" }
|
||||
|
@ -248,15 +248,7 @@ mod test {
|
||||
|
||||
#[actix::test]
|
||||
async fn full_check() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
// account
|
||||
let account = test_create_account(&mut t).await;
|
||||
@ -351,7 +343,7 @@ mod test {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(default_address, address);
|
||||
}
|
||||
}
|
||||
|
@ -268,15 +268,7 @@ mod tests {
|
||||
|
||||
#[actix::test]
|
||||
async fn create_account() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let login: String = fake::faker::internet::en::Username().fake();
|
||||
let email: String = fake::faker::internet::en::FreeEmail().fake();
|
||||
@ -310,36 +302,21 @@ mod tests {
|
||||
|
||||
#[actix::test]
|
||||
async fn all_accounts() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
test_create_account(&mut t, None, None, None).await;
|
||||
test_create_account(&mut t, None, None, None).await;
|
||||
test_create_account(&mut t, None, None, None).await;
|
||||
|
||||
let v: Vec<FullAccount> = super::all_accounts(AllAccounts, &mut t).await.unwrap();
|
||||
|
||||
testx::db_rollback!(t);
|
||||
assert!(v.len() >= 3);
|
||||
t.rollback().await.unwrap();
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn update_account_without_pass() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let original_login: String = fake::faker::internet::en::Username().fake();
|
||||
let original_email: String = fake::faker::internet::en::FreeEmail().fake();
|
||||
@ -380,22 +357,14 @@ mod tests {
|
||||
state: AccountState::Active,
|
||||
};
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_ne!(original_account, expected);
|
||||
assert_eq!(updated_account, expected);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn update_account_with_pass() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let original_login: String = fake::faker::internet::en::Username().fake();
|
||||
let original_email: String = fake::faker::internet::en::FreeEmail().fake();
|
||||
@ -437,22 +406,14 @@ mod tests {
|
||||
state: AccountState::Active,
|
||||
};
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_ne!(original_account, expected);
|
||||
assert_eq!(updated_account, expected);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn find() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let account = test_create_account(&mut t, None, None, None).await;
|
||||
|
||||
@ -465,21 +426,13 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(account, res);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn find_identity_email() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let account = test_create_account(&mut t, None, None, None).await;
|
||||
|
||||
@ -493,21 +446,13 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(account, res);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn find_identity_login() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let account = test_create_account(&mut t, None, None, None).await;
|
||||
|
||||
@ -521,7 +466,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(account, res);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ async fn all_stocks(
|
||||
r#"
|
||||
SELECT id, product_id, quantity, quantity_unit
|
||||
FROM stocks
|
||||
ORDER BY id ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(pool)
|
||||
@ -235,30 +236,16 @@ mod tests {
|
||||
|
||||
#[actix::test]
|
||||
async fn create_stock() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
testx::db_t!(t);
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
test_stock(&mut t, None, None, None).await;
|
||||
t.rollback().await.unwrap();
|
||||
|
||||
testx::db_rollback!(t);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn products_stock() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut t = pool.begin().await.unwrap();
|
||||
testx::db_t!(t);
|
||||
|
||||
let first = test_stock(&mut t, None, None, None).await;
|
||||
let second = test_stock(&mut t, None, None, None).await;
|
||||
@ -272,7 +259,42 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
t.rollback().await.unwrap();
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(stocks, vec![first, second]);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn all_stocks() {
|
||||
testx::db_t!(t);
|
||||
|
||||
let first = test_stock(&mut t, None, None, None).await;
|
||||
let second = test_stock(&mut t, None, None, None).await;
|
||||
|
||||
let stocks: Vec<Stock> = super::all_stocks(AllStocks, &mut t).await.unwrap();
|
||||
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(stocks, vec![first, second]);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn delete_stock() {
|
||||
testx::db_t!(t);
|
||||
|
||||
let first = test_stock(&mut t, None, None, None).await;
|
||||
let second = test_stock(&mut t, None, None, None).await;
|
||||
|
||||
let deleted: Option<Stock> = super::delete_stock(
|
||||
DeleteStock {
|
||||
stock_id: second.id,
|
||||
},
|
||||
&mut t,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
// let reloaded = super::Stock
|
||||
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(deleted, Some(second));
|
||||
assert_ne!(deleted, Some(first));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use actix::Message;
|
||||
use model::{AccountId, Audience, Token};
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{db_async_handler, Result};
|
||||
|
||||
@ -36,16 +35,19 @@ pub struct TokenByJti {
|
||||
pub jti: uuid::Uuid,
|
||||
}
|
||||
|
||||
db_async_handler!(TokenByJti, token_by_jti, Token);
|
||||
db_async_handler!(TokenByJti, token_by_jti, Token, inner_token_by_jti);
|
||||
|
||||
pub(crate) async fn token_by_jti(msg: TokenByJti, pool: PgPool) -> Result<Token> {
|
||||
pub(crate) async fn token_by_jti(
|
||||
msg: TokenByJti,
|
||||
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<Token> {
|
||||
sqlx::query_as(r#"
|
||||
SELECT id, customer_id, role, issuer, subject, audience, expiration_time, not_before_time, issued_at_time, jwt_id
|
||||
FROM tokens
|
||||
WHERE jwt_id = $1 AND expiration_time > now()
|
||||
"#)
|
||||
.bind(msg.jti)
|
||||
.fetch_one(&pool)
|
||||
.fetch_one(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
log::error!("{e:?}");
|
||||
@ -62,9 +64,12 @@ pub struct CreateToken {
|
||||
pub audience: Audience,
|
||||
}
|
||||
|
||||
db_async_handler!(CreateToken, create_token, Token);
|
||||
db_async_handler!(CreateToken, create_token, Token, inner_create_token);
|
||||
|
||||
pub(crate) async fn create_token(msg: CreateToken, pool: PgPool) -> Result<Token> {
|
||||
pub(crate) async fn create_token(
|
||||
msg: CreateToken,
|
||||
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<Token> {
|
||||
let CreateToken {
|
||||
customer_id,
|
||||
role,
|
||||
@ -80,7 +85,7 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not
|
||||
.bind(role)
|
||||
.bind(subject)
|
||||
.bind(audience)
|
||||
.fetch_one(&pool)
|
||||
.fetch_one(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
log::error!("{e:?}");
|
||||
@ -98,9 +103,17 @@ pub struct CreateExtendedToken {
|
||||
pub expiration_time: chrono::NaiveDateTime,
|
||||
}
|
||||
|
||||
db_async_handler!(CreateExtendedToken, create_extended_token, Token);
|
||||
db_async_handler!(
|
||||
CreateExtendedToken,
|
||||
create_extended_token,
|
||||
Token,
|
||||
inner_create_extended_token
|
||||
);
|
||||
|
||||
pub(crate) async fn create_extended_token(msg: CreateExtendedToken, pool: PgPool) -> Result<Token> {
|
||||
pub(crate) async fn create_extended_token(
|
||||
msg: CreateExtendedToken,
|
||||
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<Token> {
|
||||
let CreateExtendedToken {
|
||||
customer_id,
|
||||
role,
|
||||
@ -118,7 +131,7 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not
|
||||
.bind(subject)
|
||||
.bind(audience)
|
||||
.bind(expiration_time)
|
||||
.fetch_one(&pool)
|
||||
.fetch_one(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
log::error!("{e:?}");
|
||||
@ -128,7 +141,6 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix::Addr;
|
||||
use config::UpdateConfig;
|
||||
use fake::Fake;
|
||||
use model::*;
|
||||
@ -140,25 +152,27 @@ mod tests {
|
||||
|
||||
impl UpdateConfig for NoOpts {}
|
||||
|
||||
async fn test_create_account(db: Addr<Database>) -> FullAccount {
|
||||
async fn test_create_account(t: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> FullAccount {
|
||||
use fake::faker::internet::en;
|
||||
let login: String = en::Username().fake();
|
||||
let email: String = en::FreeEmail().fake();
|
||||
let hash: String = en::Password(10..20).fake();
|
||||
|
||||
db.send(CreateAccount {
|
||||
crate::create_account(
|
||||
CreateAccount {
|
||||
email: Email::new(email),
|
||||
login: Login::new(login),
|
||||
pass_hash: PassHash::new(hash),
|
||||
role: Role::Admin,
|
||||
})
|
||||
},
|
||||
t,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn test_create_token_extended(
|
||||
db: Addr<Database>,
|
||||
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
customer_id: Option<Uuid>,
|
||||
role: Option<Role>,
|
||||
subject: Option<AccountId>,
|
||||
@ -169,93 +183,77 @@ mod tests {
|
||||
let role = role.unwrap_or_else(|| Role::Admin);
|
||||
let subject = match subject {
|
||||
Some(id) => id,
|
||||
_ => test_create_account(db.clone()).await.id,
|
||||
_ => test_create_account(t).await.id,
|
||||
};
|
||||
let audience = audience.unwrap_or_else(|| Audience::Web);
|
||||
let expiration_time = expiration_time
|
||||
.unwrap_or_else(|| (chrono::Utc::now() + chrono::Duration::days(60)).naive_utc());
|
||||
|
||||
db.send(CreateExtendedToken {
|
||||
super::create_extended_token(
|
||||
CreateExtendedToken {
|
||||
customer_id,
|
||||
role,
|
||||
subject,
|
||||
audience,
|
||||
expiration_time,
|
||||
})
|
||||
},
|
||||
t,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn create_token() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
testx::db_t!(t);
|
||||
|
||||
let db = Database::build(config).await.start();
|
||||
|
||||
db.send(CreateToken {
|
||||
super::create_token(
|
||||
CreateToken {
|
||||
customer_id: Uuid::new_v4(),
|
||||
role: Role::Admin,
|
||||
subject: test_create_account(db.clone()).await.id,
|
||||
subject: test_create_account(&mut t).await.id,
|
||||
audience: Audience::Web,
|
||||
})
|
||||
},
|
||||
&mut t,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn create_extended_token() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
testx::db_t!(t);
|
||||
|
||||
let db = Database::build(config).await.start();
|
||||
test_create_account(&mut t).await;
|
||||
|
||||
test_create_account(db).await;
|
||||
testx::db_rollback!(t);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn find_by_jti() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
testx::db_t!(t);
|
||||
|
||||
let db = Database::build(config).await.start();
|
||||
let original = test_create_token_extended(&mut t, None, None, None, None, None).await;
|
||||
|
||||
let original = test_create_token_extended(db.clone(), None, None, None, None, None).await;
|
||||
|
||||
let found = db
|
||||
.send(TokenByJti {
|
||||
let found = super::token_by_jti(
|
||||
TokenByJti {
|
||||
jti: original.jwt_id,
|
||||
})
|
||||
},
|
||||
&mut t,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(found, original);
|
||||
}
|
||||
|
||||
#[actix::test]
|
||||
async fn find_by_jti_expired() {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await.start();
|
||||
testx::db_t!(t);
|
||||
|
||||
let original = test_create_token_extended(
|
||||
db.clone(),
|
||||
&mut t,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -264,13 +262,15 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
let found = db
|
||||
.send(TokenByJti {
|
||||
let found = super::token_by_jti(
|
||||
TokenByJti {
|
||||
jti: original.jwt_id,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
},
|
||||
&mut t,
|
||||
)
|
||||
.await;
|
||||
|
||||
testx::db_rollback!(t);
|
||||
assert_eq!(found, Err(crate::Error::Token(super::Error::Jti)));
|
||||
}
|
||||
}
|
||||
|
@ -862,7 +862,7 @@ pub struct Product {
|
||||
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
|
||||
#[cfg_attr(feature = "db", derive(sqlx::Type))]
|
||||
#[cfg_attr(feature = "db", sqlx(transparent))]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct StockId(pub RecordId);
|
||||
|
||||
|
6
shared/testx/Cargo.toml
Normal file
6
shared/testx/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "testx"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
21
shared/testx/src/lib.rs
Normal file
21
shared/testx/src/lib.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#[macro_export]
|
||||
macro_rules! db_t {
|
||||
($t: ident) => {
|
||||
let config = config::default_load(&mut NoOpts);
|
||||
config
|
||||
.lock()
|
||||
.database_mut()
|
||||
.set_url("postgres://postgres@localhost/bazzar_test");
|
||||
|
||||
let db = Database::build(config).await;
|
||||
let pool = db.pool();
|
||||
let mut $t = pool.begin().await.unwrap();
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! db_rollback {
|
||||
($t: expr) => {
|
||||
$t.rollback().await.unwrap();
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user