Ver Fonte

config doc create test

appflowy há 3 anos atrás
pai
commit
68df54e9f2

+ 29 - 45
backend/tests/api/auth.rs

@@ -1,9 +1,9 @@
-use crate::helper::{spawn_app, TestApp};
+use crate::helper::{spawn_server, TestServer};
 use flowy_user::entities::{SignInParams, SignUpParams, SignUpResponse, UpdateUserParams};
 
 #[actix_rt::test]
 async fn user_register() {
-    let app = spawn_app().await;
+    let app = spawn_server().await;
     let response = register_user(&app, "[email protected]", "HelloWorld123!").await;
     log::info!("{:?}", response);
 }
@@ -11,7 +11,7 @@ async fn user_register() {
 #[actix_rt::test]
 #[should_panic]
 async fn user_sign_in_with_invalid_password() {
-    let app = spawn_app().await;
+    let app = spawn_server().await;
     let email = "[email protected]";
     let password = "123";
     let _ = register_user(&app, email, password).await;
@@ -20,7 +20,7 @@ async fn user_sign_in_with_invalid_password() {
 #[actix_rt::test]
 #[should_panic]
 async fn user_sign_in_with_invalid_email() {
-    let app = spawn_app().await;
+    let app = spawn_server().await;
     let email = "annie@gmail@";
     let password = "HelloWorld123!";
     let _ = register_user(&app, email, password).await;
@@ -28,7 +28,7 @@ async fn user_sign_in_with_invalid_email() {
 
 #[actix_rt::test]
 async fn user_sign_in() {
-    let app = spawn_app().await;
+    let app = spawn_server().await;
     let email = "[email protected]";
     let password = "HelloWorld123!";
     let _ = register_user(&app, email, password).await;
@@ -42,48 +42,37 @@ async fn user_sign_in() {
 #[actix_rt::test]
 #[should_panic]
 async fn user_sign_out() {
-    let app = spawn_app().await;
-    let email = "[email protected]";
-    let password = "HelloWorld123!";
-    let _ = register_user(&app, email, password).await;
-
-    let params = SignInParams {
-        email: email.to_string(),
-        password: password.to_string(),
-    };
-    let sign_in_resp = app.sign_in(params).await.unwrap();
-    let token = sign_in_resp.token.clone();
-    app.sign_out(&token).await;
+    let server = TestServer::new().await;
+    server.sign_out().await;
 
     // user_detail will be empty because use was sign out.
-    app.get_user_profile(&token).await;
+    server.get_user_profile().await;
 }
 
 #[actix_rt::test]
 async fn user_get_detail() {
-    let app = spawn_app().await;
-    let sign_up_resp = sign_up_user(&app).await;
-    log::info!("{:?}", app.get_user_profile(&sign_up_resp.token).await);
+    let server = TestServer::new().await;
+    log::info!("{:?}", server.get_user_profile().await);
 }
 
 #[actix_rt::test]
 async fn user_update_password() {
-    let app = spawn_app().await;
+    let mut server = spawn_server().await;
     let email = "[email protected]";
     let password = "HelloWorld123!";
-    let sign_up_resp = register_user(&app, email, password).await;
+    let sign_up_resp = register_user(&server, email, password).await;
 
     let params = UpdateUserParams::new(&sign_up_resp.user_id).password("Hello123!");
-    app.update_user_profile(&sign_up_resp.token, params)
-        .await
-        .unwrap();
+    server.user_token = Some(sign_up_resp.token);
+
+    server.update_user_profile(params).await.unwrap();
 
     let sign_in_params = SignInParams {
         email: email.to_string(),
         password: password.to_string(),
     };
 
-    match app.sign_in(sign_in_params).await {
+    match server.sign_in(sign_in_params).await {
         Ok(_) => {},
         Err(e) => {
             assert_eq!(e.code, flowy_user::errors::ErrorCode::PasswordNotMatch);
@@ -93,46 +82,41 @@ async fn user_update_password() {
 
 #[actix_rt::test]
 async fn user_update_name() {
-    let app = spawn_app().await;
-    let sign_up_resp = sign_up_user(&app).await;
+    let server = TestServer::new().await;
+
     let name = "tom".to_string();
-    let params = UpdateUserParams::new(&sign_up_resp.user_id).name(&name);
-    app.update_user_profile(&sign_up_resp.token, params)
-        .await
-        .unwrap();
+    let params = UpdateUserParams::new(&server.user_id()).name(&name);
+    server.update_user_profile(params).await.unwrap();
 
-    let user = app.get_user_profile(&sign_up_resp.token).await;
+    let user = server.get_user_profile().await;
     assert_eq!(user.name, name);
 }
 
 #[actix_rt::test]
 async fn user_update_email() {
-    let app = spawn_app().await;
-    let sign_up_resp = sign_up_user(&app).await;
+    let server = TestServer::new().await;
     let email = "[email protected]".to_string();
-    let params = UpdateUserParams::new(&sign_up_resp.user_id).email(&email);
-    app.update_user_profile(&sign_up_resp.token, params)
-        .await
-        .unwrap();
+    let params = UpdateUserParams::new(server.user_id()).email(&email);
+    server.update_user_profile(params).await.unwrap();
 
-    let user = app.get_user_profile(&sign_up_resp.token).await;
+    let user = server.get_user_profile().await;
     assert_eq!(user.email, email);
 }
 
-async fn sign_up_user(app: &TestApp) -> SignUpResponse {
+async fn sign_up_user(server: &TestServer) -> SignUpResponse {
     let email = "[email protected]";
     let password = "HelloWorld123!";
-    let response = register_user(&app, email, password).await;
+    let response = register_user(server, email, password).await;
     response
 }
 
-async fn register_user(app: &TestApp, email: &str, password: &str) -> SignUpResponse {
+async fn register_user(server: &TestServer, email: &str, password: &str) -> SignUpResponse {
     let params = SignUpParams {
         email: email.to_string(),
         name: "annie".to_string(),
         password: password.to_string(),
     };
 
-    let response = app.register_user(params).await;
+    let response = server.register(params).await;
     response
 }

+ 8 - 0
backend/tests/api/doc.rs

@@ -0,0 +1,8 @@
+use crate::helper::DocTest;
+
+#[actix_rt::test]
+async fn doc_create() {
+    let test = DocTest::new().await;
+
+    log::info!("{:?}", test.doc);
+}

+ 232 - 49
backend/tests/api/helper.rs

@@ -3,22 +3,30 @@ use backend::{
     config::{get_configuration, DatabaseSettings},
 };
 
+use flowy_document::{
+    entities::doc::{CreateDocParams, Doc},
+    prelude::*,
+};
 use flowy_user::{errors::UserError, prelude::*};
 use flowy_workspace::prelude::{server::*, *};
 use sqlx::{Connection, Executor, PgConnection, PgPool};
 use uuid::Uuid;
 
-pub struct TestApp {
+pub struct TestServer {
     pub address: String,
     pub port: u16,
     pub pg_pool: PgPool,
+    pub user_token: Option<String>,
+    pub user_id: Option<String>,
 }
 
-impl TestApp {
-    pub async fn register_user(&self, params: SignUpParams) -> SignUpResponse {
-        let url = format!("{}/api/register", self.address);
-        let resp = user_sign_up_request(params, &url).await.unwrap();
-        resp
+impl TestServer {
+    pub async fn new() -> Self {
+        let mut server = spawn_server().await;
+        let response = server.register_user().await;
+        server.user_token = Some(response.token);
+        server.user_id = Some(response.user_id);
+        server
     }
 
     pub async fn sign_in(&self, params: SignInParams) -> Result<SignInResponse, UserError> {
@@ -26,109 +34,152 @@ impl TestApp {
         user_sign_in_request(params, &url).await
     }
 
-    pub async fn sign_out(&self, token: &str) {
+    pub async fn sign_out(&self) {
         let url = format!("{}/api/auth", self.address);
-        let _ = user_sign_out_request(token, &url).await.unwrap();
+        let _ = user_sign_out_request(self.user_token(), &url)
+            .await
+            .unwrap();
+    }
+
+    pub fn user_token(&self) -> &str {
+        self.user_token
+            .as_ref()
+            .expect("must call register_user first ")
+    }
+
+    pub fn user_id(&self) -> &str {
+        self.user_id
+            .as_ref()
+            .expect("must call register_user first ")
     }
 
-    pub async fn get_user_profile(&self, token: &str) -> UserProfile {
+    pub async fn get_user_profile(&self) -> UserProfile {
         let url = format!("{}/api/user", self.address);
-        let user_profile = get_user_profile_request(token, &url).await.unwrap();
+        let user_profile = get_user_profile_request(self.user_token(), &url)
+            .await
+            .unwrap();
         user_profile
     }
 
-    pub async fn update_user_profile(
-        &self,
-        token: &str,
-        params: UpdateUserParams,
-    ) -> Result<(), UserError> {
+    pub async fn update_user_profile(&self, params: UpdateUserParams) -> Result<(), UserError> {
         let url = format!("{}/api/user", self.address);
-        update_user_profile_request(token, params, &url).await
+        update_user_profile_request(self.user_token(), params, &url).await
     }
 
-    pub async fn create_workspace(&self, params: CreateWorkspaceParams, token: &str) -> Workspace {
+    pub async fn create_workspace(&self, params: CreateWorkspaceParams) -> Workspace {
         let url = format!("{}/api/workspace", self.address);
-        let workspace = create_workspace_request(token, params, &url).await.unwrap();
+        let workspace = create_workspace_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         workspace
     }
 
-    pub async fn read_workspaces(
-        &self,
-        params: QueryWorkspaceParams,
-        token: &str,
-    ) -> RepeatedWorkspace {
+    pub async fn read_workspaces(&self, params: QueryWorkspaceParams) -> RepeatedWorkspace {
         let url = format!("{}/api/workspace", self.address);
-        let workspaces = read_workspaces_request(token, params, &url).await.unwrap();
+        let workspaces = read_workspaces_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         workspaces
     }
 
-    pub async fn update_workspace(&self, params: UpdateWorkspaceParams, token: &str) {
+    pub async fn update_workspace(&self, params: UpdateWorkspaceParams) {
         let url = format!("{}/api/workspace", self.address);
-        update_workspace_request(token, params, &url).await.unwrap();
+        update_workspace_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub async fn delete_workspace(&self, params: DeleteWorkspaceParams, token: &str) {
+    pub async fn delete_workspace(&self, params: DeleteWorkspaceParams) {
         let url = format!("{}/api/workspace", self.address);
-        delete_workspace_request(token, params, &url).await.unwrap();
+        delete_workspace_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub async fn create_app(&self, params: CreateAppParams, token: &str) -> App {
+    pub async fn create_app(&self, params: CreateAppParams) -> App {
         let url = format!("{}/api/app", self.address);
-        let app = create_app_request(token, params, &url).await.unwrap();
+        let app = create_app_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         app
     }
 
-    pub async fn read_app(&self, params: QueryAppParams, token: &str) -> Option<App> {
+    pub async fn read_app(&self, params: QueryAppParams) -> Option<App> {
         let url = format!("{}/api/app", self.address);
-        let app = read_app_request(token, params, &url).await.unwrap();
+        let app = read_app_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         app
     }
 
-    pub async fn update_app(&self, params: UpdateAppParams, token: &str) {
+    pub async fn update_app(&self, params: UpdateAppParams) {
         let url = format!("{}/api/app", self.address);
-        update_app_request(token, params, &url).await.unwrap();
+        update_app_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub async fn delete_app(&self, params: DeleteAppParams, token: &str) {
+    pub async fn delete_app(&self, params: DeleteAppParams) {
         let url = format!("{}/api/app", self.address);
-        delete_app_request(token, params, &url).await.unwrap();
+        delete_app_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub async fn create_view(&self, params: CreateViewParams, token: &str) -> View {
+    pub async fn create_view(&self, params: CreateViewParams) -> View {
         let url = format!("{}/api/view", self.address);
-        let view = create_view_request(token, params, &url).await.unwrap();
+        let view = create_view_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         view
     }
 
-    pub async fn read_view(&self, params: QueryViewParams, token: &str) -> Option<View> {
+    pub async fn read_view(&self, params: QueryViewParams) -> Option<View> {
         let url = format!("{}/api/view", self.address);
-        let view = read_view_request(token, params, &url).await.unwrap();
+        let view = read_view_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
         view
     }
 
-    pub async fn update_view(&self, params: UpdateViewParams, token: &str) {
+    pub async fn update_view(&self, params: UpdateViewParams) {
         let url = format!("{}/api/view", self.address);
-        update_view_request(token, params, &url).await.unwrap();
+        update_view_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub async fn delete_view(&self, params: DeleteViewParams, token: &str) {
+    pub async fn delete_view(&self, params: DeleteViewParams) {
         let url = format!("{}/api/view", self.address);
-        delete_view_request(token, params, &url).await.unwrap();
+        delete_view_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
     }
 
-    pub(crate) async fn register_test_user(&self) -> SignUpResponse {
+    pub async fn create_doc(&self, params: CreateDocParams) {
+        let url = format!("{}/api/doc", self.address);
+        let _ = create_doc_request(self.user_token(), params, &url)
+            .await
+            .unwrap();
+    }
+
+    pub(crate) async fn register_user(&self) -> SignUpResponse {
         let params = SignUpParams {
             email: "[email protected]".to_string(),
             name: "annie".to_string(),
             password: "HelloAppFlowy123!".to_string(),
         };
 
-        let response = self.register_user(params).await;
+        self.register(params).await
+    }
+
+    pub(crate) async fn register(&self, params: SignUpParams) -> SignUpResponse {
+        let url = format!("{}/api/register", self.address);
+        let response = user_sign_up_request(params, &url).await.unwrap();
         response
     }
 }
-
-pub async fn spawn_app() -> TestApp {
+pub async fn spawn_server() -> TestServer {
     let database_name = format!("{}", Uuid::new_v4().to_string());
     let configuration = {
         let mut c = get_configuration().expect("Failed to read configuration.");
@@ -149,12 +200,14 @@ pub async fn spawn_app() -> TestApp {
         // drop_test_database(database_name).await;
     });
 
-    TestApp {
+    TestServer {
         address: format!("http://localhost:{}", application_port),
         port: application_port,
         pg_pool: get_connection_pool(&configuration.database)
             .await
             .expect("Failed to connect to the database"),
+        user_token: None,
+        user_id: None,
     }
 }
 
@@ -200,3 +253,133 @@ async fn drop_test_database(database_name: String) {
         .await
         .expect("Failed to drop database.");
 }
+
+pub(crate) async fn create_test_workspace(server: &TestServer) -> Workspace {
+    let params = CreateWorkspaceParams {
+        name: "My first workspace".to_string(),
+        desc: "This is my first workspace".to_string(),
+    };
+
+    let workspace = server.create_workspace(params).await;
+    workspace
+}
+
+pub(crate) async fn create_test_app(server: &TestServer, workspace_id: &str) -> App {
+    let params = CreateAppParams {
+        workspace_id: workspace_id.to_owned(),
+        name: "My first app".to_string(),
+        desc: "This is my first app".to_string(),
+        color_style: ColorStyle::default(),
+    };
+
+    let app = server.create_app(params).await;
+    app
+}
+
+pub(crate) async fn create_test_view(application: &TestServer, app_id: &str) -> View {
+    let params = CreateViewParams {
+        belong_to_id: app_id.to_string(),
+        name: "My first view".to_string(),
+        desc: "This is my first view".to_string(),
+        thumbnail: "http://1.png".to_string(),
+        view_type: ViewType::Doc,
+    };
+    let app = application.create_view(params).await;
+    app
+}
+
+pub(crate) async fn create_test_doc(server: &TestServer, view_id: &str, data: &str) -> Doc {
+    let params = CreateDocParams {
+        id: view_id.to_string(),
+        data: data.to_string(),
+    };
+    let doc = Doc {
+        id: params.id.clone(),
+        data: params.data.clone(),
+    };
+    let _ = server.create_doc(params).await;
+    doc
+}
+
+pub struct WorkspaceTest {
+    pub server: TestServer,
+    pub workspace: Workspace,
+}
+
+impl WorkspaceTest {
+    pub async fn new() -> Self {
+        let server = TestServer::new().await;
+        let workspace = create_test_workspace(&server).await;
+        Self { server, workspace }
+    }
+
+    pub async fn create_app(&self) -> App {
+        create_test_app(&self.server, &self.workspace.id).await
+    }
+}
+
+pub struct AppTest {
+    pub server: TestServer,
+    pub workspace: Workspace,
+    pub app: App,
+}
+
+impl AppTest {
+    pub async fn new() -> Self {
+        let server = TestServer::new().await;
+        let workspace = create_test_workspace(&server).await;
+        let app = create_test_app(&server, &workspace.id).await;
+        Self {
+            server,
+            workspace,
+            app,
+        }
+    }
+}
+
+pub struct ViewTest {
+    pub server: TestServer,
+    pub workspace: Workspace,
+    pub app: App,
+    pub view: View,
+}
+
+impl ViewTest {
+    pub async fn new() -> Self {
+        let server = TestServer::new().await;
+        let workspace = create_test_workspace(&server).await;
+        let app = create_test_app(&server, &workspace.id).await;
+        let view = create_test_view(&server, &app.id).await;
+        Self {
+            server,
+            workspace,
+            app,
+            view,
+        }
+    }
+}
+
+pub struct DocTest {
+    pub server: TestServer,
+    pub workspace: Workspace,
+    pub app: App,
+    pub view: View,
+    pub doc: Doc,
+}
+
+impl DocTest {
+    pub async fn new() -> Self {
+        let server = TestServer::new().await;
+        let workspace = create_test_workspace(&server).await;
+        let app = create_test_app(&server, &workspace.id).await;
+        let view = create_test_view(&server, &app.id).await;
+        let doc = create_test_doc(&server, &view.id, "").await;
+        Self {
+            server,
+            workspace,
+            app,
+            view,
+            doc,
+        }
+    }
+}

+ 81 - 148
backend/tests/api/workspace.rs

@@ -1,6 +1,6 @@
-use crate::helper::{spawn_app, TestApp};
+use crate::helper::*;
 use flowy_workspace::entities::{
-    app::{App, ColorStyle, CreateAppParams, DeleteAppParams, QueryAppParams, UpdateAppParams},
+    app::{DeleteAppParams, QueryAppParams, UpdateAppParams},
     view::{CreateViewParams, DeleteViewParams, QueryViewParams, UpdateViewParams, View, ViewType},
     workspace::{
         CreateWorkspaceParams,
@@ -13,246 +13,179 @@ use flowy_workspace::entities::{
 
 #[actix_rt::test]
 async fn workspace_create() {
-    let app = spawn_app().await;
-    let (workspace, _) = create_test_workspace(&app).await;
-    log::info!("{:?}", workspace);
+    let test = WorkspaceTest::new().await;
+    log::info!("{:?}", test.workspace);
 }
 
 #[actix_rt::test]
 async fn workspace_read() {
-    let app = spawn_app().await;
-    let (workspace_1, token) = create_test_workspace(&app).await;
-    let read_params = QueryWorkspaceParams::new().workspace_id(&workspace_1.id);
-    log::info!("{:?}", app.read_workspaces(read_params, &token).await);
+    let test = WorkspaceTest::new().await;
+    let read_params = QueryWorkspaceParams::new().workspace_id(&test.workspace.id);
+    log::info!("{:?}", test.server.read_workspaces(read_params).await);
 }
 
 #[actix_rt::test]
 async fn workspace_read_with_belongs() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let _ = create_test_app(&application, &workspace.id, &token).await;
-    let _ = create_test_app(&application, &workspace.id, &token).await;
-    let _ = create_test_app(&application, &workspace.id, &token).await;
-
-    let read_params = QueryWorkspaceParams::new().workspace_id(&workspace.id);
-    let workspaces = application.read_workspaces(read_params, &token).await;
+    let test = WorkspaceTest::new().await;
+
+    let _ = test.create_app().await;
+    let _ = test.create_app().await;
+    let _ = test.create_app().await;
+
+    let read_params = QueryWorkspaceParams::new().workspace_id(&test.workspace.id);
+    let workspaces = test.server.read_workspaces(read_params).await;
     let workspace = workspaces.items.first().unwrap();
     assert_eq!(workspace.apps.len(), 3);
 }
 
 #[actix_rt::test]
 async fn workspace_update() {
-    let app = spawn_app().await;
-    let (workspace_1, token) = create_test_workspace(&app).await;
+    let test = WorkspaceTest::new().await;
+    let new_name = "rename workspace name";
+    let new_desc = "rename workspace description";
+
     let update_params = UpdateWorkspaceParams {
-        id: workspace_1.id.clone(),
-        name: Some("workspace 2".to_string()),
-        desc: Some("rename workspace description".to_string()),
+        id: test.workspace.id.clone(),
+        name: Some(new_name.to_string()),
+        desc: Some(new_desc.to_string()),
     };
-    app.update_workspace(update_params, &token).await;
+    test.server.update_workspace(update_params).await;
+    let read_params = QueryWorkspaceParams::new().workspace_id(&test.workspace.id);
+    let repeated_workspace = test.server.read_workspaces(read_params).await;
 
-    let read_params = QueryWorkspaceParams::new().workspace_id(&workspace_1.id);
-    let workspace_2 = app.read_workspaces(read_params, &token).await;
-    log::info!("{:?}", workspace_2);
+    let workspace = repeated_workspace.first().unwrap();
+    assert_eq!(workspace.name, new_name);
+    assert_eq!(workspace.desc, new_desc);
 }
 
 #[actix_rt::test]
 async fn workspace_delete() {
-    let app = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&app).await;
+    let test = WorkspaceTest::new().await;
     let delete_params = DeleteWorkspaceParams {
-        workspace_id: workspace.id.clone(),
+        workspace_id: test.workspace.id.clone(),
     };
 
-    let _ = app.delete_workspace(delete_params, &token).await;
-    let read_params = QueryWorkspaceParams::new().workspace_id(&workspace.id);
-    let repeated_workspace = app.read_workspaces(read_params, &token).await;
+    let _ = test.server.delete_workspace(delete_params).await;
+    let read_params = QueryWorkspaceParams::new().workspace_id(&test.workspace.id);
+    let repeated_workspace = test.server.read_workspaces(read_params).await;
     assert_eq!(repeated_workspace.len(), 0);
 }
 
-async fn create_test_workspace(app: &TestApp) -> (Workspace, String) {
-    let response = app.register_test_user().await;
-
-    let params = CreateWorkspaceParams {
-        name: "My first workspace".to_string(),
-        desc: "This is my first workspace".to_string(),
-    };
-    let workspace = app.create_workspace(params, &response.token).await;
-    (workspace, response.token)
-}
-
 #[actix_rt::test]
 async fn app_create() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
-    log::info!("{:?}", app);
+    let test = AppTest::new().await;
+    log::info!("{:?}", test.app);
 }
 
 #[actix_rt::test]
 async fn app_read() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
-    let read_params = QueryAppParams::new(&app.id);
-    log::info!(
-        "{:?}",
-        application.read_app(read_params, &token).await.unwrap()
-    );
+    let test = AppTest::new().await;
+    let read_params = QueryAppParams::new(&test.app.id);
+    assert_eq!(test.server.read_app(read_params).await.is_some(), true);
 }
 
 #[actix_rt::test]
 async fn app_read_with_belongs() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
+    let test = AppTest::new().await;
 
-    let _ = create_test_view(&application, &app.id, &token).await;
-    let _ = create_test_view(&application, &app.id, &token).await;
+    let _ = create_test_view(&test.server, &test.app.id).await;
+    let _ = create_test_view(&test.server, &test.app.id).await;
 
-    let read_params = QueryAppParams::new(&app.id).read_belongings();
-    let app = application.read_app(read_params, &token).await.unwrap();
+    let read_params = QueryAppParams::new(&test.app.id).read_belongings();
+    let app = test.server.read_app(read_params).await.unwrap();
     assert_eq!(app.belongings.len(), 2);
 }
 
 #[actix_rt::test]
 async fn app_read_with_belongs_in_trash() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
+    let test = AppTest::new().await;
 
-    let _ = create_test_view(&application, &app.id, &token).await;
-    let view = create_test_view(&application, &app.id, &token).await;
+    let _ = create_test_view(&test.server, &test.app.id).await;
+    let view = create_test_view(&test.server, &test.app.id).await;
 
     let update_params = UpdateViewParams::new(&view.id).trash();
-    application.update_view(update_params, &token).await;
+    test.server.update_view(update_params).await;
 
-    let read_params = QueryAppParams::new(&app.id).read_belongings();
-    let app = application.read_app(read_params, &token).await.unwrap();
+    let read_params = QueryAppParams::new(&test.app.id).read_belongings();
+    let app = test.server.read_app(read_params).await.unwrap();
     assert_eq!(app.belongings.len(), 1);
 }
 
 #[actix_rt::test]
 async fn app_update() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
+    let test = AppTest::new().await;
 
-    let update_params = UpdateAppParams::new(&app.id).name("flowy");
-    application.update_app(update_params, &token).await;
+    let new_name = "flowy";
 
-    let read_params = QueryAppParams::new(&app.id);
-    let app = application.read_app(read_params, &token).await.unwrap();
-    log::info!("{:?}", app);
+    let update_params = UpdateAppParams::new(&test.app.id).name(new_name);
+    test.server.update_app(update_params).await;
+
+    let read_params = QueryAppParams::new(&test.app.id);
+    let app = test.server.read_app(read_params).await.unwrap();
+    assert_eq!(&app.name, new_name);
 }
 
 #[actix_rt::test]
 async fn app_delete() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
+    let test = AppTest::new().await;
 
     let delete_params = DeleteAppParams {
-        app_id: app.id.clone(),
-    };
-    application.delete_app(delete_params, &token).await;
-
-    let read_params = QueryAppParams::new(&app.id);
-    assert_eq!(
-        application.read_app(read_params, &token).await.is_none(),
-        true
-    );
-}
-
-async fn create_test_app(app: &TestApp, workspace_id: &str, token: &str) -> App {
-    let params = CreateAppParams {
-        workspace_id: workspace_id.to_owned(),
-        name: "My first app".to_string(),
-        desc: "This is my first app".to_string(),
-        color_style: ColorStyle::default(),
+        app_id: test.app.id.clone(),
     };
-
-    let app = app.create_app(params, token).await;
-    app
+    test.server.delete_app(delete_params).await;
+    let read_params = QueryAppParams::new(&test.app.id);
+    assert_eq!(test.server.read_app(read_params).await.is_none(), true);
 }
 
 #[actix_rt::test]
 async fn view_create() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
-
-    let view = create_test_view(&application, &app.id, &token).await;
-    log::info!("{:?}", view);
+    let test = ViewTest::new().await;
+    log::info!("{:?}", test.view);
 }
 
 #[actix_rt::test]
 async fn view_update() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
-    let view = create_test_view(&application, &app.id, &token).await;
+    let test = ViewTest::new().await;
+    let new_name = "name view name";
 
     // update
-    let update_params = UpdateViewParams::new(&view.id)
-        .trash()
-        .name("new view name");
-    application.update_view(update_params, &token).await;
+    let update_params = UpdateViewParams::new(&test.view.id).trash().name(new_name);
+    test.server.update_view(update_params).await;
 
     // read
-    let read_params = QueryViewParams::new(&view.id).trash();
-    let view = application.read_view(read_params, &token).await;
-    log::info!("{:?}", view);
+    let read_params = QueryViewParams::new(&test.view.id).trash();
+    let view = test.server.read_view(read_params).await.unwrap();
+    assert_eq!(&view.name, new_name);
 }
 
 #[actix_rt::test]
 async fn view_delete() {
-    let application = spawn_app().await;
-    let (workspace, token) = create_test_workspace(&application).await;
-    let app = create_test_app(&application, &workspace.id, &token).await;
-    let view = create_test_view(&application, &app.id, &token).await;
-
+    let test = ViewTest::new().await;
     // delete
     let delete_params = DeleteViewParams {
-        view_id: view.id.clone(),
+        view_id: test.view.id.clone(),
     };
-    application.delete_view(delete_params, &token).await;
+    test.server.delete_view(delete_params).await;
 
     // read
-    let read_params = QueryViewParams::new(&view.id).trash();
-    assert_eq!(
-        application.read_view(read_params, &token).await.is_none(),
-        true
-    );
-}
-
-async fn create_test_view(application: &TestApp, app_id: &str, token: &str) -> View {
-    let params = CreateViewParams {
-        belong_to_id: app_id.to_string(),
-        name: "My first view".to_string(),
-        desc: "This is my first view".to_string(),
-        thumbnail: "http://1.png".to_string(),
-        view_type: ViewType::Doc,
-    };
-    let app = application.create_view(params, token).await;
-    app
+    let read_params = QueryViewParams::new(&test.view.id).trash();
+    assert_eq!(test.server.read_view(read_params).await.is_none(), true);
 }
 
 #[actix_rt::test]
 async fn workspace_list_read() {
-    let application = spawn_app().await;
-    let response = application.register_test_user().await;
+    let mut server = spawn_server().await;
+    let token = server.register_user().await.token;
+    server.user_token = Some(token);
     for i in 0..3 {
         let params = CreateWorkspaceParams {
             name: format!("{} workspace", i),
             desc: format!("This is my {} workspace", i),
         };
-        let _ = application.create_workspace(params, &response.token).await;
+        let _ = server.create_workspace(params).await;
     }
 
     let read_params = QueryWorkspaceParams::new();
-    let workspaces = application
-        .read_workspaces(read_params, &response.token)
-        .await;
+    let workspaces = server.read_workspaces(read_params).await;
     assert_eq!(workspaces.len(), 4);
 }

+ 1 - 1
rust-lib/flowy-document/src/lib.rs

@@ -12,5 +12,5 @@ mod sql_tables;
 extern crate flowy_database;
 
 pub mod prelude {
-    pub use crate::module::*;
+    pub use crate::{module::*, services::server::*};
 }

+ 1 - 1
rust-lib/flowy-user/src/lib.rs

@@ -13,5 +13,5 @@ pub mod services;
 extern crate flowy_database;
 
 pub mod prelude {
-    pub use crate::{entities::*, services::user::*};
+    pub use crate::{entities::*, services::server::*};
 }

+ 1 - 1
rust-lib/flowy-user/src/services/mod.rs

@@ -1,2 +1,2 @@
-mod server;
+pub mod server;
 pub mod user;

+ 0 - 2
rust-lib/flowy-user/src/services/user/mod.rs

@@ -1,8 +1,6 @@
 pub use builder::*;
 pub use user_session::*;
 
-pub use crate::services::server::*;
-
 mod builder;
 pub mod database;
 mod user_session;

+ 5 - 2
rust-lib/flowy-user/src/services/user/user_session.rs

@@ -1,11 +1,14 @@
 use crate::{
     entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile},
     errors::{ErrorBuilder, ErrorCode, UserError},
-    services::user::{construct_user_server, database::UserDB},
+    services::user::database::UserDB,
     sql_tables::{UserTable, UserTableChangeset},
 };
 
-use crate::{observable::*, services::server::Server};
+use crate::{
+    observable::*,
+    services::server::{construct_user_server, Server},
+};
 use flowy_database::{
     query_dsl::*,
     schema::{user_table, user_table::dsl},