enable test with single user id

This commit is contained in:
appflowy 2021-07-17 10:26:05 +08:00
parent ce6412722f
commit 848975e7f4
14 changed files with 89 additions and 139 deletions

View File

@ -10,14 +10,13 @@ pub type ArcFlowyServer = std::sync::Arc<dyn FlowyServer>;
pub trait FlowyServer: UserServer {} pub trait FlowyServer: UserServer {}
pub struct MockFlowyServer {} pub struct FlowyServerMocker {}
impl FlowyServer for MockFlowyServer {} impl FlowyServer for FlowyServerMocker {}
impl UserServer for MockFlowyServer { impl UserServer for FlowyServerMocker {
fn sign_up(&self, params: SignUpParams) -> Result<User, UserError> { fn sign_up(&self, params: SignUpParams) -> Result<User, UserError> {
// let user_id = "9527".to_owned(); let user_id = params.email.clone();
let user_id = uuid();
Ok(User::new( Ok(User::new(
user_id, user_id,
params.name, params.name,
@ -27,7 +26,7 @@ impl UserServer for MockFlowyServer {
} }
fn sign_in(&self, params: SignInParams) -> Result<User, UserError> { fn sign_in(&self, params: SignInParams) -> Result<User, UserError> {
let user_id = uuid(); let user_id = params.email.clone();
Ok(User::new( Ok(User::new(
user_id, user_id,
"".to_owned(), "".to_owned(),

View File

@ -1,7 +1,7 @@
mod flowy_server; mod flowy_server;
pub mod module; pub mod module;
use crate::flowy_server::{ArcFlowyServer, MockFlowyServer}; pub use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker};
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
use module::build_modules; use module::build_modules;
pub use module::*; pub use module::*;
@ -18,19 +18,21 @@ pub struct FlowySDK {
impl FlowySDK { impl FlowySDK {
pub fn new(root: &str) -> Self { pub fn new(root: &str) -> Self {
let server = Arc::new(MockFlowyServer {}); let server = Arc::new(FlowyServerMocker {});
Self { Self {
root: root.to_owned(), root: root.to_owned(),
server, server,
} }
} }
pub fn construct(self) { pub fn construct(self) { FlowySDK::construct_with(&self.root, self.server.clone()) }
FlowySDK::init_log(&self.root);
tracing::info!("🔥 Root path: {}", self.root); pub fn construct_with(root: &str, server: ArcFlowyServer) {
let _ = flowy_infra::kv::KVStore::init(&self.root); FlowySDK::init_log(root);
FlowySDK::init_modules(&self.root, self.server);
tracing::info!("🔥 Root path: {}", root);
let _ = flowy_infra::kv::KVStore::init(root);
FlowySDK::init_modules(root, server);
} }
fn init_log(directory: &str) { fn init_log(directory: &str) {

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, MockFlowyServer}; use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker};
use flowy_database::DBConnection; use flowy_database::DBConnection;
use flowy_workspace::prelude::*; use flowy_workspace::prelude::*;
@ -15,7 +15,7 @@ pub fn build_modules(config: ModuleConfig, _server: ArcFlowyServer) -> Vec<Modul
let user_session = Arc::new( let user_session = Arc::new(
UserSessionBuilder::new() UserSessionBuilder::new()
.root_dir(&config.root) .root_dir(&config.root)
.build(Arc::new(MockFlowyServer {})), .build(Arc::new(FlowyServerMocker {})),
); );
let workspace_user_impl = Arc::new(WorkspaceUserImpl { let workspace_user_impl = Arc::new(WorkspaceUserImpl {

View File

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

View File

@ -5,7 +5,10 @@ use std::{
hash::Hash, hash::Hash,
}; };
use crate::tester::{TesterContext, TesterTrait}; use crate::{
helper::valid_email,
tester::{TesterContext, TesterTrait},
};
use flowy_user::errors::UserError; use flowy_user::errors::UserError;
use flowy_workspace::errors::WorkspaceError; use flowy_workspace::errors::WorkspaceError;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -114,7 +117,9 @@ where
{ {
type Error = Error; type Error = Error;
fn context(&mut self) -> &mut TesterContext { &mut self.context } fn mut_context(&mut self) -> &mut TesterContext { &mut self.context }
fn context(&self) -> &TesterContext { &self.context }
} }
pub struct FixedUserTester<Error> { pub struct FixedUserTester<Error> {
@ -128,7 +133,7 @@ where
{ {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
context: TesterContext::default(), context: TesterContext::new(valid_email()),
err_phantom: PhantomData, err_phantom: PhantomData,
} }
} }
@ -140,5 +145,7 @@ where
{ {
type Error = Error; type Error = Error;
fn context(&mut self) -> &mut TesterContext { &mut self.context } fn mut_context(&mut self) -> &mut TesterContext { &mut self.context }
fn context(&self) -> &TesterContext { &self.context }
} }

View File

@ -1,3 +1,4 @@
use flowy_infra::uuid;
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
pub fn root_dir() -> String { pub fn root_dir() -> String {
@ -16,6 +17,8 @@ pub fn root_dir() -> String {
root_dir root_dir
} }
pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() } pub fn random_valid_email() -> String { format!("{}@appflowy.io", uuid()) }
pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() } pub fn valid_email() -> String { "annie@appflowy.io".to_string() }
pub fn valid_password() -> String { "HelloWorld!123".to_string() }

View File

@ -3,23 +3,22 @@ mod helper;
mod tester; mod tester;
use crate::helper::root_dir; use crate::helper::root_dir;
use flowy_sdk::FlowySDK; use flowy_sdk::{ArcFlowyServer, FlowySDK};
use std::sync::Once; use std::sync::Once;
pub mod prelude { pub mod prelude {
pub use crate::{ pub use crate::{
builder::{TestBuilder, *}, builder::{TestBuilder, *},
helper::*, helper::*,
tester::Tester,
}; };
pub use flowy_dispatch::prelude::*; pub use flowy_dispatch::prelude::*;
} }
static INIT: Once = Once::new(); static INIT: Once = Once::new();
pub fn init_sdk() { pub fn init_test_sdk(server: ArcFlowyServer) {
let root_dir = root_dir(); let root_dir = root_dir();
INIT.call_once(|| { INIT.call_once(|| {
FlowySDK::new(&root_dir).construct(); FlowySDK::construct_with(&root_dir, server);
}); });
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
helper::{valid_email, valid_password}, helper::{random_valid_email, valid_password},
init_sdk, init_test_sdk,
}; };
use flowy_dispatch::prelude::*; use flowy_dispatch::prelude::*;
pub use flowy_sdk::*; pub use flowy_sdk::*;
@ -13,93 +13,24 @@ use std::{
convert::TryFrom, convert::TryFrom,
fmt::{Debug, Display}, fmt::{Debug, Display},
hash::Hash, hash::Hash,
marker::PhantomData, sync::Arc,
thread, thread,
}; };
pub struct Tester<Error> {
inner_request: Option<ModuleRequest>,
assert_status_code: Option<StatusCode>,
response: Option<EventResponse>,
err_phantom: PhantomData<Error>,
user_detail: Option<UserDetail>,
}
impl<Error> Tester<Error>
where
Error: FromBytes + Debug,
{
pub fn new<E>(event: E) -> Self
where
E: Eq + Hash + Debug + Clone + Display,
{
init_sdk();
log::trace!(
"{:?} thread started: thread_id= {}",
thread::current(),
thread_id::get()
);
Self {
inner_request: Some(ModuleRequest::new(event)),
assert_status_code: None,
response: None,
err_phantom: PhantomData,
user_detail: None,
}
}
pub fn set_request<P>(&mut self, request: P)
where
P: ToBytes,
{
let mut inner_request = self.inner_request.take().unwrap();
let bytes = request.into_bytes().unwrap();
inner_request = inner_request.payload(bytes);
self.inner_request = Some(inner_request);
}
pub fn assert_error(&mut self) { self.assert_status_code = Some(StatusCode::Err); }
pub fn assert_success(&mut self) { self.assert_status_code = Some(StatusCode::Ok); }
pub async fn async_send(&mut self) {
assert_eq!(self.inner_request.is_some(), true, "must set event");
let resp = EventDispatch::async_send(self.inner_request.take().unwrap()).await;
self.response = Some(resp);
}
pub fn sync_send(&mut self) {
let resp = EventDispatch::sync_send(self.inner_request.take().unwrap());
self.response = Some(resp);
}
pub fn parse<R>(self) -> R
where
R: FromBytes,
{
let response = self.response.unwrap();
match response.parse::<R, Error>() {
Ok(Ok(data)) => data,
Ok(Err(e)) => panic!("parse failed: {:?}", e),
Err(e) => panic!("Internal error: {:?}", e),
}
}
pub fn error(self) -> Error {
let response = self.response.unwrap();
assert_eq!(response.status_code, StatusCode::Err);
<Data<Error>>::try_from(response.payload)
.unwrap()
.into_inner()
}
}
pub struct TesterContext { pub struct TesterContext {
request: Option<ModuleRequest>, request: Option<ModuleRequest>,
status_code: StatusCode,
response: Option<EventResponse>, response: Option<EventResponse>,
status_code: StatusCode,
server: ArcFlowyServer,
user_email: String,
}
impl TesterContext {
pub fn new(email: String) -> Self {
let mut ctx = TesterContext::default();
ctx.user_email = email;
ctx
}
} }
impl std::default::Default for TesterContext { impl std::default::Default for TesterContext {
@ -108,6 +39,8 @@ impl std::default::Default for TesterContext {
request: None, request: None,
status_code: StatusCode::Ok, status_code: StatusCode::Ok,
response: None, response: None,
server: Arc::new(FlowyServerMocker {}),
user_email: random_valid_email(),
} }
} }
} }
@ -115,18 +48,20 @@ impl std::default::Default for TesterContext {
pub trait TesterTrait { pub trait TesterTrait {
type Error: FromBytes + Debug; type Error: FromBytes + Debug;
fn context(&mut self) -> &mut TesterContext; fn mut_context(&mut self) -> &mut TesterContext;
fn assert_error(&mut self) { self.context().status_code = StatusCode::Err; } fn context(&self) -> &TesterContext;
fn assert_success(&mut self) { self.context().status_code = StatusCode::Ok; } fn assert_error(&mut self) { self.mut_context().status_code = StatusCode::Err; }
fn assert_success(&mut self) { self.mut_context().status_code = StatusCode::Ok; }
fn set_event<E>(&mut self, event: E) fn set_event<E>(&mut self, event: E)
where where
E: Eq + Hash + Debug + Clone + Display, E: Eq + Hash + Debug + Clone + Display,
{ {
init_sdk(); init_test_sdk(self.context().server.clone());
self.context().request = Some(ModuleRequest::new(event)); self.mut_context().request = Some(ModuleRequest::new(event));
} }
fn set_payload<P>(&mut self, payload: P) fn set_payload<P>(&mut self, payload: P)
@ -134,20 +69,20 @@ pub trait TesterTrait {
P: ToBytes, P: ToBytes,
{ {
let bytes = payload.into_bytes().unwrap(); let bytes = payload.into_bytes().unwrap();
let module_request = self.context().request.take().unwrap(); let module_request = self.mut_context().request.take().unwrap();
self.context().request = Some(module_request.payload(bytes)); self.mut_context().request = Some(module_request.payload(bytes));
} }
fn sync_send(&mut self) { fn sync_send(&mut self) {
let resp = EventDispatch::sync_send(self.context().request.take().unwrap()); let resp = EventDispatch::sync_send(self.mut_context().request.take().unwrap());
self.context().response = Some(resp); self.mut_context().response = Some(resp);
} }
fn parse<R>(&mut self) -> R fn parse<R>(&mut self) -> R
where where
R: FromBytes, R: FromBytes,
{ {
let response = self.context().response.clone().unwrap(); let response = self.mut_context().response.clone().unwrap();
match response.parse::<R, Self::Error>() { match response.parse::<R, Self::Error>() {
Ok(Ok(data)) => data, Ok(Ok(data)) => data,
Ok(Err(e)) => panic!("parse failed: {:?}", e), Ok(Err(e)) => panic!("parse failed: {:?}", e),
@ -156,7 +91,7 @@ pub trait TesterTrait {
} }
fn error(&mut self) -> Self::Error { fn error(&mut self) -> Self::Error {
let response = self.context().response.clone().unwrap(); let response = self.mut_context().response.clone().unwrap();
assert_eq!(response.status_code, StatusCode::Err); assert_eq!(response.status_code, StatusCode::Err);
<Data<Self::Error>>::try_from(response.payload) <Data<Self::Error>>::try_from(response.payload)
.unwrap() .unwrap()
@ -164,21 +99,26 @@ pub trait TesterTrait {
} }
fn login(&self) -> UserDetail { fn login(&self) -> UserDetail {
init_sdk(); init_test_sdk(self.context().server.clone());
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); self.logout();
let request = SignInRequest { let payload = SignInRequest {
email: valid_email(), email: self.context().user_email.clone(),
password: valid_password(), password: valid_password(),
}; }
.into_bytes()
.unwrap();
let mut tester = Tester::<UserError>::new(SignIn); let request = ModuleRequest::new(SignIn).payload(payload);
tester.set_request(request); let user_detail = EventDispatch::sync_send(request)
tester.sync_send(); .parse::<UserDetail, UserError>()
tester.parse::<UserDetail>() .unwrap()
.unwrap();
user_detail
} }
fn logout(&self) { fn logout(&self) {
init_sdk(); init_test_sdk(self.context().server.clone());
let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut));
} }
} }

View File

@ -143,7 +143,7 @@ impl UserSession {
} }
} }
fn current_user_id() -> Result<String, UserError> { pub fn current_user_id() -> Result<String, UserError> {
match KVStore::get_str(USER_ID_DISK_CACHE_KEY) { match KVStore::get_str(USER_ID_DISK_CACHE_KEY) {
None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()),
Some(user_id) => Ok(user_id), Some(user_id) => Ok(user_id),

View File

@ -1,5 +1,7 @@
pub use flowy_test::builder::UserTestBuilder; pub use flowy_test::builder::UserTestBuilder;
pub use flowy_test::prelude::{random_valid_email, valid_password};
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
vec![ vec![
@ -35,8 +37,4 @@ pub(crate) fn invalid_password_test_case() -> Vec<String> {
.collect::<Vec<_>>() .collect::<Vec<_>>()
} }
pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() }
pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() }
pub(crate) fn valid_name() -> String { "AppFlowy".to_string() } pub(crate) fn valid_name() -> String { "AppFlowy".to_string() }

View File

@ -6,7 +6,7 @@ use serial_test::*;
#[serial] #[serial]
fn sign_in_success() { fn sign_in_success() {
let request = SignInRequest { let request = SignInRequest {
email: valid_email(), email: random_valid_email(),
password: valid_password(), password: valid_password(),
}; };
@ -43,7 +43,7 @@ fn sign_in_with_invalid_email() {
fn sign_in_with_invalid_password() { fn sign_in_with_invalid_password() {
for password in invalid_password_test_case() { for password in invalid_password_test_case() {
let request = SignInRequest { let request = SignInRequest {
email: valid_email(), email: random_valid_email(),
password, password,
}; };

View File

@ -7,7 +7,7 @@ use serial_test::*;
fn sign_up_success() { fn sign_up_success() {
let _ = UserTestBuilder::new().event(SignOut).sync_send(); let _ = UserTestBuilder::new().event(SignOut).sync_send();
let request = SignUpRequest { let request = SignUpRequest {
email: valid_email(), email: random_valid_email(),
name: valid_name(), name: valid_name(),
password: valid_password(), password: valid_password(),
}; };
@ -44,7 +44,7 @@ fn sign_up_with_invalid_email() {
fn sign_up_with_invalid_password() { fn sign_up_with_invalid_password() {
for password in invalid_password_test_case() { for password in invalid_password_test_case() {
let request = SignUpRequest { let request = SignUpRequest {
email: valid_email(), email: random_valid_email(),
name: valid_name(), name: valid_name(),
password, password,
}; };

View File

@ -17,7 +17,7 @@ fn user_status_get_failed_before_login() {
#[serial] #[serial]
fn user_status_get_success_after_login() { fn user_status_get_success_after_login() {
let request = SignInRequest { let request = SignInRequest {
email: valid_email(), email: random_valid_email(),
password: valid_password(), password: valid_password(),
}; };

View File

@ -13,6 +13,7 @@ fn workspace_create_success() {
}; };
let response = WorkspaceTestBuilder::new() let response = WorkspaceTestBuilder::new()
.login()
.event(CreateWorkspace) .event(CreateWorkspace)
.request(request) .request(request)
.sync_send() .sync_send()