refactor build with generic tester

This commit is contained in:
appflowy 2021-07-17 08:24:17 +08:00
parent ffc4a67e2e
commit ce6412722f
11 changed files with 149 additions and 101 deletions

View File

@ -83,6 +83,9 @@
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra/build" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra/.pub" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/.pub" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@ -29,7 +29,7 @@ impl FlowySDK {
FlowySDK::init_log(&self.root);
tracing::info!("🔥 Root path: {}", self.root);
flowy_infra::kv::KVStore::init(&self.root);
let _ = flowy_infra::kv::KVStore::init(&self.root);
FlowySDK::init_modules(&self.root, self.server);
}

View File

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

View File

@ -1,46 +1,52 @@
use crate::{helper::new_user_after_login, init_sdk, tester::Tester};
use flowy_dispatch::prelude::{EventDispatch, FromBytes, ModuleRequest, ToBytes};
use flowy_user::{entities::UserDetail, event::UserEvent::SignOut};
use flowy_dispatch::prelude::{FromBytes, ToBytes};
use flowy_user::entities::UserDetail;
use std::{
fmt::{Debug, Display},
hash::Hash,
};
pub struct TestBuilder<Error> {
login: Option<bool>,
inner: Option<Tester<Error>>,
pub user_detail: Option<UserDetail>,
}
use crate::tester::{TesterContext, TesterTrait};
use flowy_user::errors::UserError;
use flowy_workspace::errors::WorkspaceError;
use std::marker::PhantomData;
impl<Error> TestBuilder<Error>
where
Error: FromBytes + Debug,
{
pub type WorkspaceTestBuilder = TestBuilder<FixedUserTester<WorkspaceError>>;
impl WorkspaceTestBuilder {
pub fn new() -> Self {
TestBuilder::<Error> {
login: None,
inner: None,
Self {
tester: Box::new(FixedUserTester::<WorkspaceError>::new()),
user_detail: None,
}
}
}
pub type UserTestBuilder = TestBuilder<RandomUserTester<UserError>>;
impl UserTestBuilder {
pub fn new() -> Self {
Self {
tester: Box::new(RandomUserTester::<UserError>::new()),
user_detail: None,
}
}
}
pub struct TestBuilder<T: TesterTrait> {
pub tester: Box<T>,
pub user_detail: Option<UserDetail>,
}
impl<T> TestBuilder<T>
where
T: TesterTrait,
{
pub fn login(mut self) -> Self {
let user_detail = new_user_after_login();
let user_detail = self.tester.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.tester.logout();
self
}
@ -48,12 +54,20 @@ where
where
P: ToBytes,
{
self.inner.as_mut().unwrap().set_request(request);
self.tester.set_payload(request);
self
}
pub fn event<E>(mut self, event: E) -> Self
where
E: Eq + Hash + Debug + Clone + Display,
{
self.tester.set_event(event);
self
}
pub fn sync_send(mut self) -> Self {
self.inner.as_mut().unwrap().sync_send();
self.tester.sync_send();
self
}
@ -61,22 +75,70 @@ where
where
R: FromBytes,
{
let inner = self.inner.take().unwrap();
inner.parse::<R>()
self.tester.parse::<R>()
}
pub fn error(mut self) -> Error {
let inner = self.inner.take().unwrap();
inner.error()
}
pub fn error(mut self) -> <T as TesterTrait>::Error { self.tester.error() }
pub fn assert_error(mut self) -> Self {
self.inner.as_mut().unwrap().assert_error();
self.tester.assert_error();
self
}
pub fn assert_success(mut self) -> Self {
self.inner.as_mut().unwrap().assert_success();
self.tester.assert_success();
self
}
}
pub struct RandomUserTester<Error> {
context: TesterContext,
err_phantom: PhantomData<Error>,
}
impl<Error> RandomUserTester<Error>
where
Error: FromBytes + Debug,
{
pub fn new() -> Self {
Self {
context: TesterContext::default(),
err_phantom: PhantomData,
}
}
}
impl<Error> TesterTrait for RandomUserTester<Error>
where
Error: FromBytes + Debug,
{
type Error = Error;
fn context(&mut self) -> &mut TesterContext { &mut self.context }
}
pub struct FixedUserTester<Error> {
context: TesterContext,
err_phantom: PhantomData<Error>,
}
impl<Error> FixedUserTester<Error>
where
Error: FromBytes + Debug,
{
pub fn new() -> Self {
Self {
context: TesterContext::default(),
err_phantom: PhantomData,
}
}
}
impl<Error> TesterTrait for FixedUserTester<Error>
where
Error: FromBytes + Debug,
{
type Error = Error;
fn context(&mut self) -> &mut TesterContext { &mut self.context }
}

View File

@ -1,10 +1,3 @@
use crate::{init_sdk, tester::Tester};
use flowy_dispatch::prelude::*;
use flowy_user::{
entities::{SignInRequest, UserDetail},
errors::UserError,
event::UserEvent::{SignIn, SignOut},
};
use std::{fs, path::PathBuf};
pub fn root_dir() -> String {
@ -23,21 +16,6 @@ pub fn root_dir() -> String {
root_dir
}
pub 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 mut tester = Tester::<UserError>::new(SignIn);
tester.set_request(request);
tester.sync_send();
tester.parse::<UserDetail>()
}
pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() }
pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() }

View File

@ -1,13 +1,17 @@
mod builder;
pub mod builder;
mod helper;
mod tester;
use crate::helper::root_dir;
use flowy_sdk::FlowySDK;
use std::{sync::Once, thread};
use std::sync::Once;
pub mod prelude {
pub use crate::{builder::TestBuilder, tester::Tester};
pub use crate::{
builder::{TestBuilder, *},
helper::*,
tester::Tester,
};
pub use flowy_dispatch::prelude::*;
}

View File

@ -1,7 +1,14 @@
use crate::init_sdk;
use crate::{
helper::{valid_email, valid_password},
init_sdk,
};
use flowy_dispatch::prelude::*;
pub use flowy_sdk::*;
use flowy_user::prelude::*;
use flowy_user::{
errors::UserError,
event::UserEvent::{SignIn, SignOut},
prelude::*,
};
use std::{
convert::TryFrom,
fmt::{Debug, Display},
@ -89,32 +96,6 @@ where
}
}
pub struct RandomUserTester<Error> {
context: TesterContext,
err_phantom: PhantomData<Error>,
}
impl<Error> RandomUserTester<Error>
where
Error: FromBytes + Debug,
{
pub fn new() -> Self {
Self {
context: TesterContext::default(),
err_phantom: PhantomData,
}
}
}
impl<Error> TesterTrait for RandomUserTester<Error>
where
Error: FromBytes + Debug,
{
type Error = Error;
fn context(&mut self) -> &mut TesterContext { &mut self.context }
}
pub struct TesterContext {
request: Option<ModuleRequest>,
status_code: StatusCode,
@ -140,12 +121,20 @@ pub trait TesterTrait {
fn assert_success(&mut self) { self.context().status_code = StatusCode::Ok; }
fn set_event<E>(&mut self, event: E)
where
E: Eq + Hash + Debug + Clone + Display,
{
init_sdk();
self.context().request = Some(ModuleRequest::new(event));
}
fn set_payload<P>(&mut self, payload: P)
where
P: ToBytes,
{
let bytes = payload.into_bytes().unwrap();
let mut module_request = self.context().request.take().unwrap();
let module_request = self.context().request.take().unwrap();
self.context().request = Some(module_request.payload(bytes));
}
@ -173,4 +162,23 @@ pub trait TesterTrait {
.unwrap()
.into_inner()
}
fn login(&self) -> UserDetail {
init_sdk();
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut));
let request = SignInRequest {
email: valid_email(),
password: valid_password(),
};
let mut tester = Tester::<UserError>::new(SignIn);
tester.set_request(request);
tester.sync_send();
tester.parse::<UserDetail>()
}
fn logout(&self) {
init_sdk();
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut));
}
}

View File

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

View File

@ -1,5 +1,4 @@
use crate::helper::*;
use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*};
use serial_test::*;

View File

@ -1,5 +1,4 @@
use crate::helper::*;
use flowy_user::{errors::*, event::UserEvent::*, prelude::*};
use serial_test::*;

View File

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