lib.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. use std::convert::TryFrom;
  2. use std::env::temp_dir;
  3. use std::sync::Arc;
  4. use bytes::Bytes;
  5. use nanoid::nanoid;
  6. use parking_lot::RwLock;
  7. use flowy_core::{AppFlowyCore, AppFlowyCoreConfig};
  8. use flowy_database2::entities::*;
  9. use flowy_folder2::entities::*;
  10. use flowy_user::entities::{AuthTypePB, UserProfilePB};
  11. use flowy_user::errors::FlowyError;
  12. use crate::event_builder::EventBuilder;
  13. use crate::user_event::{async_sign_up, init_user_setting, SignUpContext};
  14. pub mod document_event;
  15. pub mod event_builder;
  16. pub mod folder_event;
  17. pub mod user_event;
  18. #[derive(Clone)]
  19. pub struct FlowyCoreTest {
  20. auth_type: Arc<RwLock<AuthTypePB>>,
  21. inner: AppFlowyCore,
  22. }
  23. impl Default for FlowyCoreTest {
  24. fn default() -> Self {
  25. let temp_dir = temp_dir();
  26. let config =
  27. AppFlowyCoreConfig::new(temp_dir.to_str().unwrap(), nanoid!(6)).log_filter("info", vec![]);
  28. let inner = std::thread::spawn(|| AppFlowyCore::new(config))
  29. .join()
  30. .unwrap();
  31. let auth_type = Arc::new(RwLock::new(AuthTypePB::Local));
  32. std::mem::forget(inner.dispatcher());
  33. Self { inner, auth_type }
  34. }
  35. }
  36. impl FlowyCoreTest {
  37. pub fn new() -> Self {
  38. Self::default()
  39. }
  40. pub async fn new_with_user() -> Self {
  41. let test = Self::default();
  42. test.sign_up().await;
  43. test
  44. }
  45. pub async fn sign_up(&self) -> SignUpContext {
  46. let auth_type = self.auth_type.read().clone();
  47. async_sign_up(self.inner.dispatcher(), auth_type).await
  48. }
  49. pub fn set_auth_type(&self, auth_type: AuthTypePB) {
  50. *self.auth_type.write() = auth_type;
  51. }
  52. pub async fn init_user(&self) -> UserProfilePB {
  53. let auth_type = self.auth_type.read().clone();
  54. let context = async_sign_up(self.inner.dispatcher(), auth_type).await;
  55. init_user_setting(self.inner.dispatcher()).await;
  56. context.user_profile
  57. }
  58. pub async fn get_current_workspace(&self) -> WorkspaceSettingPB {
  59. EventBuilder::new(self.clone())
  60. .event(flowy_folder2::event_map::FolderEvent::GetCurrentWorkspace)
  61. .async_send()
  62. .await
  63. .parse::<flowy_folder2::entities::WorkspaceSettingPB>()
  64. }
  65. pub async fn get_all_workspace_views(&self) -> Vec<ViewPB> {
  66. EventBuilder::new(self.clone())
  67. .event(flowy_folder2::event_map::FolderEvent::ReadWorkspaceViews)
  68. .async_send()
  69. .await
  70. .parse::<flowy_folder2::entities::RepeatedViewPB>()
  71. .items
  72. }
  73. pub async fn delete_view(&self, view_id: &str) {
  74. let payload = RepeatedViewIdPB {
  75. items: vec![view_id.to_string()],
  76. };
  77. // delete the view. the view will be moved to trash
  78. EventBuilder::new(self.clone())
  79. .event(flowy_folder2::event_map::FolderEvent::DeleteView)
  80. .payload(payload)
  81. .async_send()
  82. .await;
  83. }
  84. pub async fn update_view(&self, changeset: UpdateViewPayloadPB) -> Option<FlowyError> {
  85. // delete the view. the view will be moved to trash
  86. EventBuilder::new(self.clone())
  87. .event(flowy_folder2::event_map::FolderEvent::UpdateView)
  88. .payload(changeset)
  89. .async_send()
  90. .await
  91. .error()
  92. }
  93. pub async fn create_view(&self, parent_id: &str, name: String) -> ViewPB {
  94. let payload = CreateViewPayloadPB {
  95. parent_view_id: parent_id.to_string(),
  96. name,
  97. desc: "".to_string(),
  98. thumbnail: None,
  99. layout: Default::default(),
  100. initial_data: vec![],
  101. meta: Default::default(),
  102. set_as_current: false,
  103. };
  104. EventBuilder::new(self.clone())
  105. .event(flowy_folder2::event_map::FolderEvent::CreateView)
  106. .payload(payload)
  107. .async_send()
  108. .await
  109. .parse::<flowy_folder2::entities::ViewPB>()
  110. }
  111. pub async fn create_grid(&self, parent_id: &str, name: String, initial_data: Vec<u8>) -> ViewPB {
  112. let payload = CreateViewPayloadPB {
  113. parent_view_id: parent_id.to_string(),
  114. name,
  115. desc: "".to_string(),
  116. thumbnail: None,
  117. layout: ViewLayoutPB::Grid,
  118. initial_data,
  119. meta: Default::default(),
  120. set_as_current: true,
  121. };
  122. EventBuilder::new(self.clone())
  123. .event(flowy_folder2::event_map::FolderEvent::CreateView)
  124. .payload(payload)
  125. .async_send()
  126. .await
  127. .parse::<flowy_folder2::entities::ViewPB>()
  128. }
  129. pub async fn create_board(&self, parent_id: &str, name: String, initial_data: Vec<u8>) -> ViewPB {
  130. let payload = CreateViewPayloadPB {
  131. parent_view_id: parent_id.to_string(),
  132. name,
  133. desc: "".to_string(),
  134. thumbnail: None,
  135. layout: ViewLayoutPB::Board,
  136. initial_data,
  137. meta: Default::default(),
  138. set_as_current: true,
  139. };
  140. EventBuilder::new(self.clone())
  141. .event(flowy_folder2::event_map::FolderEvent::CreateView)
  142. .payload(payload)
  143. .async_send()
  144. .await
  145. .parse::<flowy_folder2::entities::ViewPB>()
  146. }
  147. pub async fn create_calendar(
  148. &self,
  149. parent_id: &str,
  150. name: String,
  151. initial_data: Vec<u8>,
  152. ) -> ViewPB {
  153. let payload = CreateViewPayloadPB {
  154. parent_view_id: parent_id.to_string(),
  155. name,
  156. desc: "".to_string(),
  157. thumbnail: None,
  158. layout: ViewLayoutPB::Calendar,
  159. initial_data,
  160. meta: Default::default(),
  161. set_as_current: true,
  162. };
  163. EventBuilder::new(self.clone())
  164. .event(flowy_folder2::event_map::FolderEvent::CreateView)
  165. .payload(payload)
  166. .async_send()
  167. .await
  168. .parse::<flowy_folder2::entities::ViewPB>()
  169. }
  170. pub async fn get_database(&self, view_id: &str) -> DatabasePB {
  171. EventBuilder::new(self.clone())
  172. .event(flowy_database2::event_map::DatabaseEvent::GetDatabase)
  173. .payload(DatabaseViewIdPB {
  174. value: view_id.to_string(),
  175. })
  176. .async_send()
  177. .await
  178. .parse::<flowy_database2::entities::DatabasePB>()
  179. }
  180. pub async fn get_all_database_fields(&self, view_id: &str) -> RepeatedFieldPB {
  181. EventBuilder::new(self.clone())
  182. .event(flowy_database2::event_map::DatabaseEvent::GetFields)
  183. .payload(GetFieldPayloadPB {
  184. view_id: view_id.to_string(),
  185. field_ids: None,
  186. })
  187. .async_send()
  188. .await
  189. .parse::<RepeatedFieldPB>()
  190. }
  191. pub async fn create_field(&self, view_id: &str, field_type: FieldType) -> FieldPB {
  192. EventBuilder::new(self.clone())
  193. .event(flowy_database2::event_map::DatabaseEvent::CreateTypeOption)
  194. .payload(CreateFieldPayloadPB {
  195. view_id: view_id.to_string(),
  196. field_type,
  197. type_option_data: None,
  198. })
  199. .async_send()
  200. .await
  201. .parse::<TypeOptionPB>()
  202. .field
  203. }
  204. pub async fn update_field(&self, changeset: FieldChangesetPB) {
  205. EventBuilder::new(self.clone())
  206. .event(flowy_database2::event_map::DatabaseEvent::UpdateField)
  207. .payload(changeset)
  208. .async_send()
  209. .await;
  210. }
  211. pub async fn delete_field(&self, view_id: &str, field_id: &str) -> Option<FlowyError> {
  212. EventBuilder::new(self.clone())
  213. .event(flowy_database2::event_map::DatabaseEvent::DeleteField)
  214. .payload(DeleteFieldPayloadPB {
  215. view_id: view_id.to_string(),
  216. field_id: field_id.to_string(),
  217. })
  218. .async_send()
  219. .await
  220. .error()
  221. }
  222. pub async fn update_field_type(
  223. &self,
  224. view_id: &str,
  225. field_id: &str,
  226. field_type: FieldType,
  227. ) -> Option<FlowyError> {
  228. EventBuilder::new(self.clone())
  229. .event(flowy_database2::event_map::DatabaseEvent::UpdateFieldType)
  230. .payload(UpdateFieldTypePayloadPB {
  231. view_id: view_id.to_string(),
  232. field_id: field_id.to_string(),
  233. field_type,
  234. })
  235. .async_send()
  236. .await
  237. .error()
  238. }
  239. pub async fn duplicate_field(&self, view_id: &str, field_id: &str) -> Option<FlowyError> {
  240. EventBuilder::new(self.clone())
  241. .event(flowy_database2::event_map::DatabaseEvent::DuplicateField)
  242. .payload(DuplicateFieldPayloadPB {
  243. view_id: view_id.to_string(),
  244. field_id: field_id.to_string(),
  245. })
  246. .async_send()
  247. .await
  248. .error()
  249. }
  250. pub async fn get_primary_field(&self, database_view_id: &str) -> FieldPB {
  251. EventBuilder::new(self.clone())
  252. .event(flowy_database2::event_map::DatabaseEvent::GetPrimaryField)
  253. .payload(DatabaseViewIdPB {
  254. value: database_view_id.to_string(),
  255. })
  256. .async_send()
  257. .await
  258. .parse::<FieldPB>()
  259. }
  260. pub async fn create_row(
  261. &self,
  262. view_id: &str,
  263. start_row_id: Option<String>,
  264. data: Option<RowDataPB>,
  265. ) -> RowMetaPB {
  266. EventBuilder::new(self.clone())
  267. .event(flowy_database2::event_map::DatabaseEvent::CreateRow)
  268. .payload(CreateRowPayloadPB {
  269. view_id: view_id.to_string(),
  270. start_row_id,
  271. group_id: None,
  272. data,
  273. })
  274. .async_send()
  275. .await
  276. .parse::<RowMetaPB>()
  277. }
  278. pub async fn delete_row(&self, view_id: &str, row_id: &str) -> Option<FlowyError> {
  279. EventBuilder::new(self.clone())
  280. .event(flowy_database2::event_map::DatabaseEvent::DeleteRow)
  281. .payload(RowIdPB {
  282. view_id: view_id.to_string(),
  283. row_id: row_id.to_string(),
  284. group_id: None,
  285. })
  286. .async_send()
  287. .await
  288. .error()
  289. }
  290. pub async fn get_row(&self, view_id: &str, row_id: &str) -> OptionalRowPB {
  291. EventBuilder::new(self.clone())
  292. .event(flowy_database2::event_map::DatabaseEvent::GetRow)
  293. .payload(RowIdPB {
  294. view_id: view_id.to_string(),
  295. row_id: row_id.to_string(),
  296. group_id: None,
  297. })
  298. .async_send()
  299. .await
  300. .parse::<OptionalRowPB>()
  301. }
  302. pub async fn get_row_meta(&self, view_id: &str, row_id: &str) -> RowMetaPB {
  303. EventBuilder::new(self.clone())
  304. .event(flowy_database2::event_map::DatabaseEvent::GetRowMeta)
  305. .payload(RowIdPB {
  306. view_id: view_id.to_string(),
  307. row_id: row_id.to_string(),
  308. group_id: None,
  309. })
  310. .async_send()
  311. .await
  312. .parse::<RowMetaPB>()
  313. }
  314. pub async fn update_row_meta(&self, changeset: UpdateRowMetaChangesetPB) -> Option<FlowyError> {
  315. EventBuilder::new(self.clone())
  316. .event(flowy_database2::event_map::DatabaseEvent::UpdateRowMeta)
  317. .payload(changeset)
  318. .async_send()
  319. .await
  320. .error()
  321. }
  322. pub async fn duplicate_row(&self, view_id: &str, row_id: &str) -> Option<FlowyError> {
  323. EventBuilder::new(self.clone())
  324. .event(flowy_database2::event_map::DatabaseEvent::DuplicateRow)
  325. .payload(RowIdPB {
  326. view_id: view_id.to_string(),
  327. row_id: row_id.to_string(),
  328. group_id: None,
  329. })
  330. .async_send()
  331. .await
  332. .error()
  333. }
  334. pub async fn move_row(&self, view_id: &str, row_id: &str, to_row_id: &str) -> Option<FlowyError> {
  335. EventBuilder::new(self.clone())
  336. .event(flowy_database2::event_map::DatabaseEvent::MoveRow)
  337. .payload(MoveRowPayloadPB {
  338. view_id: view_id.to_string(),
  339. from_row_id: row_id.to_string(),
  340. to_row_id: to_row_id.to_string(),
  341. })
  342. .async_send()
  343. .await
  344. .error()
  345. }
  346. pub async fn update_cell(&self, changeset: CellChangesetPB) -> Option<FlowyError> {
  347. EventBuilder::new(self.clone())
  348. .event(flowy_database2::event_map::DatabaseEvent::UpdateCell)
  349. .payload(changeset)
  350. .async_send()
  351. .await
  352. .error()
  353. }
  354. pub async fn update_date_cell(&self, changeset: DateChangesetPB) -> Option<FlowyError> {
  355. EventBuilder::new(self.clone())
  356. .event(flowy_database2::event_map::DatabaseEvent::UpdateDateCell)
  357. .payload(changeset)
  358. .async_send()
  359. .await
  360. .error()
  361. }
  362. pub async fn get_cell(&self, view_id: &str, row_id: &str, field_id: &str) -> CellPB {
  363. EventBuilder::new(self.clone())
  364. .event(flowy_database2::event_map::DatabaseEvent::GetCell)
  365. .payload(CellIdPB {
  366. view_id: view_id.to_string(),
  367. row_id: row_id.to_string(),
  368. field_id: field_id.to_string(),
  369. })
  370. .async_send()
  371. .await
  372. .parse::<CellPB>()
  373. }
  374. pub async fn get_date_cell(&self, view_id: &str, row_id: &str, field_id: &str) -> DateCellDataPB {
  375. let cell = self.get_cell(view_id, row_id, field_id).await;
  376. DateCellDataPB::try_from(Bytes::from(cell.data)).unwrap()
  377. }
  378. pub async fn get_checklist_cell(
  379. &self,
  380. view_id: &str,
  381. field_id: &str,
  382. row_id: &str,
  383. ) -> ChecklistCellDataPB {
  384. EventBuilder::new(self.clone())
  385. .event(flowy_database2::event_map::DatabaseEvent::GetChecklistCellData)
  386. .payload(CellIdPB {
  387. view_id: view_id.to_string(),
  388. row_id: row_id.to_string(),
  389. field_id: field_id.to_string(),
  390. })
  391. .async_send()
  392. .await
  393. .parse::<ChecklistCellDataPB>()
  394. }
  395. pub async fn update_checklist_cell(
  396. &self,
  397. changeset: ChecklistCellDataChangesetPB,
  398. ) -> Option<FlowyError> {
  399. EventBuilder::new(self.clone())
  400. .event(flowy_database2::event_map::DatabaseEvent::UpdateChecklistCell)
  401. .payload(changeset)
  402. .async_send()
  403. .await
  404. .error()
  405. }
  406. pub async fn insert_option(
  407. &self,
  408. view_id: &str,
  409. field_id: &str,
  410. row_id: &str,
  411. name: &str,
  412. ) -> Option<FlowyError> {
  413. let option = EventBuilder::new(self.clone())
  414. .event(flowy_database2::event_map::DatabaseEvent::CreateSelectOption)
  415. .payload(CreateSelectOptionPayloadPB {
  416. field_id: field_id.to_string(),
  417. view_id: view_id.to_string(),
  418. option_name: name.to_string(),
  419. })
  420. .async_send()
  421. .await
  422. .parse::<SelectOptionPB>();
  423. EventBuilder::new(self.clone())
  424. .event(flowy_database2::event_map::DatabaseEvent::InsertOrUpdateSelectOption)
  425. .payload(RepeatedSelectOptionPayload {
  426. view_id: view_id.to_string(),
  427. field_id: field_id.to_string(),
  428. row_id: row_id.to_string(),
  429. items: vec![option],
  430. })
  431. .async_send()
  432. .await
  433. .error()
  434. }
  435. pub async fn get_groups(&self, view_id: &str) -> Vec<GroupPB> {
  436. EventBuilder::new(self.clone())
  437. .event(flowy_database2::event_map::DatabaseEvent::GetGroups)
  438. .payload(DatabaseViewIdPB {
  439. value: view_id.to_string(),
  440. })
  441. .async_send()
  442. .await
  443. .parse::<RepeatedGroupPB>()
  444. .items
  445. }
  446. pub async fn move_group(&self, view_id: &str, from_id: &str, to_id: &str) -> Option<FlowyError> {
  447. EventBuilder::new(self.clone())
  448. .event(flowy_database2::event_map::DatabaseEvent::MoveGroup)
  449. .payload(MoveGroupPayloadPB {
  450. view_id: view_id.to_string(),
  451. from_group_id: from_id.to_string(),
  452. to_group_id: to_id.to_string(),
  453. })
  454. .async_send()
  455. .await
  456. .error()
  457. }
  458. pub async fn set_group_by_field(&self, view_id: &str, field_id: &str) -> Option<FlowyError> {
  459. EventBuilder::new(self.clone())
  460. .event(flowy_database2::event_map::DatabaseEvent::SetGroupByField)
  461. .payload(GroupByFieldPayloadPB {
  462. field_id: field_id.to_string(),
  463. view_id: view_id.to_string(),
  464. })
  465. .async_send()
  466. .await
  467. .error()
  468. }
  469. pub async fn update_group(
  470. &self,
  471. view_id: &str,
  472. group_id: &str,
  473. name: Option<String>,
  474. visible: Option<bool>,
  475. ) -> Option<FlowyError> {
  476. EventBuilder::new(self.clone())
  477. .event(flowy_database2::event_map::DatabaseEvent::UpdateGroup)
  478. .payload(UpdateGroupPB {
  479. view_id: view_id.to_string(),
  480. group_id: group_id.to_string(),
  481. name,
  482. visible,
  483. })
  484. .async_send()
  485. .await
  486. .error()
  487. }
  488. pub async fn update_setting(&self, changeset: DatabaseSettingChangesetPB) -> Option<FlowyError> {
  489. EventBuilder::new(self.clone())
  490. .event(flowy_database2::event_map::DatabaseEvent::UpdateDatabaseSetting)
  491. .payload(changeset)
  492. .async_send()
  493. .await
  494. .error()
  495. }
  496. pub async fn get_all_calendar_events(&self, view_id: &str) -> Vec<CalendarEventPB> {
  497. EventBuilder::new(self.clone())
  498. .event(flowy_database2::event_map::DatabaseEvent::GetAllCalendarEvents)
  499. .payload(CalendarEventRequestPB {
  500. view_id: view_id.to_string(),
  501. })
  502. .async_send()
  503. .await
  504. .parse::<RepeatedCalendarEventPB>()
  505. .items
  506. }
  507. pub async fn get_view(&self, view_id: &str) -> ViewPB {
  508. EventBuilder::new(self.clone())
  509. .event(flowy_folder2::event_map::FolderEvent::ReadView)
  510. .payload(ViewIdPB {
  511. value: view_id.to_string(),
  512. })
  513. .async_send()
  514. .await
  515. .parse::<flowy_folder2::entities::ViewPB>()
  516. }
  517. }
  518. impl std::ops::Deref for FlowyCoreTest {
  519. type Target = AppFlowyCore;
  520. fn deref(&self) -> &Self::Target {
  521. &self.inner
  522. }
  523. }
  524. // pub struct TestNotificationSender {
  525. // pub(crate) sender: tokio::sync::mpsc::Sender<()>,
  526. // }
  527. //
  528. // impl NotificationSender for TestNotificationSender {
  529. // fn send_subject(&self, subject: SubscribeObject) -> Result<(), String> {
  530. // todo!()
  531. // }
  532. // }