add test builder

This commit is contained in:
appflowy 2021-07-14 23:00:58 +08:00
parent 182adafee5
commit e767cc3a01
12 changed files with 141 additions and 53 deletions

View File

@ -1,10 +1,7 @@
mod flowy_server; mod flowy_server;
pub mod module; pub mod module;
use crate::{ use crate::flowy_server::{ArcFlowyServer, MockFlowyServer};
flowy_server::{ArcFlowyServer, MockFlowyServer},
user_server::MockUserServer,
};
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
use module::build_modules; use module::build_modules;
pub use module::*; pub use module::*;
@ -32,7 +29,7 @@ impl FlowySDK {
FlowySDK::init_log(&self.root); FlowySDK::init_log(&self.root);
tracing::info!("🔥 Root path: {}", self.root); tracing::info!("🔥 Root path: {}", self.root);
flowy_infra::kv::KVStore::init(path); flowy_infra::kv::KVStore::init(&self.root);
FlowySDK::init_modules(&self.root, self.server); FlowySDK::init_modules(&self.root, self.server);
} }

View File

@ -1,7 +1,7 @@
use flowy_dispatch::prelude::Module; use flowy_dispatch::prelude::Module;
use flowy_user::prelude::*; use flowy_user::prelude::*;
use crate::{flowy_server::ArcFlowyServer, user_server::MockUserServer}; use crate::flowy_server::{ArcFlowyServer, MockFlowyServer};
use flowy_database::DBConnection; use flowy_database::DBConnection;
use flowy_user::errors::UserError; use flowy_user::errors::UserError;
use flowy_workspace::prelude::*; use flowy_workspace::prelude::*;
@ -15,7 +15,7 @@ pub fn build_modules(config: ModuleConfig, server: ArcFlowyServer) -> Vec<Module
let user_session = Arc::new( let user_session = Arc::new(
UserSessionBuilder::new() UserSessionBuilder::new()
.root_dir(&config.root) .root_dir(&config.root)
.build(config.server), .build(Arc::new(MockFlowyServer {})),
); );
let workspace_user_impl = Arc::new(WorkspaceUserImpl { let workspace_user_impl = Arc::new(WorkspaceUserImpl {

View File

@ -8,6 +8,7 @@ edition = "2018"
[dependencies] [dependencies]
flowy-sdk = { path = "../flowy-sdk"} flowy-sdk = { path = "../flowy-sdk"}
flowy-dispatch = { path = "../flowy-dispatch"} flowy-dispatch = { path = "../flowy-dispatch"}
flowy-user = { path = "../flowy-user"}
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
bincode = { version = "1.3"} bincode = { version = "1.3"}

View File

@ -1,5 +1,10 @@
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
pub use flowy_sdk::*; pub use flowy_sdk::*;
use flowy_user::{
errors::UserError,
event::UserEvent::{SignIn, SignOut},
prelude::*,
};
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
fmt::{Debug, Display}, fmt::{Debug, Display},
@ -12,7 +17,7 @@ use std::{
}; };
pub mod prelude { pub mod prelude {
pub use crate::EventTester; pub use crate::Tester;
pub use flowy_dispatch::prelude::*; pub use flowy_dispatch::prelude::*;
pub use std::convert::TryFrom; pub use std::convert::TryFrom;
} }
@ -42,18 +47,82 @@ fn root_dir() -> String {
root_dir root_dir
} }
pub trait TesterConfig { pub struct TestBuilder<Error> {
fn auto_sign_in() -> bool { false } login: Option<bool>,
inner: Option<Tester<Error>>,
pub user_detail: Option<UserDetail>,
} }
pub struct EventTester<Error> { impl<Error> TestBuilder<Error>
where
Error: FromBytes + Debug,
{
pub fn new() -> Self {
TestBuilder::<Error> {
login: None,
inner: None,
user_detail: None,
}
}
pub fn login(mut self) -> Self {
let user_detail = new_user_after_login();
self.user_detail = Some(user_detail);
self
}
pub fn logout(self) -> Self {
init_sdk();
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut));
self
}
pub fn event<E>(mut self, event: E) -> Self
where
E: Eq + Hash + Debug + Clone + Display,
{
self.inner = Some(Tester::<Error>::new(event));
self
}
pub fn request<P>(mut self, request: P) -> Self
where
P: ToBytes,
{
let mut inner = self.inner.unwrap();
self.inner = Some(inner.request(request));
self
}
pub fn sync_send(mut self) -> Self {
let inner = self.inner.take().unwrap();
self.inner = Some(inner.sync_send());
self
}
pub fn parse<R>(mut self) -> R
where
R: FromBytes,
{
let inner = self.inner.take().unwrap();
inner.parse::<R>()
}
pub fn error(mut self) -> Error {
let inner = self.inner.take().unwrap();
inner.error()
}
}
pub struct Tester<Error> {
inner_request: Option<ModuleRequest>, inner_request: Option<ModuleRequest>,
assert_status_code: Option<StatusCode>, assert_status_code: Option<StatusCode>,
response: Option<EventResponse>, response: Option<EventResponse>,
err_phantom: PhantomData<Error>, err_phantom: PhantomData<Error>,
user_detail: Option<UserDetail>,
} }
impl<Error> EventTester<Error> impl<Error> Tester<Error>
where where
Error: FromBytes + Debug, Error: FromBytes + Debug,
{ {
@ -73,6 +142,7 @@ where
assert_status_code: None, assert_status_code: None,
response: None, response: None,
err_phantom: PhantomData, err_phantom: PhantomData,
user_detail: None,
} }
} }
@ -97,7 +167,6 @@ where
self self
} }
#[allow(dead_code)]
pub async fn async_send(mut self) -> Self { pub async fn async_send(mut self) -> Self {
let resp = let resp =
EventDispatch::async_send(self.inner_request.take().unwrap(), |_| Box::pin(async {})) EventDispatch::async_send(self.inner_request.take().unwrap(), |_| Box::pin(async {}))
@ -148,3 +217,23 @@ fn check(response: &EventResponse, status_code: &Option<StatusCode>) {
assert_eq!(&response.status_code, status_code) assert_eq!(&response.status_code, status_code)
} }
} }
fn new_user_after_login() -> UserDetail {
init_sdk();
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut));
let request = SignInRequest {
email: valid_email(),
password: valid_password(),
};
let user_detail = Tester::<UserError>::new(SignIn)
.request(request)
.sync_send()
.parse::<UserDetail>();
user_detail
}
pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() }
pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() }

View File

@ -1,4 +1,5 @@
use crate::services::user_session::{user_server::UserServer, UserSession, UserSessionConfig}; use crate::services::user_session::{user_server::UserServer, UserSession, UserSessionConfig};
use std::sync::Arc;
pub struct UserSessionBuilder { pub struct UserSessionBuilder {
config: Option<UserSessionConfig>, config: Option<UserSessionConfig>,
@ -12,7 +13,7 @@ impl UserSessionBuilder {
self self
} }
pub fn build<S>(mut self, server: S) -> UserSession pub fn build<S>(mut self, server: Arc<S>) -> UserSession
where where
S: 'static + UserServer + Send + Sync, S: 'static + UserServer + Send + Sync,
{ {

View File

@ -7,7 +7,7 @@ use flowy_database::{
}; };
use flowy_infra::kv::KVStore; use flowy_infra::kv::KVStore;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::sync::RwLock; use std::sync::{Arc, RwLock};
use crate::{ use crate::{
entities::{SignInParams, SignUpParams, UpdateUserParams, UserDetail}, entities::{SignInParams, SignUpParams, UpdateUserParams, UserDetail},
@ -31,11 +31,11 @@ impl UserSessionConfig {
pub struct UserSession { pub struct UserSession {
database: UserDB, database: UserDB,
config: UserSessionConfig, config: UserSessionConfig,
server: Box<dyn UserServer + Send + Sync>, server: Arc<dyn UserServer + Send + Sync>,
} }
impl UserSession { impl UserSession {
pub fn new<R>(config: UserSessionConfig, server: R) -> Self pub fn new<R>(config: UserSessionConfig, server: Arc<R>) -> Self
where where
R: 'static + UserServer + Send + Sync, R: 'static + UserServer + Send + Sync,
{ {
@ -43,7 +43,7 @@ impl UserSession {
Self { Self {
database: db, database: db,
config, config,
server: Box::new(server), server,
} }
} }

View File

@ -1,7 +1,7 @@
use flowy_test::{EventTester, TesterConfig}; use flowy_test::{TestBuilder, Tester};
use flowy_user::errors::UserError; use flowy_user::errors::UserError;
pub type UserEventTester = EventTester<UserError, TesterConfig>; pub type UserTestBuilder = TestBuilder<UserError>;
pub(crate) fn invalid_email_test_case() -> Vec<String> { pub(crate) fn invalid_email_test_case() -> Vec<String> {
// https://gist.github.com/cjaoude/fd9910626629b53c4d25 // https://gist.github.com/cjaoude/fd9910626629b53c4d25

View File

@ -6,13 +6,14 @@ use serial_test::*;
#[test] #[test]
#[serial] #[serial]
fn sign_in_success() { fn sign_in_success() {
let _ = UserEventTester::new(SignOut).sync_send();
let request = SignInRequest { let request = SignInRequest {
email: valid_email(), email: valid_email(),
password: valid_password(), password: valid_password(),
}; };
let response = UserEventTester::new(SignIn) let response = UserTestBuilder::new()
.logout()
.event(SignIn)
.request(request) .request(request)
.sync_send() .sync_send()
.parse::<UserDetail>(); .parse::<UserDetail>();
@ -28,7 +29,8 @@ fn sign_in_with_invalid_email() {
}; };
assert_eq!( assert_eq!(
UserEventTester::new(SignIn) UserTestBuilder::new()
.event(SignIn)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()
@ -47,7 +49,8 @@ fn sign_in_with_invalid_password() {
}; };
assert_eq!( assert_eq!(
UserEventTester::new(SignIn) UserTestBuilder::new()
.event(SignIn)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()

View File

@ -6,14 +6,17 @@ use serial_test::*;
#[test] #[test]
#[serial] #[serial]
fn sign_up_success() { fn sign_up_success() {
let _ = UserEventTester::new(SignOut).sync_send(); let _ = UserTestBuilder::new().event(SignOut).sync_send();
let request = SignUpRequest { let request = SignUpRequest {
email: valid_email(), email: valid_email(),
name: valid_name(), name: valid_name(),
password: valid_password(), password: valid_password(),
}; };
let _response = UserEventTester::new(SignUp).request(request).sync_send(); let _response = UserTestBuilder::new()
.event(SignUp)
.request(request)
.sync_send();
// .parse::<SignUpResponse>(); // .parse::<SignUpResponse>();
// dbg!(&response); // dbg!(&response);
} }
@ -28,7 +31,8 @@ fn sign_up_with_invalid_email() {
}; };
assert_eq!( assert_eq!(
UserEventTester::new(SignUp) UserTestBuilder::new()
.event(SignUp)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()
@ -47,7 +51,8 @@ fn sign_up_with_invalid_password() {
}; };
assert_eq!( assert_eq!(
UserEventTester::new(SignUp) UserTestBuilder::new()
.event(SignUp)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()

View File

@ -1,5 +1,4 @@
use crate::helper::*; use crate::helper::*;
use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*}; use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*};
use serial_test::*; use serial_test::*;
@ -7,8 +6,9 @@ use serial_test::*;
#[should_panic] #[should_panic]
#[serial] #[serial]
fn user_status_not_found_before_login() { fn user_status_not_found_before_login() {
let _ = UserEventTester::new(SignOut).sync_send(); let _ = UserTestBuilder::new()
let _ = UserEventTester::new(GetStatus) .logout()
.event(GetStatus)
.sync_send() .sync_send()
.parse::<UserDetail>(); .parse::<UserDetail>();
} }
@ -16,19 +16,21 @@ fn user_status_not_found_before_login() {
#[test] #[test]
#[serial] #[serial]
fn user_status_did_found_after_login() { fn user_status_did_found_after_login() {
let _ = UserEventTester::new(SignOut).sync_send();
let request = SignInRequest { let request = SignInRequest {
email: valid_email(), email: valid_email(),
password: valid_password(), password: valid_password(),
}; };
let response = UserEventTester::new(SignIn) let response = UserTestBuilder::new()
.logout()
.event(SignIn)
.request(request) .request(request)
.sync_send() .sync_send()
.parse::<UserDetail>(); .parse::<UserDetail>();
dbg!(&response); dbg!(&response);
let _ = UserEventTester::new(GetStatus) let _ = UserTestBuilder::new()
.event(GetStatus)
.sync_send() .sync_send()
.parse::<UserDetail>(); .parse::<UserDetail>();
} }
@ -36,20 +38,7 @@ fn user_status_did_found_after_login() {
#[test] #[test]
#[serial] #[serial]
fn user_update_with_invalid_email() { fn user_update_with_invalid_email() {
let _ = UserEventTester::new(SignOut).sync_send(); let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
let request = SignInRequest {
email: valid_email(),
password: valid_password(),
};
let _ = UserEventTester::new(SignIn)
.request(request)
.sync_send()
.parse::<UserDetail>();
let user_detail = UserEventTester::new(GetStatus)
.sync_send()
.parse::<UserDetail>();
for email in invalid_email_test_case() { for email in invalid_email_test_case() {
let request = UpdateUserRequest { let request = UpdateUserRequest {
@ -61,7 +50,8 @@ fn user_update_with_invalid_email() {
}; };
assert_eq!( assert_eq!(
UserEventTester::new(UpdateUser) UserTestBuilder::new()
.event(UpdateUser)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()

View File

@ -1,7 +1,7 @@
use flowy_test::EventTester; use flowy_test::TestBuilder;
use flowy_workspace::errors::WorkspaceError; use flowy_workspace::errors::WorkspaceError;
pub type WorkspaceEventTester = EventTester<WorkspaceError>; pub type WorkspaceTestBuilder = TestBuilder<WorkspaceError>;
pub(crate) fn invalid_workspace_name_test_case() -> Vec<String> { pub(crate) fn invalid_workspace_name_test_case() -> Vec<String> {
vec!["", "1234".repeat(100).as_str()] vec!["", "1234".repeat(100).as_str()]

View File

@ -12,7 +12,8 @@ fn workspace_create_success() {
desc: "".to_owned(), desc: "".to_owned(),
}; };
let response = WorkspaceEventTester::new(CreateWorkspace) let response = WorkspaceTestBuilder::new()
.event(CreateWorkspace)
.request(request) .request(request)
.sync_send() .sync_send()
.parse::<WorkspaceDetail>(); .parse::<WorkspaceDetail>();
@ -28,7 +29,8 @@ fn workspace_create_with_invalid_name_test() {
}; };
assert_eq!( assert_eq!(
WorkspaceEventTester::new(CreateWorkspace) WorkspaceTestBuilder::new()
.event(CreateWorkspace)
.request(request) .request(request)
.sync_send() .sync_send()
.error() .error()