mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: rename flowy-test to event-integration (#3667)
This commit is contained in:
@ -0,0 +1 @@
|
||||
mod test;
|
@ -0,0 +1,13 @@
|
||||
use event_integration::FlowyCoreTest;
|
||||
|
||||
use crate::util::{generate_test_email, get_af_cloud_config};
|
||||
|
||||
#[tokio::test]
|
||||
async fn af_cloud_sign_up_test() {
|
||||
if get_af_cloud_config().is_some() {
|
||||
let test = FlowyCoreTest::new();
|
||||
let email = generate_test_email();
|
||||
let user = test.af_cloud_sign_in_with_email(&email).await.unwrap();
|
||||
assert_eq!(user.email, email);
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
use event_integration::user_event::*;
|
||||
use event_integration::{event_builder::EventBuilder, FlowyCoreTest};
|
||||
use flowy_user::entities::{AuthTypePB, SignInPayloadPB, SignUpPayloadPB};
|
||||
use flowy_user::errors::ErrorCode;
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
|
||||
use crate::user::local_test::helper::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn sign_up_with_invalid_email() {
|
||||
for email in invalid_email_test_case() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let request = SignUpPayloadPB {
|
||||
email: email.to_string(),
|
||||
name: valid_name(),
|
||||
password: login_password(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
EventBuilder::new(sdk)
|
||||
.event(SignUp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.error()
|
||||
.unwrap()
|
||||
.code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn sign_up_with_long_password() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let request = SignUpPayloadPB {
|
||||
email: random_email(),
|
||||
name: valid_name(),
|
||||
password: "1234".repeat(100).as_str().to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
EventBuilder::new(sdk)
|
||||
.event(SignUp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.error()
|
||||
.unwrap()
|
||||
.code,
|
||||
ErrorCode::PasswordTooLong
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sign_in_with_invalid_email() {
|
||||
for email in invalid_email_test_case() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let request = SignInPayloadPB {
|
||||
email: email.to_string(),
|
||||
password: login_password(),
|
||||
name: "".to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
EventBuilder::new(sdk)
|
||||
.event(SignIn)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.error()
|
||||
.unwrap()
|
||||
.code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sign_in_with_invalid_password() {
|
||||
for password in invalid_password_test_case() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
|
||||
let request = SignInPayloadPB {
|
||||
email: random_email(),
|
||||
password,
|
||||
name: "".to_string(),
|
||||
auth_type: AuthTypePB::Local,
|
||||
device_id: "".to_string(),
|
||||
};
|
||||
|
||||
assert!(EventBuilder::new(sdk)
|
||||
.event(SignIn)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.error()
|
||||
.is_some())
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
pub(crate) fn invalid_email_test_case() -> Vec<String> {
|
||||
// https://gist.github.com/cjaoude/fd9910626629b53c4d25
|
||||
vec![
|
||||
"annie@",
|
||||
"annie@gmail@",
|
||||
"#@%^%#$@#$@#.com",
|
||||
"@example.com",
|
||||
"Joe Smith <email@example.com>",
|
||||
"email.example.com",
|
||||
"email@example@example.com",
|
||||
"email@-example.com",
|
||||
"email@example..com",
|
||||
"あいうえお@example.com",
|
||||
/* The following email is valid according to the validate_email function return
|
||||
* ".email@example.com",
|
||||
* "email.@example.com",
|
||||
* "email..email@example.com",
|
||||
* "email@example",
|
||||
* "email@example.web",
|
||||
* "email@111.222.333.44444",
|
||||
* "Abc..123@example.com", */
|
||||
]
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub(crate) fn invalid_password_test_case() -> Vec<String> {
|
||||
vec!["123456", "1234".repeat(100).as_str()]
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub(crate) fn valid_name() -> String {
|
||||
"AppFlowy".to_string()
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
mod auth_test;
|
||||
mod helper;
|
||||
mod user_awareness_test;
|
||||
mod user_profile_test;
|
@ -0,0 +1,39 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use event_integration::event_builder::EventBuilder;
|
||||
use event_integration::FlowyCoreTest;
|
||||
use flowy_user::entities::{ReminderPB, RepeatedReminderPB};
|
||||
use flowy_user::event_map::UserEvent::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_name() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let _ = sdk.sign_up_as_guest().await;
|
||||
let mut meta = HashMap::new();
|
||||
meta.insert("object_id".to_string(), "".to_string());
|
||||
|
||||
let payload = ReminderPB {
|
||||
id: "".to_string(),
|
||||
scheduled_at: 0,
|
||||
is_ack: false,
|
||||
is_read: false,
|
||||
title: "".to_string(),
|
||||
message: "".to_string(),
|
||||
object_id: "".to_string(),
|
||||
meta,
|
||||
};
|
||||
let _ = EventBuilder::new(sdk.clone())
|
||||
.event(CreateReminder)
|
||||
.payload(payload)
|
||||
.async_send()
|
||||
.await;
|
||||
|
||||
let reminders = EventBuilder::new(sdk.clone())
|
||||
.event(GetAllReminders)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedReminderPB>()
|
||||
.items;
|
||||
|
||||
assert_eq!(reminders.len(), 1);
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
use crate::user::local_test::helper::*;
|
||||
use event_integration::{event_builder::EventBuilder, FlowyCoreTest};
|
||||
use flowy_user::entities::{UpdateUserProfilePayloadPB, UserProfilePB};
|
||||
use flowy_user::{errors::ErrorCode, event_map::UserEvent::*};
|
||||
use nanoid::nanoid;
|
||||
|
||||
// use serial_test::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_profile_get_failed() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let result = EventBuilder::new(sdk)
|
||||
.event(GetUserProfile)
|
||||
.async_send()
|
||||
.await
|
||||
.error();
|
||||
assert!(result.is_some())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_profile_get() {
|
||||
let test = FlowyCoreTest::new();
|
||||
let user_profile = test.init_user().await;
|
||||
let user = EventBuilder::new(test.clone())
|
||||
.event(GetUserProfile)
|
||||
.sync_send()
|
||||
.parse::<UserProfilePB>();
|
||||
assert_eq!(user_profile, user);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_name() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let user = sdk.init_user().await;
|
||||
let new_name = "hello_world".to_owned();
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).name(&new_name);
|
||||
let _ = EventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.sync_send();
|
||||
|
||||
let user_profile = EventBuilder::new(sdk.clone())
|
||||
.event(GetUserProfile)
|
||||
.sync_send()
|
||||
.parse::<UserProfilePB>();
|
||||
|
||||
assert_eq!(user_profile.name, new_name,);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_ai_key() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let user = sdk.init_user().await;
|
||||
let openai_key = "openai_key".to_owned();
|
||||
let stability_ai_key = "stability_ai_key".to_owned();
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id)
|
||||
.openai_key(&openai_key)
|
||||
.stability_ai_key(&stability_ai_key);
|
||||
let _ = EventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.sync_send();
|
||||
|
||||
let user_profile = EventBuilder::new(sdk.clone())
|
||||
.event(GetUserProfile)
|
||||
.sync_send()
|
||||
.parse::<UserProfilePB>();
|
||||
|
||||
assert_eq!(user_profile.openai_key, openai_key,);
|
||||
assert_eq!(user_profile.stability_ai_key, stability_ai_key,);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_email() {
|
||||
let sdk = FlowyCoreTest::new();
|
||||
let user = sdk.init_user().await;
|
||||
let new_email = format!("{}@gmail.com", nanoid!(6));
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).email(&new_email);
|
||||
let _ = EventBuilder::new(sdk.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.sync_send();
|
||||
let user_profile = EventBuilder::new(sdk.clone())
|
||||
.event(GetUserProfile)
|
||||
.sync_send()
|
||||
.parse::<UserProfilePB>();
|
||||
|
||||
assert_eq!(user_profile.email, new_email,);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_invalid_email() {
|
||||
let test = FlowyCoreTest::new();
|
||||
let user = test.init_user().await;
|
||||
for email in invalid_email_test_case() {
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).email(&email);
|
||||
assert_eq!(
|
||||
EventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.sync_send()
|
||||
.error()
|
||||
.unwrap()
|
||||
.code,
|
||||
ErrorCode::EmailFormatInvalid
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_invalid_password() {
|
||||
let test = FlowyCoreTest::new();
|
||||
let user = test.init_user().await;
|
||||
for password in invalid_password_test_case() {
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).password(&password);
|
||||
|
||||
assert!(EventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.error()
|
||||
.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn user_update_with_invalid_name() {
|
||||
let test = FlowyCoreTest::new();
|
||||
let user = test.init_user().await;
|
||||
let request = UpdateUserProfilePayloadPB::new(user.id).name("");
|
||||
assert!(EventBuilder::new(test.clone())
|
||||
.event(UpdateUserProfile)
|
||||
.payload(request)
|
||||
.sync_send()
|
||||
.error()
|
||||
.is_some())
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
use event_integration::FlowyCoreTest;
|
||||
use flowy_core::DEFAULT_NAME;
|
||||
use flowy_folder2::entities::ViewLayoutPB;
|
||||
|
||||
use crate::util::unzip_history_user_db;
|
||||
|
||||
#[tokio::test]
|
||||
async fn migrate_historical_empty_document_test() {
|
||||
let (cleaner, user_db_path) = unzip_history_user_db(
|
||||
"./tests/user/migration_test/history_user_db",
|
||||
"historical_empty_document",
|
||||
)
|
||||
.unwrap();
|
||||
let test = FlowyCoreTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string());
|
||||
|
||||
let views = test.get_all_workspace_views().await;
|
||||
assert_eq!(views.len(), 3);
|
||||
for view in views {
|
||||
assert_eq!(view.layout, ViewLayoutPB::Document);
|
||||
let data = test.open_document(view.id).await.data;
|
||||
assert!(!data.page_id.is_empty());
|
||||
assert_eq!(data.blocks.len(), 2);
|
||||
assert!(!data.meta.children_map.is_empty());
|
||||
}
|
||||
|
||||
drop(cleaner);
|
||||
}
|
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
|
||||
## 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
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
mod document_test;
|
||||
mod version_test;
|
@ -0,0 +1,39 @@
|
||||
use event_integration::FlowyCoreTest;
|
||||
use flowy_core::DEFAULT_NAME;
|
||||
use flowy_folder2::entities::ViewLayoutPB;
|
||||
|
||||
use crate::util::unzip_history_user_db;
|
||||
|
||||
#[tokio::test]
|
||||
async fn migrate_020_historical_empty_document_test() {
|
||||
let (cleaner, user_db_path) = unzip_history_user_db(
|
||||
"./tests/user/migration_test/history_user_db",
|
||||
"020_historical_user_data",
|
||||
)
|
||||
.unwrap();
|
||||
let test = FlowyCoreTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string());
|
||||
|
||||
let mut views = test.get_all_workspace_views().await;
|
||||
assert_eq!(views.len(), 1);
|
||||
|
||||
// Check the parent view
|
||||
let parent_view = views.pop().unwrap();
|
||||
assert_eq!(parent_view.layout, ViewLayoutPB::Document);
|
||||
let data = test.open_document(parent_view.id.clone()).await.data;
|
||||
assert!(!data.page_id.is_empty());
|
||||
assert_eq!(data.blocks.len(), 2);
|
||||
assert!(!data.meta.children_map.is_empty());
|
||||
|
||||
// Check the child views of the parent view
|
||||
let child_views = test.get_views(&parent_view.id).await.child_views;
|
||||
assert_eq!(child_views.len(), 4);
|
||||
assert_eq!(child_views[0].layout, ViewLayoutPB::Document);
|
||||
assert_eq!(child_views[1].layout, ViewLayoutPB::Grid);
|
||||
assert_eq!(child_views[2].layout, ViewLayoutPB::Calendar);
|
||||
assert_eq!(child_views[3].layout, ViewLayoutPB::Board);
|
||||
|
||||
let database = test.get_database(&child_views[1].id).await;
|
||||
assert_eq!(database.fields.len(), 8);
|
||||
assert_eq!(database.rows.len(), 3);
|
||||
drop(cleaner);
|
||||
}
|
6
frontend/rust-lib/event-integration/tests/user/mod.rs
Normal file
6
frontend/rust-lib/event-integration/tests/user/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
mod local_test;
|
||||
mod migration_test;
|
||||
|
||||
mod af_cloud_test;
|
||||
#[cfg(feature = "supabase_cloud_test")]
|
||||
mod supabase_test;
|
@ -0,0 +1,520 @@
|
||||
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;
|
||||
|
||||
// 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)
|
||||
.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);
|
||||
|
||||
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)
|
||||
.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)
|
||||
.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()
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
## 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
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
mod auth_test;
|
||||
mod workspace_test;
|
@ -0,0 +1,43 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use event_integration::{event_builder::EventBuilder, FlowyCoreTest};
|
||||
use flowy_folder2::entities::WorkspaceSettingPB;
|
||||
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspace;
|
||||
use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
|
||||
use flowy_user::entities::{AuthTypePB, 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 = 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!("{}@gmail.com", uuid::Uuid::new_v4()),
|
||||
);
|
||||
let payload = OauthSignInPB {
|
||||
map,
|
||||
auth_type: AuthTypePB::Supabase,
|
||||
};
|
||||
|
||||
let _ = EventBuilder::new(test.clone())
|
||||
.event(OauthSignIn)
|
||||
.payload(payload)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<UserProfilePB>();
|
||||
|
||||
let workspace_settings = EventBuilder::new(test.clone())
|
||||
.event(GetCurrentWorkspace)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<WorkspaceSettingPB>();
|
||||
|
||||
assert!(workspace_settings.latest_view.is_some());
|
||||
dbg!(&workspace_settings);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user