mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
support run tests on remote
This commit is contained in:
parent
a6346dffae
commit
ccb51234c5
@ -25,6 +25,7 @@ log = "0.4.14"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = {version = "1.0"}
|
||||
bytes = { version = "1.0" }
|
||||
parking_lot = "0.11"
|
||||
|
||||
flowy-dispatch = {path = "../flowy-dispatch"}
|
||||
flowy-sdk = {path = "../flowy-sdk"}
|
||||
|
@ -9,15 +9,22 @@ use crate::{
|
||||
};
|
||||
use flowy_dispatch::prelude::*;
|
||||
use flowy_sdk::*;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
use std::{ffi::CStr, os::raw::c_char, sync::Arc};
|
||||
|
||||
use std::{ffi::CStr, os::raw::c_char};
|
||||
lazy_static! {
|
||||
static ref FLOWY_SDK: RwLock<Option<Arc<FlowySDK>>> = RwLock::new(None);
|
||||
}
|
||||
|
||||
fn dispatch() -> Arc<EventDispatch> { FLOWY_SDK.read().as_ref().unwrap().dispatch() }
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
|
||||
let c_str: &CStr = unsafe { CStr::from_ptr(path) };
|
||||
let path: &str = c_str.to_str().unwrap();
|
||||
log::info!("🔥 FlowySDK start running");
|
||||
FlowySDK::new(path).construct();
|
||||
*FLOWY_SDK.write() = Some(Arc::new(FlowySDK::new(path)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -25,14 +32,9 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
|
||||
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
log::trace!(
|
||||
"[FFI]: {} Async Event: {:?} with {} port",
|
||||
&request.id,
|
||||
&request.event,
|
||||
port
|
||||
);
|
||||
log::trace!("[FFI]: {} Async Event: {:?} with {} port", &request.id, &request.event, port);
|
||||
|
||||
let _ = EventDispatch::async_send_with_callback(request, move |resp: EventResponse| {
|
||||
let _ = EventDispatch::async_send_with_callback(dispatch(), request, move |resp: EventResponse| {
|
||||
log::trace!("[FFI]: Post data to dart through {} port", port);
|
||||
Box::pin(post_to_flutter(resp, port))
|
||||
});
|
||||
@ -42,7 +44,7 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
|
||||
pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
|
||||
let request: ModuleRequest = FFIRequest::from_u8_pointer(input, len).into();
|
||||
log::trace!("[FFI]: {} Sync Event: {:?}", &request.id, &request.event,);
|
||||
let _response = EventDispatch::sync_send(request);
|
||||
let _response = EventDispatch::sync_send(dispatch(), request);
|
||||
|
||||
// FFIResponse { }
|
||||
let response_bytes = vec![];
|
||||
|
@ -8,22 +8,17 @@ use crate::{
|
||||
use derivative::*;
|
||||
use futures_core::future::BoxFuture;
|
||||
use futures_util::task::Context;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use pin_project::pin_project;
|
||||
use std::{future::Future, sync::RwLock};
|
||||
use std::{future::Future, sync::Arc};
|
||||
use tokio::macros::support::{Pin, Poll};
|
||||
|
||||
lazy_static! {
|
||||
static ref EVENT_DISPATCH: RwLock<Option<EventDispatch>> = RwLock::new(None);
|
||||
}
|
||||
|
||||
pub struct EventDispatch {
|
||||
module_map: ModuleMap,
|
||||
runtime: tokio::runtime::Runtime,
|
||||
}
|
||||
|
||||
impl EventDispatch {
|
||||
pub fn construct<F>(module_factory: F)
|
||||
pub fn construct<F>(module_factory: F) -> EventDispatch
|
||||
where
|
||||
F: FnOnce() -> Vec<Module>,
|
||||
{
|
||||
@ -32,60 +27,88 @@ impl EventDispatch {
|
||||
let module_map = as_module_map(modules);
|
||||
let runtime = tokio_default_runtime().unwrap();
|
||||
let dispatch = EventDispatch { module_map, runtime };
|
||||
*(EVENT_DISPATCH.write().unwrap()) = Some(dispatch);
|
||||
dispatch
|
||||
}
|
||||
|
||||
pub fn async_send<Req>(request: Req) -> DispatchFuture<EventResponse>
|
||||
pub fn async_send<Req>(dispatch: Arc<EventDispatch>, request: Req) -> DispatchFuture<EventResponse>
|
||||
where
|
||||
Req: std::convert::Into<ModuleRequest>,
|
||||
{
|
||||
EventDispatch::async_send_with_callback(request, |_| Box::pin(async {}))
|
||||
EventDispatch::async_send_with_callback(dispatch, request, |_| Box::pin(async {}))
|
||||
}
|
||||
|
||||
pub fn async_send_with_callback<Req, Callback>(request: Req, callback: Callback) -> DispatchFuture<EventResponse>
|
||||
pub fn async_send_with_callback<Req, Callback>(
|
||||
dispatch: Arc<EventDispatch>,
|
||||
request: Req,
|
||||
callback: Callback,
|
||||
) -> DispatchFuture<EventResponse>
|
||||
where
|
||||
Req: std::convert::Into<ModuleRequest>,
|
||||
Callback: FnOnce(EventResponse) -> BoxFuture<'static, ()> + 'static + Send + Sync,
|
||||
{
|
||||
let request: ModuleRequest = request.into();
|
||||
match EVENT_DISPATCH.read() {
|
||||
Ok(dispatch) => {
|
||||
let dispatch = dispatch.as_ref().unwrap();
|
||||
let module_map = dispatch.module_map.clone();
|
||||
let service = Box::new(DispatchService { module_map });
|
||||
log::trace!("Async event: {:?}", &request.event);
|
||||
let service_ctx = DispatchContext {
|
||||
request,
|
||||
callback: Some(Box::new(callback)),
|
||||
};
|
||||
let join_handle = dispatch.runtime.spawn(async move {
|
||||
service
|
||||
.call(service_ctx)
|
||||
.await
|
||||
.unwrap_or_else(|e| InternalError::Other(format!("{:?}", e)).as_response())
|
||||
});
|
||||
let module_map = dispatch.module_map.clone();
|
||||
let service = Box::new(DispatchService { module_map });
|
||||
log::trace!("Async event: {:?}", &request.event);
|
||||
let service_ctx = DispatchContext {
|
||||
request,
|
||||
callback: Some(Box::new(callback)),
|
||||
};
|
||||
let join_handle = dispatch.runtime.spawn(async move {
|
||||
service
|
||||
.call(service_ctx)
|
||||
.await
|
||||
.unwrap_or_else(|e| InternalError::Other(format!("{:?}", e)).as_response())
|
||||
});
|
||||
|
||||
DispatchFuture {
|
||||
fut: Box::pin(async move {
|
||||
join_handle.await.unwrap_or_else(|e| {
|
||||
let error = InternalError::JoinError(format!("EVENT_DISPATCH join error: {:?}", e));
|
||||
error.as_response()
|
||||
})
|
||||
}),
|
||||
}
|
||||
},
|
||||
|
||||
Err(e) => {
|
||||
let msg = format!("EVENT_DISPATCH read failed. {:?}", e);
|
||||
DispatchFuture {
|
||||
fut: Box::pin(async { InternalError::Lock(msg).as_response() }),
|
||||
}
|
||||
},
|
||||
DispatchFuture {
|
||||
fut: Box::pin(async move {
|
||||
join_handle.await.unwrap_or_else(|e| {
|
||||
let error = InternalError::JoinError(format!("EVENT_DISPATCH join error: {:?}", e));
|
||||
error.as_response()
|
||||
})
|
||||
}),
|
||||
}
|
||||
// match dispatch.read() {
|
||||
// Ok(dispatch) => {
|
||||
// let dispatch = dispatch.as_ref().unwrap();
|
||||
// let module_map = dispatch.module_map.clone();
|
||||
// let service = Box::new(DispatchService { module_map });
|
||||
// log::trace!("Async event: {:?}", &request.event);
|
||||
// let service_ctx = DispatchContext {
|
||||
// request,
|
||||
// callback: Some(Box::new(callback)),
|
||||
// };
|
||||
// let join_handle = dispatch.runtime.spawn(async move {
|
||||
// service
|
||||
// .call(service_ctx)
|
||||
// .await
|
||||
// .unwrap_or_else(|e|
|
||||
// InternalError::Other(format!("{:?}", e)).as_response())
|
||||
// });
|
||||
//
|
||||
// DispatchFuture {
|
||||
// fut: Box::pin(async move {
|
||||
// join_handle.await.unwrap_or_else(|e| {
|
||||
// let error =
|
||||
// InternalError::JoinError(format!("EVENT_DISPATCH join error: {:?}",
|
||||
// e)); error.as_response()
|
||||
// })
|
||||
// }),
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// Err(e) => {
|
||||
// let msg = format!("EVENT_DISPATCH read failed. {:?}", e);
|
||||
// DispatchFuture {
|
||||
// fut: Box::pin(async {
|
||||
// InternalError::Lock(msg).as_response() }), }
|
||||
// },
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn sync_send(request: ModuleRequest) -> EventResponse {
|
||||
futures::executor::block_on(async { EventDispatch::async_send_with_callback(request, |_| Box::pin(async {})).await })
|
||||
pub fn sync_send(dispatch: Arc<EventDispatch>, request: ModuleRequest) -> EventResponse {
|
||||
futures::executor::block_on(async { EventDispatch::async_send_with_callback(dispatch, request, |_| Box::pin(async {})).await })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,17 +16,7 @@ use crate::{
|
||||
module::{container::ModuleDataMap, Unit},
|
||||
request::{payload::Payload, EventRequest, FromRequest},
|
||||
response::{EventResponse, Responder},
|
||||
service::{
|
||||
factory,
|
||||
BoxService,
|
||||
BoxServiceFactory,
|
||||
Handler,
|
||||
HandlerService,
|
||||
Service,
|
||||
ServiceFactory,
|
||||
ServiceRequest,
|
||||
ServiceResponse,
|
||||
},
|
||||
service::{factory, BoxService, BoxServiceFactory, Handler, HandlerService, Service, ServiceFactory, ServiceRequest, ServiceResponse},
|
||||
};
|
||||
use futures_core::future::BoxFuture;
|
||||
use std::sync::Arc;
|
||||
@ -51,8 +41,7 @@ impl<T: Display + Eq + Hash + Debug + Clone> std::convert::From<T> for Event {
|
||||
fn from(t: T) -> Self { Event(format!("{}", t)) }
|
||||
}
|
||||
|
||||
pub type EventServiceFactory =
|
||||
BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>;
|
||||
pub type EventServiceFactory = BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>;
|
||||
|
||||
pub struct Module {
|
||||
pub name: String,
|
||||
@ -75,9 +64,7 @@ impl Module {
|
||||
}
|
||||
|
||||
pub fn data<D: 'static + Send + Sync>(mut self, data: D) -> Self {
|
||||
Arc::get_mut(&mut self.module_data)
|
||||
.unwrap()
|
||||
.insert(Unit::new(data));
|
||||
Arc::get_mut(&mut self.module_data).unwrap().insert(Unit::new(data));
|
||||
|
||||
self
|
||||
}
|
||||
@ -102,15 +89,10 @@ impl Module {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn events(&self) -> Vec<Event> {
|
||||
self.service_map
|
||||
.keys()
|
||||
.map(|key| key.clone())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
pub fn events(&self) -> Vec<Event> { self.service_map.keys().map(|key| key.clone()).collect::<Vec<_>>() }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleRequest {
|
||||
pub id: String,
|
||||
pub event: Event,
|
||||
@ -139,9 +121,7 @@ impl ModuleRequest {
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ModuleRequest {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}:{:?}", self.id, self.event)
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}:{:?}", self.id, self.event) }
|
||||
}
|
||||
|
||||
impl ServiceFactory<ModuleRequest> for Module {
|
||||
@ -155,10 +135,7 @@ impl ServiceFactory<ModuleRequest> for Module {
|
||||
let service_map = self.service_map.clone();
|
||||
let module_data = self.module_data.clone();
|
||||
Box::pin(async move {
|
||||
let service = ModuleService {
|
||||
service_map,
|
||||
module_data,
|
||||
};
|
||||
let service = ModuleService { service_map, module_data };
|
||||
let module_service = Box::new(service) as Self::Service;
|
||||
Ok(module_service)
|
||||
})
|
||||
@ -193,10 +170,7 @@ impl Service<ModuleRequest> for ModuleService {
|
||||
Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })
|
||||
},
|
||||
None => {
|
||||
let msg = format!(
|
||||
"Can not find service factory for event: {:?}",
|
||||
request.event
|
||||
);
|
||||
let msg = format!("Can not find service factory for event: {:?}", request.event);
|
||||
Box::pin(async { Err(InternalError::ServiceNotFound(msg).into()) })
|
||||
},
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ pub fn setup_env() {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn init_dispatch<F>(module_factory: F)
|
||||
pub fn init_dispatch<F>(module_factory: F) -> EventDispatch
|
||||
where
|
||||
F: FnOnce() -> Vec<Module>,
|
||||
{
|
||||
EventDispatch::construct(module_factory);
|
||||
EventDispatch::construct(module_factory)
|
||||
}
|
||||
|
@ -1,19 +1,21 @@
|
||||
use crate::helper::*;
|
||||
use flowy_dispatch::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn hello() -> String { "say hello".to_string() }
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_init() {
|
||||
async fn test() {
|
||||
setup_env();
|
||||
let event = "1";
|
||||
init_dispatch(|| vec![Module::new().event(event, hello)]);
|
||||
|
||||
let dispatch = Arc::new(init_dispatch(|| vec![Module::new().event(event, hello)]));
|
||||
let request = ModuleRequest::new(event);
|
||||
let _ = EventDispatch::async_send_with_callback(request, |resp| {
|
||||
let _ = EventDispatch::async_send_with_callback(dispatch.clone(), request, |resp| {
|
||||
Box::pin(async move {
|
||||
dbg!(&resp);
|
||||
})
|
||||
})
|
||||
.await;
|
||||
|
||||
std::mem::forget(dispatch);
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
use crate::helper::*;
|
||||
use flowy_test::builder::UserTestBuilder;
|
||||
use flowy_test::TestSDKBuilder;
|
||||
|
||||
#[test]
|
||||
fn file_create_test() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let doc_desc = create_doc("hello world", "flutter ❤️ rust", "123");
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let doc_desc = create_doc(&sdk, "hello world", "flutter ❤️ rust", "123");
|
||||
dbg!(&doc_desc);
|
||||
|
||||
let doc = read_doc_data(&doc_desc.id, &doc_desc.path);
|
||||
let doc = read_doc_data(&sdk, &doc_desc.id, &doc_desc.path);
|
||||
assert_eq!(doc.text, "123".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_update_text_test() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let doc_desc = create_doc("hello world", "flutter ❤️ rust", "");
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let doc_desc = create_doc(&sdk, "hello world", "flutter ❤️ rust", "");
|
||||
dbg!(&doc_desc);
|
||||
|
||||
let content = "😁😁😁😁😁😁😁😁😁😁".to_owned();
|
||||
save_doc(&doc_desc, &content);
|
||||
save_doc(&sdk, &doc_desc, &content);
|
||||
|
||||
let doc = read_doc_data(&doc_desc.id, &doc_desc.path);
|
||||
let doc = read_doc_data(&sdk, &doc_desc.id, &doc_desc.path);
|
||||
assert_eq!(doc.text, content);
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ use flowy_test::builder::DocTestBuilder;
|
||||
|
||||
use flowy_document::{entities::doc::*, event::EditorEvent::*};
|
||||
use flowy_infra::uuid;
|
||||
use flowy_test::prelude::*;
|
||||
|
||||
pub fn create_doc(name: &str, desc: &str, text: &str) -> DocInfo {
|
||||
pub fn create_doc(sdk: &FlowyTestSDK, name: &str, desc: &str, text: &str) -> DocInfo {
|
||||
let request = CreateDocRequest {
|
||||
id: uuid(),
|
||||
name: name.to_owned(),
|
||||
@ -11,7 +12,7 @@ pub fn create_doc(name: &str, desc: &str, text: &str) -> DocInfo {
|
||||
text: text.to_owned(),
|
||||
};
|
||||
|
||||
let doc = DocTestBuilder::new()
|
||||
let doc = DocTestBuilder::new(sdk.clone())
|
||||
.event(CreateDoc)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -19,7 +20,7 @@ pub fn create_doc(name: &str, desc: &str, text: &str) -> DocInfo {
|
||||
doc
|
||||
}
|
||||
|
||||
pub fn save_doc(desc: &DocInfo, content: &str) {
|
||||
pub fn save_doc(sdk: &FlowyTestSDK, desc: &DocInfo, content: &str) {
|
||||
let request = UpdateDocRequest {
|
||||
id: desc.id.clone(),
|
||||
name: Some(desc.name.clone()),
|
||||
@ -27,7 +28,7 @@ pub fn save_doc(desc: &DocInfo, content: &str) {
|
||||
text: Some(content.to_owned()),
|
||||
};
|
||||
|
||||
let _ = DocTestBuilder::new().event(UpdateDoc).request(request).sync_send();
|
||||
let _ = DocTestBuilder::new(sdk.clone()).event(UpdateDoc).request(request).sync_send();
|
||||
}
|
||||
|
||||
// #[allow(dead_code)]
|
||||
@ -45,13 +46,13 @@ pub fn save_doc(desc: &DocInfo, content: &str) {
|
||||
// doc
|
||||
// }
|
||||
|
||||
pub(crate) fn read_doc_data(doc_id: &str, path: &str) -> DocData {
|
||||
pub(crate) fn read_doc_data(sdk: &FlowyTestSDK, doc_id: &str, path: &str) -> DocData {
|
||||
let request = QueryDocDataRequest {
|
||||
doc_id: doc_id.to_string(),
|
||||
path: path.to_string(),
|
||||
};
|
||||
|
||||
let doc = DocTestBuilder::new()
|
||||
let doc = DocTestBuilder::new(sdk.clone())
|
||||
.event(ReadDocData)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
|
@ -80,8 +80,7 @@ impl HttpRequestBuilder {
|
||||
// reqwest client is not 'Sync' by channel is.
|
||||
tokio::spawn(async move {
|
||||
let client = default_client();
|
||||
let mut builder = client.request(method, url).headers(headers);
|
||||
|
||||
let mut builder = client.request(method.clone(), url).headers(headers);
|
||||
if let Some(body) = body {
|
||||
builder = builder.body(body);
|
||||
}
|
||||
@ -90,7 +89,7 @@ impl HttpRequestBuilder {
|
||||
match tx.send(response) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
log::error!("Send http response failed: {:?}", e)
|
||||
log::error!("[{}] Send http request failed: {:?}", method, e);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
@ -7,8 +7,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
flowy-dispatch = { path = "../flowy-dispatch", features = ["use_tracing"]}
|
||||
#flowy-log = { path = "../flowy-log" }
|
||||
flowy-log = { path = "../flowy-log", features = ["use_bunyan"] }
|
||||
flowy-log = { path = "../flowy-log" }
|
||||
#flowy-log = { path = "../flowy-log", features = ["use_bunyan"] }
|
||||
flowy-user = { path = "../flowy-user" }
|
||||
flowy-infra = { path = "../flowy-infra" }
|
||||
flowy-workspace = { path = "../flowy-workspace" }
|
||||
|
@ -5,39 +5,49 @@ pub mod module;
|
||||
use flowy_dispatch::prelude::*;
|
||||
use module::build_modules;
|
||||
pub use module::*;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
static INIT_LOG: AtomicBool = AtomicBool::new(false);
|
||||
#[derive(Clone)]
|
||||
pub struct FlowySDK {
|
||||
root: String,
|
||||
dispatch: Arc<EventDispatch>,
|
||||
}
|
||||
|
||||
impl FlowySDK {
|
||||
pub fn new(root: &str) -> Self { Self { root: root.to_owned() } }
|
||||
pub fn new(root: &str) -> Self {
|
||||
init_log(root);
|
||||
init_kv(root);
|
||||
|
||||
pub fn construct(self) { FlowySDK::construct_with(&self.root) }
|
||||
|
||||
pub fn construct_with(root: &str) {
|
||||
FlowySDK::init_log(root);
|
||||
|
||||
tracing::info!("🔥 Root path: {}", root);
|
||||
match flowy_infra::kv::KV::init(root) {
|
||||
Ok(_) => {},
|
||||
Err(e) => tracing::error!("Init kv store failedL: {}", e),
|
||||
}
|
||||
FlowySDK::init_modules(root);
|
||||
let dispatch = Arc::new(init_dispatch(root));
|
||||
let root = root.to_owned();
|
||||
Self { root, dispatch }
|
||||
}
|
||||
|
||||
fn init_log(directory: &str) {
|
||||
if !INIT_LOG.load(Ordering::SeqCst) {
|
||||
INIT_LOG.store(true, Ordering::SeqCst);
|
||||
pub fn dispatch(&self) -> Arc<EventDispatch> { self.dispatch.clone() }
|
||||
}
|
||||
|
||||
let _ = flowy_log::Builder::new("flowy").local(directory).env_filter("info").build();
|
||||
}
|
||||
}
|
||||
|
||||
fn init_modules(root: &str) {
|
||||
let config = ModuleConfig { root: root.to_owned() };
|
||||
EventDispatch::construct(|| build_modules(config));
|
||||
fn init_kv(root: &str) {
|
||||
tracing::info!("🔥 Root path: {}", root);
|
||||
match flowy_infra::kv::KV::init(root) {
|
||||
Ok(_) => {},
|
||||
Err(e) => tracing::error!("Init kv store failedL: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn init_log(directory: &str) {
|
||||
if !INIT_LOG.load(Ordering::SeqCst) {
|
||||
INIT_LOG.store(true, Ordering::SeqCst);
|
||||
|
||||
let _ = flowy_log::Builder::new("flowy").local(directory).env_filter("info").build();
|
||||
}
|
||||
}
|
||||
|
||||
fn init_dispatch(root: &str) -> EventDispatch {
|
||||
let config = ModuleConfig { root: root.to_owned() };
|
||||
let dispatch = EventDispatch::construct(|| build_modules(config));
|
||||
dispatch
|
||||
}
|
||||
|
@ -1,137 +1,190 @@
|
||||
use flowy_dispatch::prelude::{FromBytes, ToBytes};
|
||||
use flowy_dispatch::prelude::{EventDispatch, EventResponse, FromBytes, ModuleRequest, StatusCode, ToBytes};
|
||||
use flowy_user::entities::UserDetail;
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
hash::Hash,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
helper::{create_default_workspace_if_need, login_email, login_password},
|
||||
init_test_sdk,
|
||||
tester::{TesterContext, TesterTrait},
|
||||
};
|
||||
use crate::helper::{create_default_workspace_if_need, login_email, login_password, random_email};
|
||||
use flowy_dispatch::prelude::*;
|
||||
use flowy_document::errors::DocError;
|
||||
use flowy_user::errors::UserError;
|
||||
pub use flowy_sdk::*;
|
||||
use flowy_user::{
|
||||
errors::UserError,
|
||||
event::UserEvent::{SignOut, SignUp},
|
||||
prelude::*,
|
||||
};
|
||||
use flowy_workspace::errors::WorkspaceError;
|
||||
use std::marker::PhantomData;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
pub type WorkspaceTestBuilder = Builder<RandomUserTester<WorkspaceError>>;
|
||||
impl WorkspaceTestBuilder {
|
||||
pub fn new() -> Self { Builder::test(Box::new(RandomUserTester::<WorkspaceError>::new())) }
|
||||
}
|
||||
use crate::FlowyTestSDK;
|
||||
use flowy_user::event::UserEvent::SignIn;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub type DocTestBuilder = Builder<RandomUserTester<DocError>>;
|
||||
pub type DocTestBuilder = Builder<DocError>;
|
||||
impl DocTestBuilder {
|
||||
pub fn new() -> Self { Builder::test(Box::new(RandomUserTester::<DocError>::new())) }
|
||||
pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) }
|
||||
}
|
||||
|
||||
pub type UserTestBuilder = Builder<RandomUserTester<UserError>>;
|
||||
impl UserTestBuilder {
|
||||
pub fn new() -> Self { Builder::test(Box::new(RandomUserTester::<UserError>::new())) }
|
||||
pub type WorkspaceTestBuilder = Builder<WorkspaceError>;
|
||||
impl WorkspaceTestBuilder {
|
||||
pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) }
|
||||
}
|
||||
|
||||
pub fn sign_up(mut self) -> SignUpContext {
|
||||
let (user_detail, password) = self.tester.sign_up();
|
||||
let _ = create_default_workspace_if_need(&user_detail.id);
|
||||
pub type UserTestBuilder = Builder<UserError>;
|
||||
impl UserTestBuilder {
|
||||
pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) }
|
||||
|
||||
pub fn sign_up(self) -> SignUpContext {
|
||||
let password = login_password();
|
||||
let payload = SignUpRequest {
|
||||
email: random_email(),
|
||||
name: "app flowy".to_string(),
|
||||
password: password.clone(),
|
||||
}
|
||||
.into_bytes()
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(SignUp).payload(payload);
|
||||
let user_detail = EventDispatch::sync_send(self.dispatch(), request)
|
||||
.parse::<UserDetail, UserError>()
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let _ = create_default_workspace_if_need(self.dispatch(), &user_detail.id);
|
||||
SignUpContext { user_detail, password }
|
||||
}
|
||||
|
||||
pub fn sign_in(mut self) -> Self {
|
||||
let user_detail = self.tester.sign_in();
|
||||
#[allow(dead_code)]
|
||||
fn sign_in(mut self) -> Self {
|
||||
let payload = SignInRequest {
|
||||
email: login_email(),
|
||||
password: login_password(),
|
||||
}
|
||||
.into_bytes()
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(SignIn).payload(payload);
|
||||
let user_detail = EventDispatch::sync_send(self.dispatch(), request)
|
||||
.parse::<UserDetail, UserError>()
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
self.user_detail = Some(user_detail);
|
||||
self
|
||||
}
|
||||
|
||||
fn login_if_need(&mut self) {
|
||||
let user_detail = self.tester.login_if_need();
|
||||
self.user_detail = Some(user_detail);
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
fn logout(&self) { let _ = EventDispatch::sync_send(self.dispatch(), ModuleRequest::new(SignOut)); }
|
||||
|
||||
pub fn get_user_detail(&self) -> &Option<UserDetail> { &self.user_detail }
|
||||
pub fn user_detail(&self) -> &Option<UserDetail> { &self.user_detail }
|
||||
}
|
||||
|
||||
pub struct Builder<T: TesterTrait> {
|
||||
pub tester: Box<T>,
|
||||
#[derive(Clone)]
|
||||
pub struct Builder<E> {
|
||||
context: TestContext,
|
||||
user_detail: Option<UserDetail>,
|
||||
err_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<T> Builder<T>
|
||||
impl<E> Builder<E>
|
||||
where
|
||||
T: TesterTrait,
|
||||
E: FromBytes + Debug,
|
||||
{
|
||||
fn test(tester: Box<T>) -> Self {
|
||||
init_test_sdk();
|
||||
Self { tester, user_detail: None }
|
||||
pub(crate) fn test(context: TestContext) -> Self {
|
||||
Self {
|
||||
context,
|
||||
user_detail: None,
|
||||
err_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request<P>(mut self, request: P) -> Self
|
||||
pub fn request<P>(mut self, payload: P) -> Self
|
||||
where
|
||||
P: ToBytes,
|
||||
{
|
||||
self.tester.set_payload(request);
|
||||
match payload.into_bytes() {
|
||||
Ok(bytes) => {
|
||||
let module_request = self.get_request();
|
||||
self.context.request = Some(module_request.payload(bytes))
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Set payload failed: {:?}", e);
|
||||
},
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn event<E>(mut self, event: E) -> Self
|
||||
pub fn event<Event>(mut self, event: Event) -> Self
|
||||
where
|
||||
E: Eq + Hash + Debug + Clone + Display,
|
||||
Event: Eq + Hash + Debug + Clone + Display,
|
||||
{
|
||||
self.tester.set_event(event);
|
||||
self.context.request = Some(ModuleRequest::new(event));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sync_send(mut self) -> Self {
|
||||
self.tester.sync_send();
|
||||
let request = self.get_request();
|
||||
let resp = EventDispatch::sync_send(self.dispatch(), request);
|
||||
self.context.response = Some(resp);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn parse<R>(mut self) -> R
|
||||
pub fn parse<R>(self) -> R
|
||||
where
|
||||
R: FromBytes,
|
||||
{
|
||||
self.tester.parse::<R>()
|
||||
let response = self.get_response();
|
||||
match response.parse::<R, E>() {
|
||||
Ok(Ok(data)) => data,
|
||||
Ok(Err(e)) => {
|
||||
panic!("parse failed: {:?}", e)
|
||||
},
|
||||
Err(e) => panic!("Internal error: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(mut self) -> <T as TesterTrait>::Error { self.tester.error() }
|
||||
pub fn error(self) -> E {
|
||||
let response = self.get_response();
|
||||
assert_eq!(response.status_code, StatusCode::Err);
|
||||
<Data<E>>::try_from(response.payload).unwrap().into_inner()
|
||||
}
|
||||
|
||||
pub fn assert_error(mut self) -> Self {
|
||||
self.tester.assert_error();
|
||||
pub fn assert_error(self) -> Self {
|
||||
// self.context.assert_error();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn assert_success(mut self) -> Self {
|
||||
self.tester.assert_success();
|
||||
pub fn assert_success(self) -> Self {
|
||||
// self.context.assert_success();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sdk(&self) -> FlowySDK { self.context.sdk.clone() }
|
||||
|
||||
fn dispatch(&self) -> Arc<EventDispatch> { self.context.sdk.dispatch() }
|
||||
|
||||
fn get_response(&self) -> EventResponse { self.context.response.as_ref().expect("must call sync_send first").clone() }
|
||||
|
||||
fn get_request(&mut self) -> ModuleRequest { self.context.request.take().expect("must call event first") }
|
||||
}
|
||||
|
||||
pub struct RandomUserTester<Error> {
|
||||
context: TesterContext,
|
||||
err_phantom: PhantomData<Error>,
|
||||
#[derive(Clone)]
|
||||
pub struct TestContext {
|
||||
sdk: FlowyTestSDK,
|
||||
request: Option<ModuleRequest>,
|
||||
response: Option<EventResponse>,
|
||||
}
|
||||
|
||||
impl<Error> RandomUserTester<Error>
|
||||
where
|
||||
Error: FromBytes + Debug,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
impl TestContext {
|
||||
pub fn new(sdk: FlowyTestSDK) -> Self {
|
||||
Self {
|
||||
context: TesterContext::default(),
|
||||
err_phantom: PhantomData,
|
||||
sdk,
|
||||
request: None,
|
||||
response: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Error> TesterTrait for RandomUserTester<Error>
|
||||
where
|
||||
Error: FromBytes + Debug,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn mut_context(&mut self) -> &mut TesterContext { &mut self.context }
|
||||
|
||||
fn context(&self) -> &TesterContext { &self.context }
|
||||
}
|
||||
|
||||
pub struct SignUpContext {
|
||||
pub user_detail: UserDetail,
|
||||
pub password: String,
|
||||
|
@ -1,13 +1,14 @@
|
||||
use bytes::Bytes;
|
||||
use flowy_dispatch::prelude::{DispatchError, EventDispatch, ModuleRequest, ToBytes};
|
||||
use flowy_dispatch::prelude::{EventDispatch, ModuleRequest, ToBytes};
|
||||
use flowy_infra::{kv::KV, uuid};
|
||||
|
||||
use flowy_user::errors::{ErrorBuilder, ErrorCode, UserError};
|
||||
use flowy_workspace::{
|
||||
entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace},
|
||||
errors::WorkspaceError,
|
||||
event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace},
|
||||
};
|
||||
use std::{fs, path::PathBuf};
|
||||
use std::{fs, path::PathBuf, sync::Arc};
|
||||
|
||||
pub fn root_dir() -> String {
|
||||
// https://doc.rust-lang.org/cargo/reference/environment-variables.html
|
||||
@ -35,7 +36,7 @@ const DEFAULT_WORKSPACE_NAME: &'static str = "My workspace";
|
||||
const DEFAULT_WORKSPACE_DESC: &'static str = "This is your first workspace";
|
||||
const DEFAULT_WORKSPACE: &'static str = "Default_Workspace";
|
||||
|
||||
pub(crate) fn create_default_workspace_if_need(user_id: &str) -> Result<(), UserError> {
|
||||
pub(crate) fn create_default_workspace_if_need(dispatch: Arc<EventDispatch>, user_id: &str) -> Result<(), UserError> {
|
||||
let key = format!("{}{}", user_id, DEFAULT_WORKSPACE);
|
||||
if KV::get_bool(&key).unwrap_or(false) {
|
||||
return Err(ErrorBuilder::new(ErrorCode::DefaultWorkspaceAlreadyExist).build());
|
||||
@ -50,12 +51,11 @@ pub(crate) fn create_default_workspace_if_need(user_id: &str) -> Result<(), User
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(CreateWorkspace).payload(payload);
|
||||
let result = EventDispatch::sync_send(request)
|
||||
let result = EventDispatch::sync_send(dispatch.clone(), request)
|
||||
.parse::<Workspace, WorkspaceError>()
|
||||
.map_err(|e| ErrorBuilder::new(ErrorCode::CreateDefaultWorkspaceFailed).error(e).build())?;
|
||||
|
||||
let workspace = result.map_err(|e| ErrorBuilder::new(ErrorCode::CreateDefaultWorkspaceFailed).error(e).build())?;
|
||||
|
||||
let query: Bytes = QueryWorkspaceRequest {
|
||||
workspace_id: Some(workspace.id.clone()),
|
||||
}
|
||||
@ -63,7 +63,7 @@ pub(crate) fn create_default_workspace_if_need(user_id: &str) -> Result<(), User
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(OpenWorkspace).payload(query);
|
||||
let _result = EventDispatch::sync_send(request)
|
||||
let _result = EventDispatch::sync_send(dispatch.clone(), request)
|
||||
.parse::<Workspace, WorkspaceError>()
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
@ -1,21 +1,34 @@
|
||||
pub mod builder;
|
||||
mod helper;
|
||||
mod tester;
|
||||
// pub mod workspace_builder;
|
||||
|
||||
use crate::helper::root_dir;
|
||||
use crate::{builder::UserTestBuilder, helper::root_dir};
|
||||
use flowy_sdk::FlowySDK;
|
||||
use std::sync::Once;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{builder::*, helper::*};
|
||||
pub use crate::{builder::*, helper::*, *};
|
||||
pub use flowy_dispatch::prelude::*;
|
||||
}
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
pub fn init_test_sdk() {
|
||||
let root_dir = root_dir();
|
||||
pub type FlowyTestSDK = FlowySDK;
|
||||
|
||||
INIT.call_once(|| {
|
||||
FlowySDK::construct_with(&root_dir);
|
||||
});
|
||||
#[derive(Clone)]
|
||||
pub struct TestSDKBuilder {
|
||||
inner: FlowyTestSDK,
|
||||
}
|
||||
|
||||
impl TestSDKBuilder {
|
||||
pub fn new() -> Self { Self { inner: init_test_sdk() } }
|
||||
|
||||
pub fn sign_up(self) -> Self {
|
||||
let _ = UserTestBuilder::new(self.inner.clone()).sign_up();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> FlowyTestSDK { self.inner }
|
||||
}
|
||||
|
||||
pub fn init_test_sdk() -> FlowyTestSDK {
|
||||
let root_dir = root_dir();
|
||||
FlowySDK::new(&root_dir)
|
||||
}
|
||||
|
@ -1,142 +0,0 @@
|
||||
use crate::{
|
||||
helper::{login_password, random_email},
|
||||
init_test_sdk,
|
||||
};
|
||||
use flowy_dispatch::prelude::*;
|
||||
pub use flowy_sdk::*;
|
||||
use flowy_user::{
|
||||
errors::UserError,
|
||||
event::UserEvent::{GetUserProfile, SignOut, SignUp},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use crate::helper::login_email;
|
||||
use flowy_user::event::UserEvent::SignIn;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
fmt::{Debug, Display},
|
||||
hash::Hash,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct TesterContext {
|
||||
request: Option<ModuleRequest>,
|
||||
response: Option<EventResponse>,
|
||||
status_code: StatusCode,
|
||||
}
|
||||
|
||||
impl TesterContext {
|
||||
pub fn new(email: String) -> Self { TesterContext::default() }
|
||||
}
|
||||
|
||||
impl std::default::Default for TesterContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
request: None,
|
||||
status_code: StatusCode::Ok,
|
||||
response: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TesterTrait {
|
||||
type Error: FromBytes + Debug;
|
||||
|
||||
fn mut_context(&mut self) -> &mut TesterContext;
|
||||
|
||||
fn context(&self) -> &TesterContext;
|
||||
|
||||
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)
|
||||
where
|
||||
E: Eq + Hash + Debug + Clone + Display,
|
||||
{
|
||||
self.mut_context().request = Some(ModuleRequest::new(event));
|
||||
}
|
||||
|
||||
fn set_payload<P>(&mut self, payload: P)
|
||||
where
|
||||
P: ToBytes,
|
||||
{
|
||||
match payload.into_bytes() {
|
||||
Ok(bytes) => {
|
||||
let module_request = self.mut_context().request.take().unwrap();
|
||||
self.mut_context().request = Some(module_request.payload(bytes));
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Set payload failed: {:?}", e);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn sync_send(&mut self) {
|
||||
let resp = EventDispatch::sync_send(self.mut_context().request.take().unwrap());
|
||||
self.mut_context().response = Some(resp);
|
||||
}
|
||||
|
||||
// TODO: support return Option<R>
|
||||
fn parse<R>(&mut self) -> R
|
||||
where
|
||||
R: FromBytes,
|
||||
{
|
||||
let response = self.mut_context().response.clone().unwrap();
|
||||
match response.parse::<R, Self::Error>() {
|
||||
Ok(Ok(data)) => data,
|
||||
Ok(Err(e)) => {
|
||||
panic!("parse failed: {:?}", e)
|
||||
},
|
||||
Err(e) => panic!("Internal error: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn error(&mut self) -> Self::Error {
|
||||
let response = self.mut_context().response.clone().unwrap();
|
||||
assert_eq!(response.status_code, StatusCode::Err);
|
||||
<Data<Self::Error>>::try_from(response.payload).unwrap().into_inner()
|
||||
}
|
||||
|
||||
fn sign_up(&self) -> (UserDetail, String) {
|
||||
let password = login_password();
|
||||
let payload = SignUpRequest {
|
||||
email: login_email(),
|
||||
name: "app flowy".to_string(),
|
||||
password: password.clone(),
|
||||
}
|
||||
.into_bytes()
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(SignUp).payload(payload);
|
||||
let user_detail = EventDispatch::sync_send(request).parse::<UserDetail, UserError>().unwrap().unwrap();
|
||||
|
||||
(user_detail, password)
|
||||
}
|
||||
|
||||
fn sign_in(&self) -> UserDetail {
|
||||
let payload = SignInRequest {
|
||||
email: login_email(),
|
||||
password: login_password(),
|
||||
}
|
||||
.into_bytes()
|
||||
.unwrap();
|
||||
|
||||
let request = ModuleRequest::new(SignIn).payload(payload);
|
||||
let user_detail = EventDispatch::sync_send(request).parse::<UserDetail, UserError>().unwrap().unwrap();
|
||||
|
||||
user_detail
|
||||
}
|
||||
|
||||
fn login_if_need(&self) -> UserDetail {
|
||||
match EventDispatch::sync_send(ModuleRequest::new(GetUserProfile))
|
||||
.parse::<UserDetail, UserError>()
|
||||
.unwrap()
|
||||
{
|
||||
Ok(user_detail) => user_detail,
|
||||
Err(_e) => self.sign_in(),
|
||||
}
|
||||
}
|
||||
|
||||
fn logout(&self) { let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); }
|
||||
}
|
60
rust-lib/flowy-test/src/workspace_builder.rs
Normal file
60
rust-lib/flowy-test/src/workspace_builder.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use super::builder::Builder;
|
||||
use crate::{builder::TestContext, helper::FlowyTestSDK};
|
||||
use flowy_workspace::{
|
||||
entities::{app::App, view::View, workspace::*},
|
||||
errors::WorkspaceError,
|
||||
event::WorkspaceEvent::*,
|
||||
};
|
||||
|
||||
pub enum WorkspaceAction {
|
||||
CreateWorkspace(CreateWorkspaceRequest),
|
||||
ReadWorkspace(QueryWorkspaceRequest),
|
||||
}
|
||||
|
||||
type Inner = Builder<WorkspaceError>;
|
||||
|
||||
pub struct WorkspaceTestBuilder {
|
||||
workspace: Option<Workspace>,
|
||||
app: Option<App>,
|
||||
view: Option<View>,
|
||||
inner: Builder<WorkspaceError>,
|
||||
}
|
||||
|
||||
impl WorkspaceTestBuilder {
|
||||
pub fn new(sdk: FlowyTestSDK) -> Self {
|
||||
Self {
|
||||
workspace: None,
|
||||
app: None,
|
||||
view: None,
|
||||
inner: Builder::test(TestContext::new(sdk)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(mut self, actions: Vec<WorkspaceAction>) {
|
||||
let inner = self.inner;
|
||||
for action in actions {
|
||||
match action {
|
||||
WorkspaceAction::CreateWorkspace(request) => {
|
||||
let workspace = inner
|
||||
.clone()
|
||||
.event(CreateWorkspace)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
.parse::<Workspace>();
|
||||
self.workspace = Some(workspace);
|
||||
},
|
||||
WorkspaceAction::ReadWorkspace(request) => {
|
||||
let mut repeated_workspace = inner
|
||||
.clone()
|
||||
.event(ReadWorkspaces)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
.parse::<RepeatedWorkspace>();
|
||||
|
||||
debug_assert_eq!(repeated_workspace.len(), 1, "Default workspace not found");
|
||||
repeated_workspace.drain(..1).collect::<Vec<Workspace>>().pop()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -49,4 +49,4 @@ futures = "0.3.15"
|
||||
serial_test = "0.5.1"
|
||||
|
||||
[features]
|
||||
mock_server = []
|
||||
http_server = []
|
@ -17,7 +17,7 @@ impl std::default::Default for UserStatus {
|
||||
fn default() -> Self { UserStatus::Unknown }
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default, Debug, PartialEq, Eq)]
|
||||
#[derive(ProtoBuf, Default, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct UserDetail {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
@ -135,36 +135,19 @@ impl TryInto<UpdateUserParams> for UpdateUserRequest {
|
||||
|
||||
let name = match self.name {
|
||||
None => None,
|
||||
Some(name) => Some(
|
||||
UserName::parse(name)
|
||||
.map_err(|e| ErrorBuilder::new(e).build())?
|
||||
.0,
|
||||
),
|
||||
Some(name) => Some(UserName::parse(name).map_err(|e| ErrorBuilder::new(e).build())?.0),
|
||||
};
|
||||
|
||||
let email = match self.email {
|
||||
None => None,
|
||||
Some(email) => Some(
|
||||
UserEmail::parse(email)
|
||||
.map_err(|e| ErrorBuilder::new(e).build())?
|
||||
.0,
|
||||
),
|
||||
Some(email) => Some(UserEmail::parse(email).map_err(|e| ErrorBuilder::new(e).build())?.0),
|
||||
};
|
||||
|
||||
let password = match self.password {
|
||||
None => None,
|
||||
Some(password) => Some(
|
||||
UserPassword::parse(password)
|
||||
.map_err(|e| ErrorBuilder::new(e).build())?
|
||||
.0,
|
||||
),
|
||||
Some(password) => Some(UserPassword::parse(password).map_err(|e| ErrorBuilder::new(e).build())?.0),
|
||||
};
|
||||
|
||||
Ok(UpdateUserParams {
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
})
|
||||
Ok(UpdateUserParams { id, name, email, password })
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ pub trait UserServerAPI {
|
||||
}
|
||||
|
||||
pub(crate) fn construct_user_server() -> Arc<dyn UserServerAPI + Send + Sync> {
|
||||
if cfg!(feature = "mock_server") {
|
||||
Arc::new(UserServerMock {})
|
||||
} else {
|
||||
if cfg!(feature = "http_server") {
|
||||
Arc::new(UserServer {})
|
||||
} else {
|
||||
Arc::new(UserServerMock {})
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use flowy_database::{DBConnection, Database};
|
||||
use flowy_sqlite::ConnectionPool;
|
||||
use lazy_static::lazy_static;
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::{lock_api::RwLockReadGuard, Mutex, RawRwLock, RwLock};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||
lazy_static! {
|
||||
static ref DB: RwLock<Option<Database>> = RwLock::new(None);
|
||||
|
@ -170,7 +170,7 @@ impl UserSession {
|
||||
}
|
||||
|
||||
fn set_session(&self, session: Option<Session>) -> Result<(), UserError> {
|
||||
log::trace!("Update user session: {:?}", session);
|
||||
log::debug!("Update user session: {:?}", session);
|
||||
match &session {
|
||||
None => KV::remove(SESSION_CACHE_KEY).map_err(|e| UserError::new(ErrorCode::SqlInternalError, &e))?,
|
||||
Some(session) => KV::set_str(SESSION_CACHE_KEY, session.clone().into()),
|
||||
|
@ -1,19 +1,13 @@
|
||||
use crate::helper::*;
|
||||
use flowy_test::builder::UserTestBuilder;
|
||||
use flowy_test::{builder::UserTestBuilder, init_test_sdk};
|
||||
use flowy_user::{errors::ErrorCode, event::UserEvent::*, prelude::*};
|
||||
use serial_test::*;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn sign_up_success() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
log::info!("{:?}", user_detail);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn sign_up_with_invalid_email() {
|
||||
for email in invalid_email_test_case() {
|
||||
let sdk = init_test_sdk();
|
||||
let request = SignUpRequest {
|
||||
email: email.to_string(),
|
||||
name: valid_name(),
|
||||
@ -21,7 +15,7 @@ fn sign_up_with_invalid_email() {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
UserTestBuilder::new().event(SignUp).request(request).sync_send().error().code,
|
||||
UserTestBuilder::new(sdk).event(SignUp).request(request).sync_send().error().code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
@ -30,28 +24,30 @@ fn sign_up_with_invalid_email() {
|
||||
#[serial]
|
||||
fn sign_up_with_invalid_password() {
|
||||
for password in invalid_password_test_case() {
|
||||
let sdk = init_test_sdk();
|
||||
let request = SignUpRequest {
|
||||
email: random_email(),
|
||||
name: valid_name(),
|
||||
password,
|
||||
};
|
||||
|
||||
UserTestBuilder::new().event(SignUp).request(request).sync_send().assert_error();
|
||||
UserTestBuilder::new(sdk).event(SignUp).request(request).sync_send().assert_error();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn sign_in_success() {
|
||||
let context = UserTestBuilder::new().sign_up();
|
||||
let _ = UserTestBuilder::new().event(SignOut).sync_send();
|
||||
let sdk = init_test_sdk();
|
||||
let context = UserTestBuilder::new(sdk.clone()).sign_up();
|
||||
let _ = UserTestBuilder::new(sdk.clone()).event(SignOut).sync_send();
|
||||
|
||||
let request = SignInRequest {
|
||||
email: context.user_detail.email,
|
||||
password: context.password,
|
||||
};
|
||||
|
||||
let response = UserTestBuilder::new()
|
||||
let response = UserTestBuilder::new(sdk)
|
||||
.event(SignIn)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -63,13 +59,14 @@ fn sign_in_success() {
|
||||
#[serial]
|
||||
fn sign_in_with_invalid_email() {
|
||||
for email in invalid_email_test_case() {
|
||||
let sdk = init_test_sdk();
|
||||
let request = SignInRequest {
|
||||
email: email.to_string(),
|
||||
password: login_password(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
UserTestBuilder::new().event(SignIn).request(request).sync_send().error().code,
|
||||
UserTestBuilder::new(sdk).event(SignIn).request(request).sync_send().error().code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
@ -79,11 +76,12 @@ fn sign_in_with_invalid_email() {
|
||||
#[serial]
|
||||
fn sign_in_with_invalid_password() {
|
||||
for password in invalid_password_test_case() {
|
||||
let sdk = init_test_sdk();
|
||||
let request = SignInRequest {
|
||||
email: random_email(),
|
||||
password,
|
||||
};
|
||||
|
||||
UserTestBuilder::new().event(SignIn).request(request).sync_send().assert_error();
|
||||
UserTestBuilder::new(sdk).event(SignIn).request(request).sync_send().assert_error();
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
use crate::helper::*;
|
||||
use flowy_infra::uuid;
|
||||
use flowy_test::builder::UserTestBuilder;
|
||||
use flowy_test::{builder::UserTestBuilder, init_test_sdk};
|
||||
use flowy_user::{errors::ErrorCode, event::UserEvent::*, prelude::*};
|
||||
use serial_test::*;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_status_get_failed() {
|
||||
let tester = UserTestBuilder::new().event(GetUserProfile).assert_error().sync_send();
|
||||
assert!(tester.get_user_detail().is_none())
|
||||
fn user_profile_get_failed() {
|
||||
let sdk = init_test_sdk();
|
||||
let result = UserTestBuilder::new(sdk).event(GetUserProfile).assert_error().sync_send();
|
||||
assert!(result.user_detail().is_none())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_detail_get() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
fn user_profile_get() {
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
|
||||
let user_detail2 = UserTestBuilder::new().event(GetUserProfile).sync_send().parse::<UserDetail>();
|
||||
let user_detail2 = UserTestBuilder::new(sdk).event(GetUserProfile).sync_send().parse::<UserDetail>();
|
||||
|
||||
assert_eq!(user_detail, user_detail2);
|
||||
}
|
||||
@ -24,12 +26,13 @@ fn user_detail_get() {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_name() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
let new_name = "hello_world".to_owned();
|
||||
let request = UpdateUserRequest::new(&user_detail.id).name(&new_name);
|
||||
let _ = UserTestBuilder::new().event(UpdateUser).request(request).sync_send();
|
||||
let _ = UserTestBuilder::new(sdk.clone()).event(UpdateUser).request(request).sync_send();
|
||||
|
||||
let user_detail = UserTestBuilder::new()
|
||||
let user_detail = UserTestBuilder::new(sdk)
|
||||
.event(GetUserProfile)
|
||||
.assert_error()
|
||||
.sync_send()
|
||||
@ -41,13 +44,14 @@ fn user_update_with_name() {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_email() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
let new_email = format!("{}@gmai.com", uuid());
|
||||
let request = UpdateUserRequest::new(&user_detail.id).email(&new_email);
|
||||
|
||||
let _ = UserTestBuilder::new().event(UpdateUser).request(request).sync_send();
|
||||
let _ = UserTestBuilder::new(sdk.clone()).event(UpdateUser).request(request).sync_send();
|
||||
|
||||
let user_detail = UserTestBuilder::new()
|
||||
let user_detail = UserTestBuilder::new(sdk)
|
||||
.event(GetUserProfile)
|
||||
.assert_error()
|
||||
.sync_send()
|
||||
@ -59,11 +63,12 @@ fn user_update_with_email() {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_password() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
let new_password = "H123world!".to_owned();
|
||||
let request = UpdateUserRequest::new(&user_detail.id).password(&new_password);
|
||||
|
||||
let _ = UserTestBuilder::new()
|
||||
let _ = UserTestBuilder::new(sdk)
|
||||
.event(UpdateUser)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -73,11 +78,17 @@ fn user_update_with_password() {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_invalid_email() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
for email in invalid_email_test_case() {
|
||||
let request = UpdateUserRequest::new(&user_detail.id).email(&email);
|
||||
assert_eq!(
|
||||
UserTestBuilder::new().event(UpdateUser).request(request).sync_send().error().code,
|
||||
UserTestBuilder::new(sdk.clone())
|
||||
.event(UpdateUser)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
.error()
|
||||
.code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
@ -86,19 +97,29 @@ fn user_update_with_invalid_email() {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_invalid_password() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
for password in invalid_password_test_case() {
|
||||
let request = UpdateUserRequest::new(&user_detail.id).password(&password);
|
||||
|
||||
UserTestBuilder::new().event(UpdateUser).request(request).sync_send().assert_error();
|
||||
UserTestBuilder::new(sdk.clone())
|
||||
.event(UpdateUser)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
.assert_error();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn user_update_with_invalid_name() {
|
||||
let user_detail = UserTestBuilder::new().sign_up().user_detail;
|
||||
let sdk = init_test_sdk();
|
||||
let user_detail = UserTestBuilder::new(sdk.clone()).sign_up().user_detail;
|
||||
let request = UpdateUserRequest::new(&user_detail.id).name("");
|
||||
|
||||
UserTestBuilder::new().event(UpdateUser).request(request).sync_send().assert_error();
|
||||
UserTestBuilder::new(sdk)
|
||||
.event(UpdateUser)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
.assert_error();
|
||||
}
|
||||
|
@ -37,4 +37,4 @@ serial_test = "0.5.1"
|
||||
|
||||
|
||||
[features]
|
||||
mock_server = []
|
||||
http_server = []
|
@ -1,8 +1,4 @@
|
||||
use crate::{
|
||||
entities::workspace::*,
|
||||
errors::{ErrorBuilder, ErrorCode, WorkspaceError},
|
||||
services::WorkspaceController,
|
||||
};
|
||||
use crate::{entities::workspace::*, errors::WorkspaceError, services::WorkspaceController};
|
||||
use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
|
||||
|
@ -51,9 +51,9 @@ pub trait WorkspaceServerAPI {
|
||||
}
|
||||
|
||||
pub(crate) fn construct_workspace_server() -> Arc<dyn WorkspaceServerAPI + Send + Sync> {
|
||||
if cfg!(feature = "mock_server") {
|
||||
Arc::new(WorkspaceServerMock {})
|
||||
} else {
|
||||
if cfg!(feature = "http_server") {
|
||||
Arc::new(WorkspaceServer {})
|
||||
} else {
|
||||
Arc::new(WorkspaceServerMock {})
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
services::{helper::spawn, server::Server, AppController},
|
||||
sql_tables::workspace::{WorkspaceSql, WorkspaceTable, WorkspaceTableChangeset},
|
||||
};
|
||||
use flowy_dispatch::prelude::DispatchFuture;
|
||||
|
||||
use flowy_infra::kv::KV;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::helper::*;
|
||||
use flowy_test::prelude::*;
|
||||
|
||||
use flowy_test::builder::UserTestBuilder;
|
||||
use flowy_workspace::entities::{
|
||||
app::{QueryAppRequest, UpdateAppRequest},
|
||||
view::*,
|
||||
@ -8,40 +8,39 @@ use flowy_workspace::entities::{
|
||||
|
||||
#[test]
|
||||
fn app_create() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let app = create_app(&sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
dbg!(&app);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn app_delete() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
delete_app(&app.id);
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let app = create_app(&sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
delete_app(&sdk, &app.id);
|
||||
let query = QueryAppRequest::new(&app.id);
|
||||
let _ = read_app(query);
|
||||
let _ = read_app(&sdk, query);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_read() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let app = create_app(&sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
let query = QueryAppRequest::new(&app.id);
|
||||
let app_from_db = read_app(query);
|
||||
let app_from_db = read_app(&sdk, query);
|
||||
assert_eq!(app_from_db, app);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_create_with_view() {
|
||||
let _a = UserTestBuilder::new().sign_up();
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let app = create_app(&sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
let request_a = CreateViewRequest {
|
||||
belong_to_id: app.id.clone(),
|
||||
name: "View A".to_string(),
|
||||
@ -58,11 +57,11 @@ fn app_create_with_view() {
|
||||
view_type: ViewType::Doc,
|
||||
};
|
||||
|
||||
let view_a = create_view_with_request(request_a);
|
||||
let view_b = create_view_with_request(request_b);
|
||||
let view_a = create_view_with_request(&sdk, request_a);
|
||||
let view_b = create_view_with_request(&sdk, request_b);
|
||||
|
||||
let query = QueryAppRequest::new(&app.id).set_read_views(true);
|
||||
let view_from_db = read_app(query);
|
||||
let view_from_db = read_app(&sdk, query);
|
||||
|
||||
assert_eq!(view_from_db.belongings[0], view_a);
|
||||
assert_eq!(view_from_db.belongings[1], view_b);
|
||||
@ -70,24 +69,24 @@ fn app_create_with_view() {
|
||||
|
||||
#[test]
|
||||
fn app_set_trash_flag() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let app_id = create_app_with_trash_flag();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let app_id = create_app_with_trash_flag(&sdk);
|
||||
let query = QueryAppRequest::new(&app_id).set_is_trash(true);
|
||||
let _ = read_app(query);
|
||||
let _ = read_app(&sdk, query);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn app_set_trash_flag_2() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let app_id = create_app_with_trash_flag();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let app_id = create_app_with_trash_flag(&sdk);
|
||||
let query = QueryAppRequest::new(&app_id);
|
||||
let _ = read_app(query);
|
||||
let _ = read_app(&sdk, query);
|
||||
}
|
||||
|
||||
fn create_app_with_trash_flag() -> String {
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
fn create_app_with_trash_flag(sdk: &FlowyTestSDK) -> String {
|
||||
let workspace = create_workspace(sdk, "Workspace", "");
|
||||
let app = create_app(sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
let request = UpdateAppRequest {
|
||||
app_id: app.id.clone(),
|
||||
name: None,
|
||||
@ -95,7 +94,7 @@ fn create_app_with_trash_flag() -> String {
|
||||
color_style: None,
|
||||
is_trash: Some(true),
|
||||
};
|
||||
update_app(request);
|
||||
update_app(sdk, request);
|
||||
|
||||
app.id
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use flowy_test::builder::{UserTestBuilder, WorkspaceTestBuilder};
|
||||
use flowy_test::prelude::*;
|
||||
use flowy_workspace::{
|
||||
entities::{app::*, view::*, workspace::*},
|
||||
event::WorkspaceEvent::*,
|
||||
@ -11,13 +11,13 @@ pub(crate) fn invalid_workspace_name_test_case() -> Vec<String> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn create_workspace(name: &str, desc: &str) -> Workspace {
|
||||
pub fn create_workspace(sdk: &FlowyTestSDK, name: &str, desc: &str) -> Workspace {
|
||||
let request = CreateWorkspaceRequest {
|
||||
name: name.to_owned(),
|
||||
desc: desc.to_owned(),
|
||||
};
|
||||
|
||||
let workspace = WorkspaceTestBuilder::new()
|
||||
let workspace = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(CreateWorkspace)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -25,8 +25,8 @@ pub fn create_workspace(name: &str, desc: &str) -> Workspace {
|
||||
workspace
|
||||
}
|
||||
|
||||
pub fn read_workspaces(request: QueryWorkspaceRequest) -> Option<Workspace> {
|
||||
let mut repeated_workspace = WorkspaceTestBuilder::new()
|
||||
pub fn read_workspaces(sdk: &FlowyTestSDK, request: QueryWorkspaceRequest) -> Option<Workspace> {
|
||||
let mut repeated_workspace = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(ReadWorkspaces)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -36,7 +36,7 @@ pub fn read_workspaces(request: QueryWorkspaceRequest) -> Option<Workspace> {
|
||||
repeated_workspace.drain(..1).collect::<Vec<Workspace>>().pop()
|
||||
}
|
||||
|
||||
pub fn create_app(name: &str, desc: &str, workspace_id: &str) -> App {
|
||||
pub fn create_app(sdk: &FlowyTestSDK, name: &str, desc: &str, workspace_id: &str) -> App {
|
||||
let create_app_request = CreateAppRequest {
|
||||
workspace_id: workspace_id.to_owned(),
|
||||
name: name.to_string(),
|
||||
@ -44,7 +44,7 @@ pub fn create_app(name: &str, desc: &str, workspace_id: &str) -> App {
|
||||
color_style: Default::default(),
|
||||
};
|
||||
|
||||
let app = WorkspaceTestBuilder::new()
|
||||
let app = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(CreateApp)
|
||||
.request(create_app_request)
|
||||
.sync_send()
|
||||
@ -52,18 +52,23 @@ pub fn create_app(name: &str, desc: &str, workspace_id: &str) -> App {
|
||||
app
|
||||
}
|
||||
|
||||
pub fn delete_app(app_id: &str) {
|
||||
pub fn delete_app(sdk: &FlowyTestSDK, app_id: &str) {
|
||||
let delete_app_request = DeleteAppRequest {
|
||||
app_id: app_id.to_string(),
|
||||
};
|
||||
|
||||
WorkspaceTestBuilder::new().event(DeleteApp).request(delete_app_request).sync_send();
|
||||
WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(DeleteApp)
|
||||
.request(delete_app_request)
|
||||
.sync_send();
|
||||
}
|
||||
|
||||
pub fn update_app(request: UpdateAppRequest) { WorkspaceTestBuilder::new().event(UpdateApp).request(request).sync_send(); }
|
||||
pub fn update_app(sdk: &FlowyTestSDK, request: UpdateAppRequest) {
|
||||
WorkspaceTestBuilder::new(sdk.clone()).event(UpdateApp).request(request).sync_send();
|
||||
}
|
||||
|
||||
pub fn read_app(request: QueryAppRequest) -> App {
|
||||
let app = WorkspaceTestBuilder::new()
|
||||
pub fn read_app(sdk: &FlowyTestSDK, request: QueryAppRequest) -> App {
|
||||
let app = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(ReadApp)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -72,8 +77,8 @@ pub fn read_app(request: QueryAppRequest) -> App {
|
||||
app
|
||||
}
|
||||
|
||||
pub fn create_view_with_request(request: CreateViewRequest) -> View {
|
||||
let view = WorkspaceTestBuilder::new()
|
||||
pub fn create_view_with_request(sdk: &FlowyTestSDK, request: CreateViewRequest) -> View {
|
||||
let view = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(CreateView)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -82,8 +87,8 @@ pub fn create_view_with_request(request: CreateViewRequest) -> View {
|
||||
view
|
||||
}
|
||||
|
||||
pub fn create_view(workspace_id: &str) -> View {
|
||||
let app = create_app("App A", "AppFlowy Github Project", workspace_id);
|
||||
pub fn create_view(sdk: &FlowyTestSDK, workspace_id: &str) -> View {
|
||||
let app = create_app(sdk, "App A", "AppFlowy Github Project", workspace_id);
|
||||
let request = CreateViewRequest {
|
||||
belong_to_id: app.id.clone(),
|
||||
name: "View A".to_string(),
|
||||
@ -92,13 +97,18 @@ pub fn create_view(workspace_id: &str) -> View {
|
||||
view_type: ViewType::Doc,
|
||||
};
|
||||
|
||||
create_view_with_request(request)
|
||||
create_view_with_request(sdk, request)
|
||||
}
|
||||
|
||||
pub fn update_view(request: UpdateViewRequest) { WorkspaceTestBuilder::new().event(UpdateView).request(request).sync_send(); }
|
||||
pub fn update_view(sdk: &FlowyTestSDK, request: UpdateViewRequest) {
|
||||
WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(UpdateView)
|
||||
.request(request)
|
||||
.sync_send();
|
||||
}
|
||||
|
||||
pub fn read_view(request: QueryViewRequest) -> View {
|
||||
WorkspaceTestBuilder::new()
|
||||
pub fn read_view(sdk: &FlowyTestSDK, request: QueryViewRequest) -> View {
|
||||
WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(ReadView)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
|
@ -1,37 +1,36 @@
|
||||
use crate::helper::*;
|
||||
|
||||
use flowy_test::builder::UserTestBuilder;
|
||||
use flowy_test::{FlowyTestSDK, TestSDKBuilder};
|
||||
use flowy_workspace::entities::view::*;
|
||||
|
||||
#[test]
|
||||
fn view_create() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let _ = create_view(&workspace.id);
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let _ = create_view(&sdk, &workspace.id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_set_trash_flag() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let view_id = create_view_with_trash_flag();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let view_id = create_view_with_trash_flag(&sdk);
|
||||
let query = QueryViewRequest::new(&view_id).set_is_trash(true);
|
||||
let _ = read_view(query);
|
||||
let _ = read_view(&sdk, query);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn view_set_trash_flag2() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
|
||||
let view_id = create_view_with_trash_flag();
|
||||
let view_id = create_view_with_trash_flag(&sdk);
|
||||
let query = QueryViewRequest::new(&view_id);
|
||||
let _ = read_view(query);
|
||||
let _ = read_view(&sdk, query);
|
||||
}
|
||||
|
||||
fn create_view_with_trash_flag() -> String {
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let view = create_view(&workspace.id);
|
||||
fn create_view_with_trash_flag(sdk: &FlowyTestSDK) -> String {
|
||||
let workspace = create_workspace(sdk, "Workspace", "");
|
||||
let view = create_view(sdk, &workspace.id);
|
||||
let request = UpdateViewRequest {
|
||||
view_id: view.id.clone(),
|
||||
name: None,
|
||||
@ -39,7 +38,7 @@ fn create_view_with_trash_flag() -> String {
|
||||
thumbnail: None,
|
||||
is_trash: Some(true),
|
||||
};
|
||||
update_view(request);
|
||||
update_view(sdk, request);
|
||||
|
||||
view.id
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::helper::*;
|
||||
use flowy_test::builder::*;
|
||||
use flowy_test::{builder::*, TestSDKBuilder};
|
||||
use flowy_workspace::{
|
||||
entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, RepeatedWorkspace},
|
||||
event::WorkspaceEvent::*,
|
||||
@ -7,14 +7,17 @@ use flowy_workspace::{
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn workspace_create_success() { let _ = create_workspace("First workspace", ""); }
|
||||
fn workspace_create_success() {
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let _ = create_workspace(&sdk, "First workspace", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_read_all() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let _ = create_workspace("Workspace A", "workspace_create_and_then_get_workspace_success");
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let _ = create_workspace(&sdk, "Workspace A", "workspace_create_and_then_get_workspace_success");
|
||||
|
||||
let workspaces = WorkspaceTestBuilder::new()
|
||||
let workspaces = WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(ReadWorkspaces)
|
||||
.request(QueryWorkspaceRequest::new())
|
||||
.sync_send()
|
||||
@ -25,29 +28,32 @@ fn workspace_read_all() {
|
||||
|
||||
#[test]
|
||||
fn workspace_create_and_then_get_workspace() {
|
||||
let workspace = create_workspace("Workspace A", "workspace_create_and_then_get_workspace_success");
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace A", "workspace_create_and_then_get_workspace_success");
|
||||
let request = QueryWorkspaceRequest::new().workspace_id(&workspace.id);
|
||||
let workspace_from_db = read_workspaces(request).unwrap();
|
||||
let workspace_from_db = read_workspaces(&sdk, request).unwrap();
|
||||
assert_eq!(workspace.name, workspace_from_db.name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_create_with_apps() {
|
||||
let workspace = create_workspace("Workspace", "");
|
||||
let app = create_app("App A", "AppFlowy Github Project", &workspace.id);
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
let workspace = create_workspace(&sdk, "Workspace", "");
|
||||
let app = create_app(&sdk, "App A", "AppFlowy Github Project", &workspace.id);
|
||||
|
||||
let request = QueryWorkspaceRequest::new().workspace_id(&workspace.id);
|
||||
let workspace_from_db = read_workspaces(request).unwrap();
|
||||
let workspace_from_db = read_workspaces(&sdk, request).unwrap();
|
||||
assert_eq!(&app, workspace_from_db.apps.first_or_crash());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_create_with_invalid_name() {
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
for name in invalid_workspace_name_test_case() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let _ = UserTestBuilder::new(sdk.clone()).sign_up();
|
||||
let request = CreateWorkspaceRequest { name, desc: "".to_owned() };
|
||||
assert_eq!(
|
||||
WorkspaceTestBuilder::new()
|
||||
WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(CreateWorkspace)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
@ -60,11 +66,11 @@ fn workspace_create_with_invalid_name() {
|
||||
|
||||
#[test]
|
||||
fn workspace_update_with_invalid_name() {
|
||||
let _ = UserTestBuilder::new().sign_up();
|
||||
let sdk = TestSDKBuilder::new().sign_up().build();
|
||||
for name in invalid_workspace_name_test_case() {
|
||||
let request = CreateWorkspaceRequest { name, desc: "".to_owned() };
|
||||
assert_eq!(
|
||||
WorkspaceTestBuilder::new()
|
||||
WorkspaceTestBuilder::new(sdk.clone())
|
||||
.event(CreateWorkspace)
|
||||
.request(request)
|
||||
.sync_send()
|
||||
|
@ -5,16 +5,15 @@ dependencies = ["rm_cache"]
|
||||
description = "Build desktop targets."
|
||||
script = '''
|
||||
cd rust-lib
|
||||
cargo test --features "flowy-workspace/mock_server","flowy-user/mock_server"
|
||||
cargo test
|
||||
'''
|
||||
|
||||
|
||||
[tasks.test_remote]
|
||||
dependencies = ["rm_cache", "run_server"]
|
||||
[tasks.run_test_remote_command]
|
||||
dependencies = ["rm_cache"]
|
||||
script = """
|
||||
cd rust-lib
|
||||
cargo test
|
||||
cargo test --features "flowy-workspace/http_server","flowy-user/http_server"
|
||||
"""
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user