add integration test in model

This commit is contained in:
Namekuji 2023-05-27 05:50:07 -04:00
parent 737ccfe11c
commit 4012d38f7f
No known key found for this signature in database
GPG Key ID: B541BD6E646CABC7
9 changed files with 173 additions and 15 deletions

View File

@ -22,12 +22,12 @@ mod tests {
use crate::{error::Error, init_database}; use crate::{error::Error, init_database};
#[test] #[test]
fn error_uninitialized() { fn unit_lib_error_uninitialized() {
assert_eq!(get_database().unwrap_err(), Error::Uninitialized); assert_eq!(get_database().unwrap_err(), Error::Uninitialized);
} }
#[tokio::test] #[tokio::test]
async fn connect_in_memory_sqlite() -> Result<(), Error> { async fn unit_lib_connect_in_memory_sqlite() -> Result<(), Error> {
init_database("sqlite::memory:").await?; init_database("sqlite::memory:").await?;
get_database()?; get_database()?;
Ok(()) Ok(())

View File

@ -6,6 +6,6 @@ use schemars::JsonSchema;
use crate::error::Error; use crate::error::Error;
#[async_trait] #[async_trait]
trait Repository<T: JsonSchema> { pub trait Repository<T: JsonSchema> {
async fn pack(self) -> Result<T, Error>; async fn pack(self) -> Result<T, Error>;
} }

View File

@ -7,7 +7,7 @@ use utoipa::ToSchema;
use super::{Keyword, Schema, StringList}; use super::{Keyword, Schema, StringList};
use crate::entity::sea_orm_active_enums::AntennaSrcEnum; use crate::entity::sea_orm_active_enums::AntennaSrcEnum;
#[derive(Debug, JsonSchema, ToSchema)] #[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Antenna { pub struct Antenna {
pub id: String, pub id: String,
@ -33,9 +33,10 @@ pub struct Antenna {
pub has_unread_note: bool, pub has_unread_note: bool,
} }
#[derive(Debug, FromStr, JsonSchema, ToSchema)] #[derive(Clone, Debug, FromStr, PartialEq, Eq, JsonSchema, ToSchema)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "camelCase")]
#[display(style = "lowercase")] #[display(style = "camelCase")]
#[display("'{}'")]
pub enum AntennaSrc { pub enum AntennaSrc {
Home, Home,
All, All,
@ -62,10 +63,18 @@ pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(|| Antenna::validator());
mod tests { mod tests {
use serde_json::json; use serde_json::json;
use crate::{entity::sea_orm_active_enums::AntennaSrcEnum, schema::antenna::AntennaSrc};
use super::VALIDATOR; use super::VALIDATOR;
#[test] #[test]
fn valid() { fn unit_schema_src_from_active_enum() {
let src = AntennaSrc::try_from(AntennaSrcEnum::All).unwrap();
assert_eq!(src, AntennaSrc::All);
}
#[test]
fn unit_schema_antenna_valid() {
let instance = json!({ let instance = json!({
"id": "9f4x0bkx1u", "id": "9f4x0bkx1u",
"createdAt": "2023-05-24T06:56:14.323Z", "createdAt": "2023-05-24T06:56:14.323Z",
@ -89,7 +98,7 @@ mod tests {
} }
#[test] #[test]
fn invalid() { fn unit_schema_antenna_invalid() {
let instance = json!({ let instance = json!({
// "id" is required // "id" is required
"id": null, "id": null,

View File

@ -5,7 +5,7 @@ use utoipa::ToSchema;
use super::Schema; use super::Schema;
#[derive(Debug, JsonSchema, ToSchema)] #[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct App { pub struct App {
pub id: String, pub id: String,
@ -19,7 +19,7 @@ pub struct App {
} }
/// This represents `permissions` in `packages/calckey-js/src/consts.ts`. /// This represents `permissions` in `packages/calckey-js/src/consts.ts`.
#[derive(Debug, JsonSchema, ToSchema)] #[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)]
pub enum Permission { pub enum Permission {
#[serde(rename = "read:account")] #[serde(rename = "read:account")]
ReadAccount, ReadAccount,
@ -96,12 +96,12 @@ pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(|| App::validator());
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]
fn valid() { fn unit_schema_app_valid() {
todo!(); todo!();
} }
#[test] #[test]
fn invalid() { fn unit_shcmea_app_invalid() {
todo!(); todo!();
} }
} }

View File

@ -0,0 +1,88 @@
extern crate model;
mod repository;
use chrono::Utc;
use model::entity::{antenna, sea_orm_active_enums::AntennaSrcEnum, user};
use sea_orm::{
ActiveModelTrait, ActiveValue::Set, DatabaseConnection, DbErr, EntityTrait, TransactionTrait,
};
use serde_json::json;
use std::env;
use util::{
id::{create_id, init_id},
random::gen_string,
};
/// Insert predefined entries in the database.
async fn prepare() {
let conn_uri = env::var("DATABASE_URL")
.unwrap_or("postgres://calckey:calckey@localhost/calckey".to_string());
database::init_database(conn_uri)
.await
.expect("Unable to initialize database connection");
let db = database::get_database().expect("Unable to get database connection from pool");
setup_model(db).await;
}
/// Delete all entries in the database.
async fn cleanup() {
let db = database::get_database().unwrap();
db.transaction::<_, (), DbErr>(|txn| {
Box::pin(async move {
user::Entity::delete_many().exec(txn).await.unwrap();
antenna::Entity::delete_many().exec(txn).await.unwrap();
Ok(())
})
})
.await
.expect("Unable to delete predefined models");
}
async fn setup_model(db: &DatabaseConnection) {
init_id(12);
db.transaction::<_, (), DbErr>(|txn| {
Box::pin(async move {
let user_id = create_id().unwrap();
let name = "Alice";
let user_model = user::ActiveModel {
id: Set(user_id.to_owned()),
created_at: Set(Utc::now().into()),
username: Set(name.to_lowercase().to_string()),
username_lower: Set(name.to_lowercase().to_string()),
name: Set(Some(name.to_string())),
token: Set(Some(gen_string(16))),
is_admin: Set(true),
..Default::default()
};
user_model.insert(txn).await?;
let antenna_model = antenna::ActiveModel {
id: Set(create_id().unwrap()),
created_at: Set(Utc::now().into()),
user_id: Set(user_id.to_owned()),
name: Set("Test Antenna".to_string()),
src: Set(AntennaSrcEnum::All),
keywords: Set(json!([["foo", "bar"], ["foobar"]])),
exclude_keywords: Set(json!([["abc"], ["def", "ghi"]])),
with_file: Set(false),
notify: Set(true),
case_sensitive: Set(true),
with_replies: Set(false),
..Default::default()
};
antenna_model.insert(txn).await?;
Ok(())
})
})
.await
.expect("Unable to setup predefined models");
}
#[tokio::test]
async fn inte_common_prepare_and_cleanup() {
prepare().await;
cleanup().await;
}

View File

@ -0,0 +1,60 @@
use model::{
entity::{antenna, user},
repository::Repository,
schema,
};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use crate::{cleanup, prepare};
#[tokio::test]
async fn inte_repository_antenna_can_pack() {
prepare().await;
let db = database::get_database().unwrap();
let alice_antenna = user::Entity::find()
.filter(user::Column::Username.eq("alice"))
.find_also_related(antenna::Entity)
.one(db)
.await
.unwrap()
.expect("alice not found")
.1
.expect("alice's antenna not found");
let packed = alice_antenna
.to_owned()
.pack()
.await
.expect("Unable to pack");
assert_eq!(
packed,
schema::antenna::Antenna {
id: alice_antenna.id,
created_at: alice_antenna.created_at.into(),
name: "Test Antenna".to_string(),
keywords: vec![
vec!["foo".to_string(), "bar".to_string()],
vec!["foobar".to_string()]
],
exclude_keywords: vec![
vec!["abc".to_string()],
vec!["def".to_string(), "ghi".to_string()]
],
src: schema::antenna::AntennaSrc::All,
user_list_id: None,
user_group_id: None,
users: vec![],
instances: vec![],
case_sensitive: true,
notify: true,
with_replies: false,
with_file: false,
has_unread_note: false,
}
);
cleanup().await;
}

View File

@ -0,0 +1 @@
mod antenna;

View File

@ -27,7 +27,7 @@ mod tests {
use crate::id; use crate::id;
#[test] #[test]
fn can_generate() { fn unit_id_can_generate() {
assert_eq!(id::create_id(), Err(id::ErrorUninitialized)); assert_eq!(id::create_id(), Err(id::ErrorUninitialized));
id::init_id(12); id::init_id(12);
assert_eq!(id::create_id().unwrap().len(), 12); assert_eq!(id::create_id().unwrap().len(), 12);

View File

@ -15,7 +15,7 @@ mod tests {
use super::gen_string; use super::gen_string;
#[test] #[test]
fn can_generate_string() { fn unit_random_can_generate_string() {
assert_eq!(gen_string(16).len(), 16); assert_eq!(gen_string(16).len(), 16);
assert_ne!(gen_string(16), gen_string(16)); assert_ne!(gen_string(16), gen_string(16));
let s1 = thread::spawn(|| gen_string(16)); let s1 = thread::spawn(|| gen_string(16));