refactor tests

This commit is contained in:
appflowy
2021-12-08 17:33:22 +08:00
parent 4450d4410b
commit 7ac55f29db
30 changed files with 467 additions and 454 deletions

View File

@ -0,0 +1,22 @@
use crate::{helper::ViewTest, FlowySDKTest};
use flowy_document::services::doc::edit::ClientDocEditor;
use flowy_document_infra::entities::doc::DocIdentifier;
use std::sync::Arc;
pub struct EditorTest {
pub sdk: FlowySDKTest,
}
impl EditorTest {
pub async fn new() -> Self {
let sdk = FlowySDKTest::setup();
let _ = sdk.init_user().await;
Self { sdk }
}
pub async fn create_doc(&self) -> Arc<ClientDocEditor> {
let test = ViewTest::new(&self.sdk).await;
let doc_identifier: DocIdentifier = test.view.id.clone().into();
self.sdk.flowy_document.open(doc_identifier).await.unwrap()
}
}

View File

@ -5,37 +5,36 @@ use std::{
hash::Hash,
};
use crate::FlowyTestSDK;
use lib_dispatch::prelude::*;
use crate::FlowySDKTest;
use flowy_core::errors::WorkspaceError;
use flowy_sdk::*;
use flowy_user::errors::UserError;
use lib_dispatch::prelude::*;
use std::{convert::TryFrom, marker::PhantomData, sync::Arc};
pub type FlowyWorkspaceTest = Builder<WorkspaceError>;
impl FlowyWorkspaceTest {
pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) }
pub type CoreModuleEventBuilder = EventBuilder<WorkspaceError>;
impl CoreModuleEventBuilder {
pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) }
}
pub type UserTest = Builder<UserError>;
impl UserTest {
pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) }
pub type UserModuleEventBuilder = EventBuilder<UserError>;
impl UserModuleEventBuilder {
pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) }
pub fn user_profile(&self) -> &Option<UserProfile> { &self.user_profile }
}
#[derive(Clone)]
pub struct Builder<E> {
pub struct EventBuilder<E> {
context: TestContext,
user_profile: Option<UserProfile>,
err_phantom: PhantomData<E>,
}
impl<E> Builder<E>
impl<E> EventBuilder<E>
where
E: FromBytes + Debug,
{
pub(crate) fn test(context: TestContext) -> Self {
fn test(context: TestContext) -> Self {
Self {
context,
user_profile: None,
@ -111,8 +110,6 @@ where
self
}
pub fn sdk(&self) -> FlowySDK { self.context.sdk.clone() }
fn dispatch(&self) -> Arc<EventDispatcher> { self.context.sdk.dispatcher() }
fn get_response(&self) -> EventResponse {
@ -128,13 +125,13 @@ where
#[derive(Clone)]
pub struct TestContext {
sdk: FlowyTestSDK,
pub sdk: FlowySDKTest,
request: Option<ModuleRequest>,
response: Option<EventResponse>,
}
impl TestContext {
pub fn new(sdk: FlowyTestSDK) -> Self {
pub fn new(sdk: FlowySDKTest) -> Self {
Self {
sdk,
request: None,

View File

@ -1,19 +1,282 @@
use crate::prelude::*;
use bytes::Bytes;
use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes};
use lib_infra::{kv::KV, uuid};
use flowy_core::{
entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace},
errors::WorkspaceError,
event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace},
entities::{
app::*,
trash::{RepeatedTrash, TrashIdentifier},
view::*,
workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace, *},
},
errors::{ErrorCode, WorkspaceError},
event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace, *},
};
use flowy_document_infra::entities::doc::Doc;
use flowy_user::{
entities::{SignInRequest, SignUpRequest, UserProfile},
errors::UserError,
event::UserEvent::{SignIn, SignOut, SignUp},
};
use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes};
use lib_infra::{kv::KV, uuid};
use std::{fs, path::PathBuf, sync::Arc};
pub struct WorkspaceTest {
pub sdk: FlowySDKTest,
pub workspace: Workspace,
}
impl WorkspaceTest {
pub async fn new() -> Self {
let sdk = FlowySDKTest::setup();
let _ = sdk.init_user().await;
let workspace = create_workspace(&sdk, "Workspace", "").await;
open_workspace(&sdk, &workspace.id).await;
Self { sdk, workspace }
}
}
pub struct AppTest {
pub sdk: FlowySDKTest,
pub workspace: Workspace,
pub app: App,
}
impl AppTest {
pub async fn new() -> Self {
let sdk = FlowySDKTest::setup();
let _ = sdk.init_user().await;
let workspace = create_workspace(&sdk, "Workspace", "").await;
open_workspace(&sdk, &workspace.id).await;
let app = create_app(&sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
Self { sdk, workspace, app }
}
pub async fn move_app_to_trash(&self) {
let request = UpdateAppRequest {
app_id: self.app.id.clone(),
name: None,
desc: None,
color_style: None,
is_trash: Some(true),
};
update_app(&self.sdk, request).await;
}
}
pub struct ViewTest {
pub sdk: FlowySDKTest,
pub workspace: Workspace,
pub app: App,
pub view: View,
}
impl ViewTest {
pub async fn new(sdk: &FlowySDKTest) -> Self {
let workspace = create_workspace(&sdk, "Workspace", "").await;
open_workspace(&sdk, &workspace.id).await;
let app = create_app(&sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
let view = create_view(&sdk, &app.id).await;
Self {
sdk: sdk.clone(),
workspace,
app,
view,
}
}
pub async fn delete_views(&self, view_ids: Vec<String>) {
let request = QueryViewRequest { view_ids };
delete_view(&self.sdk, request).await;
}
pub async fn delete_views_permanent(&self, view_ids: Vec<String>) {
let request = QueryViewRequest { view_ids };
delete_view(&self.sdk, request).await;
CoreModuleEventBuilder::new(self.sdk.clone())
.event(DeleteAll)
.async_send()
.await;
}
}
pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
vec![
("".to_owned(), ErrorCode::WorkspaceNameInvalid),
("1234".repeat(100), ErrorCode::WorkspaceNameTooLong),
]
}
pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace {
let request = CreateWorkspaceRequest {
name: name.to_owned(),
desc: desc.to_owned(),
};
let workspace = CoreModuleEventBuilder::new(sdk.clone())
.event(CreateWorkspace)
.request(request)
.async_send()
.await
.parse::<Workspace>();
workspace
}
async fn open_workspace(sdk: &FlowySDKTest, workspace_id: &str) {
let request = QueryWorkspaceRequest {
workspace_id: Some(workspace_id.to_owned()),
};
let _ = CoreModuleEventBuilder::new(sdk.clone())
.event(OpenWorkspace)
.request(request)
.async_send()
.await;
}
pub async fn read_workspace(sdk: &FlowySDKTest, request: QueryWorkspaceRequest) -> Vec<Workspace> {
let repeated_workspace = CoreModuleEventBuilder::new(sdk.clone())
.event(ReadWorkspaces)
.request(request.clone())
.async_send()
.await
.parse::<RepeatedWorkspace>();
let workspaces;
if let Some(workspace_id) = &request.workspace_id {
workspaces = repeated_workspace
.into_inner()
.into_iter()
.filter(|workspace| &workspace.id == workspace_id)
.collect::<Vec<Workspace>>();
debug_assert_eq!(workspaces.len(), 1);
} else {
workspaces = repeated_workspace.items;
}
workspaces
}
pub async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &str) -> App {
let create_app_request = CreateAppRequest {
workspace_id: workspace_id.to_owned(),
name: name.to_string(),
desc: desc.to_string(),
color_style: Default::default(),
};
let app = CoreModuleEventBuilder::new(sdk.clone())
.event(CreateApp)
.request(create_app_request)
.async_send()
.await
.parse::<App>();
app
}
pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
let delete_app_request = AppIdentifier {
app_id: app_id.to_string(),
};
CoreModuleEventBuilder::new(sdk.clone())
.event(DeleteApp)
.request(delete_app_request)
.async_send()
.await;
}
pub async fn update_app(sdk: &FlowySDKTest, request: UpdateAppRequest) {
CoreModuleEventBuilder::new(sdk.clone())
.event(UpdateApp)
.request(request)
.async_send()
.await;
}
pub async fn read_app(sdk: &FlowySDKTest, request: QueryAppRequest) -> App {
let app = CoreModuleEventBuilder::new(sdk.clone())
.event(ReadApp)
.request(request)
.async_send()
.await
.parse::<App>();
app
}
pub async fn create_view_with_request(sdk: &FlowySDKTest, request: CreateViewRequest) -> View {
let view = CoreModuleEventBuilder::new(sdk.clone())
.event(CreateView)
.request(request)
.async_send()
.await
.parse::<View>();
view
}
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View {
let request = CreateViewRequest {
belong_to_id: app_id.to_string(),
name: "View A".to_string(),
desc: "".to_string(),
thumbnail: Some("http://1.png".to_string()),
view_type: ViewType::Doc,
};
create_view_with_request(sdk, request).await
}
pub async fn update_view(sdk: &FlowySDKTest, request: UpdateViewRequest) {
CoreModuleEventBuilder::new(sdk.clone())
.event(UpdateView)
.request(request)
.async_send()
.await;
}
pub async fn read_view(sdk: &FlowySDKTest, request: QueryViewRequest) -> View {
CoreModuleEventBuilder::new(sdk.clone())
.event(ReadView)
.request(request)
.async_send()
.await
.parse::<View>()
}
pub async fn delete_view(sdk: &FlowySDKTest, request: QueryViewRequest) {
CoreModuleEventBuilder::new(sdk.clone())
.event(DeleteView)
.request(request)
.async_send()
.await;
}
pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash {
CoreModuleEventBuilder::new(sdk.clone())
.event(ReadTrash)
.async_send()
.await
.parse::<RepeatedTrash>()
}
pub async fn putback_trash(sdk: &FlowySDKTest, id: TrashIdentifier) {
CoreModuleEventBuilder::new(sdk.clone())
.event(PutbackTrash)
.request(id)
.async_send()
.await;
}
pub async fn open_view(sdk: &FlowySDKTest, request: QueryViewRequest) -> Doc {
CoreModuleEventBuilder::new(sdk.clone())
.event(OpenView)
.request(request)
.async_send()
.await
.parse::<Doc>()
}
pub fn root_dir() -> String {
// https://doc.rust-lang.org/cargo/reference/environment-variables.html
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "./".to_owned());

View File

@ -1,6 +1,6 @@
pub mod builder;
mod helper;
pub mod workspace;
pub mod editor;
pub mod event_builder;
pub mod helper;
use crate::helper::*;
use backend_service::configuration::{get_client_server_configuration, ClientServerConfiguration};
@ -9,40 +9,40 @@ use flowy_user::entities::UserProfile;
use lib_infra::uuid;
pub mod prelude {
pub use crate::{builder::*, helper::*, *};
pub use crate::{event_builder::*, helper::*, *};
pub use lib_dispatch::prelude::*;
}
pub type FlowyTestSDK = FlowySDK;
#[derive(Clone)]
pub struct FlowyTest {
pub sdk: FlowyTestSDK,
pub struct FlowySDKTest(pub FlowySDK);
impl std::ops::Deref for FlowySDKTest {
type Target = FlowySDK;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl FlowyTest {
impl FlowySDKTest {
pub fn setup() -> Self {
let server_config = get_client_server_configuration().unwrap();
let test = Self::setup_with(server_config);
std::mem::forget(test.sdk.dispatcher());
test
}
pub async fn sign_up(&self) -> SignUpContext {
let context = async_sign_up(self.sdk.dispatcher()).await;
context
}
pub async fn init_user(&self) -> UserProfile {
let context = async_sign_up(self.sdk.dispatcher()).await;
context.user_profile
let sdk = Self::setup_with(server_config);
std::mem::forget(sdk.dispatcher());
sdk
}
pub fn setup_with(server_config: ClientServerConfiguration) -> Self {
let config = FlowySDKConfig::new(&root_dir(), server_config, &uuid()).log_filter("debug");
let sdk = FlowySDK::new(config);
Self { sdk }
Self(sdk)
}
pub fn sdk(&self) -> FlowyTestSDK { self.sdk.clone() }
pub async fn sign_up(&self) -> SignUpContext {
let context = async_sign_up(self.0.dispatcher()).await;
context
}
pub async fn init_user(&self) -> UserProfile {
let context = async_sign_up(self.0.dispatcher()).await;
context.user_profile
}
}

View File

@ -1,276 +0,0 @@
use crate::prelude::*;
use flowy_core::{
entities::{
app::*,
trash::{RepeatedTrash, TrashIdentifier},
view::*,
workspace::*,
},
errors::ErrorCode,
event::WorkspaceEvent::*,
};
use flowy_document_infra::entities::doc::Doc;
pub struct WorkspaceTest {
pub sdk: FlowyTestSDK,
pub workspace: Workspace,
}
impl WorkspaceTest {
pub async fn new() -> Self {
let test = FlowyTest::setup();
let _ = test.init_user().await;
let workspace = create_workspace(&test.sdk, "Workspace", "").await;
open_workspace(&test.sdk, &workspace.id).await;
Self {
sdk: test.sdk,
workspace,
}
}
}
pub struct AppTest {
pub sdk: FlowyTestSDK,
pub workspace: Workspace,
pub app: App,
}
impl AppTest {
pub async fn new() -> Self {
let test = FlowyTest::setup();
let _ = test.init_user().await;
let workspace = create_workspace(&test.sdk, "Workspace", "").await;
open_workspace(&test.sdk, &workspace.id).await;
let app = create_app(&test.sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
Self {
sdk: test.sdk,
workspace,
app,
}
}
pub async fn move_app_to_trash(&self) {
let request = UpdateAppRequest {
app_id: self.app.id.clone(),
name: None,
desc: None,
color_style: None,
is_trash: Some(true),
};
update_app(&self.sdk, request).await;
}
}
pub struct ViewTest {
pub sdk: FlowyTestSDK,
pub workspace: Workspace,
pub app: App,
pub view: View,
}
impl ViewTest {
pub async fn new(test: &FlowyTest) -> Self {
let workspace = create_workspace(&test.sdk, "Workspace", "").await;
open_workspace(&test.sdk, &workspace.id).await;
let app = create_app(&test.sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
let view = create_view(&test.sdk, &app.id).await;
Self {
sdk: test.sdk.clone(),
workspace,
app,
view,
}
}
pub async fn delete_views(&self, view_ids: Vec<String>) {
let request = QueryViewRequest { view_ids };
delete_view(&self.sdk, request).await;
}
pub async fn delete_views_permanent(&self, view_ids: Vec<String>) {
let request = QueryViewRequest { view_ids };
delete_view(&self.sdk, request).await;
FlowyWorkspaceTest::new(self.sdk.clone())
.event(DeleteAll)
.async_send()
.await;
}
}
pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
vec![
("".to_owned(), ErrorCode::WorkspaceNameInvalid),
("1234".repeat(100), ErrorCode::WorkspaceNameTooLong),
]
}
pub async fn create_workspace(sdk: &FlowyTestSDK, name: &str, desc: &str) -> Workspace {
let request = CreateWorkspaceRequest {
name: name.to_owned(),
desc: desc.to_owned(),
};
let workspace = FlowyWorkspaceTest::new(sdk.clone())
.event(CreateWorkspace)
.request(request)
.async_send()
.await
.parse::<Workspace>();
workspace
}
async fn open_workspace(sdk: &FlowyTestSDK, workspace_id: &str) {
let request = QueryWorkspaceRequest {
workspace_id: Some(workspace_id.to_owned()),
};
let _ = FlowyWorkspaceTest::new(sdk.clone())
.event(OpenWorkspace)
.request(request)
.async_send()
.await;
}
pub async fn read_workspace(sdk: &FlowyTestSDK, request: QueryWorkspaceRequest) -> Vec<Workspace> {
let repeated_workspace = FlowyWorkspaceTest::new(sdk.clone())
.event(ReadWorkspaces)
.request(request.clone())
.async_send()
.await
.parse::<RepeatedWorkspace>();
let workspaces;
if let Some(workspace_id) = &request.workspace_id {
workspaces = repeated_workspace
.into_inner()
.into_iter()
.filter(|workspace| &workspace.id == workspace_id)
.collect::<Vec<Workspace>>();
debug_assert_eq!(workspaces.len(), 1);
} else {
workspaces = repeated_workspace.items;
}
workspaces
}
pub async 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(),
desc: desc.to_string(),
color_style: Default::default(),
};
let app = FlowyWorkspaceTest::new(sdk.clone())
.event(CreateApp)
.request(create_app_request)
.async_send()
.await
.parse::<App>();
app
}
pub async fn delete_app(sdk: &FlowyTestSDK, app_id: &str) {
let delete_app_request = AppIdentifier {
app_id: app_id.to_string(),
};
FlowyWorkspaceTest::new(sdk.clone())
.event(DeleteApp)
.request(delete_app_request)
.async_send()
.await;
}
pub async fn update_app(sdk: &FlowyTestSDK, request: UpdateAppRequest) {
FlowyWorkspaceTest::new(sdk.clone())
.event(UpdateApp)
.request(request)
.async_send()
.await;
}
pub async fn read_app(sdk: &FlowyTestSDK, request: QueryAppRequest) -> App {
let app = FlowyWorkspaceTest::new(sdk.clone())
.event(ReadApp)
.request(request)
.async_send()
.await
.parse::<App>();
app
}
pub async fn create_view_with_request(sdk: &FlowyTestSDK, request: CreateViewRequest) -> View {
let view = FlowyWorkspaceTest::new(sdk.clone())
.event(CreateView)
.request(request)
.async_send()
.await
.parse::<View>();
view
}
pub async fn create_view(sdk: &FlowyTestSDK, app_id: &str) -> View {
let request = CreateViewRequest {
belong_to_id: app_id.to_string(),
name: "View A".to_string(),
desc: "".to_string(),
thumbnail: Some("http://1.png".to_string()),
view_type: ViewType::Doc,
};
create_view_with_request(sdk, request).await
}
pub async fn update_view(sdk: &FlowyTestSDK, request: UpdateViewRequest) {
FlowyWorkspaceTest::new(sdk.clone())
.event(UpdateView)
.request(request)
.async_send()
.await;
}
pub async fn read_view(sdk: &FlowyTestSDK, request: QueryViewRequest) -> View {
FlowyWorkspaceTest::new(sdk.clone())
.event(ReadView)
.request(request)
.async_send()
.await
.parse::<View>()
}
pub async fn delete_view(sdk: &FlowyTestSDK, request: QueryViewRequest) {
FlowyWorkspaceTest::new(sdk.clone())
.event(DeleteView)
.request(request)
.async_send()
.await;
}
pub async fn read_trash(sdk: &FlowyTestSDK) -> RepeatedTrash {
FlowyWorkspaceTest::new(sdk.clone())
.event(ReadTrash)
.async_send()
.await
.parse::<RepeatedTrash>()
}
pub async fn putback_trash(sdk: &FlowyTestSDK, id: TrashIdentifier) {
FlowyWorkspaceTest::new(sdk.clone())
.event(PutbackTrash)
.request(id)
.async_send()
.await;
}
pub async fn open_view(sdk: &FlowyTestSDK, request: QueryViewRequest) -> Doc {
FlowyWorkspaceTest::new(sdk.clone())
.event(OpenView)
.request(request)
.async_send()
.await
.parse::<Doc>()
}