chore: delete supabase test

This commit is contained in:
Nathan 2025-04-22 10:15:19 +08:00
parent eaac387c8d
commit 403f343371
15 changed files with 0 additions and 1217 deletions

View file

@ -1,106 +0,0 @@
use std::ops::Deref;
use assert_json_diff::assert_json_eq;
use collab::core::collab::MutexCollab;
use collab::core::origin::CollabOrigin;
use collab::preclude::updates::decoder::Decode;
use collab::preclude::{Collab, JsonValue, Update};
use collab_entity::CollabType;
use event_integration_test::event_builder::EventBuilder;
use flowy_database2::entities::{DatabasePB, DatabaseViewIdPB, RepeatedDatabaseSnapshotPB};
use flowy_database2::event_map::DatabaseEvent::*;
use flowy_folder::entities::ViewPB;
use crate::util::FlowySupabaseTest;
pub struct FlowySupabaseDatabaseTest {
pub uuid: String,
inner: FlowySupabaseTest,
}
impl FlowySupabaseDatabaseTest {
#[allow(dead_code)]
pub async fn new_with_user(uuid: String) -> Option<Self> {
let inner = FlowySupabaseTest::new().await?;
inner.supabase_sign_up_with_uuid(&uuid, None).await.unwrap();
Some(Self { uuid, inner })
}
pub async fn new_with_new_user() -> Option<Self> {
let inner = FlowySupabaseTest::new().await?;
let uuid = uuid::Uuid::new_v4().to_string();
let _ = inner.supabase_sign_up_with_uuid(&uuid, None).await.unwrap();
Some(Self { uuid, inner })
}
pub async fn create_database(&self) -> (ViewPB, DatabasePB) {
let current_workspace = self.inner.get_current_workspace().await;
let view = self
.inner
.create_grid(&current_workspace.id, "my database".to_string(), vec![])
.await;
let database = self.inner.get_database(&view.id).await;
(view, database)
}
pub async fn get_collab_json(&self, database_id: &str) -> JsonValue {
let database_editor = self
.database_manager
.get_database(database_id)
.await
.unwrap();
// let address = Arc::into_raw(database_editor.clone());
let database = database_editor.get_mutex_database().lock();
database.get_mutex_collab().to_json_value()
}
pub async fn get_database_snapshots(&self, view_id: &str) -> RepeatedDatabaseSnapshotPB {
EventBuilder::new(self.inner.deref().clone())
.event(GetDatabaseSnapshots)
.payload(DatabaseViewIdPB {
value: view_id.to_string(),
})
.async_send()
.await
.parse::<RepeatedDatabaseSnapshotPB>()
}
pub async fn get_database_collab_update(&self, database_id: &str) -> Vec<u8> {
let workspace_id = self.user_manager.workspace_id().unwrap();
let cloud_service = self.database_manager.get_cloud_service().clone();
cloud_service
.get_database_object_doc_state(database_id, CollabType::Database, &workspace_id)
.await
.unwrap()
.unwrap()
}
}
pub fn assert_database_collab_content(
database_id: &str,
collab_update: &[u8],
expected: JsonValue,
) {
let collab = MutexCollab::new(Collab::new_with_origin(
CollabOrigin::Server,
database_id,
vec![],
false,
));
collab.lock().with_origin_transact_mut(|txn| {
let update = Update::decode_v1(collab_update).unwrap();
txn.apply_update(update).unwrap();
});
let json = collab.to_json_value();
assert_json_eq!(json, expected);
}
impl Deref for FlowySupabaseDatabaseTest {
type Target = FlowySupabaseTest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}

View file

@ -1,2 +0,0 @@
mod helper;
mod test;

View file

@ -1,108 +0,0 @@
use std::time::Duration;
use flowy_database2::entities::{
DatabaseSnapshotStatePB, DatabaseSyncState, DatabaseSyncStatePB, FieldChangesetPB, FieldType,
};
use flowy_database2::notification::DatabaseNotification::DidUpdateDatabaseSnapshotState;
use crate::database::supabase_test::helper::{
assert_database_collab_content, FlowySupabaseDatabaseTest,
};
use crate::util::receive_with_timeout;
#[tokio::test]
async fn supabase_initial_database_snapshot_test() {
if let Some(test) = FlowySupabaseDatabaseTest::new_with_new_user().await {
let (view, database) = test.create_database().await;
let rx = test
.notification_sender
.subscribe::<DatabaseSnapshotStatePB>(&database.id, DidUpdateDatabaseSnapshotState);
receive_with_timeout(rx, Duration::from_secs(30))
.await
.unwrap();
let expected = test.get_collab_json(&database.id).await;
let snapshots = test.get_database_snapshots(&view.id).await;
assert_eq!(snapshots.items.len(), 1);
assert_database_collab_content(&database.id, &snapshots.items[0].data, expected);
}
}
#[tokio::test]
async fn supabase_edit_database_test() {
if let Some(test) = FlowySupabaseDatabaseTest::new_with_new_user().await {
let (view, database) = test.create_database().await;
let existing_fields = test.get_all_database_fields(&view.id).await;
for field in existing_fields.items {
if !field.is_primary {
test.delete_field(&view.id, &field.id).await;
}
}
let field = test.create_field(&view.id, FieldType::Checklist).await;
test
.update_field(FieldChangesetPB {
field_id: field.id.clone(),
view_id: view.id.clone(),
name: Some("hello world".to_string()),
..Default::default()
})
.await;
// wait all updates are send to the remote
let rx = test
.notification_sender
.subscribe_with_condition::<DatabaseSyncStatePB, _>(&database.id, |pb| {
pb.value == DatabaseSyncState::SyncFinished
});
receive_with_timeout(rx, Duration::from_secs(30))
.await
.unwrap();
assert_eq!(test.get_all_database_fields(&view.id).await.items.len(), 2);
let expected = test.get_collab_json(&database.id).await;
let update = test.get_database_collab_update(&database.id).await;
assert_database_collab_content(&database.id, &update, expected);
}
}
// #[tokio::test]
// async fn cloud_test_supabase_login_sync_database_test() {
// if let Some(test) = FlowySupabaseDatabaseTest::new_with_new_user().await {
// let uuid = test.uuid.clone();
// let (view, database) = test.create_database().await;
// // wait all updates are send to the remote
// let mut rx = test
// .notification_sender
// .subscribe_with_condition::<DatabaseSyncStatePB, _>(&database.id, |pb| pb.is_finish);
// receive_with_timeout(&mut rx, Duration::from_secs(30))
// .await
// .unwrap();
// let expected = test.get_collab_json(&database.id).await;
// test.sign_out().await;
// // Drop the test will cause the test resources to be dropped, which will
// // delete the user data folder.
// drop(test);
//
// let new_test = FlowySupabaseDatabaseTest::new_with_user(uuid)
// .await
// .unwrap();
// // let actual = new_test.get_collab_json(&database.id).await;
// // assert_json_eq!(actual, json!(""));
//
// new_test.open_database(&view.id).await;
//
// // wait all updates are synced from the remote
// let mut rx = new_test
// .notification_sender
// .subscribe_with_condition::<DatabaseSyncStatePB, _>(&database.id, |pb| pb.is_finish);
// receive_with_timeout(&mut rx, Duration::from_secs(30))
// .await
// .unwrap();
//
// // when the new sync is finished, the database should be the same as the old one
// let actual = new_test.get_collab_json(&database.id).await;
// assert_json_eq!(actual, expected);
// }
// }

View file

@ -1,65 +0,0 @@
use std::time::Duration;
use event_integration_test::document_event::assert_document_data_equal;
use flowy_document::entities::{DocumentSyncState, DocumentSyncStatePB};
use crate::document::supabase_test::helper::FlowySupabaseDocumentTest;
use crate::util::receive_with_timeout;
#[tokio::test]
async fn supabase_document_edit_sync_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await {
let view = test.create_document().await;
let document_id = view.id.clone();
let cloned_test = test.clone();
let cloned_document_id = document_id.clone();
test.appflowy_core.dispatcher().spawn(async move {
cloned_test
.insert_document_text(&cloned_document_id, "hello world", 0)
.await;
});
// wait all update are send to the remote
let rx = test
.notification_sender
.subscribe_with_condition::<DocumentSyncStatePB, _>(&document_id, |pb| {
pb.value != DocumentSyncState::Syncing
});
receive_with_timeout(rx, Duration::from_secs(30))
.await
.unwrap();
let document_data = test.get_document_data(&document_id).await;
let update = test.get_document_doc_state(&document_id).await;
assert_document_data_equal(&update, &document_id, document_data);
}
}
#[tokio::test]
async fn supabase_document_edit_sync_test2() {
if let Some(test) = FlowySupabaseDocumentTest::new().await {
let view = test.create_document().await;
let document_id = view.id.clone();
for i in 0..10 {
test
.insert_document_text(&document_id, "hello world", i)
.await;
}
// wait all update are send to the remote
let rx = test
.notification_sender
.subscribe_with_condition::<DocumentSyncStatePB, _>(&document_id, |pb| {
pb.value != DocumentSyncState::Syncing
});
receive_with_timeout(rx, Duration::from_secs(30))
.await
.unwrap();
let document_data = test.get_document_data(&document_id).await;
let update = test.get_document_doc_state(&document_id).await;
assert_document_data_equal(&update, &document_id, document_data);
}
}

View file

@ -1,118 +0,0 @@
// use std::fs::File;
// use std::io::{Cursor, Read};
// use std::path::Path;
//
// use uuid::Uuid;
// use zip::ZipArchive;
//
// use flowy_storage::StorageObject;
//
// use crate::document::supabase_test::helper::FlowySupabaseDocumentTest;
//
// #[tokio::test]
// async fn supabase_document_upload_text_file_test() {
// if let Some(test) = FlowySupabaseDocumentTest::new().await {
// let workspace_id = test.get_current_workspace().await.id;
// let storage_service = test
// .document_manager
// .get_file_storage_service()
// .upgrade()
// .unwrap();
//
// let object = StorageObject::from_bytes(
// &workspace_id,
// &Uuid::new_v4().to_string(),
// "hello world".as_bytes(),
// "text/plain".to_string(),
// );
//
// let url = storage_service.create_object(object).await.unwrap();
//
// let bytes = storage_service
// .get_object(url.clone())
// .await
// .unwrap();
// let s = String::from_utf8(bytes.to_vec()).unwrap();
// assert_eq!(s, "hello world");
//
// // Delete the text file
// let _ = storage_service.delete_object(url).await;
// }
// }
//
// #[tokio::test]
// async fn supabase_document_upload_zip_file_test() {
// if let Some(test) = FlowySupabaseDocumentTest::new().await {
// let workspace_id = test.get_current_workspace().await.id;
// let storage_service = test
// .document_manager
// .get_file_storage_service()
// .upgrade()
// .unwrap();
//
// // Upload zip file
// let object = StorageObject::from_file(
// &workspace_id,
// &Uuid::new_v4().to_string(),
// "./tests/asset/test.txt.zip",
// );
// let url = storage_service.create_object(object).await.unwrap();
//
// // Read zip file
// let zip_data = storage_service
// .get_object(url.clone())
// .await
// .unwrap();
// let reader = Cursor::new(zip_data);
// let mut archive = ZipArchive::new(reader).unwrap();
// for i in 0..archive.len() {
// let mut file = archive.by_index(i).unwrap();
// let name = file.name().to_string();
// let mut out = Vec::new();
// file.read_to_end(&mut out).unwrap();
//
// if name.starts_with("__MACOSX/") {
// continue;
// }
// assert_eq!(name, "test.txt");
// assert_eq!(String::from_utf8(out).unwrap(), "hello world");
// }
//
// // Delete the zip file
// let _ = storage_service.delete_object(url).await;
// }
// }
// #[tokio::test]
// async fn supabase_document_upload_image_test() {
// if let Some(test) = FlowySupabaseDocumentTest::new().await {
// let workspace_id = test.get_current_workspace().await.id;
// let storage_service = test
// .document_manager
// .get_file_storage_service()
// .upgrade()
// .unwrap();
//
// // Upload zip file
// let object = StorageObject::from_file(
// &workspace_id,
// &Uuid::new_v4().to_string(),
// "./tests/asset/logo.png",
// );
// let url = storage_service.create_object(object).await.unwrap();
//
// let image_data = storage_service
// .get_object(url.clone())
// .await
// .unwrap();
//
// // Read the image file
// let mut file = File::open(Path::new("./tests/asset/logo.png")).unwrap();
// let mut local_data = Vec::new();
// file.read_to_end(&mut local_data).unwrap();
//
// assert_eq!(image_data, local_data);
//
// // Delete the image
// let _ = storage_service.delete_object(url).await;
// }
// }

View file

@ -1,49 +0,0 @@
use std::ops::Deref;
use event_integration_test::event_builder::EventBuilder;
use flowy_document::entities::{OpenDocumentPayloadPB, RepeatedDocumentSnapshotMetaPB};
use flowy_document::event_map::DocumentEvent::GetDocumentSnapshotMeta;
use flowy_folder::entities::ViewPB;
use crate::util::FlowySupabaseTest;
pub struct FlowySupabaseDocumentTest {
inner: FlowySupabaseTest,
}
impl FlowySupabaseDocumentTest {
pub async fn new() -> Option<Self> {
let inner = FlowySupabaseTest::new().await?;
let uuid = uuid::Uuid::new_v4().to_string();
let _ = inner.supabase_sign_up_with_uuid(&uuid, None).await;
Some(Self { inner })
}
pub async fn create_document(&self) -> ViewPB {
let current_workspace = self.inner.get_current_workspace().await;
self
.inner
.create_and_open_document(&current_workspace.id, "my document".to_string(), vec![])
.await
}
#[allow(dead_code)]
pub async fn get_document_snapshots(&self, view_id: &str) -> RepeatedDocumentSnapshotMetaPB {
EventBuilder::new(self.inner.deref().clone())
.event(GetDocumentSnapshotMeta)
.payload(OpenDocumentPayloadPB {
document_id: view_id.to_string(),
})
.async_send()
.await
.parse::<RepeatedDocumentSnapshotMetaPB>()
}
}
impl Deref for FlowySupabaseDocumentTest {
type Target = FlowySupabaseTest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}

View file

@ -1,3 +0,0 @@
mod edit_test;
mod file_test;
mod helper;

View file

@ -1,91 +0,0 @@
use std::ops::Deref;
use assert_json_diff::assert_json_eq;
use collab::core::collab::MutexCollab;
use collab::core::origin::CollabOrigin;
use collab::preclude::updates::decoder::Decode;
use collab::preclude::{Collab, JsonValue, Update};
use collab_entity::CollabType;
use collab_folder::FolderData;
use event_integration_test::event_builder::EventBuilder;
use flowy_folder::entities::{FolderSnapshotPB, RepeatedFolderSnapshotPB, WorkspaceIdPB};
use flowy_folder::event_map::FolderEvent::GetFolderSnapshots;
use crate::util::FlowySupabaseTest;
pub struct FlowySupabaseFolderTest {
inner: FlowySupabaseTest,
}
impl FlowySupabaseFolderTest {
pub async fn new() -> Option<Self> {
let inner = FlowySupabaseTest::new().await?;
let uuid = uuid::Uuid::new_v4().to_string();
let _ = inner.supabase_sign_up_with_uuid(&uuid, None).await;
Some(Self { inner })
}
pub async fn get_collab_json(&self) -> JsonValue {
let folder = self.folder_manager.get_mutex_folder().lock();
folder.as_ref().unwrap().to_json_value()
}
pub async fn get_local_folder_data(&self) -> FolderData {
let folder = self.folder_manager.get_mutex_folder().lock();
folder.as_ref().unwrap().get_folder_data().unwrap()
}
pub async fn get_folder_snapshots(&self, workspace_id: &str) -> Vec<FolderSnapshotPB> {
EventBuilder::new(self.inner.deref().clone())
.event(GetFolderSnapshots)
.payload(WorkspaceIdPB {
value: workspace_id.to_string(),
})
.async_send()
.await
.parse::<RepeatedFolderSnapshotPB>()
.items
}
pub async fn get_collab_update(&self, workspace_id: &str) -> Vec<u8> {
let cloud_service = self.folder_manager.get_cloud_service().clone();
cloud_service
.get_folder_doc_state(
workspace_id,
self.user_manager.user_id().unwrap(),
CollabType::Folder,
workspace_id,
)
.await
.unwrap()
}
}
pub fn assert_folder_collab_content(workspace_id: &str, collab_update: &[u8], expected: JsonValue) {
if collab_update.is_empty() {
panic!("collab update is empty");
}
let collab = MutexCollab::new(Collab::new_with_origin(
CollabOrigin::Server,
workspace_id,
vec![],
false,
));
collab.lock().with_origin_transact_mut(|txn| {
let update = Update::decode_v1(collab_update).unwrap();
txn.apply_update(update).unwrap();
});
let json = collab.to_json_value();
assert_json_eq!(json["folder"], expected);
}
impl Deref for FlowySupabaseFolderTest {
type Target = FlowySupabaseTest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}

View file

@ -1,2 +0,0 @@
mod helper;
mod test;

View file

@ -1,122 +0,0 @@
use std::time::Duration;
use assert_json_diff::assert_json_eq;
use serde_json::json;
use flowy_folder::entities::{FolderSnapshotStatePB, FolderSyncStatePB};
use flowy_folder::notification::FolderNotification::DidUpdateFolderSnapshotState;
use crate::folder::supabase_test::helper::{assert_folder_collab_content, FlowySupabaseFolderTest};
use crate::util::{get_folder_data_from_server, receive_with_timeout};
#[tokio::test]
async fn supabase_encrypt_folder_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = test.enable_encryption().await;
let local_folder_data = test.get_local_folder_data().await;
let workspace_id = test.get_current_workspace().await.id;
let remote_folder_data = get_folder_data_from_server(&uid, &workspace_id, Some(secret))
.await
.unwrap()
.unwrap();
assert_json_eq!(json!(local_folder_data), json!(remote_folder_data));
}
}
#[tokio::test]
async fn supabase_decrypt_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "encrypt view".to_string())
.await;
let rx = test
.notification_sender
.subscribe_with_condition::<FolderSyncStatePB, _>(&workspace_id, |pb| pb.is_finish);
receive_with_timeout(rx, Duration::from_secs(10))
.await
.unwrap();
let folder_data = get_folder_data_from_server(&uid, &workspace_id, secret)
.await
.unwrap()
.unwrap();
assert_eq!(folder_data.views.len(), 2);
assert_eq!(folder_data.views[1].name, "encrypt view");
}
}
#[tokio::test]
#[should_panic]
async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let _ = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "encrypt view".to_string())
.await;
let rx = test
.notification_sender
.subscribe_with_condition::<FolderSyncStatePB, _>(&workspace_id, |pb| pb.is_finish);
receive_with_timeout(rx, Duration::from_secs(10))
.await
.unwrap();
let _ = get_folder_data_from_server(&uid, &workspace_id, Some("invalid secret".to_string()))
.await
.unwrap();
}
}
#[tokio::test]
async fn supabase_folder_snapshot_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.id;
let rx = test
.notification_sender
.subscribe::<FolderSnapshotStatePB>(&workspace_id, DidUpdateFolderSnapshotState);
receive_with_timeout(rx, Duration::from_secs(10))
.await
.unwrap();
let expected = test.get_collab_json().await;
let snapshots = test.get_folder_snapshots(&workspace_id).await;
assert_eq!(snapshots.len(), 1);
assert_folder_collab_content(&workspace_id, &snapshots[0].data, expected);
}
}
#[tokio::test]
async fn supabase_initial_folder_snapshot_test2() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "supabase test view1".to_string())
.await;
test
.create_view(&workspace_id, "supabase test view2".to_string())
.await;
test
.create_view(&workspace_id, "supabase test view3".to_string())
.await;
let rx = test
.notification_sender
.subscribe_with_condition::<FolderSyncStatePB, _>(&workspace_id, |pb| pb.is_finish);
receive_with_timeout(rx, Duration::from_secs(10))
.await
.unwrap();
let expected = test.get_collab_json().await;
let update = test.get_collab_update(&workspace_id).await;
assert_folder_collab_content(&workspace_id, &update, expected);
}
}

View file

@ -1,502 +0,0 @@
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::FolderData;
use nanoid::nanoid;
use serde_json::json;
use event_integration_test::document::document_event::DocumentEventTest;
use event_integration_test::event_builder::EventBuilder;
use event_integration_test::EventIntegrationTest;
use flowy_core::DEFAULT_NAME;
use flowy_encrypt::decrypt_text;
use flowy_server::supabase::define::{USER_DEVICE_ID, USER_EMAIL, USER_UUID};
use flowy_user::entities::{
AuthenticatorPB, 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 = EventIntegrationTest::new().await;
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)),
);
map.insert(USER_DEVICE_ID.to_string(), uuid::Uuid::new_v4().to_string());
let payload = OauthSignInPB {
map,
authenticator: AuthenticatorPB::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 = EventIntegrationTest::new().await;
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 = EventIntegrationTest::new().await;
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());
map.insert(USER_DEVICE_ID.to_string(), uuid::Uuid::new_v4().to_string());
let response_1 = EventBuilder::new(test.clone())
.event(OauthSignIn)
.payload(OauthSignInPB {
map: map.clone(),
authenticator: AuthenticatorPB::Supabase,
})
.async_send()
.await
.parse::<UserProfilePB>();
dbg!(&response_1);
let response_2 = EventBuilder::new(test.clone())
.event(OauthSignIn)
.payload(OauthSignInPB {
map: map.clone(),
authenticator: AuthenticatorPB::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 = EventIntegrationTest::new().await;
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 = EventIntegrationTest::new_anon().await;
let old_views = test
.folder_manager
.get_current_workspace_public_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_public_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.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 = EventIntegrationTest::new_anon().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_public_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_anon().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_public_views()
.await
.unwrap();
assert_eq!(new_cloud_workspace, old_cloud_workspace);
assert_eq!(new_cloud_views, old_cloud_views);
}
}
#[tokio::test]
async fn get_user_profile_test() {
if let Some(test) = FlowySupabaseTest::new().await {
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().await {
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().await {
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 = EventIntegrationTest::new().await;
let user_profile = test.sign_up_as_anon().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(
"./tests/user/supabase_test/history_user_db",
"workspace_sync",
)
.unwrap();
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
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, &user_profile.id)
.await
.unwrap()
.unwrap();
let expected_folder_data = expected_workspace_sync_folder_data();
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.workspace.id, expected_folder_data.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_database_object_doc_state(&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()
}

View file

@ -1,4 +0,0 @@
## Don't modify the zip files in this folder
The zip files in this folder are used for integration tests. If the tests fail, it means users upgrading to this version of AppFlowy will encounter issues

View file

@ -1,2 +0,0 @@
mod auth_test;
mod workspace_test;

View file

@ -1,43 +0,0 @@
use std::collections::HashMap;
use event_integration_test::{event_builder::EventBuilder, EventIntegrationTest};
use flowy_folder::entities::WorkspaceSettingPB;
use flowy_folder::event_map::FolderEvent::GetCurrentWorkspaceSetting;
use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
use flowy_user::entities::{AuthenticatorPB, OauthSignInPB, UserProfilePB};
use flowy_user::event_map::UserEvent::*;
use crate::util::*;
#[tokio::test]
async fn initial_workspace_test() {
if get_supabase_config().is_some() {
let test = EventIntegrationTest::new().await;
let mut map = HashMap::new();
map.insert(USER_UUID.to_string(), uuid::Uuid::new_v4().to_string());
map.insert(
USER_EMAIL.to_string(),
format!("{}@gmail.com", uuid::Uuid::new_v4()),
);
let payload = OauthSignInPB {
map,
authenticator: AuthenticatorPB::Supabase,
};
let _ = EventBuilder::new(test.clone())
.event(OauthSignIn)
.payload(payload)
.async_send()
.await
.parse::<UserProfilePB>();
let workspace_settings = EventBuilder::new(test.clone())
.event(GetCurrentWorkspaceSetting)
.async_send()
.await
.parse::<WorkspaceSettingPB>();
assert!(workspace_settings.latest_view.is_some());
dbg!(&workspace_settings);
}
}