123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- use std::collections::HashMap;
- use assert_json_diff::assert_json_eq;
- use collab_database::rows::database_row_document_id_from_row_id;
- use collab_document::blocks::DocumentData;
- use collab_entity::CollabType;
- use collab_folder::core::FolderData;
- use nanoid::nanoid;
- use serde_json::json;
- use event_integration::document::document_event::DocumentEventTest;
- use event_integration::event_builder::EventBuilder;
- use event_integration::FlowyCoreTest;
- use flowy_core::DEFAULT_NAME;
- use flowy_encrypt::decrypt_text;
- use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
- use flowy_user::entities::{AuthTypePB, OauthSignInPB, UpdateUserProfilePayloadPB, UserProfilePB};
- use flowy_user::errors::ErrorCode;
- use flowy_user::event_map::UserEvent::*;
- use crate::util::*;
- #[tokio::test]
- async fn third_party_sign_up_test() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new();
- let mut map = HashMap::new();
- map.insert(USER_UUID.to_string(), uuid::Uuid::new_v4().to_string());
- map.insert(
- USER_EMAIL.to_string(),
- format!("{}@appflowy.io", nanoid!(6)),
- );
- let payload = OauthSignInPB {
- map,
- auth_type: AuthTypePB::Supabase,
- };
- let response = EventBuilder::new(test.clone())
- .event(OauthSignIn)
- .payload(payload)
- .async_send()
- .await
- .parse::<UserProfilePB>();
- dbg!(&response);
- }
- }
- #[tokio::test]
- async fn third_party_sign_up_with_encrypt_test() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new();
- test.supabase_party_sign_up().await;
- let user_profile = test.get_user_profile().await.unwrap();
- assert!(user_profile.encryption_sign.is_empty());
- let secret = test.enable_encryption().await;
- let user_profile = test.get_user_profile().await.unwrap();
- assert!(!user_profile.encryption_sign.is_empty());
- let decryption_sign = decrypt_text(user_profile.encryption_sign, &secret).unwrap();
- assert_eq!(decryption_sign, user_profile.id.to_string());
- }
- }
- #[tokio::test]
- async fn third_party_sign_up_with_duplicated_uuid() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new();
- let email = format!("{}@appflowy.io", nanoid!(6));
- let mut map = HashMap::new();
- map.insert(USER_UUID.to_string(), uuid::Uuid::new_v4().to_string());
- map.insert(USER_EMAIL.to_string(), email.clone());
- let response_1 = EventBuilder::new(test.clone())
- .event(OauthSignIn)
- .payload(OauthSignInPB {
- map: map.clone(),
- auth_type: AuthTypePB::Supabase,
- })
- .async_send()
- .await
- .parse::<UserProfilePB>();
- dbg!(&response_1);
- let response_2 = EventBuilder::new(test.clone())
- .event(OauthSignIn)
- .payload(OauthSignInPB {
- map: map.clone(),
- auth_type: AuthTypePB::Supabase,
- })
- .async_send()
- .await
- .parse::<UserProfilePB>();
- assert_eq!(response_1, response_2);
- };
- }
- #[tokio::test]
- async fn third_party_sign_up_with_duplicated_email() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new();
- let email = format!("{}@appflowy.io", nanoid!(6));
- test
- .supabase_sign_up_with_uuid(&uuid::Uuid::new_v4().to_string(), Some(email.clone()))
- .await
- .unwrap();
- let error = test
- .supabase_sign_up_with_uuid(&uuid::Uuid::new_v4().to_string(), Some(email.clone()))
- .await
- .err()
- .unwrap();
- assert_eq!(error.code, ErrorCode::Conflict);
- };
- }
- #[tokio::test]
- async fn sign_up_as_guest_and_then_update_to_new_cloud_user_test() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new_with_guest_user().await;
- let old_views = test
- .folder_manager
- .get_current_workspace_views()
- .await
- .unwrap();
- let old_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- let uuid = uuid::Uuid::new_v4().to_string();
- test.supabase_sign_up_with_uuid(&uuid, None).await.unwrap();
- let new_views = test
- .folder_manager
- .get_current_workspace_views()
- .await
- .unwrap();
- let new_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- assert_eq!(old_views.len(), new_views.len());
- assert_eq!(old_workspace.name, new_workspace.name);
- assert_eq!(old_workspace.views.len(), new_workspace.views.len());
- for (index, view) in old_views.iter().enumerate() {
- assert_eq!(view.name, new_views[index].name);
- assert_eq!(view.id, new_views[index].id);
- assert_eq!(view.layout, new_views[index].layout);
- assert_eq!(view.create_time, new_views[index].create_time);
- }
- }
- }
- #[tokio::test]
- async fn sign_up_as_guest_and_then_update_to_existing_cloud_user_test() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new_with_guest_user().await;
- let uuid = uuid::Uuid::new_v4().to_string();
- let email = format!("{}@appflowy.io", nanoid!(6));
- // The workspace of the guest will be migrated to the new user with given uuid
- let _user_profile = test
- .supabase_sign_up_with_uuid(&uuid, Some(email.clone()))
- .await
- .unwrap();
- let old_cloud_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- let old_cloud_views = test
- .folder_manager
- .get_current_workspace_views()
- .await
- .unwrap();
- assert_eq!(old_cloud_views.len(), 1);
- assert_eq!(old_cloud_views.first().unwrap().child_views.len(), 1);
- // sign out and then sign in as a guest
- test.sign_out().await;
- let _sign_up_context = test.sign_up_as_guest().await;
- let new_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- test
- .create_view(&new_workspace.id, "new workspace child view".to_string())
- .await;
- let new_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- assert_eq!(new_workspace.views.len(), 2);
- // upload to cloud user with given uuid. This time the workspace of the guest will not be merged
- // because the cloud user already has a workspace
- test
- .supabase_sign_up_with_uuid(&uuid, Some(email))
- .await
- .unwrap();
- let new_cloud_workspace = test.folder_manager.get_current_workspace().await.unwrap();
- let new_cloud_views = test
- .folder_manager
- .get_current_workspace_views()
- .await
- .unwrap();
- assert_eq!(new_cloud_workspace, old_cloud_workspace);
- assert_eq!(new_cloud_views, old_cloud_views);
- }
- }
- #[tokio::test]
- async fn check_not_exist_user_test() {
- if let Some(test) = FlowySupabaseTest::new() {
- let err = test
- .check_user_with_uuid(&uuid::Uuid::new_v4().to_string())
- .await
- .unwrap_err();
- assert_eq!(err.code, ErrorCode::RecordNotFound);
- }
- }
- #[tokio::test]
- async fn get_user_profile_test() {
- if let Some(test) = FlowySupabaseTest::new() {
- let uuid = uuid::Uuid::new_v4().to_string();
- test.supabase_sign_up_with_uuid(&uuid, None).await.unwrap();
- let result = test.get_user_profile().await;
- assert!(result.is_ok());
- }
- }
- #[tokio::test]
- async fn update_user_profile_test() {
- if let Some(test) = FlowySupabaseTest::new() {
- let uuid = uuid::Uuid::new_v4().to_string();
- let profile = test.supabase_sign_up_with_uuid(&uuid, None).await.unwrap();
- test
- .update_user_profile(UpdateUserProfilePayloadPB::new(profile.id).name("lucas"))
- .await;
- let new_profile = test.get_user_profile().await.unwrap();
- assert_eq!(new_profile.name, "lucas")
- }
- }
- #[tokio::test]
- async fn update_user_profile_with_existing_email_test() {
- if let Some(test) = FlowySupabaseTest::new() {
- let email = format!("{}@appflowy.io", nanoid!(6));
- let _ = test
- .supabase_sign_up_with_uuid(&uuid::Uuid::new_v4().to_string(), Some(email.clone()))
- .await;
- let profile = test
- .supabase_sign_up_with_uuid(
- &uuid::Uuid::new_v4().to_string(),
- Some(format!("{}@appflowy.io", nanoid!(6))),
- )
- .await
- .unwrap();
- let error = test
- .update_user_profile(
- UpdateUserProfilePayloadPB::new(profile.id)
- .name("lucas")
- .email(&email),
- )
- .await
- .unwrap();
- assert_eq!(error.code, ErrorCode::Conflict);
- }
- }
- #[tokio::test]
- async fn migrate_anon_document_on_cloud_signup() {
- if get_supabase_config().is_some() {
- let test = FlowyCoreTest::new();
- let user_profile = test.sign_up_as_guest().await.user_profile;
- let view = test
- .create_view(&user_profile.workspace_id, "My first view".to_string())
- .await;
- let document_event = DocumentEventTest::new_with_core(test.clone());
- let block_id = document_event
- .insert_index(&view.id, "hello world", 1, None)
- .await;
- let _ = test.supabase_party_sign_up().await;
- let workspace_id = test.user_manager.workspace_id().unwrap();
- // After sign up, the documents should be migrated to the cloud
- // So, we can get the document data from the cloud
- let data: DocumentData = test
- .document_manager
- .get_cloud_service()
- .get_document_data(&view.id, &workspace_id)
- .await
- .unwrap()
- .unwrap();
- let block = data.blocks.get(&block_id).unwrap();
- assert_json_eq!(
- block.data,
- json!({
- "delta": [
- {
- "insert": "hello world"
- }
- ]
- })
- );
- }
- }
- #[tokio::test]
- async fn migrate_anon_data_on_cloud_signup() {
- if get_supabase_config().is_some() {
- let (cleaner, user_db_path) = unzip_history_user_db(
- "./tests/user/supabase_test/history_user_db",
- "workspace_sync",
- )
- .unwrap();
- let test = FlowyCoreTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string());
- let user_profile = test.supabase_party_sign_up().await;
- // Get the folder data from remote
- let folder_data: FolderData = test
- .folder_manager
- .get_cloud_service()
- .get_folder_data(&user_profile.workspace_id)
- .await
- .unwrap()
- .unwrap();
- let expected_folder_data = expected_workspace_sync_folder_data();
- if folder_data.workspaces.len() != expected_folder_data.workspaces.len() {
- dbg!(&folder_data.workspaces);
- }
- assert_eq!(
- folder_data.workspaces.len(),
- expected_folder_data.workspaces.len()
- );
- assert_eq!(folder_data.views.len(), expected_folder_data.views.len());
- // After migration, the ids of the folder_data should be different from the expected_folder_data
- for i in 0..folder_data.views.len() {
- let left_view = &folder_data.views[i];
- let right_view = &expected_folder_data.views[i];
- assert_ne!(left_view.id, right_view.id);
- assert_ne!(left_view.parent_view_id, right_view.parent_view_id);
- assert_eq!(left_view.name, right_view.name);
- }
- assert_ne!(
- folder_data.current_workspace_id,
- expected_folder_data.current_workspace_id
- );
- assert_ne!(folder_data.current_view, expected_folder_data.current_view);
- let database_views = folder_data
- .views
- .iter()
- .filter(|view| view.layout.is_database())
- .collect::<Vec<_>>();
- // Try to load the database from the cloud.
- for (i, database_view) in database_views.iter().enumerate() {
- let cloud_service = test.database_manager.get_cloud_service();
- let database_id = test
- .database_manager
- .get_database_id_with_view_id(&database_view.id)
- .await
- .unwrap();
- let editor = test
- .database_manager
- .get_database(&database_id)
- .await
- .unwrap();
- // The database view setting should be loaded by the view id
- let _ = editor
- .get_database_view_setting(&database_view.id)
- .await
- .unwrap();
- let rows = editor.get_rows(&database_view.id).await.unwrap();
- assert_eq!(rows.len(), 3);
- let workspace_id = test.user_manager.workspace_id().unwrap();
- if i == 0 {
- let first_row = rows.first().unwrap().as_ref();
- let icon_url = first_row.meta.icon_url.clone().unwrap();
- assert_eq!(icon_url, "😄");
- let document_id = database_row_document_id_from_row_id(&first_row.row.id);
- let document_data: DocumentData = test
- .document_manager
- .get_cloud_service()
- .get_document_data(&document_id, &workspace_id)
- .await
- .unwrap()
- .unwrap();
- let editor = test
- .document_manager
- .get_document(&document_id)
- .await
- .unwrap();
- let expected_document_data = editor.lock().get_document_data().unwrap();
- // let expected_document_data = test
- // .document_manager
- // .get_document_data(&document_id)
- // .await
- // .unwrap();
- assert_eq!(document_data, expected_document_data);
- let json = json!(document_data);
- assert_eq!(
- json["blocks"]["LPMpo0Qaab"]["data"]["delta"][0]["insert"],
- json!("Row document")
- );
- }
- assert!(cloud_service
- .get_collab_update(&database_id, CollabType::Database, &workspace_id)
- .await
- .is_ok());
- }
- drop(cleaner);
- }
- }
- fn expected_workspace_sync_folder_data() -> FolderData {
- serde_json::from_value::<FolderData>(json!({
- "current_view": "e0811131-9928-4541-a174-20b7553d9e4c",
- "current_workspace_id": "8df7f755-fa5d-480e-9f8e-48ea0fed12b3",
- "views": [
- {
- "children": {
- "items": [
- {
- "id": "e0811131-9928-4541-a174-20b7553d9e4c"
- },
- {
- "id": "53333949-c262-447b-8597-107589697059"
- }
- ]
- },
- "created_at": 1693147093,
- "desc": "",
- "icon": null,
- "id": "e203afb3-de5d-458a-8380-33cd788a756e",
- "is_favorite": false,
- "layout": 0,
- "name": "⭐️ Getting started",
- "parent_view_id": "8df7f755-fa5d-480e-9f8e-48ea0fed12b3"
- },
- {
- "children": {
- "items": [
- {
- "id": "11c697ba-5ed1-41c0-adfc-576db28ad27b"
- },
- {
- "id": "4a5c25e2-a734-440c-973b-4c0e7ab0039c"
- }
- ]
- },
- "created_at": 1693147096,
- "desc": "",
- "icon": null,
- "id": "e0811131-9928-4541-a174-20b7553d9e4c",
- "is_favorite": false,
- "layout": 1,
- "name": "database",
- "parent_view_id": "e203afb3-de5d-458a-8380-33cd788a756e"
- },
- {
- "children": {
- "items": []
- },
- "created_at": 1693147124,
- "desc": "",
- "icon": null,
- "id": "11c697ba-5ed1-41c0-adfc-576db28ad27b",
- "is_favorite": false,
- "layout": 3,
- "name": "calendar",
- "parent_view_id": "e0811131-9928-4541-a174-20b7553d9e4c"
- },
- {
- "children": {
- "items": []
- },
- "created_at": 1693147125,
- "desc": "",
- "icon": null,
- "id": "4a5c25e2-a734-440c-973b-4c0e7ab0039c",
- "is_favorite": false,
- "layout": 2,
- "name": "board",
- "parent_view_id": "e0811131-9928-4541-a174-20b7553d9e4c"
- },
- {
- "children": {
- "items": []
- },
- "created_at": 1693147133,
- "desc": "",
- "icon": null,
- "id": "53333949-c262-447b-8597-107589697059",
- "is_favorite": false,
- "layout": 0,
- "name": "document",
- "parent_view_id": "e203afb3-de5d-458a-8380-33cd788a756e"
- }
- ],
- "workspaces": [
- {
- "child_views": {
- "items": [
- {
- "id": "e203afb3-de5d-458a-8380-33cd788a756e"
- }
- ]
- },
- "created_at": 1693147093,
- "id": "8df7f755-fa5d-480e-9f8e-48ea0fed12b3",
- "name": "Workspace"
- }
- ]
- }))
- .unwrap()
- }
|